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

企业版SDK参考

@stablechain/enterprise 的完整概览。这涵盖了客户端从 createStableEnterprise 到其三个特性(免燃气费中继保证区块空间保证中继交易)、低级构建辅助函数以及共享结果和错误类型。有关这些概念的解释,请参阅Stable企业版SDK免燃气费保证区块空间

安装

npm install @stablechain/enterprise viem
added 2 packages, audited 3 packages in 2s

viem >= 2.0.0 是一个对等依赖项。该包以 @stablechain/enterprise 的形式发布,并重新导出 viem/chains 中的 stablestableTestnet,因此您无需单独导入它们。

createStableEnterprise(config)

构造一个 StableEnterpriseClient。每个模块仅在您配置它时才存在,因此在使用前请进行空值检查。

import { createStableEnterprise, stable } from "@stablechain/enterprise";
import { privateKeyToAccount } from "viem/accounts";
 
const enterprise = createStableEnterprise({
  chain: stable,
  gasWaiver: { account: privateKeyToAccount("0xYOUR_WAIVER_KEY") },
});
StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver: undefined }

StableEnterpriseConfig

字段类型默认值描述
chainStableChain目标链。传递 stablestableTestnet(由包重新导出)。必填。
rpcEndpointsstring[]?链的内置RPC一个或多个Stable RPC端点,在失败时按顺序尝试。仅在指向私有端点时才覆盖。
enterpriseRpcEndpointsstring[]?一个或多个企业版RPC网关端点,在失败时按顺序尝试。guaranteedBlockguaranteedWaiver 必填。
batchSizeLimitnumber?100每个批处理RPC调用的最大交易数量。
signerSigner?免燃气费模块(gasWaiverguaranteedWaiver)的默认签名者,当模块没有自己的密钥时。设置一次以通过单个托管后端驱动两者。请参阅签名密钥和托管
gasWaiverGasWaiverConfig?启用免燃气费中继
guaranteedBlockGuaranteedBlockConfig?启用保证区块空间
guaranteedWaiverGuaranteedWaiverConfig?启用保证中继交易

签名密钥和托管

持有免燃气费密钥的模块(gasWaiverguaranteedWaiver)按顺序解析它:模块自己的 signer,然后是其 account(一个进程内 viem 密钥),然后是客户端配置上的顶级 signer,然后是 STABLE_ENTERPRISE_PRIVATE_KEY 环境变量。设置顶级 signer 一次,以通过单个托管后端驱动两个免燃气费模块。guaranteedBlock 使用其自己的已拨款 account 进行签名。

Signer 签署一个 32 字节的摘要,因此密钥永远不会离开托管后端。使用 awsKmsSigner 用于 AWS KMS,toSigner(account) 用于适配 viem 账户,或者 privateKeySigner(key) / envSigner() 用于进程内密钥。传递给模块的 send / sendBatch 的每次调用发送者也可以是 viem 账户或 Signer,因此 KMS/HSM 密钥可以在不降级到 relay 的情况下签署内部交易。

npm install @aws-sdk/client-kms
import { createStableEnterprise, stable } from "@stablechain/enterprise";
import { awsKmsSigner } from "@stablechain/enterprise/aws-kms";
 
// KMS 密钥必须是 ECC_SECG_P256K1 (secp256k1);SDK 从中派生地址
const signer = await awsKmsSigner({ keyId: process.env.AWS_KMS_KEY_ID });
 
const enterprise = createStableEnterprise({
  chain: stable,
  gasWaiver: { signer }, // 托管级别的免燃气费密钥,代替 `account`
});

awsKmsSigner@stablechain/enterprise/aws-kms 子路径中提供,因此 @aws-sdk/client-kms 仍然是一个可选的对等依赖项,不在核心安装中。

StableEnterpriseClient

interface StableEnterpriseClient {
  gasWaiver?: GasWaiverClient;
  guaranteedBlock?: GuaranteedBlockClient;
  guaranteedWaiver?: GuaranteedWaiverClient;
}

免燃气费中继

gasWaiver 模块中继免燃气费交易。列入白名单的免燃气费账户将用户的零燃气费交易 (InnerTx) 封装到 WaiverTx 中并广播。用户无需USDT0。每个方法都返回 H_inner,即 InnerTx 的哈希值,而不是封装哈希值。

在配置中启用 gasWaiver

const enterprise = createStableEnterprise({
  chain: stable,
  gasWaiver: {
    account: privateKeyToAccount("0xYOUR_WAIVER_KEY"),
    // 可选的每个合作伙伴的策略限制
    maxGasLimit: 500_000n,
    allowedTargets: [{ address: "0xToken", selectors: ["0xa9059cbb"] }],
  },
});
 
const gw = enterprise.gasWaiver;

GasWaiverConfig

扩展 ValidationLimitsSignerSource

字段类型描述
signerSigner?列入白名单的、治理注册的免燃气费密钥作为托管签名者(AWS KMS、HSM)。请参阅签名密钥和托管。优先于 account
accountLocalAccount?免燃气费密钥作为进程内viem账户。如果两者都未设置,则回退到 STABLE_ENTERPRISE_PRIVATE_KEY
maxGasLimitbigint?继承自 ValidationLimits
maxDataLengthnumber?继承自 ValidationLimits
allowedTargetsAllowedTarget[]?继承自 ValidationLimits

send(account, tx)

在一个调用中从 account 构建、签名和中继一个 InnerTx。gasPrice: 0、旧版类型、chainId 和待处理 nonce 都为您处理。如果拒绝,则抛出 StableEnterpriseRelayError

const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n });
{ txHash: "0x8f3a...2d41" }

tx 参数是 WaiverInnerTx 加上一个可选的 nonce。返回 RelayResult

sendBatch(account, txs)

从一个 account 构建、签名和中继多个 InnerTx。Nonce 从账户的待处理 nonce 自动排序。每个输入返回一个结果,按顺序。

const results = await gw.sendBatch(user, [
  { to: token, data: dataA, gas: 150_000n },
  { to: token, data: dataB, gas: 150_000n },
]);
[ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: true, txHash: "0x..." } ]

txs 是一个只读的 WaiverInnerTx 数组。返回 BatchResultItem[]

relay(signedInnerTxHex)

中继一个预签名的零燃气费 InnerTx。这用于非托管流程,用户在其自己的环境中签名并只向您提供签名的十六进制,因此免燃气费操作员永远不会看到用户的密钥。使用 buildWaiverInnerTx 构建一个。如果拒绝,则抛出错误。

import { buildWaiverInnerTx, toSigner } from "@stablechain/enterprise";
 
const signed = await buildWaiverInnerTx(toSigner(user), stable.id, { to, data, gas: 150_000n, nonce });
const { txHash } = await gw.relay(signed);
{ txHash: "0x8f3a...2d41" }

relayBatch(signedInnerTxHexes)

中继一批预签名的 InnerTx。按顺序返回每个输入的 BatchResultItem

const results = await gw.relayBatch([signed0, signed1]);
[ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: false, error: { code: "TARGET_NOT_ALLOWED", message: "..." } } ]

保证区块空间

guaranteedBlock 模块通过企业版 RPC 网关中继 GuaranteedTx(类型 0x3F CustomTx),以便它们落在预留的企业版通道区块空间中。与免燃气费不同,签名者支付自己的燃气费并且必须有资金。每笔交易都带有与企业版通道关联的二维 nonce,并且广播仅通过网关进行。

通过 guaranteedBlockenterpriseRpcEndpoints 启用它:

const enterprise = createStableEnterprise({
  chain: stable,
  enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL], // Stable 提供的网关 URL
  guaranteedBlock: {
    account: privateKeyToAccount("0xFUNDED_SIGNER_KEY"),
    laneId: 0n,
  },
});
 
const gb = enterprise.guaranteedBlock;

GuaranteedBlockConfig

字段类型描述
accountLocalAccount签署每笔 GuaranteedTx 并支付其燃气费的已拨款账户。
laneIdbigint企业版通道ID。必须在 [0, ENTERPRISE_MASK - 1] 范围内。无效ID将提前被拒绝。

send(account, tx)

构建、签名和中继一笔 GuaranteedTx。需要 1559 费用字段,因为签名者支付燃气费。chainId、企业版 nonceKey 和二维 nonce(从网关发现)都为您处理。

const gasPrice = await publicClient.getGasPrice();
 
const { txHash } = await gb.send(signer, {
  to: recipient,
  gas: 21_000n,
  gasFeeCap: gasPrice * 2n,
  gasTipCap: gasPrice,
});
{ txHash: "0xabcd...7890" }

tx 参数是 GuaranteedTxRequest 加上一个可选的 nonce。返回 RelayResult

sendBatch(account, txs)

构建、签名并中继多个 GuaranteedTx。Nonce 从发现的基础自动排序。一次失败会影响其后续交易。

const results = await gb.sendBatch(signer, [
  { to: a, gas: 21_000n, gasFeeCap: gasPrice * 2n, gasTipCap: gasPrice },
  { to: b, gas: 21_000n, gasFeeCap: gasPrice * 2n, gasTipCap: gasPrice },
]);
[ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: true, txHash: "0x..." } ]

返回 BatchResultItem[]

relay(signedTx) / relayBatch(signedTxs)

中继预签名的 GuaranteedTx,或批量中继。使用 nonceKeyForLane 作为企业版 nonce 密钥,在其他地方使用 buildGuaranteedTx 构建并签名交易,然后只将签名的十六进制交给操作员。

import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise";
 
const signed = await buildGuaranteedTx(toSigner(signer), stable.id, {
  to,
  gas: 21_000n,
  gasFeeCap,
  gasTipCap,
  nonce, // 账户当前的二维通道 nonce
  nonceKey: nonceKeyForLane(0n),
});
const { txHash } = await gb.relay(signed);
{ txHash: "0xabcd...7890" }

保证中继交易

guaranteedWaiver 模块结合了上述两个功能:通过保证区块空间路由的免燃气费交易。内部和外部交易都是 0x3F CustomTx,共享一个企业版 nonceKey,因此它像 guaranteedBlock 一样通过网关广播。免燃气费发起者承担燃气费,因此用户不需要余额和费用字段,就像 gasWaiver 一样。每个方法都返回 H_inner

通过 guaranteedWaiverenterpriseRpcEndpoints 启用它:

const enterprise = createStableEnterprise({
  chain: stable,
  enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL], // Stable 提供的网关 URL
  guaranteedWaiver: {
    account: privateKeyToAccount("0xYOUR_WAIVER_KEY"),
    laneId: 0n,
  },
});
 
const gw = enterprise.guaranteedWaiver;

GuaranteedWaiverConfig

扩展 ValidationLimitsSignerSource。它与 GasWaiverConfig 完全一样地获取外部包装器的免燃气费密钥(signer,然后是 account,然后是环境变量),并接受相同的 maxGasLimitmaxDataLengthallowedTargets 策略控制。

字段类型描述
signerSigner?列入白名单的免燃气费密钥(签署外部包装器)作为托管签名者。优先于 account。请参阅签名密钥和托管
accountLocalAccount?免燃气费密钥作为进程内viem账户。如果两者都未设置,则回退到 STABLE_ENTERPRISE_PRIVATE_KEY
laneIdbigint企业版通道ID。必须在 [0, ENTERPRISE_MASK - 1] 范围内。

send(user, tx) / sendBatch(user, txs)

user 构建并签名内部 0x3F CustomTx,用免燃气费密钥包装,然后中继。由于燃气费已免除,因此不需要费用字段。内部二维 nonce 从网关发现,并且批处理从该基础自动排序。

// 单个
const { txHash } = await gw.send(user, { to: recipient });
 
// 批处理
const results = await gw.sendBatch(user, [{ to: a }, { to: b }]);
{ txHash: "0x8f3a...2d41" }

tx 参数是 GuaranteedWaiverTxRequest 加上一个可选的 noncesend 返回 RelayResultsendBatch 返回 BatchResultItem[]

relay(signedInnerTx) / relayBatch(signedInnerTxs)

对于非托管流程,用户使用 buildGuaranteedTx 签名内部 0x3F CustomTx(费用为 0n,使用 nonceKeyForLane(laneId)),并只将签名的十六进制交给操作员。操作员用免燃气费密钥包装并中继。

import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise";
 
const signedInner = await buildGuaranteedTx(toSigner(user), stable.id, {
  to,
  gas: 100_000n,
  gasFeeCap: 0n, // 已免除
  gasTipCap: 0n,
  nonce,
  nonceKey: nonceKeyForLane(0n),
});
const { txHash } = await gw.relay(signedInner); // 免燃气费包装 + 广播 → H_inner
{ txHash: "0x8f3a...2d41" }

构建辅助函数

用于非托管 relay 路径的低级签名者。每个都以 Hex 形式返回一个已签名的交易,没有 nonce 获取或费用估算。第一个参数是 Signer:用 toSigner(account) 包装一个 viem 账户,或传递一个托管签名者,例如 awsKmsSigner

buildWaiverInnerTx(signer, chainId, req)

使用预设的免燃气费不变量(gasPrice: 0、旧版类型和给定的 chainId)签署一个免燃气费就绪的 InnerTx。req 是一个 WaiverInnerTx 加上一个必需的 nonce

const signed = await buildWaiverInnerTx(toSigner(user), stable.id, { to, data, gas: 150_000n, nonce });

buildGuaranteedTx(signer, chainId, req)

构建并签署一个 GuaranteedTx (0x3F CustomTx)。req 是一个 GuaranteedTxRequest 加上一个必需的 noncenonceKey

buildGuaranteedWaiverTx(...)

将预签名的内部交易包装到外部 0x3F 免燃气费 CustomTx 中。由 guaranteedWaiver.relay 内部使用;为高级流程导出。

nonceKeyForLane(laneId)

返回用于 buildGuaranteedTx 的通道 ID 的企业版 nonceKey

import { nonceKeyForLane } from "@stablechain/enterprise";
 
const nonceKey = nonceKeyForLane(0n);

类型

SignerSource

免燃气费模块 (gasWaiver, guaranteedWaiver) 接受的签名密钥字段。按顺序解析:signer,然后是 account,然后是客户端的顶级 signer,然后是 STABLE_ENTERPRISE_PRIVATE_KEY 环境变量。请参阅签名密钥和托管

字段类型描述
signerSigner?托管级别的签名者(AWS KMS、HSM 或 privateKeySigner)。优先于 account
accountLocalAccount?一个进程内 viem 账户,通过 toSigner 适配为 Signer

Signer

一个可插拔的签名者,SDK 通过它签署 32 字节的摘要,因此密钥永远不会离开托管后端。可以使用 awsKmsSignertoSignerprivateKeySignerenvSigner 构造一个。

interface Signer {
  readonly address: Address;
  signDigest(hash: Hex): Promise<Hex>;
}
辅助函数导入描述
awsKmsSigner({ keyId, client? })@stablechain/enterprise/aws-kms由 AWS KMS ECC_SECG_P256K1 密钥支持的签名者。返回 Promise<Signer>
toSigner(account)@stablechain/enterprise将 viem LocalAccount 适配为 Signer
privateKeySigner(key)@stablechain/enterprise包装进程中原始私钥的签名者。
envSigner(varName?)@stablechain/enterpriseSTABLE_ENTERPRISE_PRIVATE_KEY(或 varName)读取密钥的签名者。

WaiverInnerTx

每个调用不同的 InnerTx 字段。

字段类型默认值描述
toAddress目标地址:ERC-20 转账的代币合约,原生代币的接收者。
gasbigint?DEFAULT_INNER_GAS (150_000n)燃气限额。因为 gasPrice 为 0,所以慷慨的限额是免费的。
dataHex?"0x"调用数据。
valuebigint?0n要发送的原生代币值。

GuaranteedTxRequest

字段类型默认值描述
toAddress?目标地址。
gasbigint燃气限额。必填。
gasFeeCapbigintmaxFeePerGas。必填。
gasTipCapbigintmaxPriorityFeePerGas。必填。
dataHex?"0x"调用数据。
valuebigint?0n要发送的原生代币值。

GuaranteedWaiverTxRequest

费用字段始终为 0,因此此处省略。

字段类型默认值描述
toAddress目标地址。
gasbigint?共享的内部燃气默认值燃气限额。
dataHex?"0x"调用数据。
valuebigint?0n要发送的原生值。免燃气费允许进行值转移。

ValidationLimits

应用于 gasWaiverguaranteedWaiver 的每个 InnerTx 的合作伙伴策略。

字段类型默认值描述
maxGasLimitbigint?10_000_000nInnerTx 的最大燃气限额。超出此限额将导致 GAS_LIMIT_EXCEEDED 错误。
maxDataLengthnumber?131_072 (128 KB)调用数据的最大字节大小。超出此限额将导致 DATA_TOO_LARGE 错误。
allowedTargetsAllowedTarget[]?免燃气费可能赞助的合约和方法的允许列表。如果设置,则不在列表中的目标将导致 TARGET_NOT_ALLOWED 错误。

AllowedTarget

字段类型描述
addressAddress | "*"InnerTx 可能调用的合约,或 "*" 以匹配任何合约。
selectorsHex[]?允许的 4 字节方法选择器(例如,ERC-20 transfer"0xa9059cbb")。省略或留空以允许 address 上的任何方法。

RelayResult

interface RelayResult {
  txHash: Hash; // 对于免燃气费是 H_inner,对于独立的保证区块是 GuaranteedTx 哈希
}

BatchResultItem

批处理中每个输入的条目,按输入顺序。批处理不会抛出错误,而是报告每个项目的结果。

字段类型描述
indexnumber与输入数组匹配的从零开始的位置。
successboolean此项目是否已中继。
txHashHash?成功时存在:内部交易哈希。
error{ code: ErrorCode; message: string }?失败时存在。

错误

单交易方法 (send, relay) 在拒绝时抛出错误。批处理方法则在 BatchResultItem.error 中报告每项失败。所有错误类都继承自 StableEnterpriseError

抛出条件有用字段
StableEnterpriseError所有 SDK 错误的基类。message
StableEnterpriseRelayError交易在 RPC 或中继层被拒绝。code
WaiverValidationErrorInnerTx 在广播前未通过策略检查(燃气费、数据大小或目标允许列表)。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

抛出的错误或 BatchResultItem.error 上的 code 是以下之一:

代码含义
UNKNOWN_ERROR没有特定代码时的回退。
BROADCAST_FAILED广播在 RPC 层被拒绝,或者网关中继失败。
INVALID_TRANSACTIONInnerTx 解码或解析失败。
INVALID_SIGNATURE签名验证失败。
UNSUPPORTED_TX_TYPEInnerTx 类型不是 legacy、eip2930 或 eip1559。
WRONG_CHAIN_IDInnerTx chainId 缺失或与目标链不匹配。
NON_ZERO_GAS_PRICEInnerTx 带有非零燃气价格(对于免燃气费必须为零)。
GAS_LIMIT_EXCEEDEDInnerTx 燃气限制超过 maxGasLimit
DATA_TOO_LARGEInnerTx 调用数据超过 maxDataLength
TARGET_NOT_ALLOWEDInnerTx 目标不在 allowedTargets 中。
GATEWAY_UNAUTHORIZED企业版 RPC 网关拒绝了 API 密钥(缺失、无效或过期)。
QUOTA_EXCEEDED企业版 RPC 网关燃气配额已用尽。

常量

常量类型描述
DEFAULT_INNER_GASbigintgas 被省略时,InnerTx 的默认燃气限额 (150_000n)。
ENTERPRISE_FLAGbigint在通道的 nonceKey 上设置的企业版位。
ENTERPRISE_MASKbigint通道 ID 的上限:laneId 必须在 [0, ENTERPRISE_MASK - 1] 范围内。

下一步建议