w3-kitdocs

claim-rewards

Claim accumulated staking rewards from a staking contract (EVM) or withdraw from a native stake account (Solana).

evmsolana

Dependencies

viem@solana/web3.js
claim-rewards/evm.tsx
/**
 * claim-rewards/evm.tsx
 * Generic EVM reward-claim pattern: read pendingRewards → call claim/harvest.
 * Replace STAKING_ADDRESS and STAKING_ABI with your target protocol.
 */

import { useEffect } from "react";
import { useAccount, useReadContract, useWriteContract,
         useWaitForTransactionReceipt } from "wagmi";
import { formatUnits } from "viem";

const STAKING_ADDRESS = "0xSTAKING" as `0x${string}`;
const REWARD_DECIMALS = 18;

const STAKING_ABI = [
  { name: "pendingRewards", type: "function", stateMutability: "view",
    inputs: [{ name: "account", type: "address" }],
    outputs: [{ type: "uint256" }] },
  { name: "claim", type: "function", stateMutability: "nonpayable",
    inputs: [], outputs: [] },
] as const;

export function useClaimRewards() {
  const { address } = useAccount();

  const { data: pending, refetch } = useReadContract({
    address: STAKING_ADDRESS,
    abi: STAKING_ABI,
    functionName: "pendingRewards",
    args: address ? [address] : undefined,
    query: { enabled: !!address, refetchInterval: 15_000 },
  });

  const { writeContract, data: txHash } = useWriteContract();
  const { isLoading: claiming, isSuccess: claimed } =
    useWaitForTransactionReceipt({ hash: txHash });

  function handleClaim() {
    writeContract({
      address: STAKING_ADDRESS,
      abi: STAKING_ABI,
      functionName: "claim",
    });
  }

  // Refresh pending balance after successful claim
  useEffect(() => { if (claimed) refetch(); }, [claimed, refetch]);

  return {
    pendingRewards: pending ? formatUnits(pending, REWARD_DECIMALS) : "0",
    handleClaim,
    claiming,
    claimed,
  };
}

Learn: Claiming Rewards

How reward distribution works

Epoch-based (Solana native, some EVM protocols)

Rewards are calculated and distributed at the end of each epoch. Your effective yield depends on when in the epoch you staked (partial epochs may earn partial rewards).

Continuous / per-block (most EVM DeFi)

Protocols like Synthetix, Curve, and Convex accumulate rewards every block. pendingRewards or earned returns the unclaimed balance at any time.

Auto-compounding

Some protocols (e.g. Beefy, Yearn) auto-compound rewards on your behalf by:

  1. Claiming rewards periodically.
  2. Swapping reward tokens back to the staked asset.
  3. Re-staking — increasing your principal.

This converts APR into effective APY. Cost: a small protocol fee (typically 1–5% of yield).

Manual compounding

If the protocol doesn't auto-compound, you can manually:

  1. Claim rewards.
  2. Swap reward token → staking token (see swap-tokens recipe).
  3. Stake again (see stake-tokens recipe).

Gas cost per compounding cycle reduces net yield; compound less frequently on high-fee networks (Ethereum mainnet).

Tax considerations

In many jurisdictions:

  • Staking rewards are taxed as income at the time of receipt (fair market value when earned).
  • Selling the reward token is a capital gains event.
  • Keep records of reward amounts and timestamps.

Not financial or tax advice — consult a professional for your jurisdiction.

Key takeaway

Claiming rewards is straightforward on EVM. On Solana native staking, there is no explicit "claim" — rewards are realised during the withdraw flow. For auto-compounding, LST protocols or yield aggregators are the simplest option.