wagmi Tempo `token.renounceRoles` 实战指南:TIP-20 代币角色放弃的同步/异步调用与源码解析
2026/9/18 1:10:29 网站建设 项目流程

wagmi Tempotoken.renounceRoles实战指南:TIP-20 代币角色放弃的同步/异步调用与源码解析

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

token.renounceRoles是 wagmi Tempo 模块中用于从调用者自身地址放弃(renounce)一个或多个 TIP-20 代币角色的核心 Action,常用于治理与安全流程——例如代币合约不再需要issuer(发行)权限时主动交出角色,以降低被滥用的风险。本文将以 site/tempo/actions/token.renounceRoles.md 为骨架,结合 wagmi 仓库源码与测试,完整讲解同步/异步两种调用方式、返回值结构、全部参数含义,以及 React Hook 用法,帮助你直接落地可运行的代码。

TIP-20 角色模型与 renounceRoles 的定位

在 Tempo 的 TIP-20 代币标准中,代币合约通过**角色(Role)**来控制关键权限,而非仅靠单一所有者。文档定义的角色集合为:

("defaultAdmin" | "pause" | "unpause" | "issuer" | "burnBlocked")[]
  • defaultAdmin:默认管理员,通常拥有管理其他角色配置的权限;
  • pause:暂停代币操作;
  • unpause:恢复代币操作;
  • issuer:发行(铸造)代币;
  • burnBlocked:被禁止销毁的相关角色控制。

与"授予"(grantRoles)或"撤销"(revokeRoles)不同,renounceRoles有一个明确约束:只能放弃调用者自己地址上的角色,不能替他人放弃。这一点在文档中被直接表述为 "Renounces one or more roles from the caller's address"。它天然适合"自省式安全"场景——当合约或账户不再需要某权限时,主动交还角色。

快速上手:使用renounceRolesSync一次性完成

文档推荐的最直接用法是*Sync变体。renounceRolesSync等待交易被打包进区块后才返回,因此你拿到结果时,角色的放弃已经确认生效:

import { Actions } from 'wagmi/tempo' import { config } from './config' const { receipt, value } = await Actions.token.renounceRolesSync(config, { roles: ['issuer'], token: '0x20c0000000000000000000000000000000000000', }) console.log('Roles renounced:', value.length) // @log: Roles renounced: 1

其中config是 wagmi 的配置对象,文档中的示例配置(对应 site/snippets/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(), }, })

要点:

  • 通过tempoWallet()连接器提供签名账户;
  • 只配置了tempo一条链,transport 使用http()
  • multiInjectedProviderDiscovery: false避免多钱包注入冲突。

renounceRolesSync返回值中的value是本次角色变更产生的事件数组,value.length即成功放弃的角色数量。

同步与异步:按性能需求选择变体

上面的示例使用的是*Sync变体,它会一直等到交易确认入块再返回。如果追求更优性能(例如高吞吐的批处理场景),应当使用非 Sync 的token.renounceRoles,它只返回交易哈希,入块确认由你手动等待:

import { Actions as viem_Actions } from 'viem/tempo' import { Actions } from 'wagmi/tempo' import { waitForTransactionReceipt } from 'wagmi/actions' const hash = await Actions.token.renounceRoles(config, { roles: ['issuer'], token: '0x20c0000000000000000000000000000000000000', }) const receipt = await waitForTransactionReceipt(config, { hash }) const events = viem_Actions.token.renounceRoles.extractEvents(receipt.logs)

两条路径的取舍:

变体返回内容等待入块适用场景
token.renounceRoleshash否,需手动waitForTransactionReceipt性能优先、需自定义等待与错误处理的场景
token.renounceRolesSync{ receipt, value }是,内部等待确认简单直接、需要立即拿到事件数据的场景

另外,Sync变体受throwOnReceiptRevert参数影响:当其默认值true时,如果收据显示交易回滚会直接抛错;设为false则交由你自行判断收据状态。

返回值详解

renounceRolesSync的返回类型结构如下:

type ReturnType = { /** Transaction receipt */ receipt: TransactionReceipt /** Array of role membership update events */ value: readonly { /** Address that renounced the role */ account: Address /** Whether the role was granted (true) or revoked (false) */ hasRole: boolean /** Role identifier */ role: Hex /** Address that initiated the change */ sender: Address }[] }

字段说明:

  • receipt:完整交易收据,可用于 gas 消耗、区块号等链上信息的后续读取;
  • value:角色成员关系变更事件数组,每个元素记录一次变更:
    • account:放弃角色的地址(即调用者);
    • hasRoletrue表示授予、false表示撤销——在 renounce 场景中通常为false
    • role:被放弃的角色标识(Hex);
    • sender:发起这次变更的地址。

value.length可用于校验"预期放弃 N 个角色、实际产生 N 条事件"。仓库测试 packages/core/src/tempo/actions/token.test.ts 也验证了这一行为:renounceRolesSyncvalue.length1,且value[0].account等于调用者地址、value[0].hasRolefalse

参数详解

roles(必填)

  • 类型:("defaultAdmin" | "pause" | "unpause" | "issuer" | "burnBlocked")[]

要放弃的角色数组,可一次传入多个角色。注意:这些角色必须存在于调用者自己的地址上,否则交易会被链上合约拒绝或产生空事件。测试用例中先通过grantRolesSyncissuer角色授予自己,再调用renounceRoles放弃该角色(见 packages/core/src/tempo/actions/token.test.ts),这是最典型的"先授予、后放弃"闭环。

token(必填)

  • 类型:Address | bigint

目标 TIP-20 代币的地址或 ID。文档示例使用了'0x20c0000000000000000000000000000000000000'这样的地址形式;当使用代币 ID(bigint)时,适用于以 ID 而非地址标识的 TIP-20 代币。

通用写交易参数(均可选)

以下参数来自共享的写入参数集合(对应 site/shared/tempo-write-parameters.md),renounceRolesrenounceRolesSync均支持:

参数类型默认值说明
accountAccount \| Address已连接的 Wagmi 账户发送交易的账户
feeTokenAddress \| bigint交易手续费代币,可为 TIP-20 代币地址或 ID
feePayerAccount \| true手续费支付方;可为 Viem 本地账户,或传true表示使用 Fee Payer Service
gasbigint交易的 gas 上限
maxFeePerGasbigint每单位 gas 的最高费用
maxPriorityFeePerGasbigint每单位 gas 的最高优先费(小费)
noncenumber交易 nonce
nonceKey'expiring' \| bigint交易 nonce key
validBeforenumber交易必须被打包的时间戳上限(Unix)
validAfternumber交易可被打包的时间戳下限(Unix)
throwOnReceiptRevertbooleantrue收据显示回滚时是否抛错,仅对*Sync变体生效

其中feeToken/feePayer体现了 Tempo 链"第三方代付 gas"的能力;validBefore/validAfter则为交易设置时间窗约束。这些参数与chainIdconnector等 wagmi 通用参数一起,最终会透传给 viem 层执行。

源码级原理:从 config 到链上调用

在 packages/core/src/tempo/actions/token.ts 中,renounceRolesrenounceRolesSync的实现结构一致:

export async function renounceRoles<config extends Config>( config: config, parameters: renounceRoles.Parameters<config>, ): Promise<Actions.token.renounceRoles.ReturnValue> { const { account, chainId, connector } = parameters const client = await getConnectorClient(config, { account, assertChainId: false, chainId, connector, }) return Actions.token.renounceRoles(client, parameters as never) }

可以提炼出的关键点:

  1. 通过getConnectorClient获取客户端:根据传入的accountchainIdconnector参数解析出当前连接器对应的 viem 客户端。assertChainId: false表示不强制断言链 ID,允许跨链参数场景。
  2. 薄封装委托给 viem:wagmi 层仅负责"从 wagmi config 解析出 viem client + 规范化参数",实际的链上交易组装、签名与发送由Actions.token.renounceRoles/renounceRolesSync(viem/tempo 层)完成。
  3. Sync 变体的差异仅在等待逻辑:非 Sync 版本返回hash;Sync 版本额外等待交易入块并解析出receipt与角色变更事件value
  4. 类型透传Parameters类型组合了ChainIdParameterConnectorParameterOptionalTransactionOverrides,这也是上节"通用写交易参数"得以生效的底层原因。

React 集成:useRenounceRoles/useRenounceRolesSyncHook

在 React 应用中,更推荐使用wagmi/tempo导出的 Hooks(对应文档 site/tempo/hooks/token.useRenounceRoles.md)。其底层是 TanStack Query 的useMutation(见 packages/react/src/tempo/hooks/token.ts),mutationKey分别为['renounceRoles']['renounceRolesSync']

Sync 变体示例:

import { Hooks } from 'wagmi/tempo' const renounceRolesSync = Hooks.token.useRenounceRolesSync() // 在用户动作(按钮点击、表单提交)中触发 renounceRolesSync.mutate({ roles: ['issuer'], token: '0x20c0000000000000000000000000000000000000', }) console.log('Transaction hash:', renounceRolesSync.data?.receipt.transactionHash) // @log: Transaction hash: 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef

性能优先的异步写法(配合useWaitForTransactionReceipt手动等待入块):

import { Hooks } from 'wagmi/tempo' import { Actions } from 'viem/tempo' import { useWaitForTransactionReceipt } from 'wagmi' const renounceRoles = Hooks.token.useRenounceRoles() const { data: receipt } = useWaitForTransactionReceipt({ hash: renounceRoles.data }) renounceRoles.mutate({ roles: ['issuer'], token: '0x20c0000000000000000000000000000000000000', }) if (receipt) { const events = Actions.token.renounceRoles.extractEvents(receipt.logs) }

Hook 参数说明:

  • config(可选):传入Config可绕过最近的WagmiProvider,直接使用指定配置;
  • mutation(可选):透传给 TanStack QueryuseMutation的选项,可自定义onSuccessonError等回调;
  • data/mutate/mutateAsync的返回类型分别对应 Action 的 Return Type 与 Parameters。

测试验证与最佳实践

仓库测试 packages/core/src/tempo/actions/token.test.ts 完整覆盖了两个变体的主路径,可以作为你验证集成的参考流程:

  1. 连接账户(connect+config.connectors[0]);
  2. 创建新代币(token.createSync);
  3. 先授予角色给自己(grantRolesSyncroles: ['issuer']);
  4. 调用renounceRoles(断言返回hash)或renounceRolesSync(断言receipt存在、value.length === 1account为调用者、hasRole === false)。

基于文档与源码,实践中有几点建议:

  • 放弃前先确认角色归属:可通过hasRole查询确认角色确实在自己地址上,避免空操作;
  • 批量放弃时校验事件数:用value.length与传入的roles数量比对,确保每个角色都产生了对应事件;
  • 合理选择 Sync 与否:UI 交互(按钮点击)场景用 Sync 变体体验更直观;批量/后台任务用非 Sync 变体配合统一等待更高效;
  • 善用时间窗与代付参数:需要控制交易生效时间或由服务端代付 gas 时,使用validBefore/validAfterfeeToken/feePayer
  • 保持throwOnReceiptRevert默认开启:除非你想自行处理回滚收据,否则默认true能第一时间暴露链上失败。

token.renounceRoles与 viem 的token.renounceRoles一一对应,如需更深层的链上编码细节,可继续阅读 viem 的 Tempo 实现;而 wagmi 层则专注于 config 解析、连接器客户端获取与类型安全,让你在 React/Vue/Solid 等框架中以一致的 API 完成角色治理。

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

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

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

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

立即咨询