Distribute Rewards
Distribute rewards to token holders using TIP-20's built-in reward distribution mechanism. Rewards allow parties to incentivize holders of a token by distributing tokens proportionally based on their balance.
Rewards can be distributed by anyone on any TIP-20 token, and claimed by any holder who has opted in. This guide covers both the reward distributor and token holder use cases. While the demo below uses a token you create, the same principles apply to any token.
Demo
Try out the complete rewards flow: create a token, opt in to receive rewards on it, create a reward for yourself, and claim it.
Distribute Rewards
demoSteps
[Optional] Create a Stablecoin
If you would like to distribute rewards on a token you have created, follow the Create a Stablecoin guide to deploy your token.
Tell Your Users to Opt In to Rewards
Token holders must opt in to receive rewards by setting their reward recipient address. This is typically set to their own address.
import React from 'react'
import { Hooks } from 'tempo.ts/wagmi'
import { useConnection } from 'wagmi'
export function OptInToRewards() {
const { address } = useConnection()
const tokenAddress = '0x...' // Your token address
const setRecipient = Hooks.reward.useSetRecipientSync()
const handleOptIn = () => {
if (!address) return
setRecipient.mutate({
recipient: address,
token: tokenAddress,
})
}
return (
<button
disabled={setRecipient.isPending}
onClick={handleOptIn}
type="button"
>
{setRecipient.isPending ? 'Opting in...' : 'Opt In to Rewards'}
</button>
)
}Make a Reward Distribution
Anyone can make a reward distribution that allocates tokens to all opted-in holders proportionally based on their balance.
import React from 'react'
import { Hooks } from 'tempo.ts/wagmi'
import { parseUnits } from 'viem'
export function StartReward() {
const tokenAddress = '0x...' // Your token address
const { data: metadata } = Hooks.token.useGetMetadata({
token: tokenAddress,
})
const start = Hooks.reward.useStartSync()
const handleStart = () => {
if (!metadata) return
start.mutate({
amount: parseUnits('50', metadata.decimals),
token: tokenAddress,
})
}
return (
<button
disabled={start.isPending || !metadata}
onClick={handleStart}
type="button"
>
{start.isPending ? 'Starting...' : 'Start Reward'}
</button>
)
}Your Users Can Claim Rewards
Once a reward is distributed, opted-in holders can claim their share.
import React from 'react'
import { Hooks } from 'tempo.ts/wagmi'
export function ClaimReward() {
const tokenAddress = '0x...' // Your token address
const claim = Hooks.reward.useClaimSync()
const handleClaim = () => {
claim.mutate({
token: tokenAddress,
})
}
return (
<button
disabled={claim.isPending}
onClick={handleClaim}
type="button"
>
{claim.isPending ? 'Claiming...' : 'Claim Rewards'}
</button>
)
}Recipes
Watch for new reward distributions
Use useWatchRewardScheduled to listen for new reward distributions on a token. This is useful for updating your UI when a reward is distributed.
import { Hooks } from 'tempo.ts/wagmi'
function WatchRewards() {
const tokenAddress = '0x...' // Your token address
Hooks.reward.useWatchRewardScheduled({
token: tokenAddress,
onRewardScheduled(args) {
console.log('New reward scheduled:', args)
// Update UI, refetch balances, show notification, etc.
},
})
return <div>Watching for reward distributions...</div>
}Watch for reward opt-ins
Use useWatchRewardRecipientSet to listen for when users opt in to rewards by setting their recipient address. This is useful for tracking opt-in activity.
import { Hooks } from 'tempo.ts/wagmi'
function WatchOptIns() {
const tokenAddress = '0x...' // Your token address
Hooks.reward.useWatchRewardRecipientSet({
token: tokenAddress,
onRewardRecipientSet(args) {
console.log('User opted in:', args)
// Update UI, track analytics, etc.
},
})
return <div>Watching for reward opt-ins...</div>
}