使用 Gas 代付中继
使用 @stablechain/enterprise 赞助您用户的 gas。白名单中的代付账户会包装用户的零 gas 交易(内部交易),并将其广播,这样用户就可以在不持有任何 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. 执行每个合作伙伴的策略限制
通过在配置中添加策略限制来限制代付密钥可以赞助的内容。违反限制的内部交易会在广播前被拒绝。
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. 中继预签名交易
对于非托管流程,用户在其自己的环境中签署内部交易,并只将签名的十六进制字符串交给您,因此您永远不会看到他们的密钥。使用 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") {
// 内部交易目标不在配置的允许列表中
}
throw err;
}StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not allowed有关所有拒绝原因的完整信息,请参阅完整的 ErrorCode 表。
后续步骤
- 发送保证交易:在保留的 Enterprise 通道区块空间中发送交易,并结合 Gas 代付。
- Enterprise SDK 参考:所有方法、配置选项和错误类的完整信息。
- Gas 代付:零 gas 交易在协议层如何工作。

