Wagmi Tempo Actions 深度指南:使用 token.changeTransferPolicy 管理 TIP-20 代币转账策略
【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi
本篇指南围绕 Wagmi 仓库中 Tempo 模块的核心 Actiontoken.changeTransferPolicy展开,讲解如何为 TIP-20 代币切换转账策略(transfer policy),覆盖同步/异步两种调用方式、完整参数与返回值、底层源码实现以及配套 React Hooks。读完本文,你将能在 Wagmi(React 与 Core)中独立完成"代币创建后动态更换转账策略"的完整开发流程,并理解其与 Viem Tempo 的委托调用关系。
背景:TIP-20 代币与转账策略
Tempo 是一条为支付场景优化的 Layer 1 区块链,其协议内建了代币管理能力。TIP-20 是 Tempo 上的代币标准,而**转账策略(transfer policy)**定义了代币在转账、铸造、销毁等场景下需要满足的合规与业务约束(例如是否需要授权、是否冻结转账等)。
token.changeTransferPolicy正是用于修改某个 TIP-20 代币当前生效的转账策略的 Action。根据本仓库官方文档的说明,该操作要求调用者拥有默认管理员角色(default admin role),这一点与同模块中的grantRoles、revokeRoles、setRoleAdmin等权限类 Action 共同构成 Tempo 代币的权限管理体系。
前置准备:Tempo + Wagmi 环境配置
在调用该 Action 之前,需要先完成 Tempo 链与钱包的接入配置。仓库提供了现成的 React 配置示例 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 官方钱包连接器,来源为wagmi/tempo;multiInjectedProviderDiscovery: false:禁用多注入提供方自动发现,避免与 Tempo 钱包冲突;transports: { [tempo.id]: http() }:为 Tempo 链配置 HTTP 传输。
同时需要保证项目中的 Viem 版本满足要求(仓库文档注明viem@>=2.55.2),并安装accounts包。安装命令(以 pnpm 为例):
pnpm add viem@>=2.55.2 accounts若使用 Core 而非 React,只需将导入入口替换为@wagmi/core、@wagmi/core/chains、@wagmi/core/tempo,配置写法完全一致。
同步用法:changeTransferPolicySync
文档首先推荐的是*Sync变体。changeTransferPolicySync会等待交易被打包进区块后才返回结果,适合在交互式界面或脚本中需要立即拿到确认结果的场景:
import { Actions } from 'wagmi/tempo' import { config } from './config' const { receipt } = await Actions.token.changeTransferPolicySync(config, { policyId: 1n, token: '0x20c0000000000000000000000000000000000000', }) console.log('Transaction hash:', receipt.transactionHash) // @log: Transaction hash: 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef示例中的config即上文config-tempo.ts导出的配置对象。调用成功后,可以从返回的receipt.transactionHash拿到交易哈希用于链上查询或业务记录。
异步用法:changeTransferPolicy + waitForTransactionReceipt
如果追求更优性能(例如不阻塞 UI、由应用自行控制确认时机),应使用非同步版本token.changeTransferPolicy,它只负责签名并广播交易、立即返回hash,区块确认由开发者手动等待:
import { Actions as viem_Actions } from 'viem/tempo' import { Actions } from 'wagmi/tempo' import { waitForTransactionReceipt } from 'wagmi/actions' const hash = await Actions.token.changeTransferPolicy(config, { policyId: 1n, token: '0x20c0000000000000000000000000000000000000', }) const receipt = await waitForTransactionReceipt(config, { hash }) const { args } = viem_Actions.token.changeTransferPolicy.extractEvent(receipt.logs)这段代码展示了两种 Action 的差异:
| 对比维度 | changeTransferPolicySync | changeTransferPolicy |
|---|---|---|
| 返回内容 | 交易回执receipt及事件数据 | 仅交易哈希hash |
| 区块确认 | 内部等待,返回即已上链 | 不等待,需配合waitForTransactionReceipt |
| 适用场景 | 交互简单、需要即时反馈 | 性能敏感、自行控制确认流程 |
异步版本还展示了viem_Actions.token.changeTransferPolicy.extractEvent(receipt.logs)的用法:在拿到回执后,通过 Viem Tempo 的extractEvent从日志中解构出args(即事件参数),可用于解析newPolicyId、updater等链上事件字段。
返回值详解
changeTransferPolicySync的返回类型如下(文档原文定义):
type ReturnType = { /** ID of the new transfer policy */ newPolicyId: bigint /** Transaction receipt */ receipt: TransactionReceipt /** Address that updated the policy */ updater: Address }字段含义:
newPolicyId:链上生效的新转账策略 ID(bigint);receipt:完整交易回执(TransactionReceipt),其中transactionHash可提取交易哈希;updater:实际执行策略更新的地址(即默认管理员账户)。
该返回结构在仓库测试 token.test.ts 中有直接印证:调用changeTransferPolicySync后断言receipt存在,并对newPolicyId: 0n与updater: '0xf39F...2266'做了快照比对。
参数详解
changeTransferPolicy接受两个核心参数,外加一批可选的交易级参数。
policyId
- 类型:
bigint
要切换到的新转账策略 ID。策略 ID 由链上策略注册表定义,传入1n表示切换到编号为 1 的策略。
token
- 类型:
Address | bigint
目标 TIP-20 代币的地址或 ID。既支持形如0x20c0000000000000000000000000000000000000的合约地址,也支持用代币 ID(bigint)标识。测试代码中通常先用token.createSync创建一个新代币拿到其地址,再传给本参数。
通用交易参数(可选)
除上述参数外,该 Action 还继承了一组 TIP-20 写入类 Action 共用的交易参数(仓库文档见 tempo-write-parameters.md),完整清单如下:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
account | Account \| Address | 已连接的 Wagmi 账户 | 发起交易的账户 |
feeToken | Address \| bigint | — | 交易手续费代币,可为 TIP-20 地址或 ID |
feePayer | Account \| true | — | 手续费支付方;可传 Viem Account,或传true表示使用 Fee Payer Service 代付 |
gas | bigint | — | 交易 Gas 上限 |
maxFeePerGas | bigint | — | 每单位 Gas 的最高费用 |
maxPriorityFeePerGas | bigint | — | 每单位 Gas 的最高优先费(小费) |
nonce | number | — | 交易 nonce |
nonceKey | 'expiring' \| bigint | — | 交易 nonce 键,用于并发交易场景 |
validBefore | number | — | 交易必须被打包进区块之前的 Unix 时间戳 |
validAfter | number | — | 交易可以被打包进区块之后的 Unix 时间戳 |
throwOnReceiptRevert | boolean | true | 回执显示交易回滚时是否抛错;仅对*Sync变体生效 |
此外,从源码类型签名(见下文)还可以推断出chainId与connector两个可选参数:chainId用于指定目标链(多链配置下按链路由),connector用于显式指定使用的连接器,两者缺省时分别回退到配置默认链与当前活动连接器。
源码级实现原理
在 Wagmi 仓库中,该 Action 位于 packages/core/src/tempo/actions/token.ts,两个变体的实现结构高度一致。以非同步版为例:
export async function changeTransferPolicy<config extends Config>( config: config, parameters: changeTransferPolicy.Parameters<config>, ): Promise<Actions.token.changeTransferPolicy.ReturnValue> { const { account, chainId, connector } = parameters const client = await getConnectorClient(config, { account, assertChainId: false, chainId, connector, }) return Actions.token.changeTransferPolicy(client, parameters as never) }实现要点:
- 获取连接器客户端:通过
getConnectorClient(config, { account, chainId, connector })基于当前 Wagmi 配置解析出可用的 viem 客户端。注意assertChainId: false,即不强制断言链 ID,允许在未连接对应链时仍可构造客户端; - 委托给 Viem Tempo:拿到 client 后,直接调用
Actions.token.changeTransferPolicy(client, parameters),把执行细节完全交给 Viem 的 Tempo 模块,Wagmi 层只负责配置解析与客户端装配; - 类型组合:
Parameters类型由ChainIdParameter<config>、ConnectorParameter与OptionalTransactionOverrides<...>交叉组合而成,并通过UnionLooseOmit去掉chain字段——这解释了上文参数清单中chainId/connector与各项交易覆盖参数的来源。
changeTransferPolicySync(token.ts)的骨架与之完全相同,区别仅在于委托给Actions.token.changeTransferPolicySync,由 Viem 侧负责等待区块包含后返回回执与事件数据。
这种"Wagmi 薄封装 + Viem 底层实现"的分层设计,使得该 Action 在 React、Core、Solid、Vue 各框架接入层中复用同一套类型与逻辑。
测试验证
仓库测试 packages/core/src/tempo/actions/token.test.ts 为两个变体各提供了一条默认用例,覆盖了完整流程:
- 连接
config.connectors[0](测试用 mock 连接器); - 调用
token.createSync(config, { currency: 'USD', name: 'Policy Token', symbol: 'POLICY' })创建一个新代币; - 对
changeTransferPolicy断言返回值为 string 类型的交易哈希; - 对
changeTransferPolicySync断言receipt存在,且快照结果恰好为{ newPolicyId: 0n, updater: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266' }。
这与文档中 Return Type 的定义完全吻合,也验证了该 Action 在同步模式下会返回newPolicyId与updater两个事件字段。
React Hooks 用法
除了命令式 Action,仓库还提供了对应的 React Hooks。在 packages/react/src/tempo/hooks/token.ts 中,useChangeTransferPolicy与useChangeTransferPolicySync均基于useMutation封装,内部直接调用同名 Core Action:
import { Hooks } from 'wagmi/tempo' function App() { const { mutate, isPending } = Hooks.token.useChangeTransferPolicy() return ( <button onClick={() => mutate({ token: '0x...', policyId: 1n })} disabled={isPending} > Change Policy </button> ) }特性说明:
- 声明式状态:
mutate触发策略切换,isPending表示交易进行中,可安全地用于禁用按钮; - Mutation 语义:返回
UseMutationResult,可继续使用 TanStack Query 的isError、error、onSuccess等能力管理失败与成功分支; - Sync 变体:
useChangeTransferPolicySync使用方式相同,仅在回调时拿到的是已确认的回执与事件数据。
Viem 对应关系
token.changeTransferPolicy的最终实现在 Viem 的 Tempo 模块中,Wagmi 仅是转发层。Viem 侧提供同名 Action 与extractEvent工具(本文异步用法一节已演示),适合需要在纯 viem 环境下直接操作、或对底层行为做更深定制(如自定义错误处理、事件解析)的开发者。两者的参数与返回结构保持一致。
小结
token.changeTransferPolicy是 Tempo TIP-20 代币治理中高频使用的管理类 Action,本文已覆盖其完整使用链路:
- 权限前提:需要默认管理员角色;
- 两种调用形态:
changeTransferPolicy(快、异步确认)与changeTransferPolicySync(慢、返回即确认); - 核心参数:
policyId(新策略 ID)与token(代币地址或 ID),并支持feeToken、feePayer、nonceKey、validBefore/validAfter等 Tempo 交易特性参数; - 返回值:
newPolicyId、receipt、updater; - 实现与验证:Wagmi 层通过
getConnectorClient装配客户端后委托 Viem Tempo 执行,测试用例印证了返回结构与完整调用流程; - React 集成:可通过
Hooks.token.useChangeTransferPolicy( Sync)以声明式方式集成到组件。
若需要深入协议层了解各种策略 ID 的含义与注册方式,可继续阅读仓库中 Tempo Actions 索引 与其他代币治理 Action(如grantRoles、revokeRoles、setRoleAdmin、modifyWhitelist/modifyBlacklist)的文档,组合构建完整的代币合规治理方案。
【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考