Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

使用 Gas 代付中继

使用 @stablechain/enterprise 赞助您用户的 gas。一个列入白名单的代付账户会封装用户的零 gas 交易(InnerTx)并广播它,这样用户无需持有任何 USDT0 即可进行交易。gasWaiver 模块在一个调用中完成构建、签名和中继,因此您可以为每个操作调用一个方法。

每个方法都返回 H_inner,即用户交易的哈希,而不是承载它的封装器。

先决条件

  • Node.js 20 或更高版本,并安装了 @stablechain/enterprise 和 viem。请参阅 Enterprise SDK 参考。
  • 经过治理注册的代付密钥。Enterprise SDK 在 Stable 主网和 Stable 测试网上运行,访问受限:请联系 Stable 以获取白名单代付密钥。

1. 使用 Gas 代付模块创建客户端

将 gasWaiver: { account } 传递给 createStableEnterprise,其中 account 是您列入白名单的代付密钥。只有在您配置它时,该模块才会在客户端上出现。

import { createStableEnterprise, stable } from "@stablechain/enterprise";
import { privateKeyToAccount } from "viem/accounts";
 
const enterprise = createStableEnterprise({
  chain: stable,
  gasWaiver: { account: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`) },
});
 
const gw = enterprise.gasWaiver;
StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver: undefined }

rpcEndpoints 选项是可选的。如果未设置,客户端将使用链的内置 RPC。

2. 中继单个交易

使用用户的账户和变化的字段调用 send。gasPrice: 0、旧版类型、chainId 和待处理 nonce 会为您处理,因此您只需传递 to,以及可选的 data、value 和 gas。

const user = privateKeyToAccount(process.env.USER_PRIVATE_KEY as `0x${string}`);
 
const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n });
console.log("H_inner:", txHash);
H_inner: 0x8f3a...2d41

用户不需要 USDT0:代付账户会赞助 gas。gas 默认为 150_000n (DEFAULT_INNER_GAS),足以覆盖代币转账或批准。对于更重的调用,请传递显式的 gas。

3. 中继批量交易

调用 sendBatch 以中继来自一个账户的多个交易。Nonce 会根据账户的待处理 nonce 自动排序,并且您会按输入顺序获得每个输入的一个结果。

const results = await gw.sendBatch(user, [
  { to: token, data: dataA, gas: 150_000n },
  { to: token, data: dataB, gas: 150_000n },
]);
 
for (const r of results) {
  console.log(r.success ? `[${r.index}] ✔ ${r.txHash}` : `[${r.index}] ✖ ${r.error?.code}`);
}
[0] ✔ 0x8f3a...2d41
[1] ✔ 0x2b7c...9e04

批量报告失败时,每个项目的错误都在 result.error 中,而不是抛出异常,因此一个糟糕的交易不会导致其余交易失败。

4. 执行每个合作伙伴的策略限制

通过向配置添加策略限制来限制代付密钥可以赞助的内容。违反限制的 InnerTx 会在广播之前被拒绝。

const enterprise = createStableEnterprise({
  chain: stable,
  gasWaiver: {
    account: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`),
    maxGasLimit: 500_000n,
    maxDataLength: 4_096,
    allowedTargets: [
      { address: token, selectors: ["0xa9059cbb"] }, // 仅限 ERC-20 传输
    ],
  },
});

目标在 allowedTargets 之外的交易会失败并显示 TARGET_NOT_ALLOWED;超过 maxGasLimit 的交易会失败并显示 GAS_LIMIT_EXCEEDED。使用 "*" 作为 address 以允许任何合约,并省略 selectors 以允许任何方法。

5. 中继预签名交易

对于非托管流程,用户在其自己的环境中签署 InnerTx 并仅将签名十六进制交给您,这样您就永远看不到他们的密钥。使用 buildWaiverInnerTx 构建它,然后使用 relay 中继它。

import { buildWaiverInnerTx, toSigner } from "@stablechain/enterprise";
 
// 在用户端 - buildWaiverInnerTx 通过 Signer 签名;toSigner 适配 viem 账户
const signed = await buildWaiverInnerTx(toSigner(user), stable.id, { to: token, data, gas: 150_000n, nonce });
 
// 在您的后端
const { txHash } = await gw.relay(signed);
console.log("H_inner:", txHash);
H_inner: 0x8f3a...2d41

对于多个预签名交易,请使用 relayBatch,它会像 sendBatch 一样为每个输入返回一个结果。

处理拒绝

send 和 relay 在拒绝时会抛出 StableEnterpriseRelayError,其中包含一个您可以根据其进行分支的 code。

import { StableEnterpriseRelayError } from "@stablechain/enterprise";
 
try {
  await gw.send(user, { to: token, data });
} catch (err) {
  if (err instanceof StableEnterpriseRelayError && err.code === "TARGET_NOT_ALLOWED") {
    // InnerTx 目标不在配置的允许列表中
  }
  throw err;
}
StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not allowed

请参阅完整的 ErrorCode 表格,了解所有拒绝原因。

接下来去哪里

  • 发送担保交易:将交易放入保留的 Enterprise-lane 区块空间,并将其与 gas 代付结合使用。
  • Enterprise SDK 参考:所有方法、配置选项和错误类的完整说明。
  • Gas 代付:零 gas 交易在协议层面的工作原理。
  • 启用无 gas 交易:使用 Stable 托管的代付服务器,而不是注册您自己的代付。