wagmi Tempo 奖励分发事件监听指南:使用reward.useWatchRewardDistributedHook
【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi
本篇技术指南以 wagmi 仓库中 reward.useWatchRewardDistributed 文档 为核心,系统讲解 Tempo 生态中如何通过该 React Hook 实时监听"奖励已分发(RewardDistributed)"链上事件。读完本文,你将掌握reward.useWatchRewardDistributed的完整参数语义、与底层 Actionreward.watchRewardDistributed及reward.distribute的调用关系,并能直接在一套可运行的 wagmi Tempo 配置上实现"分发奖励 → 监听事件 → 更新 UI"的完整实战闭环。
一、这个 Hook 解决什么问题
在 Tempo 链的奖励机制中,reward.distribute负责向已选择参与(opt-in)的持币者分发奖励代币。当分发交易真正上链并触发RewardDistributed事件后,前端应用往往需要主动感知这一事件——例如刷新奖励余额、展示"奖励已到账"的提示、更新统计面板等。
reward.useWatchRewardDistributed正是为此设计的 React Hook:它订阅指定 TIP-20 代币上的奖励分发事件,一旦事件发生就回调你提供的onRewardDistributed函数。它在 wagmi 的 Tempo Hook 体系中属于"监听类(watch)"成员,与reward.useWatchRewardRecipientSet并列,二者分别对应RewardDistributed(奖励已分发)与RewardRecipientSet(奖励接收人已设置)两类事件,参见 hooks 总览。
二、快速上手
在 React 组件中调用该 Hook 的最小示例(与官方文档一致):
import { Hooks } from 'wagmi/tempo' function App() { Hooks.reward.useWatchRewardDistributed({ onRewardDistributed: (args, log) => { console.log('args:', args) }, token: '0x20c0000000000000000000000000000000000000', }) return <div>Watching for reward distributed events...</div> }其中token传入要监听的 TIP-20 代币地址;onRewardDistributed在每次事件触发时被调用,形参args携带事件解码后的参数,log为原始日志对象。
在仓库的 config-tempo.ts 示例 中,给出了搭配该 Hook 使用的完整 Tempo 配置:
import { createConfig, http } from 'wagmi' import { tempo } from 'wagmi/chains' import { tempoWallet } from 'wagmi/tempo' export const config = createConfig({ connectors: [tempoWallet()], chains: [tempo], multiInjectedProviderDiscovery: false, transports: { [tempo.id]: http(), }, })要点说明:
chains仅配置tempo一条链,且通过multiInjectedProviderDiscovery: false关闭浏览器内置钱包的自动发现,避免干扰tempoWallet连接器;transports为 tempo 链配置http()传输层,用于 RPC 交互与事件轮询。
三、参数详解
reward.useWatchRewardDistributed的完整参数类型为:
type Parameters<config extends Config> = UnionCompute< ExactPartial<Actions.reward.watchRewardDistributed.Parameters<config>> & ConfigParameter<config> & { enabled?: boolean | undefined } >即它继承自底层 Actionreward.watchRewardDistributed的全部参数(详见 reward.watchRewardDistributed 文档),并额外叠加config与enabled两个 Hook 专属参数。
3.1 onRewardDistributed(必填)
- 类型:
function
declare function onRewardDistributed(args: Args, log: Log): void type Args = { /** Total amount distributed */ amount: bigint /** Address that funded the distribution */ funder: Address }每次RewardDistributed事件触发时被调用:
args.amount:本次分发的总代币数量,bigint类型;args.funder:发起分发的账户地址;log:包含事件区块号、交易哈希、日志索引等原始信息的 viemLog对象,可用于精确溯源或去重。
3.2 token(必填)
- 类型:
Address
要监听的 TIP-20 代币合约地址。只有当该代币上发生RewardDistributed事件时回调才会触发。
3.3 args(可选过滤)
- 类型:
object
type Args = { /** Filter by funder address */ funder?: Address | Address[] }通过funder字段按分发者地址过滤事件,可传单个地址或地址数组,仅命中过滤条件的事件才会进入onRewardDistributed回调。
3.4 enabled(Hook 专属)
- 类型:
boolean | undefined - 默认值:
true
控制监听是否激活。在源码实现中,当enabled为false、onRewardDistributed缺失或token缺失时,useEffect会直接提前返回、不发起订阅(见 reward.ts)。典型用法是"链未连接/代币未选择时先不监听":
Hooks.reward.useWatchRewardDistributed({ enabled: isConnected, token: selectedToken, onRewardDistributed: (args) => console.log(args), })3.5 config
- 类型:
Config | undefined
不传时,Hook 会通过useConfig从最近的WagmiProvider上下文读取配置(见 WagmiProvider 文档);传入时则显式覆盖,适合在 Provider 树之外使用或有多个 config 的场景。config 的完整定义可参考 createConfig 文档。
3.6 chainId
- 类型:
ChainIdParameter
与 wagmi 其他 Hook 一致,可通过chainId指定监听的链。不传时,Hook 内部会先经useChainId取得当前配置的链 ID 作为兜底(见 reward.ts)。
四、底层实现原理
从源码看,该 Hook 是一层"React 生命周期包装",其核心逻辑位于 packages/react/src/tempo/hooks/reward.ts:
export function useWatchRewardDistributed<config extends Config>( parameters: useWatchRewardDistributed.Parameters<config> = {}, ) { const { enabled = true, onRewardDistributed, token, ...rest } = parameters const config = useConfig({ config: parameters.config }) const configChainId = useChainId({ config }) const chainId = parameters.chainId ?? configChainId useEffect(() => { if (!enabled) return if (!onRewardDistributed) return if (!token) return return Actions.reward.watchRewardDistributed(config, { ...rest, chainId, onRewardDistributed, token, }) }, [ config, enabled, chainId, token, onRewardDistributed, rest.fromBlock, rest.onError, rest.poll, rest.pollingInterval, ]) }值得关注的实现细节:
- 订阅即生命周期:Hook 自身不返回值,真正的订阅动作发生在
useEffect内,且useEffect的返回值正是 Action 返回的取消订阅函数——组件卸载或依赖变化时 React 会自动调用它完成清理,避免内存泄漏与重复订阅。 - 依赖数组显式声明:
config、enabled、chainId、token、onRewardDistributed以及rest.fromBlock、rest.onError、rest.poll、rest.pollingInterval任一变化都会触发重新订阅;其余参数通过展开rest透传,源码中对此有biome-ignore注释说明是有意为之。 - 链 ID 兜底:
chainId优先取用户显式传入的值,否则回落到当前配置链,保证多链场景下订阅始终落在正确链上。
Hook 最终调用的是 core 层包装后的 watchRewardDistributed,后者将chainId从参数中取出、通过config.getClient({ chainId })解析出对应链的 viem 客户端,再透传给 viem/tempo 的同名 Action 完成事件监听,并原样返回unwatch函数。
类型层面,reward.test-d.ts 对useWatchRewardDistributed做了编译期校验,验证其接受config、enabled、onRewardDistributed(args, log)等参数,保证 Hook 的类型签名与文档一致。
五、与 Action 配合:分发 → 监听的完整闭环
useWatchRewardDistributed监听的正是reward.distribute/reward.distributeSync所产生的链上事件。分发侧的使用方式参见 reward.distribute 文档:
import { Actions } from 'wagmi/tempo' import { parseEther } from 'viem' import { config } from './config' const { amount, funder, receipt } = await Actions.reward.distributeSync(config, { amount: parseEther('1000'), token: '0x20c0000000000000000000000000000000000000', })amount:分发数量(bigint,必须大于 0),可用parseEther('1000')换算;token:目标 TIP-20 代币地址;*Sync变体会等待交易确认后再返回;若追求性能,可使用非 Sync 的reward.distribute拿到hash后自行waitForTransactionReceipt。
将两侧组合起来,即可实现一个完整的奖励分发实时面板:
import { Hooks } from 'wagmi/tempo' import { Actions } from 'wagmi/tempo' import { parseEther } from 'viem' const TOKEN = '0x20c0000000000000000000000000000000000000' function RewardPanel() { const [events, setEvents] = useState<{ amount: bigint; funder: string }[]>([]) // 1. 实时监听奖励分发事件 Hooks.reward.useWatchRewardDistributed({ token: TOKEN, onRewardDistributed: (args) => { setEvents((prev) => [...prev, args]) }, }) // 2. 发起一次奖励分发 const handleDistribute = async () => { await Actions.reward.distributeSync(/* config */, { amount: parseEther('1000'), token: TOKEN, }) } return ( <div> <button onClick={handleDistribute}>分发奖励</button> <ul> {events.map((e, i) => ( <li key={i}> {e.funder} 分发 {e.amount.toString()} wei </li> ))} </ul> </div> ) }监听方无需手动轮询或刷新,onRewardDistributed一旦触发即可增量更新 UI。
六、实用建议与注意事项
- 回调引用稳定性:由于
onRewardDistributed位于依赖数组中,若每次渲染都内联创建新函数会导致订阅被反复重建。建议用useCallback包裹回调,或仅在确实需要时更新。 - 按需启用监听:
enabled默认true,在代币地址尚未就绪时记得显式关闭,避免无效订阅(源码会因token缺失直接跳过)。 - 合理使用过滤:多分发者场景下,优先用
args.funder过滤而非在回调里自行判断,减少不必要的事件处理。 - 事件溯源:
log参数携带完整链上元信息,可用于与reward.distribute返回的receipt相互印证,或实现基于fromBlock的历史事件回放(通过rest.fromBlock参数)。
七、延伸阅读
- reward.useWatchRewardRecipientSet:监听"奖励接收人已设置"事件的姊妹 Hook;
- reward.watchRewardDistributed Action 文档:Hook 所包装的底层 Action,含完整参数与返回类型;
- reward.distribute:触发
RewardDistributed事件的分发动作; - reward.useClaim 与 reward.useUserRewardInfo:与分发事件配套的领取、查询 Hook;
- Tempo hooks 总览:Reward、Token、DEX、Zone 等全部 Tempo Hook 索引;
- 源码实现:React Hook 定义、core Action 包装、类型测试。
【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考