Wagmi Tempo 事件监听实战:使用 `reward.watchRewardRecipientSet` 跟踪奖励接收者变更
2026/9/18 1:39:17 网站建设 项目流程

Wagmi Tempo 事件监听实战:使用reward.watchRewardRecipientSet跟踪奖励接收者变更

【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi

本文讲解 Wagmi 框架中 Tempo 链上reward.watchRewardRecipientSet动作(Action)的完整用法,涵盖参数详解、事件回调与过滤器、取消订阅生命周期,并结合 React HookuseWatchRewardRecipientSet与底层源码实现,帮助开发者在 Tempo 生态应用中实时监听代币持有者设置或更改奖励接收者的链上事件,并与其他 Reward 系列动作联动构建完整的奖励分发闭环。

动作概述:监听什么事件,为什么需要它

在 Tempo 链上,TIP-20 代币持有者可以通过reward.setRecipient为自己设置(或更改)奖励接收者地址。当这一状态发生变化时,链上会发出RewardRecipientSet事件。reward.watchRewardRecipientSet正是用于持续监听这类事件的动作:

  • 当任意持有者设置奖励接收者时,回调立即触发;
  • 回调携带事件参数args(持有者地址与新的接收者地址)以及原始事件日志log
  • 返回一个unwatch函数,用于随时停止监听。

典型的应用场景包括:奖励分发面板中实时展示"谁更新了接收者"、审计/数据分析系统追踪接收者变更流水、以及在持有者退出奖励计划(设置为零地址)时做业务提醒。

该动作属于 Tempo Actions 总览 中 Reward Actions 分组的一员,与reward.setRecipientreward.claimreward.distributereward.watchRewardDistributedreward.getUserRewardInfo共同构成完整的奖励机制。

前置准备:Tempo 配置文件

使用任何 Tempo 动作之前,都需要一个已连接 Tempo 链与钱包连接器的 Wagmi 配置。文档引用的是 config-tempo.ts:

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]声明目标链为 Tempo;
  • connectors: [tempoWallet()]接入 Tempo 钱包连接器,事件监听依赖链上 RPC 而非钱包签名,因此监听动作本身无需用户连接钱包,但同一条 Reward 业务链路上的写操作(如setRecipient)需要账户;
  • transports中为tempo.id指定http()传输层,事件轮询/订阅基于该 RPC 端点。

基本用法:开始监听与停止监听

文档中的标准示例(完整可运行):

import { Actions } from 'wagmi/tempo' import { config } from './config' const unwatch = Actions.reward.watchRewardRecipientSet(config, { onRewardRecipientSet(args, log) { console.log('args:', args) }, token: '0x20c0000000000000000000000000000000000000', }) // Later, stop watching unwatch()

使用要点:

  • 第一个参数是 Wagmiconfig(即上面的createConfig结果);
  • 第二个参数是配置对象,token必填,onRewardRecipientSet为事件回调;
  • 调用立即返回unwatch函数,页面卸载、组件销毁或业务不再需要时务必调用以释放资源;
  • 回调中log为 viem 的Log类型原始日志对象,包含blockNumbertransactionHashaddress等链上元信息,便于追溯来源交易。

参数详解

onRewardRecipientSet(必填回调)

  • 类型function
declare function onRewardRecipientSet(args: Args, log: Log): void type Args = { /** Token holder address who set their reward recipient */ holder: Address /** New reward recipient address (zero address indicates opt-out) */ recipient: Address }

回调在每次事件发生时被调用:

  • args.holder:设置奖励接收者的代币持有者地址;
  • args.recipient:新的奖励接收者地址。零地址表示该持有者已退出奖励计划(opt-out),此语义与reward.setRecipient中"使用零地址退出"的设计完全对应;
  • log:完整的链上事件日志。

token(必填)

  • 类型Address

要监听的 TIP-20 代币地址。监听粒度是"单个代币",如需同时跟踪多个代币,需要为每个代币分别调用一次watchRewardRecipientSet

args(可选过滤器)

  • 类型object
type Args = { /** Filter events by holder address */ holder?: Address /** Filter events by recipient address */ recipient?: Address }

用于收窄监听范围:

  • 只关心某个持有者的变更时传入holder
  • 只关心某个接收者被设置时传入recipient
  • 两者可组合使用。

当订阅方较多或代币活跃度高时,合理使用过滤器可以显著减少回调次数与 RPC 负载。从类型签名看,过滤器的取值沿用 viem Tempo 动作的参数定义(见下文源码解析中对Actions.reward.watchRewardRecipientSet.Parameters的透传)。

返回类型与生命周期管理

  • 返回类型() => void

返回一个取消订阅函数。调用后监听立即停止,且幂等安全——重复调用不会产生副作用。在 SPA 应用中,推荐把该函数挂到组件的卸载阶段:

import { useEffect } from 'react' import { Actions } from 'wagmi/tempo' import { config } from './config' useEffect(() => { const unwatch = Actions.reward.watchRewardRecipientSet(config, { onRewardRecipientSet(args, log) { console.log('args:', args) }, token: '0x20c0000000000000000000000000000000000000', }) return unwatch }, [])

这样监听的生命周期与组件生命周期严格对齐,避免内存泄漏与重复订阅。

源码实现:从 Wagmi 动作到 viem 底层

在 packages/core/src/tempo/actions/reward.ts 中,该动作的实现非常精简:

export function watchRewardRecipientSet<config extends Config>( config: config, parameters: watchRewardRecipientSet.Parameters<config>, ) { const { chainId, ...rest } = parameters const client = config.getClient({ chainId }) return Actions.reward.watchRewardRecipientSet(client, rest) } export declare namespace watchRewardRecipientSet { export type Parameters<config extends Config> = ChainIdParameter<config> & Actions.reward.watchRewardRecipientSet.Parameters }

从源码可以确认两点实现事实:

  1. 参数透传:Wagmi 层将chainId从参数中拆分出来,用于通过config.getClient({ chainId })获取对应链的 viem 客户端,其余参数(tokenonRewardRecipientSet、过滤器等)原样透传给 viem 的Actions.reward.watchRewardRecipientSet,因此其类型签名直接继承自 viem Tempo 动作;
  2. 客户端来源:监听动作复用 WagmiConfig中按chainId管理的客户端,这保证了与同一 config 下其他读/写动作使用一致的 RPC 端点与连接器配置。

文件头部还展示了同模块的其他动作(claimsetRecipientdistributegetUserRewardInfo等),它们与监听动作共享相同的config.getClient/getConnectorClient机制,便于组合使用。

React 场景:useWatchRewardRecipientSetHook

在 React 应用中,更推荐使用对应的 Hook 形式(见 packages/react/src/tempo/hooks/reward.ts):

import { Hooks } from 'wagmi/tempo' function App() { Hooks.reward.useWatchRewardRecipientSet({ token: '0x20c0000000000000000000000000000000000001', onRewardRecipientSet(args) { console.log('Reward recipient set:', args) }, }) return <div>Watching for reward recipient set events...</div> }

Hook 的配置参数与 Wagmi Actionreward.watchRewardRecipientSetParameters 保持一致,并额外提供:

  • configConfig | undefined,可显式传入,缺省时从最近的WagmiProvider获取;
  • enabledboolean(默认true),为false时暂停监听;
  • chainId:指定监听链;
  • fromBlockpollpollingIntervalonError等底层监听参数(从源码中useEffect依赖数组可见,见 reward.ts)。

从源码实现看,Hook 内部通过useConfiguseChainId解析 config 与链 ID,并在useEffect中调用Actions.reward.watchRewardRecipientSet(config, ...);只有enabledonRewardRecipientSettoken全部就绪时才建立监听,且依赖数组显式列出fromBlockonErrorpollpollingInterval,这些参数变化时会自动重建订阅。useEffect的 cleanup 机制会调用返回的unwatch,因此组件卸载后无需手动清理。

与 Reward 系列动作组合:完整的业务闭环

watchRewardRecipientSet单独使用只能"看见"变更,要构成完整业务需与同组动作配合(参见 Tempo Actions 总览 中的 Reward Actions):

动作职责
reward.setRecipient设置/更改奖励接收者(零地址 = 退出奖励)
reward.watchRewardRecipientSet监听接收者变更事件(本文主题)
reward.distribute向已加入(opted-in)的持有者分发奖励
reward.watchRewardDistributed监听奖励分发事件
reward.claim领取累积奖励
reward.getUserRewardInfo查询某账户的奖励余额、每代币奖励与当前接收者

组合示例——监听事件并联动查询最新状态:

import { Actions } from 'wagmi/tempo' import { config } from './config' const TOKEN = '0x20c0000000000000000000000000000000000000' const unwatch = Actions.reward.watchRewardRecipientSet(config, { token: TOKEN, onRewardRecipientSet: async ({ holder, recipient }, log) => { console.log(`Holder ${holder} set recipient to ${recipient}`) // 联动查询该持有者最新奖励信息 const { rewardBalance, rewardPerToken, rewardRecipient } = await Actions.reward.getUserRewardInfo(config, { account: holder, token: TOKEN, }) console.log({ rewardBalance, rewardPerToken, rewardRecipient }) }, })

注意事项:

  • recipient为零地址,表示持有者退出奖励计划,处理逻辑应与正常设置区分开;
  • 若你同时在实现"设置接收者"功能,可参考reward.setRecipient文档中的同步(setRecipientSync)与异步两种用法,以及"Rewards are automatically distributed to the current recipient before changing"的链上语义提示——接收者变更前,链会自动先把应得奖励结算给原接收者;
  • 性能优先时,监听回调内不要做阻塞式重操作,复杂的衍生计算建议放到队列或事件总线中异步处理。

总结

reward.watchRewardRecipientSet是 Tempo 奖励体系中面向"变更流"的监听动作:它通过 Wagmi 的config.getClient复用链客户端(源码见 packages/core/src/tempo/actions/reward.ts),将参数透传给 viem 的 Tempo 实现,并提供unwatch取消订阅函数以精确控制生命周期;React 侧对应的useWatchRewardRecipientSetHook(源码见 packages/react/src/tempo/hooks/reward.ts)则自动处理订阅与清理。掌握holder/recipient过滤器、零地址 opt-out 语义,并与setRecipientgetUserRewardInfodistributeclaim组合使用,即可构建实时、完整的 Tempo 链上奖励分发应用。

【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

立即咨询