wagmi Tempo 奖励分发事件监听指南:使用 `reward.useWatchRewardDistributed` Hook
2026/9/17 22:08:42 网站建设 项目流程

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.watchRewardDistributedreward.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 文档),并额外叠加configenabled两个 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

控制监听是否激活。在源码实现中,当enabledfalseonRewardDistributed缺失或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, ]) }

值得关注的实现细节:

  1. 订阅即生命周期:Hook 自身不返回值,真正的订阅动作发生在useEffect内,且useEffect的返回值正是 Action 返回的取消订阅函数——组件卸载或依赖变化时 React 会自动调用它完成清理,避免内存泄漏与重复订阅。
  2. 依赖数组显式声明configenabledchainIdtokenonRewardDistributed以及rest.fromBlockrest.onErrorrest.pollrest.pollingInterval任一变化都会触发重新订阅;其余参数通过展开rest透传,源码中对此有biome-ignore注释说明是有意为之。
  3. 链 ID 兜底chainId优先取用户显式传入的值,否则回落到当前配置链,保证多链场景下订阅始终落在正确链上。

Hook 最终调用的是 core 层包装后的 watchRewardDistributed,后者将chainId从参数中取出、通过config.getClient({ chainId })解析出对应链的 viem 客户端,再透传给 viem/tempo 的同名 Action 完成事件监听,并原样返回unwatch函数。

类型层面,reward.test-d.ts 对useWatchRewardDistributed做了编译期校验,验证其接受configenabledonRewardDistributed(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。

六、实用建议与注意事项

  1. 回调引用稳定性:由于onRewardDistributed位于依赖数组中,若每次渲染都内联创建新函数会导致订阅被反复重建。建议用useCallback包裹回调,或仅在确实需要时更新。
  2. 按需启用监听enabled默认true,在代币地址尚未就绪时记得显式关闭,避免无效订阅(源码会因token缺失直接跳过)。
  3. 合理使用过滤:多分发者场景下,优先用args.funder过滤而非在回调里自行判断,减少不必要的事件处理。
  4. 事件溯源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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询