From edcfddffb64934583f188a125abb1a92a780aa0d Mon Sep 17 00:00:00 2001 From: bastienrp Date: Mon, 13 Jul 2026 17:02:43 +0200 Subject: [PATCH 01/20] docs: add Enterprise SDK overview and reference Document @stablechain/enterprise: the gas waiver, guaranteed blockspace, and composed guaranteedWaiver modules, their send/relay methods, build helpers, shared types, and error codes. Note testnet-only availability and the contact-for-access gating. Add both pages to the /en sidebar under Build. Co-Authored-By: Claude Opus 4.8 --- docs/pages/en/explanation/enterprise-sdk.mdx | 67 +++ docs/pages/en/reference/enterprise-sdk.mdx | 473 +++++++++++++++++++ docs/sidebar.json | 14 + 3 files changed, 554 insertions(+) create mode 100644 docs/pages/en/explanation/enterprise-sdk.mdx create mode 100644 docs/pages/en/reference/enterprise-sdk.mdx diff --git a/docs/pages/en/explanation/enterprise-sdk.mdx b/docs/pages/en/explanation/enterprise-sdk.mdx new file mode 100644 index 0000000..c851ff0 --- /dev/null +++ b/docs/pages/en/explanation/enterprise-sdk.mdx @@ -0,0 +1,67 @@ +--- +title: "Stable Enterprise SDK" +description: "Relay gas-waived and guaranteed-blockspace transactions from your backend with the typed @stablechain/enterprise SDK." +diataxis: "explanation" +--- + +# Stable Enterprise SDK + +`@stablechain/enterprise` is a server-side TypeScript client for Stable's enterprise transaction rails. It signs and relays two kinds of privileged transactions: gas-waived transactions, where you sponsor a user's gas, and guaranteed-blockspace transactions, which land in a reserved Enterprise lane. You can enable either rail, or both, on one client. + +```ts +import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; +import { privateKeyToAccount } from "viem/accounts"; + +const enterprise = createStableEnterprise({ + chain: stableTestnet, + gasWaiver: { account: privateKeyToAccount("0xYOUR_WAIVER_KEY") }, +}); + +const { txHash } = await enterprise.gasWaiver!.send(user, { to: token, data }); +``` + +```text +txHash: 0x8f3a...2d41 +``` + +The call returns `H_inner`, the hash of the user's transaction, not the wrapper transaction that carried it. + +## What the SDK does + +The SDK exposes three modules. Each is optional and independently configured, and each carries its own signing account so you can use separate keys. + +- **`gasWaiver`**: build, sign, and relay a gas-waived transaction. A whitelisted waiver account wraps a user's zero-gas transaction so the user transacts without holding any USDT0. See [Gas waiver](/en/explanation/gas-waiver). +- **`guaranteedBlock`**: relay a GuaranteedTx through the Enterprise RPC gateway so it lands in reserved Enterprise-lane blockspace. Unlike gas waiver, the signer pays its own gas. See [Guaranteed blockspace](/en/explanation/guaranteed-blockspace). +- **`guaranteedWaiver`**: the composition of both. A gas-waived transaction routed through guaranteed blockspace, so the user needs no balance and the transaction still lands in the Enterprise lane. + +Every module offers the same four methods: `send` and `sendBatch` for the custodial path where the SDK signs, and `relay` and `relayBatch` for the non-custodial path where the user signs elsewhere and hands you only the signed hex. + +## Access + +The Enterprise SDK is currently available on Stable Testnet only. + +Both rails are gated. Gas waiver requires a governance-registered waiver key, and guaranteed blockspace requires an Enterprise RPC gateway API key. To integrate, [contact Stable](https://discord.gg/stablexyz) to get access. Stable provisions the waiver key and the gateway endpoint you need. + +## Server-side only + +:::warning +The Enterprise SDK is a stateless, server-side library that signs with private keys. Never run it in a browser. Keep the waiver key and the Enterprise RPC gateway URL on your backend. +::: + +The waiver key is a whitelisted, governance-registered account: anyone holding it can sponsor gas under your policy. The Enterprise RPC gateway URL embeds your API key. Treat both as secrets. + +## When to use it + +Reach for the Enterprise SDK when you operate a backend and want to sponsor users' gas or guarantee inclusion for your own traffic. For everyday transfers, bridges, swaps, and vault yield from either a backend or a browser, use the general-purpose [Stable SDK](/en/explanation/sdk-overview) instead. + +## Start here + +- [**Enterprise SDK reference**](/en/reference/enterprise-sdk): Every module, method, config option, and error class. +- [**Gas waiver**](/en/explanation/gas-waiver): How zero-gas transactions work at the protocol level. +- [**Guaranteed blockspace**](/en/explanation/guaranteed-blockspace): How Stable reserves block capacity for enterprise workloads. + +## Next recommended + +- [**Gas waiver protocol**](/en/reference/gas-waiver-api): Transaction formats, marker routing, and governance controls. +- [**Stable SDK**](/en/explanation/sdk-overview): The general-purpose client for transfers, bridging, swaps, and yield. +- [**Connect to Stable**](/en/reference/connect): Chain IDs, RPC endpoints, and explorers for testnet. diff --git a/docs/pages/en/reference/enterprise-sdk.mdx b/docs/pages/en/reference/enterprise-sdk.mdx new file mode 100644 index 0000000..b7063f1 --- /dev/null +++ b/docs/pages/en/reference/enterprise-sdk.mdx @@ -0,0 +1,473 @@ +--- +title: "Enterprise SDK reference" +description: "Complete reference for @stablechain/enterprise: createStableEnterprise, the gas waiver and guaranteed blockspace modules, build helpers, and error classes." +diataxis: "reference" +--- + +# Enterprise SDK reference + +Full surface of `@stablechain/enterprise`. This covers the client from [`createStableEnterprise`](#createstableenterpriseconfig), its three modules ([gas waiver](#gaswaiver-module), [guaranteed blockspace](#guaranteedblock-module), and [the composed waiver](#guaranteedwaiver-module)), the low-level build helpers, and the shared result and error types. For what these rails are, see [Stable Enterprise SDK](/en/explanation/enterprise-sdk), [Gas waiver](/en/explanation/gas-waiver), and [Guaranteed blockspace](/en/explanation/guaranteed-blockspace). + +:::note +The Enterprise SDK is available on Stable Testnet only, and both rails are gated. To integrate, [contact Stable](https://discord.gg/stablexyz) to get a governance-registered waiver key and an Enterprise RPC gateway API key. +::: + +:::warning +This is a server-side library that signs with private keys. Never run it in a browser. Keep the waiver key and the Enterprise RPC gateway URL on your backend. +::: + +## Install + +```bash +npm install @stablechain/enterprise viem +``` + +```text +added 2 packages, audited 3 packages in 2s +``` + +`viem >= 2.0.0` is a peer dependency. The package re-exports `stable` and `stableTestnet` from `viem/chains`, so you don't import them separately. + +## `createStableEnterprise(config)` + +Construct a `StableEnterpriseClient`. Each module is present only when you configure it, so guard with `!` or a null check before use. + +```ts +import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; +import { privateKeyToAccount } from "viem/accounts"; + +const enterprise = createStableEnterprise({ + chain: stableTestnet, + gasWaiver: { account: privateKeyToAccount("0xYOUR_WAIVER_KEY") }, +}); +``` + +```text +StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver: undefined } +``` + +### `StableEnterpriseConfig` + +| **Field** | **Type** | **Default** | **Description** | +| :--- | :--- | :--- | :--- | +| `chain` | `StableChain` | | Target chain. Pass `stable` or `stableTestnet` (re-exported by the package). Required. | +| `rpcEndpoints` | `string[]?` | Chain's built-in RPC | One or more Stable RPC endpoints, tried in order on failure. Override only to point at a private endpoint. | +| `enterpriseRpcEndpoints` | `string[]?` | | One or more Enterprise RPC gateway endpoints, tried in order on failure. Required for `guaranteedBlock` and `guaranteedWaiver`. | +| `batchSizeLimit` | `number?` | `100` | Maximum transactions per batched RPC call. | +| `gasWaiver` | `GasWaiverConfig?` | | Enable the [gas waiver module](#gaswaiver-module). | +| `guaranteedBlock` | `GuaranteedBlockConfig?` | | Enable the [guaranteed blockspace module](#guaranteedblock-module). | +| `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | Enable the [composed waiver module](#guaranteedwaiver-module). | + +### `StableEnterpriseClient` + +```ts +interface StableEnterpriseClient { + gasWaiver?: GasWaiverClient; + guaranteedBlock?: GuaranteedBlockClient; + guaranteedWaiver?: GuaranteedWaiverClient; +} +``` + +## `gasWaiver` module + +Relay gas-waived transactions. A whitelisted waiver account wraps a user's zero-gas transaction (the InnerTx) into a WaiverTx and broadcasts it. The user needs no USDT0. Every method returns `H_inner`, the InnerTx hash, not the wrapper hash. + +Enable it with `gasWaiver` in the config: + +```ts +const enterprise = createStableEnterprise({ + chain: stableTestnet, + gasWaiver: { + account: privateKeyToAccount("0xYOUR_WAIVER_KEY"), + // optional per-partner policy limits + maxGasLimit: 500_000n, + allowedTargets: [{ address: "0xToken", selectors: ["0xa9059cbb"] }], + }, +}); + +const gw = enterprise.gasWaiver!; +``` + +### `GasWaiverConfig` + +Extends [`ValidationLimits`](#validationlimits). + +| **Field** | **Type** | **Description** | +| :--- | :--- | :--- | +| `account` | `LocalAccount` | The whitelisted, governance-registered account that signs each WaiverTx. | +| `maxGasLimit` | `bigint?` | Inherited from `ValidationLimits`. | +| `maxDataLength` | `number?` | Inherited from `ValidationLimits`. | +| `allowedTargets` | `AllowedTarget[]?` | Inherited from `ValidationLimits`. | + +### `send(account, tx)` + +Build, sign, and relay one InnerTx from `account` in one call. The `gasPrice: 0`, legacy type, `chainId`, and pending nonce are handled for you. Throws `StableEnterpriseRelayError` on rejection. + +```ts +const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); +``` + +```text +{ txHash: "0x8f3a...2d41" } +``` + +The `tx` argument is a [`WaiverInnerTx`](#waiverinnertx) plus an optional `nonce`. Returns [`RelayResult`](#relayresult). + +### `sendBatch(account, txs)` + +Build, sign, and relay several InnerTxs from one `account`. Nonces are auto-sequenced from the account's pending nonce. Returns one result per input, in order. + +```ts +const results = await gw.sendBatch(user, [ + { to: token, data: dataA, gas: 150_000n }, + { to: token, data: dataB, gas: 150_000n }, +]); +``` + +```text +[ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: true, txHash: "0x..." } ] +``` + +`txs` is a readonly array of [`WaiverInnerTx`](#waiverinnertx). Returns [`BatchResultItem[]`](#batchresultitem). + +### `relay(signedInnerTxHex)` + +Relay a pre-signed zero-gas InnerTx. Use this for the non-custodial flow where the user signs in their own environment and hands you only the signed hex, so the waiver operator never sees the user's key. Build one with [`buildWaiverInnerTx`](#buildwaiverinnertxaccount-chainid-req). Throws on rejection. + +```ts +import { buildWaiverInnerTx } from "@stablechain/enterprise"; + +const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to, data, gas: 150_000n, nonce }); +const { txHash } = await gw.relay(signed); +``` + +```text +{ txHash: "0x8f3a...2d41" } +``` + +### `relayBatch(signedInnerTxHexes)` + +Relay a batch of pre-signed InnerTxs. Returns one [`BatchResultItem`](#batchresultitem) per input, in order. + +```ts +const results = await gw.relayBatch([signed0, signed1]); +``` + +```text +[ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: false, error: { code: "TARGET_NOT_ALLOWED", message: "..." } } ] +``` + +## `guaranteedBlock` module + +Relay GuaranteedTx (type `0x3F` CustomTx) through the Enterprise RPC gateway so they land in reserved Enterprise-lane blockspace. Unlike gas waiver, the signer pays its own gas and must be funded. Each transaction carries a 2D nonce keyed to an Enterprise lane, and broadcasting goes only through the gateway. + +Enable it with `guaranteedBlock` plus `enterpriseRpcEndpoints`: + +```ts +const enterprise = createStableEnterprise({ + chain: stableTestnet, + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // the gateway URL Stable provisions + guaranteedBlock: { + account: privateKeyToAccount("0xFUNDED_SIGNER_KEY"), + laneId: 0n, + }, +}); + +const gb = enterprise.guaranteedBlock!; +``` + +### `GuaranteedBlockConfig` + +| **Field** | **Type** | **Description** | +| :--- | :--- | :--- | +| `account` | `LocalAccount` | Funded account that signs each GuaranteedTx and pays its gas. | +| `laneId` | `bigint` | Enterprise lane id. Must be in `[0, ENTERPRISE_MASK - 1]`. An invalid id is rejected up front. | + +### `send(account, tx)` + +Build, sign, and relay one GuaranteedTx. The 1559 fee fields are required because the signer pays gas. The `chainId`, the Enterprise `nonceKey`, and the 2D nonce (discovered from the gateway) are handled for you. + +```ts +const gasPrice = await publicClient.getGasPrice(); + +const { txHash } = await gb.send(signer, { + to: recipient, + gas: 21_000n, + gasFeeCap: gasPrice * 2n, + gasTipCap: gasPrice, +}); +``` + +```text +{ txHash: "0xabcd...7890" } +``` + +The `tx` argument is a [`GuaranteedTxRequest`](#guaranteedtxrequest) plus an optional `nonce`. Returns [`RelayResult`](#relayresult). + +### `sendBatch(account, txs)` + +Build, sign, and relay several GuaranteedTxs. Nonces are auto-sequenced from the discovered base. A failure strands its successors. + +```ts +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 }, +]); +``` + +```text +[ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: true, txHash: "0x..." } ] +``` + +Returns [`BatchResultItem[]`](#batchresultitem). + +### `relay(signedTx)` / `relayBatch(signedTxs)` + +Relay a pre-signed GuaranteedTx, or a batch of them. Build and sign the transaction elsewhere with [`buildGuaranteedTx`](#buildguaranteedtxaccount-chainid-req), using [`nonceKeyForLane`](#noncekeyforlanelaneid) for the Enterprise nonce key, then hand the operator only the signed hex. + +```ts +import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; + +const signed = await buildGuaranteedTx(signer, stableTestnet.id, { + to, + gas: 21_000n, + gasFeeCap, + gasTipCap, + nonce, // the account's current 2D-lane nonce + nonceKey: nonceKeyForLane(0n), +}); +const { txHash } = await gb.relay(signed); +``` + +```text +{ txHash: "0xabcd...7890" } +``` + +## `guaranteedWaiver` module + +The composition of the two rails above: a gas-waived transaction routed through guaranteed blockspace. Both the inner and outer transaction are `0x3F` CustomTxs sharing one Enterprise `nonceKey`, so it broadcasts through the gateway like `guaranteedBlock`. The waiver sponsors gas, so the user needs no balance and no fee fields, like `gasWaiver`. Every method returns `H_inner`. + +Enable it with `guaranteedWaiver` plus `enterpriseRpcEndpoints`: + +```ts +const enterprise = createStableEnterprise({ + chain: stableTestnet, + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // the gateway URL Stable provisions + guaranteedWaiver: { + waiverAccount: privateKeyToAccount("0xYOUR_WAIVER_KEY"), + laneId: 0n, + }, +}); + +const gw = enterprise.guaranteedWaiver!; +``` + +### `GuaranteedWaiverConfig` + +Extends [`ValidationLimits`](#validationlimits), so it accepts the same `maxGasLimit`, `maxDataLength`, and `allowedTargets` policy controls as `GasWaiverConfig`. + +| **Field** | **Type** | **Description** | +| :--- | :--- | :--- | +| `waiverAccount` | `LocalAccount` | The whitelisted, governance-registered account that signs the outer wrapper. | +| `laneId` | `bigint` | Enterprise lane id. Must be in `[0, ENTERPRISE_MASK - 1]`. | + +### `send(user, tx)` / `sendBatch(user, txs)` + +Build and sign the inner `0x3F` CustomTx from `user`, wrap it with the waiver key, and relay. No fee fields are needed, since gas is waived. The inner 2D nonce is discovered from the gateway, and batches auto-sequence from that base. + +```ts +// single +const { txHash } = await gw.send(user, { to: recipient }); + +// batch +const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); +``` + +```text +{ txHash: "0x8f3a...2d41" } +``` + +The `tx` argument is a [`GuaranteedWaiverTxRequest`](#guaranteedwaivertxrequest) plus an optional `nonce`. `send` returns [`RelayResult`](#relayresult); `sendBatch` returns [`BatchResultItem[]`](#batchresultitem). + +### `relay(signedInnerTx)` / `relayBatch(signedInnerTxs)` + +For the non-custodial flow, the user signs the inner `0x3F` CustomTx with [`buildGuaranteedTx`](#buildguaranteedtxaccount-chainid-req) (fees `0n`, using `nonceKeyForLane(laneId)`) and hands the operator only the signed hex. The operator wraps it with the waiver key and relays. + +```ts +import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; + +const signedInner = await buildGuaranteedTx(user, stableTestnet.id, { + to, + gas: 100_000n, + gasFeeCap: 0n, // waived + gasTipCap: 0n, + nonce, + nonceKey: nonceKeyForLane(0n), +}); +const { txHash } = await gw.relay(signedInner); // waiver wraps + broadcasts → H_inner +``` + +```text +{ txHash: "0x8f3a...2d41" } +``` + +## Build helpers + +Low-level signers for the non-custodial `relay` paths. Each returns a signed transaction as `Hex`, with no nonce fetch or fee estimation. + +### `buildWaiverInnerTx(account, chainId, req)` + +Sign a waiver-ready InnerTx with the waiver invariants baked in: `gasPrice: 0`, legacy type, and the given `chainId`. `req` is a [`WaiverInnerTx`](#waiverinnertx) plus a required `nonce`. + +```ts +const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to, data, gas: 150_000n, nonce }); +``` + +### `buildGuaranteedTx(account, chainId, req)` + +Build and sign a GuaranteedTx (`0x3F` CustomTx). `req` is a [`GuaranteedTxRequest`](#guaranteedtxrequest) plus a required `nonce` and `nonceKey`. + +### `buildGuaranteedWaiverTx(...)` + +Wrap a pre-signed inner into the outer `0x3F` waiver CustomTx. Used internally by `guaranteedWaiver.relay`; exported for advanced flows. + +### `nonceKeyForLane(laneId)` + +Return the Enterprise `nonceKey` for a lane id, for use with `buildGuaranteedTx`. + +```ts +import { nonceKeyForLane } from "@stablechain/enterprise"; + +const nonceKey = nonceKeyForLane(0n); +``` + +## Types + +### `WaiverInnerTx` + +The fields of an InnerTx that vary per call. + +| **Field** | **Type** | **Default** | **Description** | +| :--- | :--- | :--- | :--- | +| `to` | `Address` | | Target address: token contract for an ERC-20 transfer, recipient for native. | +| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | Gas limit. Because `gasPrice` is 0, a generous limit is free. | +| `data` | `Hex?` | `"0x"` | Calldata. | +| `value` | `bigint?` | `0n` | Native value to send. | + +### `GuaranteedTxRequest` + +| **Field** | **Type** | **Default** | **Description** | +| :--- | :--- | :--- | :--- | +| `to` | `Address?` | | Target address. | +| `gas` | `bigint` | | Gas limit. Required. | +| `gasFeeCap` | `bigint` | | `maxFeePerGas`. Required. | +| `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`. Required. | +| `data` | `Hex?` | `"0x"` | Calldata. | +| `value` | `bigint?` | `0n` | Native value to send. | + +### `GuaranteedWaiverTxRequest` + +The fee fields are always 0, so they're omitted here. + +| **Field** | **Type** | **Default** | **Description** | +| :--- | :--- | :--- | :--- | +| `to` | `Address` | | Target address. | +| `gas` | `bigint?` | shared inner-gas default | Gas limit. | +| `data` | `Hex?` | `"0x"` | Calldata. | +| `value` | `bigint?` | `0n` | Native value to send. Value transfer is allowed for waivers. | + +### `ValidationLimits` + +Per-partner policy applied to each InnerTx by `gasWaiver` and `guaranteedWaiver`. + +| **Field** | **Type** | **Default** | **Description** | +| :--- | :--- | :--- | :--- | +| `maxGasLimit` | `bigint?` | `10_000_000n` | Maximum gas limit for an InnerTx. Exceeding it fails with `GAS_LIMIT_EXCEEDED`. | +| `maxDataLength` | `number?` | `131_072` (128 KB) | Maximum calldata size in bytes. Exceeding it fails with `DATA_TOO_LARGE`. | +| `allowedTargets` | `AllowedTarget[]?` | | Allowlist of contracts and methods the waiver may sponsor. When set, a target outside the list fails with `TARGET_NOT_ALLOWED`. | + +### `AllowedTarget` + +| **Field** | **Type** | **Description** | +| :--- | :--- | :--- | +| `address` | `Address \| "*"` | Contract the InnerTx may call, or `"*"` to match any contract. | +| `selectors` | `Hex[]?` | Permitted 4-byte method selectors (e.g. `"0xa9059cbb"` for ERC-20 `transfer`). Omit or leave empty to allow any method on `address`. | + +### `RelayResult` + +```ts +interface RelayResult { + txHash: Hash; // H_inner for waivers, the GuaranteedTx hash for standalone guaranteed block +} +``` + +### `BatchResultItem` + +One entry per input in a batch, in input order. Instead of throwing, a batch surfaces per-item outcomes. + +| **Field** | **Type** | **Description** | +| :--- | :--- | :--- | +| `index` | `number` | Zero-based position matching the input array. | +| `success` | `boolean` | Whether this item was relayed. | +| `txHash` | `Hash?` | Present on success: the inner-tx hash. | +| `error` | `{ code: ErrorCode; message: string }?` | Present on failure. | + +## Errors + +Single-transaction methods (`send`, `relay`) throw on rejection. Batch methods report failures per item in [`BatchResultItem.error`](#batchresultitem) instead. All error classes extend `StableEnterpriseError`. + +| **Class** | **Thrown when** | **Useful fields** | +| :--- | :--- | :--- | +| `StableEnterpriseError` | Base class for every SDK error. | `message` | +| `StableEnterpriseRelayError` | A transaction is rejected at the RPC or relay layer. | `code` | +| `WaiverValidationError` | An InnerTx fails a policy check before broadcast (gas, data size, or target allowlist). | `code` | + +```ts +import { StableEnterpriseRelayError } from "@stablechain/enterprise"; + +try { + await gw.send(user, { to: token, data }); +} catch (err) { + if (err instanceof StableEnterpriseRelayError && err.code === "TARGET_NOT_ALLOWED") { + // the InnerTx target is outside the configured allowlist + } + throw err; +} +``` + +```text +StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not allowed +``` + +### `ErrorCode` + +The `code` on a thrown error or a `BatchResultItem.error` is one of: + +| **Code** | **Meaning** | +| :--- | :--- | +| `UNKNOWN_ERROR` | Fallback when no specific code is available. | +| `BROADCAST_FAILED` | Broadcast rejected at the RPC layer, or the gateway failed to relay. | +| `INVALID_TRANSACTION` | The InnerTx failed to decode or parse. | +| `INVALID_SIGNATURE` | Signature verification failed. | +| `UNSUPPORTED_TX_TYPE` | The InnerTx type is not legacy, eip2930, or eip1559. | +| `WRONG_CHAIN_ID` | The InnerTx `chainId` is missing or doesn't match the target chain. | +| `NON_ZERO_GAS_PRICE` | The InnerTx carries a non-zero gas price (must be zero for a waiver). | +| `GAS_LIMIT_EXCEEDED` | The InnerTx gas limit exceeds `maxGasLimit`. | +| `DATA_TOO_LARGE` | The InnerTx calldata exceeds `maxDataLength`. | +| `TARGET_NOT_ALLOWED` | The InnerTx target is not in `allowedTargets`. | +| `GATEWAY_UNAUTHORIZED` | The Enterprise RPC gateway rejected the API key (missing, invalid, or expired). | +| `QUOTA_EXCEEDED` | The Enterprise RPC gateway gas quota is exhausted. | + +## Constants + +| **Constant** | **Type** | **Description** | +| :--- | :--- | :--- | +| `DEFAULT_INNER_GAS` | `bigint` | Default InnerTx gas limit (`150_000n`) when `gas` is omitted. | +| `ENTERPRISE_FLAG` | `bigint` | Enterprise bit set on a lane's `nonceKey`. | +| `ENTERPRISE_MASK` | `bigint` | Upper bound for a lane id: `laneId` must be in `[0, ENTERPRISE_MASK - 1]`. | + +## Next recommended + +- [**Stable Enterprise SDK**](/en/explanation/enterprise-sdk): What the rails are and when to use them. +- [**Gas waiver protocol**](/en/reference/gas-waiver-api): Transaction formats, marker routing, and governance controls. +- [**Guaranteed blockspace**](/en/explanation/guaranteed-blockspace): How Stable reserves block capacity for enterprise workloads. diff --git a/docs/sidebar.json b/docs/sidebar.json index 7e8c00b..37afa51 100644 --- a/docs/sidebar.json +++ b/docs/sidebar.json @@ -208,6 +208,20 @@ } ] }, + { + "text": "Enterprise SDK", + "collapsed": true, + "items": [ + { + "text": "Overview", + "link": "/en/explanation/enterprise-sdk" + }, + { + "text": "Reference", + "link": "/en/reference/enterprise-sdk" + } + ] + }, { "text": "Onboard users", "collapsed": true, From 06c418d349f34aed8baa4381c31364093c4e358c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 13 Jul 2026 15:04:54 +0000 Subject: [PATCH 02/20] i18n: auto-translate cn/ko for changed en content --- docs/pages/cn/explanation/enterprise-sdk.mdx | 69 +++ docs/pages/cn/reference/enterprise-sdk.mdx | 475 +++++++++++++++++++ docs/pages/ko/explanation/enterprise-sdk.mdx | 69 +++ docs/pages/ko/reference/enterprise-sdk.mdx | 475 +++++++++++++++++++ docs/sidebar.json | 152 +++--- 5 files changed, 1178 insertions(+), 62 deletions(-) create mode 100644 docs/pages/cn/explanation/enterprise-sdk.mdx create mode 100644 docs/pages/cn/reference/enterprise-sdk.mdx create mode 100644 docs/pages/ko/explanation/enterprise-sdk.mdx create mode 100644 docs/pages/ko/reference/enterprise-sdk.mdx diff --git a/docs/pages/cn/explanation/enterprise-sdk.mdx b/docs/pages/cn/explanation/enterprise-sdk.mdx new file mode 100644 index 0000000..c4feb86 --- /dev/null +++ b/docs/pages/cn/explanation/enterprise-sdk.mdx @@ -0,0 +1,69 @@ +--- +source_path: explanation/enterprise-sdk.mdx +source_sha: c851ff041a812cf877db582b540a0369d4777566 +title: "Stable 企业版 SDK" +description: "通过类型化的 @stablechain/enterprise SDK,从您的后端中继免 gas 费和保证区块空间的交易。" +diataxis: "explanation" +--- + +# Stable 企业版 SDK + +`@stablechain/enterprise` 是 Stable 企业交易轨道的服务器端 TypeScript 客户端。它签署并中继两种特权交易:免 gas 费交易(您为用户的 gas 费提供担保)和保证区块空间交易(它们进入预留的企业通道)。您可以在一个客户端上启用任一轨道,或两者都启用。 + +```ts +import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; +import { privateKeyToAccount } from "viem/accounts"; + +const enterprise = createStableEnterprise({ + chain: stableTestnet, + gasWaiver: { account: privateKeyToAccount("0xYOUR_WAIVER_KEY") }, +}); + +const { txHash } = await enterprise.gasWaiver!.send(user, { to: token, data }); +``` + +```text +txHash: 0x8f3a...2d41 +``` + +此调用返回 `H_inner`,即用户交易的哈希值,而不是承载它的包装交易的哈希值。 + +## SDK 的功能 + +SDK 暴露了三个模块。每个模块都是可选的,可以独立配置,并且每个模块都带有自己的签名账户,因此您可以使用不同的密钥。 + +- **`gasWaiver`**:构建、签署并中继免 gas 费交易。一个白名单豁免账户包装了用户的零 gas 交易,因此用户在没有持有任何 USDT0 的情况下进行交易。请参阅[Gas 豁免](/cn/explanation/gas-waiver)。 +- **`guaranteedBlock`**:通过企业 RPC 网关中继 GuaranteedTx,使其进入预留的企业通道区块空间。与 gas 豁免不同,签名者支付自己的 gas 费。请参阅[保证区块空间](/cn/explanation/guaranteed-blockspace)。 +- **`guaranteedWaiver`**:两者的组合。通过保证区块空间路由的免 gas 费交易,因此用户无需余额,且交易仍进入企业通道。 + +每个模块都提供相同的四种方法:`send` 和 `sendBatch` 用于 SDK 签名的托管路径,`relay` 和 `relayBatch` 用于用户在其他地方签名并只向您提供已签名十六进制的非托管路径。 + +## 访问权限 + +企业版 SDK 目前仅在 Stable 测试网上可用。 + +这两个轨道都受限。Gas 豁免需要一个治理注册的豁免密钥,而保证区块空间需要一个企业 RPC 网关 API 密钥。要进行集成,请[联系 Stable](https://discord.gg/stablexyz) 以获取访问权限。Stable 会提供您所需的豁免密钥和网关端点。 + +## 仅限服务器端 + +:::warning +企业版 SDK 是一个无状态的服务器端库,它使用私钥进行签名。切勿在浏览器中运行它。将豁免密钥和企业 RPC 网关 URL 保存在您的后端。 +::: + +豁免密钥是一个白名单,治理注册的账户:任何持有它的人都可以根据您的策略赞助 gas 费。企业 RPC 网关 URL 嵌入了您的 API 密钥。请将两者都视为秘密。 + +## 何时使用它 + +当您运营后端并希望为用户赞助 gas 费或保证您的流量被包含时,请使用企业版 SDK。对于日常转账、桥接、交换和来自后端或浏览器的金库收益,请改用通用[Stable SDK](/cn/explanation/sdk-overview)。 + +## 从这里开始 + +- [**企业版 SDK 参考**](/cn/reference/enterprise-sdk):每个模块、方法、配置选项和错误类。 +- [**Gas 豁免**](/cn/explanation/gas-waiver):零 gas 费交易如何在协议层面工作。 +- [**保证区块空间**](/cn/explanation/guaranteed-blockspace):Stable 如何为企业工作负载预留区块容量。 + +## 下一步建议 + +- [**Gas 豁免协议**](/cn/reference/gas-waiver-api):交易格式、标记路由和治理控制。 +- [**Stable SDK**](/cn/explanation/sdk-overview):用于转账、桥接、交换和收益的通用客户端。 +- [**连接到 Stable**](/cn/reference/connect):测试网的链 ID、RPC 端点和浏览器。 diff --git a/docs/pages/cn/reference/enterprise-sdk.mdx b/docs/pages/cn/reference/enterprise-sdk.mdx new file mode 100644 index 0000000..2a80010 --- /dev/null +++ b/docs/pages/cn/reference/enterprise-sdk.mdx @@ -0,0 +1,475 @@ +--- +source_path: reference/enterprise-sdk.mdx +source_sha: b7063f13645d37e2d66b8bb8c87b0dcfaf386a61 +title: "企业级SDK参考" +description: "@stablechain/enterprise 的完整参考:createStableEnterprise、免燃气费和保证区块空间模块、构建助手以及错误类。" +diataxis: "reference" +--- + +# 企业级SDK参考 + +`@stablechain/enterprise` 的完整功能。它涵盖了从 [`createStableEnterprise`](#createstableenterpriseconfig) 客户端开始,它的三个模块([免燃气费](#gaswaiver-module)、[保证区块空间](#guaranteedblock-module)和[组合免燃气费](#guaranteedwaiver-module)),低级构建助手,以及共享的结果和错误类型。有关这些机制的详细信息,请参阅[稳定企业版SDK](/cn/explanation/enterprise-sdk)、[免燃气费](/cn/explanation/gas-waiver)和[保证区块空间](/cn/explanation/guaranteed-blockspace)。 + +:::note +企业版SDK仅在Stable测试网上可用,并且两个机制都受到限制。要进行集成,请[联系Stable](https://discord.gg/stablexyz)以获取经治理注册的免燃气费密钥和企业版RPC网关API密钥。 +::: + +:::warning +这是一个使用私钥进行签名的服务器端库。切勿在浏览器中运行它。请将免燃气费密钥和企业版RPC网关URL保存在您的后端。 +::: + +## 安装 + +```bash +npm install @stablechain/enterprise viem +``` + +```text +added 2 packages, audited 3 packages in 2s +``` + +`viem >= 2.0.0` 是一个对等依赖项。该包重新导出 `stable` 和 `stableTestnet` 自 `viem/chains`,因此您无需单独导入它们。 + +## `createStableEnterprise(config)` + +构造一个 `StableEnterpriseClient`。每个模块仅在您配置它时才会存在,因此在使用前请通过 `!` 或空检查进行保护。 + +```ts +import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; +import { privateKeyToAccount } from "viem/accounts"; + +const enterprise = createStableEnterprise({ + chain: stableTestnet, + gasWaiver: { account: privateKeyToAccount("0xYOUR_WAIVER_KEY") }, +}); +``` + +```text +StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver: undefined } +``` + +### `StableEnterpriseConfig` + +| **字段** | **类型** | **默认值** | **描述** | +| :--- | :--- | :--- | :--- | +| `chain` | `StableChain` | | 目标链。传入 `stable` 或 `stableTestnet`(由包重新导出)。必填。 | +| `rpcEndpoints` | `string[]?` | 链的内置RPC | 一个或多个Stable RPC端点,失败时按顺序尝试。仅在指向私有端点时才覆盖。 | +| `enterpriseRpcEndpoints` | `string[]?` | | 一个或多个企业RPC网关端点,失败时按顺序尝试。`guaranteedBlock` 和 `guaranteedWaiver` 所需。 | +| `batchSizeLimit` | `number?` | `100` | 每个批处理RPC调用的最大交易数量。 | +| `gasWaiver` | `GasWaiverConfig?` | | 启用[免燃气费模块](#gaswaiver-module)。 | +| `guaranteedBlock` | `GuaranteedBlockConfig?` | | 启用[保证区块空间模块](#guaranteedblock-module)。 | +| `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | 启用[组合免燃气费模块](#guaranteedwaiver-module)。 | + +### `StableEnterpriseClient` + +```ts +interface StableEnterpriseClient { + gasWaiver?: GasWaiverClient; + guaranteedBlock?: GuaranteedBlockClient; + guaranteedWaiver?: GuaranteedWaiverClient; +} +``` + +## `gasWaiver` 模块 + +中继免燃气费交易。列入白名单的免燃气费账户将用户的零燃气交易(内部交易)包装成免燃气费交易并进行广播。用户不需要USDT0。每个方法都返回 `H_inner`,即内部交易哈希,而不是包装器哈希。 + +在配置中通过 `gasWaiver` 启用它: + +```ts +const enterprise = createStableEnterprise({ + chain: stableTestnet, + gasWaiver: { + account: privateKeyToAccount("0xYOUR_WAIVER_KEY"), + // 可选的每个合作伙伴策略限制 + maxGasLimit: 500_000n, + allowedTargets: [{ address: "0xToken", selectors: ["0xa9059cbb"] }], + }, +}); + +const gw = enterprise.gasWaiver!; +``` + +### `GasWaiverConfig` + +扩展 [`ValidationLimits`](#validationlimits)。 + +| **字段** | **类型** | **描述** | +| :--- | :--- | :--- | +| `account` | `LocalAccount` | 签署每个免燃气费交易的白名单、经治理注册的账户。 | +| `maxGasLimit` | `bigint?` | 继承自 `ValidationLimits`。 | +| `maxDataLength` | `number?` | 继承自 `ValidationLimits`。 | +| `allowedTargets` | `AllowedTarget[]?` | 继承自 `ValidationLimits`。 | + +### `send(account, tx)` + +从 `account` 构建、签名并中继一个内部交易,一次调用完成。`gasPrice: 0`、遗留类型、`chainId` 和待处理 Nonce 都为您处理。拒绝时抛出 `StableEnterpriseRelayError`。 + +```ts +const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); +``` + +```text +{ txHash: "0x8f3a...2d41" } +``` + +`tx` 参数是一个 [`WaiverInnerTx`](#waiverinnertx) 加上一个可选的 `nonce`。返回 [`RelayResult`](#relayresult)。 + +### `sendBatch(account, txs)` + +从一个`account`构建、签名并中继多个内部交易。Nonce会根据账户的待处理Nonce自动排序。按顺序为每个输入返回一个结果。 + +```ts +const results = await gw.sendBatch(user, [ + { to: token, data: dataA, gas: 150_000n }, + { to: token, data: dataB, gas: 150_000n }, +]); +``` + +```text +[ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: true, txHash: "0x..." } ] +``` + +`txs` 是一个只读的 [`WaiverInnerTx`](#waiverinnertx) 数组。返回 [`BatchResultItem[]`](#batchresultitem)。 + +### `relay(signedInnerTxHex)` + +中继一个已预签名的零燃气费内部交易。当用户在自己的环境中签名并只向您提供已签名十六进制数据时,可用于非托管流程,这样免燃气费操作员就永远无法看到用户的私钥。使用 [`buildWaiverInnerTx`](#buildwaiverinnertxaccount-chainid-req) 构建一个。拒绝时抛出错误。 + +```ts +import { buildWaiverInnerTx } from "@stablechain/enterprise"; + +const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to, data, gas: 150_000n, nonce }); +const { txHash } = await gw.relay(signed); +``` + +```text +{ txHash: "0x8f3a...2d41" } +``` + +### `relayBatch(signedInnerTxHexes)` + +中继一批预签名的内部交易。每个输入都会返回一个 [`BatchResultItem`](#batchresultitem),按顺序排列。 + +```ts +const results = await gw.relayBatch([signed0, signed1]); +``` + +```text +[ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: false, error: { code: "TARGET_NOT_ALLOWED", message: "..." } } ] +``` + +## `guaranteedBlock` 模块 + +通过企业级RPC网关中继GuaranteedTx(类型`0x3F` CustomTx),使其进入预留的企业级车道区块空间。与燃气费豁免不同,签名者需要支付自己的燃气费,并且必须有资金。每笔交易都带有与企业级车道关联的2D nonce,并且广播仅通过网关进行。 + +通过 `guaranteedBlock` 和 `enterpriseRpcEndpoints` 启用它: + +```ts +const enterprise = createStableEnterprise({ + chain: stableTestnet, + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable提供的网关URL + guaranteedBlock: { + account: privateKeyToAccount("0xFUNDED_SIGNER_KEY"), + laneId: 0n, + }, +}); + +const gb = enterprise.guaranteedBlock!; +``` + +### `GuaranteedBlockConfig` + +| **字段** | **类型** | **描述** | +| :--- | :--- | :--- | +| `account` | `LocalAccount` | 签署每个 GuaranteedTx 并支付其燃气费的已资助账户。 | +| `laneId` | `bigint` | 企业通道ID。必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。无效的ID会提前被拒绝。 | + +### `send(account, tx)` + +构建、签名并中继一个 GuaranteedTx。签名者需要支付燃气费,因此需要1559费率字段。`chainId`、企业 `nonceKey` 和 2D nonce(从网关发现)都为您处理。 + +```ts +const gasPrice = await publicClient.getGasPrice(); + +const { txHash } = await gb.send(signer, { + to: recipient, + gas: 21_000n, + gasFeeCap: gasPrice * 2n, + gasTipCap: gasPrice, +}); +``` + +```text +{ txHash: "0xabcd...7890" } +``` + +`tx` 参数是一个 [`GuaranteedTxRequest`](#guaranteedtxrequest) 加上一个可选的 `nonce`。返回 [`RelayResult`](#relayresult)。 + +### `sendBatch(account, txs)` + +构建、签名并中继多个 GuaranteedTx。Noncce 会从发现的基本 Nonce 自动排序。失败会影响其后续的交易。 + +```ts +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 }, +]); +``` + +```text +[ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: true, txHash: "0x..." } ] +``` + +返回 [`BatchResultItem[]`](#batchresultitem)。 + +### `relay(signedTx)` / `relayBatch(signedTxs)` + +中继一个已预签名的 GuaranteedTx,或批量中继。使用 [`nonceKeyForLane`](#noncekeyforlanelaneid) 作为企业 Nonce 密钥,使用 [`buildGuaranteedTx`](#buildguaranteedtxaccount-chainid-req) 在其他地方构建并签名交易,然后只将已签名的十六进制数据交给操作员。 + +```ts +import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; + +const signed = await buildGuaranteedTx(signer, stableTestnet.id, { + to, + gas: 21_000n, + gasFeeCap, + gasTipCap, + nonce, // the account's current 2D-lane nonce + nonceKey: nonceKeyForLane(0n), +}); +const { txHash } = await gb.relay(signed); +``` + +```text +{ txHash: "0xabcd...7890" } +``` + +## `guaranteedWaiver` 模块 + +以上两种机制的组合:通过保证区块空间路由的免燃气费交易。内部和外部交易都是 `0x3F` CustomTx,共享一个企业 `nonceKey`,因此它像 `guaranteedBlock` 一样通过网关广播。免燃气费模块赞助燃气费,所以用户不需要余额,也不需要燃气费字段,就像 `gasWaiver` 一样。每个方法都返回 `H_inner`。 + +通过 `guaranteedWaiver` 和 `enterpriseRpcEndpoints` 启用它: + +```ts +const enterprise = createStableEnterprise({ + chain: stableTestnet, + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable提供的网关URL + guaranteedWaiver: { + waiverAccount: privateKeyToAccount("0xYOUR_WAIVER_KEY"), + laneId: 0n, + }, +}); + +const gw = enterprise.guaranteedWaiver!; +``` + +### `GuaranteedWaiverConfig` + +扩展 [`ValidationLimits`](#validationlimits),因此它接受与 `GasWaiverConfig` 相同的 `maxGasLimit`、`maxDataLength` 和 `allowedTargets` 策略控制。 + +| **字段** | **类型** | **描述** | +| :--- | :--- | :--- | +| `waiverAccount` | `LocalAccount` | 签署外部包装器的白名单、经治理注册的账户。 | +| `laneId` | `bigint` | 企业通道ID。必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。 | + +### `send(user, tx)` / `sendBatch(user, txs)` + +从 `user` 构建并签名内部 `0x3F` CustomTx,用免燃气费密钥包装,然后中继。无需燃气费字段,因为燃气费已豁免。内部 2D nonce 是从网关发现的,批次从该基础自动排序。 + +```ts +// 单个 +const { txHash } = await gw.send(user, { to: recipient }); + +// 批处理 +const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); +``` + +```text +{ txHash: "0x8f3a...2d41" } +``` + +`tx` 参数是一个 [`GuaranteedWaiverTxRequest`](#guaranteedwaivertxrequest) 加上一个可选的 `nonce`。`send` 返回 [`RelayResult`](#relayresult);`sendBatch` 返回 [`BatchResultItem[]`](#batchresultitem)。 + +### `relay(signedInnerTx)` / `relayBatch(signedInnerTxs)` + +对于非托管流,用户使用 [`buildGuaranteedTx`](#buildguaranteedtxaccount-chainid-req) 签名内部 `0x3F` CustomTx (费用 `0n`,使用 `nonceKeyForLane(laneId)`),然后只将签名的十六进制数据交给操作员。操作员使用免燃气费密钥包装并中继。 + +```ts +import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; + +const signedInner = await buildGuaranteedTx(user, stableTestnet.id, { + to, + gas: 100_000n, + gasFeeCap: 0n, // waived + gasTipCap: 0n, + nonce, + nonceKey: nonceKeyForLane(0n), +}); +const { txHash } = await gw.relay(signedInner); // waiver wraps + broadcasts → H_inner +``` + +```text +{ txHash: "0x8f3a...2d41" } +``` + +## 构建助手 + +用于非托管 `relay` 路径的低级签名者。每个都返回一个已签名交易作为 `Hex`,不进行 nonce 获取或费用估算。 + +### `buildWaiverInnerTx(account, chainId, req)` + +使用免燃气费不变式(`gasPrice: 0`、遗留类型和给定 `chainId`)签署一个准备好的内部交易。`req` 是一个 [`WaiverInnerTx`](#waiverinnertx) 加上一个必需的 `nonce`。 + +```ts +const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to, data, gas: 150_000n, nonce }); +``` + +### `buildGuaranteedTx(account, chainId, req)` + +构建并签署一个 GuaranteedTx (`0x3F` CustomTx)。`req` 是一个 [`GuaranteedTxRequest`](#guaranteedtxrequest) 加上一个必需的 `nonce` 和 `nonceKey`。 + +### `buildGuaranteedWaiverTx(...)` + +将预签名内部交易包装到外部 `0x3F` 免燃气费 CustomTx 中。供 `guaranteedWaiver.relay` 内部使用;为高级流程导出。 + +### `nonceKeyForLane(laneId)` + +返回 `laneId` 的企业 `nonceKey`,供 `buildGuaranteedTx` 使用。 + +```ts +import { nonceKeyForLane } from "@stablechain/enterprise"; + +const nonceKey = nonceKeyForLane(0n); +``` + +## 类型 + +### `WaiverInnerTx` + +每次调用内部交易时会变化的字段。 + +| **字段** | **类型** | **默认值** | **描述** | +| :--- | :--- | :--- | :--- | +| `to` | `Address` | | 目标地址:用于ERC-20转账的代币合约,或用于原生资产的接收方。 | +| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | 燃气限制。由于 `gasPrice` 为 0,所以一个慷慨的限制是免费的。 | +| `data` | `Hex?` | `"0x"` | 调用数据。 | +| `value` | `bigint?` | `0n` | 要发送的原生价值。 | + +### `GuaranteedTxRequest` + +| **字段** | **类型** | **默认值** | **描述** | +| :--- | :--- | :--- | :--- | +| `to` | `Address?` | | 目标地址。 | +| `gas` | `bigint` | | 燃气限制。必填。 | +| `gasFeeCap` | `bigint` | | `maxFeePerGas`。必填。 | +| `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`。必填。 | +| `data` | `Hex?` | `"0x"` | 调用数据。 | +| `value` | `bigint?` | `0n` | 要发送的原生价值。 | + +### `GuaranteedWaiverTxRequest` + +费用字段始终为 0,因此在此处省略。 + +| **字段** | **类型** | **默认值** | **描述** | +| :--- | :--- | :--- | :--- | +| `to` | `Address` | | 目标地址。 | +| `gas` | `bigint?` | 共享内部燃气默认值 | 燃气限制。 | +| `data` | `Hex?` | `"0x"` | 调用数据。 | +| `value` | `bigint?` | `0n` | 要发送的原生价值。允许免燃气费交易进行价值转账。 | + +### `ValidationLimits` + +由 `gasWaiver` 和 `guaranteedWaiver` 应用于每个 InternalTx 的按合作方策略。 + +| **字段** | **类型** | **默认值** | **描述** | +| :--- | :--- | :--- | :--- | +| `maxGasLimit` | `bigint?` | `10_000_000n` | InternalTx 的最大燃气限制。超过此限制将导致 `GAS_LIMIT_EXCEEDED` 失败。 | +| `maxDataLength` | `number?` | `131_072` (128 KB) | 调用数据的最大字节数。超过此限制将导致 `DATA_TOO_LARGE` 失败。 | +| `allowedTargets` | `AllowedTarget[]?` | | 豁免燃气费可能赞助的合约和方法的白名单。设置后,列表之外的目标将导致 `TARGET_NOT_ALLOWED` 失败。 | + +### `AllowedTarget` + +| **字段** | **类型** | **描述** | +| :--- | :--- | :--- | +| `address` | `Address \| "*"` | 内部交易可以调用的合约,或 `"*"` 表示匹配任何合约。 | +| `selectors` | `Hex[]?` | 允许的4字节方法选择器(例如,ERC-20 `transfer` 的 `"0xa9059cbb"`)。省略或留空表示允许 `address` 上的任何方法。 | + +### `RelayResult` + +```ts +interface RelayResult { + txHash: Hash; // H_inner 用于豁免,GuaranteedTx 哈希用于独立保证区块 +} +``` + +### `BatchResultItem` + +批次中每个输入的条目,按输入顺序排列。批次不是抛出异常,而是显示每个项目的处理结果。 + +| **字段** | **类型** | **描述** | +| :--- | :--- | :--- | +| `index` | `number` | 零基位置,与输入数组匹配。 | +| `success` | `boolean` | 此项是否被中继。 | +| `txHash` | `Hash?` | 成功时存在:内部交易哈希。 | +| `error` | `{ code: ErrorCode; message: string }?` | 失败时存在。 | + +## 错误 + +单一交易方法(`send`,`relay`)在拒绝时抛出错误。批量方法则在 [`BatchResultItem.error`](#batchresultitem) 中报告每个项目的失败。所有错误类都扩展自 `StableEnterpriseError`。 + +| **类** | **抛出条件** | **有用字段** | +| :--- | :--- | :--- | +| `StableEnterpriseError` | 每个SDK错误的基础类。 | `message` | +| `StableEnterpriseRelayError` | 交易在RPC或中继层被拒绝。 | `code` | +| `WaiverValidationError` | 内部交易在广播前未能通过策略检查(燃气费、数据大小或目标白名单)。 | `code` | + +```ts +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; +} +``` + +```text +StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not allowed +``` + +### `ErrorCode` + +抛出的错误或 `BatchResultItem.error` 上的 `code` 之一是: + +| **代码** | **含义** | +| :--- | :--- | +| `UNKNOWN_ERROR` | 当没有特定代码时回退。 | +| `BROADCAST_FAILED` | 广播在RPC层被拒绝,或网关中继失败。 | +| `INVALID_TRANSACTION` | 内部交易解码或解析失败。 | +| `INVALID_SIGNATURE` | 签名验证失败。 | +| `UNSUPPORTED_TX_TYPE` | 内部交易类型不是 legacy、eip2930 或 eip1559。 | +| `WRONG_CHAIN_ID` | 内部交易 `chainId` 缺失或与目标链不匹配。 | +| `NON_ZERO_GAS_PRICE` | 内部交易携带非零燃气费(豁免时必须为零)。 | +| `GAS_LIMIT_EXCEEDED` | 内部交易燃气限制超过 `maxGasLimit`。 | +| `DATA_TOO_LARGE` | 内部交易调用数据超过 `maxDataLength`。 | +| `TARGET_NOT_ALLOWED` | 内部交易目标不在 `allowedTargets` 中。 | +| `GATEWAY_UNAUTHORIZED` | 企业版RPC网关拒绝了API密钥(缺失、无效或已过期)。 | +| `QUOTA_EXCEEDED` | 企业版RPC网关的燃气配额已用尽。 | + +## 常量 + +| **常量** | **类型** | **描述** | +| :--- | :--- | :--- | +| `DEFAULT_INNER_GAS` | `bigint` | 当 `gas` 省略时,内部交易的默认燃气限制 (`150_000n`)。 | +| `ENTERPRISE_FLAG` | `bigint` | 在通道的 `nonceKey` 上设置的企业位。 | +| `ENTERPRISE_MASK` | `bigint` | 通道 ID 的上限:`laneId` 必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。 | + +## 下一步建议 + +- [**稳定企业级SDK**](/cn/explanation/enterprise-sdk): 了解这些机制是什么以及何时使用它们。 +- [**燃气费豁免协议**](/cn/reference/gas-waiver-api): 交易格式、标记路由和治理控制。 +- [**保证区块空间**](/cn/explanation/guaranteed-blockspace): Stable如何为企业工作负载预留区块容量。 diff --git a/docs/pages/ko/explanation/enterprise-sdk.mdx b/docs/pages/ko/explanation/enterprise-sdk.mdx new file mode 100644 index 0000000..67f24b7 --- /dev/null +++ b/docs/pages/ko/explanation/enterprise-sdk.mdx @@ -0,0 +1,69 @@ +--- +source_path: explanation/enterprise-sdk.mdx +source_sha: c851ff041a812cf877db582b540a0369d4777566 +title: "Stable 엔터프라이즈 SDK" +description: "유형화된 @stablechain/enterprise SDK를 사용하여 백엔드에서 가스 면제 및 블록 공간 보장 트랜잭션을 릴레이합니다." +diataxis: "explanation" +--- + +# Stable 엔터프라이즈 SDK + +`@stablechain/enterprise`는 Stable의 엔터프라이즈 트랜잭션 레일을 위한 서버 측 TypeScript 클라이언트입니다. 가스 면제 트랜잭션(사용자 가스 후원)과 보장된 블록 공간 트랜잭션(예약된 엔터프라이즈 레인에 상륙)의 두 가지 유형의 특권 트랜잭션을 서명하고 릴레이합니다. 한 클라이언트에서 두 레일 중 하나 또는 둘 다를 활성화할 수 있습니다. + +```ts +import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; +import { privateKeyToAccount } from "viem/accounts"; + +const enterprise = createStableEnterprise({ + chain: stableTestnet, + gasWaiver: { account: privateKeyToAccount("0xYOUR_WAIVER_KEY") }, +}); + +const { txHash } = await enterprise.gasWaiver!.send(user, { to: token, data }); +``` + +```text +txHash: 0x8f3a...2d41 +``` + +호출은 사용자의 트랜잭션 해시인 `H_inner`를 반환하며, 이를 전달한 래퍼 트랜잭션 해시는 반환하지 않습니다. + +## SDK의 기능 + +SDK는 세 가지 모듈을 노출합니다. 각 모듈은 선택 사항이며 독립적으로 구성되며, 각각 고유한 서명 계정을 가지고 있어 별도의 키를 사용할 수 있습니다. + +- **`gasWaiver`**: 가스 면제 트랜잭션을 빌드, 서명 및 릴레이합니다. 화이트리스트에 있는 면제 계정이 사용자의 제로 가스 트랜잭션을 래핑하여 사용자가 USDT0를 보유하지 않고도 트랜잭션할 수 있도록 합니다. [가스 면제](/ko/explanation/gas-waiver)를 참조하십시오. +- **`guaranteedBlock`**: Enterprise RPC 게이트웨이를 통해 GuaranteedTx를 릴레이하여 예약된 Enterprise-lane 블록 공간에 상륙합니다. 가스 면제와 달리 서명자는 자체 가스를 지불합니다. [보장된 블록 공간](/ko/explanation/guaranteed-blockspace)을 참조하십시오. +- **`guaranteedWaiver`**: 둘의 조합입니다. 보장된 블록 공간을 통해 라우팅되는 가스 면제 트랜잭션이므로 사용자는 잔액이 필요 없고 트랜잭션은 여전히 Enterprise 레인에 상륙합니다. + +모든 모듈은 동일한 네 가지 메서드를 제공합니다. SDK가 서명하는 관리 경로에는 `send` 및 `sendBatch`, 사용자가 다른 곳에서 서명하고 서명된 헥스만 전달하는 비관리 경로에는 `relay` 및 `relayBatch`가 있습니다. + +## 접근 + +엔터프라이즈 SDK는 현재 Stable Testnet에서만 사용할 수 있습니다. + +두 레일 모두 게이트되었습니다. 가스 면제는 거버넌스 등록 면제 키가 필요하고, 보장된 블록 공간은 엔터프라이즈 RPC 게이트웨이 API 키가 필요합니다. 통합하려면 Stable에 문의하여 액세스 권한을 얻으십시오. Stable은 필요한 면제 키와 게이트웨이 엔드포인트를 제공합니다. + +## 서버 측 전용 + +:::warning +엔터프라이즈 SDK는 개인 키로 서명하는 무상태 서버 측 라이브러리입니다. 브라우저에서 실행하지 마십시오. 면제 키와 엔터프라이즈 RPC 게이트웨이 URL을 백엔드에 보관하십시오. +::: + +면제 키는 화이트리스트에 있는 거버넌스 등록 계정입니다. 이를 보유한 사람은 누구나 귀하의 정책에 따라 가스를 후원할 수 있습니다. 엔터프라이즈 RPC 게이트웨이 URL은 API 키를 포함합니다. 둘 다 비밀로 취급하십시오. + +## 언제 사용해야 하는가 + +백엔드를 운영하고 사용자 가스를 후원하거나 자체 트래픽에 대한 포함을 보장하려는 경우 엔터프라이즈 SDK를 사용하십시오. 백엔드 또는 브라우저에서 일상적인 전송, 브릿지, 스왑 및 볼트 수익을 위해서는 일반적인 [Stable SDK](/ko/explanation/sdk-overview)를 대신 사용하십시오. + +## 여기부터 시작 + +- [**엔터프라이즈 SDK 참조**](/ko/reference/enterprise-sdk): 모든 모듈, 메서드, 구성 옵션 및 오류 클래스. +- [**가스 면제**](/ko/explanation/gas-waiver): 제로 가스 트랜잭션이 프로토콜 수준에서 작동하는 방식. +- [**보장된 블록 공간**](/ko/explanation/guaranteed-blockspace): Stable이 엔터프라이즈 워크로드에 대한 블록 용량을 예약하는 방식. + +## 다음 권장 사항 + +- [**가스 면제 프로토콜**](/ko/reference/gas-waiver-api): 트랜잭션 형식, 마커 라우팅 및 거버넌스 제어. +- [**Stable SDK**](/ko/explanation/sdk-overview): 전송, 브리징, 스왑 및 수익을 위한 일반적인 클라이언트. +- [**Stable에 연결**](/ko/reference/connect): 테스트넷용 체인 ID, RPC 엔드포인트 및 탐색기. diff --git a/docs/pages/ko/reference/enterprise-sdk.mdx b/docs/pages/ko/reference/enterprise-sdk.mdx new file mode 100644 index 0000000..565e22f --- /dev/null +++ b/docs/pages/ko/reference/enterprise-sdk.mdx @@ -0,0 +1,475 @@ +--- +source_path: reference/enterprise-sdk.mdx +source_sha: b7063f13645d37e2d66b8bb8c87b0dcfaf386a61 +title: "엔터프라이즈 SDK 참조" +description: "@stablechain/enterprise에 대한 완벽한 참조: createStableEnterprise, 가스 면제 및 보장된 블록 공간 모듈, 빌드 헬퍼 및 오류 클래스." +diataxis: "reference" +--- + +# 엔터프라이즈 SDK 참조 + +`@stablechain/enterprise`의 전체 표면입니다. 여기에는 [`createStableEnterprise`](#createstableenterpriseconfig)의 클라이언트, 세 가지 모듈([가스 면제](#gaswaiver-module), [보장된 블록 공간](#guaranteedblock-module), [구성된 면제](#guaranteedwaiver-module)), 저수준 빌드 헬퍼, 공유 결과 및 오류 유형이 포함됩니다. 이러한 레일에 대한 자세한 내용은 [Stable 엔터프라이즈 SDK](/ko/explanation/enterprise-sdk), [가스 면제](/ko/explanation/gas-waiver), [보장된 블록 공간](/ko/explanation/guaranteed-blockspace)을 참조하세요. + +:::note +엔터프라이즈 SDK는 Stable 테스트넷에서만 사용할 수 있으며, 두 레일 모두 게이트됩니다. 통합하려면 [Stable에 문의](https://discord.gg/stablexyz)하여 거버넌스 등록 면제 키와 엔터프라이즈 RPC 게이트웨이 API 키를 받으세요. +::: + +:::warning +이것은 개인 키로 서명하는 서버 측 라이브러리입니다. 브라우저에서 실행하지 마십시오. 웨이버 키와 엔터프라이즈 RPC 게이트웨이 URL을 백엔드에 보관하십시오. +::: + +## 설치 + +```bash +npm install @stablechain/enterprise viem +``` + +```text +added 2 packages, audited 3 packages in 2s +``` + +`viem >= 2.0.0`은 피어 종속성입니다. 이 패키지는 `viem/chains`에서 `stable` 및 `stableTestnet`을 다시 내보내므로 별도로 가져올 필요가 없습니다. + +## `createStableEnterprise(config)` + +`StableEnterpriseClient`를 생성합니다. 각 모듈은 구성할 때만 존재하므로, 사용 전에 `!` 또는 null 검사로 보호하십시오. + +```ts +import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; +import { privateKeyToAccount } from "viem/accounts"; + +const enterprise = createStableEnterprise({ + chain: stableTestnet, + gasWaiver: { account: privateKeyToAccount("0xYOUR_WAIVER_KEY") }, +}); +``` + +```text +StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver: undefined } +``` + +### `StableEnterpriseConfig` + +| **필드** | **타입** | **기본값** | **설명** | +| :--- | :--- | :--- | :--- | +| `chain` | `StableChain` | | 대상 체인입니다. `stable` 또는 `stableTestnet`을 전달합니다(패키지에서 다시 내보내기). 필수입니다. | +| `rpcEndpoints` | `string[]?` | 체인의 내장 RPC | 하나 이상의 Stable RPC 엔드포인트로, 실패 시 순서대로 시도됩니다. 개인 엔드포인트를 지정하는 경우에만 재정의합니다. | +| `enterpriseRpcEndpoints` | `string[]?` | | 하나 이상의 엔터프라이즈 RPC 게이트웨이 엔드포인트로, 실패 시 순서대로 시도됩니다. `guaranteedBlock` 및 `guaranteedWaiver`에 필요합니다. | +| `batchSizeLimit` | `number?` | `100` | 일괄 RPC 호출당 최대 트랜잭션 수입니다. | +| `gasWaiver` | `GasWaiverConfig?` | | [가스 면제 모듈](#gaswaiver-module)을 활성화합니다. | +| `guaranteedBlock` | `GuaranteedBlockConfig?` | | [보장된 블록 공간 모듈](#guaranteedblock-module)을 활성화합니다. | +| `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | [구성된 면제 모듈](#guaranteedwaiver-module)을 활성화합니다. | + +### `StableEnterpriseClient` + +```ts +interface StableEnterpriseClient { + gasWaiver?: GasWaiverClient; + guaranteedBlock?: GuaranteedBlockClient; + guaranteedWaiver?: GuaranteedWaiverClient; +} +``` + +## `gasWaiver` 모듈 + +가스 면제 트랜잭션을 릴레이합니다. 화이트리스트에 등록된 면제 계정은 사용자의 제로 가스 트랜잭션(InnerTx)을 WaiverTx로 래핑하고 브로드캐스트합니다. 사용자는 USDT0이 필요하지 않습니다. 모든 메서드는 래퍼 해시가 아닌 InnerTx 해시인 `H_inner`를 반환합니다. + +구성에서 `gasWaiver`를 사용하여 활성화하세요. + +```ts +const enterprise = createStableEnterprise({ + chain: stableTestnet, + gasWaiver: { + account: privateKeyToAccount("0xYOUR_WAIVER_KEY"), + // 선택적 파트너별 정책 제한 + maxGasLimit: 500_000n, + allowedTargets: [{ address: "0xToken", selectors: ["0xa9059cbb"] }], + }, +}); + +const gw = enterprise.gasWaiver!; +``` + +### `GasWaiverConfig` + +[`ValidationLimits`](#validationlimits)를 확장합니다. + +| **필드** | **타입** | **설명** | +| :--- | :--- | :--- | +| `account` | `LocalAccount` | 각 WaiverTx에 서명하는 화이트리스트에 등록된 거버넌스 계정입니다. | +| `maxGasLimit` | `bigint?` | `ValidationLimits`에서 상속됩니다. | +| `maxDataLength` | `number?` | `ValidationLimits`에서 상속됩니다. | +| `allowedTargets` | `AllowedTarget[]?` | `ValidationLimits`에서 상속됩니다. | + +### `send(account, tx)` + +`account`에서 하나의 InnerTx를 한 번의 호출로 빌드, 서명 및 릴레이합니다. `gasPrice: 0`, 레거시 유형, `chainId`, 보류 중인 nonce는 자동으로 처리됩니다. 거부 시 `StableEnterpriseRelayError`를 throw합니다. + +```ts +const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); +``` + +```text +{ txHash: "0x8f3a...2d41" } +``` + +`tx` 인수는 [`WaiverInnerTx`](#waiverinnertx)와 선택적 `nonce`입니다. [`RelayResult`](#relayresult)를 반환합니다. + +### `sendBatch(account, txs)` + +하나의 `account`에서 여러 InnerTx를 빌드, 서명 및 릴레이합니다. Nonce는 계정의 보류 중인 nonce에서 자동으로 순서가 지정됩니다. 입력당 하나의 결과를 순서대로 반환합니다. + +```ts +const results = await gw.sendBatch(user, [ + { to: token, data: dataA, gas: 150_000n }, + { to: token, data: dataB, gas: 150_000n }, +]); +``` + +```text +[ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: true, txHash: "0x..." } ] +``` + +`txs`는 [`WaiverInnerTx`](#waiverinnertx)의 읽기 전용 배열입니다. [`BatchResultItem[]`](#batchresultitem)을 반환합니다. + +### `relay(signedInnerTxHex)` + +사전 서명된 제로 가스 InnerTx를 릴레이합니다. 사용자 키를 볼 수 없도록 사용자가 자신의 환경에서 서명하고 서명된 hex만 전달하는 비관리형 흐름에 사용하십시오. [`buildWaiverInnerTx`](#buildwaiverinnertxaccount-chainid-req)로 빌드합니다. 거부 시 throw합니다. + +```ts +import { buildWaiverInnerTx } from "@stablechain/enterprise"; + +const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to, data, gas: 150_000n, nonce }); +const { txHash } = await gw.relay(signed); +``` + +```text +{ txHash: "0x8f3a...2d41" } +``` + +### `relayBatch(signedInnerTxHexes)` + +사전 서명된 InnerTx의 배치를 릴레이합니다. 입력당 하나의 [`BatchResultItem`](#batchresultitem)을 순서대로 반환합니다. + +```ts +const results = await gw.relayBatch([signed0, signed1]); +``` + +```text +[ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: false, error: { code: "TARGET_NOT_ALLOWED", message: "..." } } ] +``` + +## `guaranteedBlock` 모듈 + +엔터프라이즈 RPC 게이트웨이를 통해 GuaranteedTx(유형 `0x3F` CustomTx)를 릴레이하여 예약된 엔터프라이즈 레인 블록 공간에 착륙시킵니다. 가스 면제와 달리 서명자는 자체 가스를 지불하며 자금이 지원되어야 합니다. 각 트랜잭션은 엔터프라이즈 레인에 키가 지정된 2D 논스를 전달하며, 브로드캐스팅은 게이트웨이를 통해서만 이루어집니다. + +`guaranteedBlock`과 `enterpriseRpcEndpoints`를 사용하여 활성화하세요. + +```ts +const enterprise = createStableEnterprise({ + chain: stableTestnet, + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable이 제공하는 게이트웨이 URL + guaranteedBlock: { + account: privateKeyToAccount("0xFUNDED_SIGNER_KEY"), + laneId: 0n, + }, +}); + +const gb = enterprise.guaranteedBlock!; +``` + +### `GuaranteedBlockConfig` + +| **필드** | **타입** | **설명** | +| :--- | :--- | :--- | +| `account` | `LocalAccount` | 각 GuaranteedTx에 서명하고 가스를 지불하는 자금이 지원되는 계정입니다. | +| `laneId` | `bigint` | 엔터프라이즈 레인 ID입니다. `[0, ENTERPRISE_MASK - 1]` 범위 내에 있어야 합니다. 유효하지 않은 ID는 즉시 거부됩니다. | + +### `send(account, tx)` + +하나의 GuaranteedTx를 빌드, 서명 및 릴레이합니다. 서명자가 가스를 지불하므로 1559 수수료 필드가 필요합니다. `chainId`, 엔터프라이즈 `nonceKey`, 그리고 2D nonce(게이트웨이에서 검색됨)는 자동으로 처리됩니다. + +```ts +const gasPrice = await publicClient.getGasPrice(); + +const { txHash } = await gb.send(signer, { + to: recipient, + gas: 21_000n, + gasFeeCap: gasPrice * 2n, + gasTipCap: gasPrice, +}); +``` + +```text +{ txHash: "0xabcd...7890" } +``` + +`tx` 인수는 [`GuaranteedTxRequest`](#guaranteedtxrequest)와 선택적 `nonce`입니다. [`RelayResult`](#relayresult)를 반환합니다. + +### `sendBatch(account, txs)` + +여러 GuaranteedTx를 빌드, 서명 및 릴레이합니다. Nonce는 검색된 베이스에서 자동으로 순서가 지정됩니다. 실패는 후속 트랜잭션에 영향을 미칩니다. + +```ts +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 }, +]); +``` + +```text +[ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: true, txHash: "0x..." } ] +``` + +[`BatchResultItem[]`](#batchresultitem)을 반환합니다. + +### `relay(signedTx)` / `relayBatch(signedTxs)` + +사전 서명된 GuaranteedTx 또는 그 배치들을 릴레이합니다. [`nonceKeyForLane`](#noncekeyforlanelaneid)을 엔터프라이즈 nonce 키로 사용하여 [`buildGuaranteedTx`](#buildguaranteedtxaccount-chainid-req)로 트랜잭션을 다른 곳에서 빌드 및 서명한 다음, 운영자에게 서명된 hex만 전달합니다. + +```ts +import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; + +const signed = await buildGuaranteedTx(signer, stableTestnet.id, { + to, + gas: 21_000n, + gasFeeCap, + gasTipCap, + nonce, // 계정의 현재 2D 레인 nonce + nonceKey: nonceKeyForLane(0n), +}); +const { txHash } = await gb.relay(signed); +``` + +```text +{ txHash: "0xabcd...7890" } +``` + +## `guaranteedWaiver` 모듈 + +위의 두 레일의 결합: 보장된 블록 공간을 통해 라우팅되는 가스 면제 트랜잭션입니다. 내부 및 외부 트랜잭션 모두 하나의 엔터프라이즈 `nonceKey`를 공유하는 `0x3F` CustomTx이므로 `guaranteedBlock`과 같이 게이트웨이를 통해 브로드캐스트됩니다. 면제가 가스를 지원하므로 사용자는 `gasWaiver`와 마찬가지로 잔액이나 수수료 필드가 필요하지 않습니다. 모든 메서드는 `H_inner`를 반환합니다. + +`guaranteedWaiver`와 `enterpriseRpcEndpoints`를 사용하여 활성화하십시오. + +```ts +const enterprise = createStableEnterprise({ + chain: stableTestnet, + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable이 제공하는 게이트웨이 URL + guaranteedWaiver: { + waiverAccount: privateKeyToAccount("0xYOUR_WAIVER_KEY"), + laneId: 0n, + }, +}); + +const gw = enterprise.guaranteedWaiver!; +``` + +### `GuaranteedWaiverConfig` + +[`ValidationLimits`](#validationlimits)를 확장하므로 `GasWaiverConfig`와 동일한 `maxGasLimit`, `maxDataLength`, `allowedTargets` 정책 제어를 허용합니다. + +| **필드** | **타입** | **설명** | +| :--- | :--- | :--- | +| `waiverAccount` | `LocalAccount` | 외부 래퍼에 서명하는 화이트리스트에 등록된 거버넌스 계정입니다. | +| `laneId` | `bigint` | 엔터프라이즈 레인 ID입니다. `[0, ENTERPRISE_MASK - 1]` 범위 내에 있어야 합니다. | + +### `send(user, tx)` / `sendBatch(user, txs)` + +`user`에서 내부 `0x3F` CustomTx를 빌드 및 서명하고, 면제 키로 래핑한 다음 릴레이합니다. 가스가 면제되므로 수수료 필드는 필요하지 않습니다. 내부 2D nonce는 게이트웨이에서 감지되며, 일괄 처리는 해당 기준에서 자동으로 시퀀싱됩니다. + +```ts +// 단일 +const { txHash } = await gw.send(user, { to: recipient }); + +// 일괄 +const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); +``` + +```text +{ txHash: "0x8f3a...2d41" } +``` + +`tx` 인수는 [`GuaranteedWaiverTxRequest`](#guaranteedwaivertxrequest)와 선택적 `nonce`입니다. `send`는 [`RelayResult`](#relayresult)를 반환하고, `sendBatch`는 [`BatchResultItem[]`](#batchresultitem)을 반환합니다. + +### `relay(signedInnerTx)` / `relayBatch(signedInnerTxs)` + +비관리형 흐름의 경우, 사용자는 [`buildGuaranteedTx`](#buildguaranteedtxaccount-chainid-req)로 내부 `0x3F` CustomTx에 서명하고(수수료 `0n`, `nonceKeyForLane(laneId)` 사용), 운영자에게 서명된 Hex 문자열만 전달합니다. 운영자는 이를 면제 키로 래핑하고 릴레이합니다. + +```ts +import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; + +const signedInner = await buildGuaranteedTx(user, stableTestnet.id, { + to, + gas: 100_000n, + gasFeeCap: 0n, // 면제됨 + gasTipCap: 0n, + nonce, + nonceKey: nonceKeyForLane(0n), +}); +const { txHash } = await gw.relay(signedInner); // 면제가 래핑 + 브로드캐스트 → H_inner +``` + +```text +{ txHash: "0x8f3a...2d41" } +``` + +## 빌드 헬퍼 + +비관리형 `relay` 경로를 위한 저수준 서명자입니다. 각 함수는 논스 가져오기 또는 수수료 추정 없이 서명된 트랜잭션을 `Hex`로 반환합니다. + +### `buildWaiverInnerTx(account, chainId, req)` + +`gasPrice: 0`, 레거시 유형, 지정된 `chainId`와 같이 웨이버 불변성이 포함된 웨이버 준비 InnerTx에 서명합니다. `req`는 [`WaiverInnerTx`](#waiverinnertx)와 필수 `nonce`입니다. + +```ts +const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to, data, gas: 150_000n, nonce }); +``` + +### `buildGuaranteedTx(account, chainId, req)` + +GuaranteedTx(`0x3F` CustomTx)를 빌드하고 서명합니다. `req`는 [`GuaranteedTxRequest`](#guaranteedtxrequest)와 필수 `nonce` 및 `nonceKey`입니다. + +### `buildGuaranteedWaiverTx(...)` + +사전 서명된 내부 트랜잭션을 외부 `0x3F` 웨이버 CustomTx로 래핑합니다. `guaranteedWaiver.relay`에서 내부적으로 사용되며, 고급 흐름을 위해 내보내집니다. + +### `nonceKeyForLane(laneId)` + +`buildGuaranteedTx`에서 사용하기 위한 레인 ID에 대한 엔터프라이즈 `nonceKey`를 반환합니다. + +```ts +import { nonceKeyForLane } from "@stablechain/enterprise"; + +const nonceKey = nonceKeyForLane(0n); +``` + +## 유형 + +### `WaiverInnerTx` + +호출마다 달라지는 InnerTx 필드입니다. + +| **필드** | **타입** | **기본값** | **설명** | +| :--- | :--- | :--- | :--- | +| `to` | `Address` | | 대상 주소: ERC-20 전송을 위한 토큰 계약, 기본 전송을 위한 수신자. | +| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | 가스 한도입니다. `gasPrice`가 0이므로 여유 있는 한도는 무료입니다. | +| `data` | `Hex?` | `"0x"` | 칼데이터. | +| `value` | `bigint?` | `0n` | 보낼 기본값입니다. | + +### `GuaranteedTxRequest` + +| **필드** | **타입** | **기본값** | **설명** | +| :--- | :--- | :--- | :--- | +| `to` | `Address?` | | 대상 주소. | +| `gas` | `bigint` | | 가스 한도. 필수입니다. | +| `gasFeeCap` | `bigint` | | `maxFeePerGas`. 필수입니다. | +| `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`. 필수입니다. | +| `data` | `Hex?` | `"0x"` | 칼데이터. | +| `value` | `bigint?` | `0n` | 보낼 네이티브 값. | + +### `GuaranteedWaiverTxRequest` + +수수료 필드는 항상 0이므로 여기서는 제외됩니다. + +| **필드** | **타입** | **기본값** | **설명** | +| :--- | :--- | :--- | :--- | +| `to` | `Address` | | 대상 주소. | +| `gas` | `bigint?` | 공유되는 내부 가스 기본값 | 가스 한도. | +| `data` | `Hex?` | `"0x"` | 칼데이터. | +| `value` | `bigint?` | `0n` | 전송할 네이티브 값. 웨이버의 경우 값 전송이 허용됩니다. | + +### `ValidationLimits` + +`gasWaiver` 및 `guaranteedWaiver`에 의해 각 InnerTx에 적용되는 파트너별 정책입니다. + +| **필드** | **타입** | **기본값** | **설명** | +| :--- | :--- | :--- | :--- | +| `maxGasLimit` | `bigint?` | `10_000_000n` | InnerTx의 최대 가스 한도. 초과 시 `GAS_LIMIT_EXCEEDED`와 함께 실패합니다. | +| `maxDataLength` | `number?` | `131_072` (128KB) | 칼데이터의 최대 크기(바이트). 초과 시 `DATA_TOO_LARGE`와 함께 실패합니다. | +| `allowedTargets` | `AllowedTarget[]?` | | 웨이버가 지원할 수 있는 계약 및 메서드의 허용 목록입니다. 설정되면 목록 외부의 대상은 `TARGET_NOT_ALLOWED`와 함께 실패합니다. | + +### `AllowedTarget` + +| **필드** | **타입** | **설명** | +| :--- | :--- | :--- | +| `address` | `Address \| "*"` | InnerTx가 호출할 수 있는 컨트랙트 또는 모든 컨트랙트와 일치하는 `"*"`. | +| `selectors` | `Hex[]?` | 허용된 4바이트 메서드 셀렉터(예: ERC-20 `transfer`의 `"0xa9059cbb"`). `address`의 모든 메서드를 허용하려면 생략하거나 비워 둡니다. | + +### `RelayResult` + +```ts +interface RelayResult { + txHash: Hash; // 웨이버의 H_inner, 독립형 보장 블록의 GuaranteedTx 해시 +} +``` + +### `BatchResultItem` + +배치에서 입력 순서대로 각 입력에 대한 하나의 항목입니다. throw하는 대신 배치는 항목별 결과를 표시합니다. + +| **필드** | **타입** | **설명** | +| :--- | :--- | :--- | +| `index` | `number` | 입력 배열과 일치하는 0부터 시작하는 위치입니다. | +| `success` | `boolean` | 이 항목이 릴레이되었는지 여부. | +| `txHash` | `Hash?` | 성공 시 존재: 내부 트랜잭션 해시. | +| `error` | `{ code: ErrorCode; message: string }?` | 실패 시 존재. | + +## 에러 + +단일 트랜잭션 메서드(`send`, `relay`)는 거부 시 실패를 throw합니다. 배치 메서드는 [`BatchResultItem.error`](#batchresultitem)에서 항목별 실패를 보고합니다. 모든 오류 클래스는 `StableEnterpriseError`를 확장합니다. + +| **클래스** | **발생 시점** | **유용한 필드** | +| :--- | :--- | :--- | +| `StableEnterpriseError` | 모든 SDK 오류의 기본 클래스. | `message` | +| `StableEnterpriseRelayError` | 트랜잭션이 RPC 또는 릴레이 계층에서 거부되었을 때. | `code` | +| `WaiverValidationError` | InnerTx가 브로드캐스트 전에 정책 검사(가스, 데이터 크기 또는 대상 허용 목록)에 실패했을 때. | `code` | + +```ts +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; +} +``` + +```text +StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not allowed +``` + +### `ErrorCode` + +throw된 오류 또는 `BatchResultItem.error`의 `code`는 다음 중 하나입니다. + +| **코드** | **의미** | +| :--- | :--- | +| `UNKNOWN_ERROR` | 특정 코드를 사용할 수 없을 때의 폴백. | +| `BROADCAST_FAILED` | RPC 계층에서 브로드캐스트가 거부되거나 게이트웨이가 릴레이에 실패했습니다. | +| `INVALID_TRANSACTION` | InnerTx 디코딩 또는 파싱에 실패했습니다. | +| `INVALID_SIGNATURE` | 서명 확인에 실패했습니다. | +| `UNSUPPORTED_TX_TYPE` | InnerTx 유형이 legacy, eip2930 또는 eip1559가 아닙니다. | +| `WRONG_CHAIN_ID` | InnerTx `chainId`가 없거나 대상 체인과 일치하지 않습니다. | +| `NON_ZERO_GAS_PRICE` | InnerTx에 0이 아닌 가스 가격이 포함되어 있습니다(웨이버의 경우 0이어야 함). | +| `GAS_LIMIT_EXCEEDED` | InnerTx 가스 한도가 `maxGasLimit`을 초과합니다. | +| `DATA_TOO_LARGE` | InnerTx calldata가 `maxDataLength`를 초과합니다. | +| `TARGET_NOT_ALLOWED` | InnerTx 대상이 `allowedTargets`에 없습니다. | +| `GATEWAY_UNAUTHORIZED` | 엔터프라이즈 RPC 게이트웨이가 API 키를 거부했습니다(누락, 유효하지 않거나 만료됨). | +| `QUOTA_EXCEEDED` | 엔터프라이즈 RPC 게이트웨이 가스 할당량이 소진되었습니다. | + +## 상수 + +| **상수** | **타입** | **설명** | +| :--- | :--- | :--- | +| `DEFAULT_INNER_GAS` | `bigint` | `gas`를 생략할 때의 기본 InnerTx 가스 제한(`150_000n`). | +| `ENTERPRISE_FLAG` | `bigint` | 레인의 `nonceKey`에 설정된 엔터프라이즈 비트. | +| `ENTERPRISE_MASK` | `bigint` | 레인 ID의 상한: `laneId`는 `[0, ENTERPRISE_MASK - 1]` 범위 내에 있어야 합니다. | + +## 다음 권장 사항 + +- [**Stable 엔터프라이즈 SDK**](/ko/explanation/enterprise-sdk): 레일이 무엇이며 언제 사용해야 하는지. +- [**가스 면제 프로토콜**](/ko/reference/gas-waiver-api): 트랜잭션 형식, 마커 라우팅 및 거버넌스 제어. +- [**보장된 블록 공간**](/ko/explanation/guaranteed-blockspace): Stable이 엔터프라이즈 워크로드에 대한 블록 용량을 예약하는 방법. diff --git a/docs/sidebar.json b/docs/sidebar.json index 37afa51..0b96d7f 100644 --- a/docs/sidebar.json +++ b/docs/sidebar.json @@ -717,11 +717,11 @@ "link": "/ko/explanation/finality" }, { - "text": "가스 가격 책정", + "text": "가스 가격", "link": "/ko/explanation/gas-pricing" }, { - "text": "가스 가격 책정 API", + "text": "가스 가격 API", "link": "/ko/reference/gas-pricing-api" }, { @@ -747,7 +747,7 @@ "link": "/ko/explanation/usdt0-bridging" }, { - "text": "브릿지 보안", + "text": "브리지 보안", "link": "/ko/explanation/bridge-security" }, { @@ -811,19 +811,19 @@ "collapsed": true, "items": [ { - "text": "결제 사용 사례", + "text": "사용 사례: 결제", "link": "/ko/explanation/use-case-payments" }, { - "text": "급여 사용 사례", + "text": "사용 사례: 급여", "link": "/ko/explanation/use-case-payroll" }, { - "text": "스폰서 사용 사례", + "text": "사용 사례: 스폰서", "link": "/ko/explanation/use-case-sponsored" }, { - "text": "개인 사용 사례", + "text": "사용 사례: 프라이빗", "link": "/ko/explanation/use-case-private" } ] @@ -867,7 +867,7 @@ "link": "/ko/tutorial/sdk-quickstart" }, { - "text": "레퍼런스", + "text": "참조", "link": "/ko/reference/sdk" }, { @@ -884,6 +884,20 @@ } ] }, + { + "text": "엔터프라이즈 SDK", + "collapsed": true, + "items": [ + { + "text": "개요", + "link": "/ko/explanation/enterprise-sdk" + }, + { + "text": "참조", + "link": "/ko/reference/enterprise-sdk" + } + ] + }, { "text": "사용자 온보딩", "collapsed": true, @@ -893,11 +907,11 @@ "link": "/ko/explanation/accounts-overview" }, { - "text": "계정 색인", + "text": "계정 인덱스", "link": "/ko/explanation/accounts-guides" }, { - "text": "지갑 생성", + "text": "월렛 생성", "link": "/ko/how-to/create-wallet" }, { @@ -919,7 +933,7 @@ "link": "/ko/explanation/payments-overview" }, { - "text": "결제 색인", + "text": "결제 인덱스", "link": "/ko/explanation/payments-guides" }, { @@ -935,11 +949,11 @@ "link": "/ko/how-to/zero-gas-transactions" }, { - "text": "USDT 가스 작업", + "text": "USDT 가스 사용", "link": "/ko/how-to/work-with-usdt-gas" }, { - "text": "USDT0 브릿지", + "text": "USDT0 브리징", "link": "/ko/tutorial/bridge-usdt0" } ] @@ -957,7 +971,7 @@ "link": "/ko/how-to/subscribe-and-collect" }, { - "text": "송장으로 결제", + "text": "인보이스로 결제", "link": "/ko/how-to/pay-with-invoice" } ] @@ -983,11 +997,11 @@ "link": "/ko/reference/subscriptions" }, { - "text": "송장", + "text": "인보이스", "link": "/ko/reference/invoices" }, { - "text": "호출당 지불", + "text": "통화 당 지불", "link": "/ko/reference/pay-per-call" }, { @@ -1007,7 +1021,7 @@ "link": "/ko/explanation/contracts-overview" }, { - "text": "계약 색인", + "text": "계약 인덱스", "link": "/ko/explanation/contracts-guides" }, { @@ -1023,7 +1037,7 @@ "link": "/ko/how-to/verify-contract" }, { - "text": "색인 계약", + "text": "계약 색인", "link": "/ko/how-to/index-contract" } ] @@ -1053,11 +1067,11 @@ "link": "/ko/reference/bank-module-api" }, { - "text": "배포 모듈", + "text": "분배 모듈", "link": "/ko/explanation/distribution-module" }, { - "text": "배포 모듈 API", + "text": "분배 모듈 API", "link": "/ko/reference/distribution-module-api" }, { @@ -1081,7 +1095,7 @@ "link": "/ko/how-to/track-unbonding" }, { - "text": "유효성 검사기 데이터 색인", + "text": "검증자 데이터 색인", "link": "/ko/how-to/index-validator-data" } ] @@ -1175,7 +1189,7 @@ "collapsed": true, "items": [ { - "text": "브릿지", + "text": "브리지", "link": "/ko/reference/bridges" }, { @@ -1199,11 +1213,11 @@ "link": "/ko/reference/ramps" }, { - "text": "지갑", + "text": "월렛", "link": "/ko/reference/wallets" }, { - "text": "수호", + "text": "수탁", "link": "/ko/reference/custody" }, { @@ -1213,7 +1227,7 @@ ] }, { - "text": "생산 준비", + "text": "운영 준비 완료", "link": "/ko/how-to/production-readiness" }, { @@ -1241,7 +1255,7 @@ "link": "/ko/reference/node-operations-overview" }, { - "text": "노드 시스템 요구 사항", + "text": "노드 시스템 요구사항", "link": "/ko/reference/node-system-requirements" }, { @@ -1257,7 +1271,7 @@ "link": "/ko/how-to/use-node-snapshots" }, { - "text": "유효성 검사기 실행", + "text": "검증자 실행", "link": "/ko/how-to/run-validator" }, { @@ -1283,11 +1297,11 @@ "link": "/ko/explanation/agent-settlement" }, { - "text": "AI 에이전트 색인", + "text": "AI 에이전트 인덱스", "link": "/ko/explanation/ai-agents-guides" }, { - "text": "x402 및 MPP를 통한 지불", + "text": "x402 및 MPP를 통한 결제", "collapsed": true, "items": [ { @@ -1303,7 +1317,7 @@ "link": "/ko/explanation/mpp-sessions" }, { - "text": "호출당 지불 구축", + "text": "통화 당 지불 구축", "link": "/ko/how-to/build-pay-per-call" }, { @@ -1321,7 +1335,7 @@ "collapsed": true, "items": [ { - "text": "AI로 개발", + "text": "AI를 이용한 개발", "link": "/ko/how-to/develop-with-ai" }, { @@ -1329,7 +1343,7 @@ "link": "/ko/reference/agentic-facilitators" }, { - "text": "에이전틱 지갑", + "text": "에이전틱 월렛", "link": "/ko/reference/agentic-wallets" } ] @@ -1363,7 +1377,7 @@ "link": "/cn/explanation/core-concepts" }, { - "text": "主要特点", + "text": "主要功能", "link": "/cn/explanation/key-features" }, { @@ -1405,15 +1419,15 @@ "link": "/cn/explanation/flow-of-funds" }, { - "text": "USDT0 跨链桥接", + "text": "USDT0 跨链桥", "link": "/cn/explanation/usdt0-bridging" }, { - "text": "桥接安全性", + "text": "跨链桥安全性", "link": "/cn/explanation/bridge-security" }, { - "text": "将 USDT0 作为 Gas 代币", + "text": "USDT 作为 Gas 代币", "link": "/cn/explanation/usdt-as-gas-token" }, { @@ -1421,7 +1435,7 @@ "link": "/cn/explanation/usdt0-behavior" }, { - "text": "Gas 豁免", + "text": "Gas 减免", "link": "/cn/explanation/gas-waiver" }, { @@ -1429,7 +1443,7 @@ "link": "/cn/explanation/guaranteed-blockspace" }, { - "text": "USDT0 转账聚合器", + "text": "USDT 转账聚合器", "link": "/cn/explanation/usdt-transfer-aggregator" }, { @@ -1455,7 +1469,7 @@ "link": "/cn/explanation/execution" }, { - "text": "Stable 数据库", + "text": "Stable DB", "link": "/cn/explanation/stable-db" }, { @@ -1473,19 +1487,19 @@ "collapsed": true, "items": [ { - "text": "支付用例", + "text": "用例:支付", "link": "/cn/explanation/use-case-payments" }, { - "text": "薪资用例", + "text": "用例:工资", "link": "/cn/explanation/use-case-payroll" }, { - "text": "赞助用例", + "text": "用例:赞助", "link": "/cn/explanation/use-case-sponsored" }, { - "text": "隐私用例", + "text": "用例:隐私", "link": "/cn/explanation/use-case-private" } ] @@ -1513,7 +1527,7 @@ "link": "/cn/explanation/build-overview" }, { - "text": "快速开始", + "text": "快速入门", "link": "/cn/tutorial/quick-start" }, { @@ -1547,7 +1561,21 @@ ] }, { - "text": "引导用户", + "text": "企业 SDK", + "collapsed": true, + "items": [ + { + "text": "概览", + "link": "/cn/explanation/enterprise-sdk" + }, + { + "text": "参考", + "link": "/cn/reference/enterprise-sdk" + } + ] + }, + { + "text": "用户 onboarding", "collapsed": true, "items": [ { @@ -1597,7 +1625,7 @@ "link": "/cn/how-to/zero-gas-transactions" }, { - "text": "使用 USDT Gas", + "text": "使用 USDT 作为 Gas", "link": "/cn/how-to/work-with-usdt-gas" }, { @@ -1619,7 +1647,7 @@ "link": "/cn/how-to/subscribe-and-collect" }, { - "text": "凭发票支付", + "text": "使用发票支付", "link": "/cn/how-to/pay-with-invoice" } ] @@ -1673,7 +1701,7 @@ "link": "/cn/explanation/contracts-guides" }, { - "text": "部署第一个合约", + "text": "部署你的第一个合约", "collapsed": true, "items": [ { @@ -1739,11 +1767,11 @@ "link": "/cn/reference/system-transactions-api" }, { - "text": "追踪解除绑定", + "text": "跟踪解除绑定", "link": "/cn/how-to/track-unbonding" }, { - "text": "索引验证者数据", + "text": "索引验证器数据", "link": "/cn/how-to/index-validator-data" } ] @@ -1815,19 +1843,19 @@ ] }, { - "text": "Gas 豁免服务", + "text": "Gas 减免服务", "collapsed": true, "items": [ { - "text": "集成 Gas 豁免", + "text": "集成 Gas 减免", "link": "/cn/how-to/integrate-gas-waiver" }, { - "text": "自托管 Gas 豁免", + "text": "自托管 Gas 减免", "link": "/cn/how-to/self-hosted-gas-waiver" }, { - "text": "Gas 豁免 API", + "text": "Gas 减免 API", "link": "/cn/reference/gas-waiver-api" } ] @@ -1837,11 +1865,11 @@ "collapsed": true, "items": [ { - "text": "桥", + "text": "跨链桥", "link": "/cn/reference/bridges" }, { - "text": "去中心化交易所", + "text": "DEX", "link": "/cn/reference/dexes" }, { @@ -1857,7 +1885,7 @@ "link": "/cn/reference/network-routing" }, { - "text": "出入金通道", + "text": "法币通道", "link": "/cn/reference/ramps" }, { @@ -1919,7 +1947,7 @@ "link": "/cn/how-to/use-node-snapshots" }, { - "text": "运行验证者", + "text": "运行验证器", "link": "/cn/how-to/run-validator" }, { @@ -1931,7 +1959,7 @@ "link": "/cn/how-to/monitor-node" }, { - "text": "节点故障排除", + "text": "故障排除节点", "link": "/cn/how-to/troubleshoot-node" } ] @@ -1953,7 +1981,7 @@ "collapsed": true, "items": [ { - "text": "X402", + "text": "x402", "link": "/cn/explanation/x402" }, { @@ -1973,7 +2001,7 @@ "link": "/cn/how-to/build-mpp-endpoint" }, { - "text": "使用 MCP 支付", + "text": "通过 MCP 支付", "link": "/cn/how-to/pay-with-mcp" } ] @@ -1987,7 +2015,7 @@ "link": "/cn/how-to/develop-with-ai" }, { - "text": "代理协调器", + "text": "代理协调者", "link": "/cn/reference/agentic-facilitators" }, { From e57805ea30248ab75da69ed8c79403c4bebe664f Mon Sep 17 00:00:00 2001 From: bastienrp Date: Mon, 13 Jul 2026 17:07:03 +0200 Subject: [PATCH 03/20] docs: add Gas Waiver and Guaranteed Blockspace to Enterprise SDK menu Co-Authored-By: Claude Opus 4.8 --- docs/sidebar.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/sidebar.json b/docs/sidebar.json index 0b96d7f..1e2f26f 100644 --- a/docs/sidebar.json +++ b/docs/sidebar.json @@ -216,6 +216,14 @@ "text": "Overview", "link": "/en/explanation/enterprise-sdk" }, + { + "text": "Gas Waiver", + "link": "/en/explanation/gas-waiver" + }, + { + "text": "Guaranteed Blockspace", + "link": "/en/explanation/guaranteed-blockspace" + }, { "text": "Reference", "link": "/en/reference/enterprise-sdk" From c198dbcbf8efb06262f4094402a7925da638fbf3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 13 Jul 2026 15:07:56 +0000 Subject: [PATCH 04/20] i18n: auto-translate cn/ko for changed en content --- docs/sidebar.json | 162 +++++++++++++++++++++++++--------------------- 1 file changed, 89 insertions(+), 73 deletions(-) diff --git a/docs/sidebar.json b/docs/sidebar.json index 1e2f26f..1c05f52 100644 --- a/docs/sidebar.json +++ b/docs/sidebar.json @@ -755,11 +755,11 @@ "link": "/ko/explanation/usdt0-bridging" }, { - "text": "브리지 보안", + "text": "브릿지 보안", "link": "/ko/explanation/bridge-security" }, { - "text": "가스 토큰으로서의 USDT", + "text": "Gas 토큰으로서의 USDT", "link": "/ko/explanation/usdt-as-gas-token" }, { @@ -789,7 +789,7 @@ "collapsed": true, "items": [ { - "text": "코어 최적화 개요", + "text": "핵심 최적화 개요", "link": "/ko/explanation/core-optimization-overview" }, { @@ -815,23 +815,23 @@ ] }, { - "text": "사용 사례 내러티브", + "text": "사용 사례 설명", "collapsed": true, "items": [ { - "text": "사용 사례: 결제", + "text": "결제 사용 사례", "link": "/ko/explanation/use-case-payments" }, { - "text": "사용 사례: 급여", + "text": "급여 사용 사례", "link": "/ko/explanation/use-case-payroll" }, { - "text": "사용 사례: 스폰서", + "text": "스폰서 사용 사례", "link": "/ko/explanation/use-case-sponsored" }, { - "text": "사용 사례: 프라이빗", + "text": "프라이빗 사용 사례", "link": "/ko/explanation/use-case-private" } ] @@ -875,7 +875,7 @@ "link": "/ko/tutorial/sdk-quickstart" }, { - "text": "참조", + "text": "참고 자료", "link": "/ko/reference/sdk" }, { @@ -901,7 +901,15 @@ "link": "/ko/explanation/enterprise-sdk" }, { - "text": "참조", + "text": "가스 면제", + "link": "/ko/explanation/gas-waiver" + }, + { + "text": "보장된 블록 공간", + "link": "/ko/explanation/guaranteed-blockspace" + }, + { + "text": "참고 자료", "link": "/ko/reference/enterprise-sdk" } ] @@ -915,11 +923,11 @@ "link": "/ko/explanation/accounts-overview" }, { - "text": "계정 인덱스", + "text": "계정 색인", "link": "/ko/explanation/accounts-guides" }, { - "text": "월렛 생성", + "text": "지갑 생성", "link": "/ko/how-to/create-wallet" }, { @@ -941,7 +949,7 @@ "link": "/ko/explanation/payments-overview" }, { - "text": "결제 인덱스", + "text": "결제 색인", "link": "/ko/explanation/payments-guides" }, { @@ -957,11 +965,11 @@ "link": "/ko/how-to/zero-gas-transactions" }, { - "text": "USDT 가스 사용", + "text": "USDT Gas 작업", "link": "/ko/how-to/work-with-usdt-gas" }, { - "text": "USDT0 브리징", + "text": "USDT0 브릿지", "link": "/ko/tutorial/bridge-usdt0" } ] @@ -1009,7 +1017,7 @@ "link": "/ko/reference/invoices" }, { - "text": "통화 당 지불", + "text": "호출당 지불", "link": "/ko/reference/pay-per-call" }, { @@ -1021,31 +1029,31 @@ ] }, { - "text": "계약 배포", + "text": "스마트 컨트랙트 배포", "collapsed": true, "items": [ { - "text": "계약 개요", + "text": "컨트랙트 개요", "link": "/ko/explanation/contracts-overview" }, { - "text": "계약 인덱스", + "text": "컨트랙트 색인", "link": "/ko/explanation/contracts-guides" }, { - "text": "첫 번째 계약 배포", + "text": "첫 컨트랙트 배포", "collapsed": true, "items": [ { - "text": "스마트 계약", + "text": "스마트 컨트랙트", "link": "/ko/tutorial/smart-contract" }, { - "text": "계약 확인", + "text": "컨트랙트 확인", "link": "/ko/how-to/verify-contract" }, { - "text": "계약 색인", + "text": "컨트랙트 색인", "link": "/ko/how-to/index-contract" } ] @@ -1103,7 +1111,7 @@ "link": "/ko/how-to/track-unbonding" }, { - "text": "검증자 데이터 색인", + "text": "검증인 데이터 색인", "link": "/ko/how-to/index-validator-data" } ] @@ -1197,11 +1205,11 @@ "collapsed": true, "items": [ { - "text": "브리지", + "text": "브릿지", "link": "/ko/reference/bridges" }, { - "text": "덱스", + "text": "DEX", "link": "/ko/reference/dexes" }, { @@ -1217,15 +1225,15 @@ "link": "/ko/reference/network-routing" }, { - "text": "램프", + "text": "온/오프 램프", "link": "/ko/reference/ramps" }, { - "text": "월렛", + "text": "지갑", "link": "/ko/reference/wallets" }, { - "text": "수탁", + "text": "커스터디", "link": "/ko/reference/custody" }, { @@ -1243,7 +1251,7 @@ "link": "/ko/reference/developer-assistance" }, { - "text": "자료", + "text": "리소스", "collapsed": true, "items": [ { @@ -1263,7 +1271,7 @@ "link": "/ko/reference/node-operations-overview" }, { - "text": "노드 시스템 요구사항", + "text": "노드 시스템 요구 사항", "link": "/ko/reference/node-system-requirements" }, { @@ -1279,7 +1287,7 @@ "link": "/ko/how-to/use-node-snapshots" }, { - "text": "검증자 실행", + "text": "검증인 실행", "link": "/ko/how-to/run-validator" }, { @@ -1305,15 +1313,15 @@ "link": "/ko/explanation/agent-settlement" }, { - "text": "AI 에이전트 인덱스", + "text": "AI 에이전트 색인", "link": "/ko/explanation/ai-agents-guides" }, { - "text": "x402 및 MPP를 통한 결제", + "text": "x402 및 MPP로 결제", "collapsed": true, "items": [ { - "text": "X402", + "text": "x402", "link": "/ko/explanation/x402" }, { @@ -1325,7 +1333,7 @@ "link": "/ko/explanation/mpp-sessions" }, { - "text": "통화 당 지불 구축", + "text": "호출당 지불 구축", "link": "/ko/how-to/build-pay-per-call" }, { @@ -1343,15 +1351,15 @@ "collapsed": true, "items": [ { - "text": "AI를 이용한 개발", + "text": "AI로 개발", "link": "/ko/how-to/develop-with-ai" }, { - "text": "에이전틱 촉진자", + "text": "자율 촉진자", "link": "/ko/reference/agentic-facilitators" }, { - "text": "에이전틱 월렛", + "text": "자율 지갑", "link": "/ko/reference/agentic-wallets" } ] @@ -1427,11 +1435,11 @@ "link": "/cn/explanation/flow-of-funds" }, { - "text": "USDT0 跨链桥", + "text": "USDT0 跨链", "link": "/cn/explanation/usdt0-bridging" }, { - "text": "跨链桥安全性", + "text": "跨链安全", "link": "/cn/explanation/bridge-security" }, { @@ -1443,19 +1451,19 @@ "link": "/cn/explanation/usdt0-behavior" }, { - "text": "Gas 减免", + "text": "Gas 豁免", "link": "/cn/explanation/gas-waiver" }, { - "text": "保证区块空间", + "text": "保障区块空间", "link": "/cn/explanation/guaranteed-blockspace" }, { - "text": "USDT 转账聚合器", + "text": "USDT 传输聚合器", "link": "/cn/explanation/usdt-transfer-aggregator" }, { - "text": "保密转账", + "text": "保密传输", "link": "/cn/explanation/confidential-transfer" } ] @@ -1535,7 +1543,7 @@ "link": "/cn/explanation/build-overview" }, { - "text": "快速入门", + "text": "快速开始", "link": "/cn/tutorial/quick-start" }, { @@ -1569,13 +1577,21 @@ ] }, { - "text": "企业 SDK", + "text": "企业级 SDK", "collapsed": true, "items": [ { "text": "概览", "link": "/cn/explanation/enterprise-sdk" }, + { + "text": "Gas 豁免", + "link": "/cn/explanation/gas-waiver" + }, + { + "text": "保障区块空间", + "link": "/cn/explanation/guaranteed-blockspace" + }, { "text": "参考", "link": "/cn/reference/enterprise-sdk" @@ -1583,7 +1599,7 @@ ] }, { - "text": "用户 onboarding", + "text": "用户引导", "collapsed": true, "items": [ { @@ -1609,7 +1625,7 @@ ] }, { - "text": "接受付款", + "text": "接受支付", "collapsed": true, "items": [ { @@ -1633,7 +1649,7 @@ "link": "/cn/how-to/zero-gas-transactions" }, { - "text": "使用 USDT 作为 Gas", + "text": "使用 USDT Gas", "link": "/cn/how-to/work-with-usdt-gas" }, { @@ -1655,7 +1671,7 @@ "link": "/cn/how-to/subscribe-and-collect" }, { - "text": "使用发票支付", + "text": "发票支付", "link": "/cn/how-to/pay-with-invoice" } ] @@ -1685,7 +1701,7 @@ "link": "/cn/reference/invoices" }, { - "text": "按次付费", + "text": "按次计费", "link": "/cn/reference/pay-per-call" }, { @@ -1697,7 +1713,7 @@ ] }, { - "text": "部署合约", + "text": "发布合约", "collapsed": true, "items": [ { @@ -1709,7 +1725,7 @@ "link": "/cn/explanation/contracts-guides" }, { - "text": "部署你的第一个合约", + "text": "部署您的第一个合约", "collapsed": true, "items": [ { @@ -1775,7 +1791,7 @@ "link": "/cn/reference/system-transactions-api" }, { - "text": "跟踪解除绑定", + "text": "追踪解绑", "link": "/cn/how-to/track-unbonding" }, { @@ -1851,19 +1867,19 @@ ] }, { - "text": "Gas 减免服务", + "text": "Gas 豁免服务", "collapsed": true, "items": [ { - "text": "集成 Gas 减免", + "text": "集成 Gas 豁免", "link": "/cn/how-to/integrate-gas-waiver" }, { - "text": "自托管 Gas 减免", + "text": "自托管 Gas 豁免", "link": "/cn/how-to/self-hosted-gas-waiver" }, { - "text": "Gas 减免 API", + "text": "Gas 豁免 API", "link": "/cn/reference/gas-waiver-api" } ] @@ -1873,7 +1889,7 @@ "collapsed": true, "items": [ { - "text": "跨链桥", + "text": "桥", "link": "/cn/reference/bridges" }, { @@ -1893,7 +1909,7 @@ "link": "/cn/reference/network-routing" }, { - "text": "法币通道", + "text": "兑换", "link": "/cn/reference/ramps" }, { @@ -1931,11 +1947,11 @@ ] }, { - "text": "操作", + "text": "运维", "collapsed": true, "items": [ { - "text": "节点操作概览", + "text": "节点运维概览", "link": "/cn/reference/node-operations-overview" }, { @@ -1967,21 +1983,21 @@ "link": "/cn/how-to/monitor-node" }, { - "text": "故障排除节点", + "text": "节点故障排除", "link": "/cn/how-to/troubleshoot-node" } ] }, { - "text": "[代理]", + "text": "[Agents]", "collapsed": true, "items": [ { - "text": "代理结算", + "text": "Agent 结算", "link": "/cn/explanation/agent-settlement" }, { - "text": "AI 代理索引", + "text": "AI Agents 索引", "link": "/cn/explanation/ai-agents-guides" }, { @@ -1989,7 +2005,7 @@ "collapsed": true, "items": [ { - "text": "x402", + "text": "X402", "link": "/cn/explanation/x402" }, { @@ -2001,7 +2017,7 @@ "link": "/cn/explanation/mpp-sessions" }, { - "text": "构建按次付费", + "text": "构建按次计费", "link": "/cn/how-to/build-pay-per-call" }, { @@ -2015,19 +2031,19 @@ ] }, { - "text": "代理基础设施", + "text": "Agent 基础设施", "collapsed": true, "items": [ { - "text": "使用 AI 开发", + "text": "使用 AI 进行开发", "link": "/cn/how-to/develop-with-ai" }, { - "text": "代理协调者", + "text": "Agentc 协调者", "link": "/cn/reference/agentic-facilitators" }, { - "text": "代理钱包", + "text": "Agentc 钱包", "link": "/cn/reference/agentic-wallets" } ] From 956c9e7e302ea8190a51bee570ddb36b43b3bbe0 Mon Sep 17 00:00:00 2001 From: bastienrp Date: Mon, 13 Jul 2026 17:17:11 +0200 Subject: [PATCH 05/20] docs: add Enterprise SDK how-to guides and feature naming Add task-focused implementation guides modeled on the Stable SDK Earn yield page: relay-with-gas-waiver and send-guaranteed-transactions (which also covers the combined guaranteed relay transactions flow). Point the Enterprise SDK menu's Gas Waiver and Guaranteed Blockspace items at these guides. List the three features by name in the overview and reference. Reiterate testnet-only, on-request availability. Co-Authored-By: Claude Opus 4.8 --- docs/pages/en/explanation/enterprise-sdk.mdx | 14 +- .../pages/en/how-to/relay-with-gas-waiver.mdx | 151 ++++++++++++++++ .../how-to/send-guaranteed-transactions.mdx | 170 ++++++++++++++++++ docs/pages/en/reference/enterprise-sdk.mdx | 22 +-- docs/sidebar.json | 4 +- 5 files changed, 341 insertions(+), 20 deletions(-) create mode 100644 docs/pages/en/how-to/relay-with-gas-waiver.mdx create mode 100644 docs/pages/en/how-to/send-guaranteed-transactions.mdx diff --git a/docs/pages/en/explanation/enterprise-sdk.mdx b/docs/pages/en/explanation/enterprise-sdk.mdx index c851ff0..3925dc6 100644 --- a/docs/pages/en/explanation/enterprise-sdk.mdx +++ b/docs/pages/en/explanation/enterprise-sdk.mdx @@ -28,13 +28,13 @@ The call returns `H_inner`, the hash of the user's transaction, not the wrapper ## What the SDK does -The SDK exposes three modules. Each is optional and independently configured, and each carries its own signing account so you can use separate keys. +The SDK exposes three features, one per module. Each is optional and independently configured, and each carries its own signing account so you can use separate keys. -- **`gasWaiver`**: build, sign, and relay a gas-waived transaction. A whitelisted waiver account wraps a user's zero-gas transaction so the user transacts without holding any USDT0. See [Gas waiver](/en/explanation/gas-waiver). -- **`guaranteedBlock`**: relay a GuaranteedTx through the Enterprise RPC gateway so it lands in reserved Enterprise-lane blockspace. Unlike gas waiver, the signer pays its own gas. See [Guaranteed blockspace](/en/explanation/guaranteed-blockspace). -- **`guaranteedWaiver`**: the composition of both. A gas-waived transaction routed through guaranteed blockspace, so the user needs no balance and the transaction still lands in the Enterprise lane. +- **Relay with gas waiver** (`gasWaiver`): build, sign, and relay a gas-waived transaction. A whitelisted waiver account wraps a user's zero-gas transaction so the user transacts without holding any USDT0. See [Gas waiver](/en/explanation/gas-waiver). +- **Guaranteed blockspace** (`guaranteedBlock`): relay a transaction through the Enterprise RPC gateway so it lands in reserved Enterprise-lane blockspace. Unlike gas waiver, the signer pays its own gas. See [Guaranteed blockspace](/en/explanation/guaranteed-blockspace). +- **Guaranteed relay transactions** (`guaranteedWaiver`): both combined. A gas-waived transaction routed through guaranteed blockspace, so the user needs no balance and the transaction still lands in the Enterprise lane. -Every module offers the same four methods: `send` and `sendBatch` for the custodial path where the SDK signs, and `relay` and `relayBatch` for the non-custodial path where the user signs elsewhere and hands you only the signed hex. +Every feature offers the same four methods: `send` and `sendBatch` for the custodial path where the SDK signs, and `relay` and `relayBatch` for the non-custodial path where the user signs elsewhere and hands you only the signed hex. ## Access @@ -56,9 +56,9 @@ Reach for the Enterprise SDK when you operate a backend and want to sponsor user ## Start here +- [**Relay with gas waiver**](/en/how-to/relay-with-gas-waiver): Sponsor a user's gas so they transact without holding USDT0. +- [**Send guaranteed transactions**](/en/how-to/send-guaranteed-transactions): Land transactions in reserved Enterprise-lane blockspace, and combine it with gas waiver. - [**Enterprise SDK reference**](/en/reference/enterprise-sdk): Every module, method, config option, and error class. -- [**Gas waiver**](/en/explanation/gas-waiver): How zero-gas transactions work at the protocol level. -- [**Guaranteed blockspace**](/en/explanation/guaranteed-blockspace): How Stable reserves block capacity for enterprise workloads. ## Next recommended diff --git a/docs/pages/en/how-to/relay-with-gas-waiver.mdx b/docs/pages/en/how-to/relay-with-gas-waiver.mdx new file mode 100644 index 0000000..b123789 --- /dev/null +++ b/docs/pages/en/how-to/relay-with-gas-waiver.mdx @@ -0,0 +1,151 @@ +--- +title: "Relay with gas waiver" +description: "Sponsor a user's gas with the Enterprise SDK: relay a zero-gas transaction, batch relays, enforce policy limits, and relay pre-signed transactions." +diataxis: "how-to" +--- + +# Relay with gas waiver + +Sponsor your users' gas with `@stablechain/enterprise`. A whitelisted waiver account wraps a user's zero-gas transaction (the InnerTx) and broadcasts it, so the user transacts without holding any USDT0. The `gasWaiver` module builds, signs, and relays in one call, so you call one method per action. + +Every method returns `H_inner`, the hash of the user's transaction, not the wrapper that carried it. + +## Prerequisites + +- Node.js 20 or later, and `@stablechain/enterprise` plus `viem` installed. See the [Enterprise SDK reference](/en/reference/enterprise-sdk#install). +- A governance-registered waiver key. The Enterprise SDK is testnet only for now, and access is gated: [contact Stable](https://discord.gg/stablexyz) to get a whitelisted waiver key. + +:::warning +This is a server-side library that signs with private keys. Never run it in a browser. Keep the waiver key on your backend. +::: + +## 1. Create a client with the gas waiver module + +Pass `gasWaiver: { account }` to `createStableEnterprise`, where `account` is your whitelisted waiver key. The module is present on the client only when you configure it. + +```ts +import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; +import { privateKeyToAccount } from "viem/accounts"; + +const enterprise = createStableEnterprise({ + chain: stableTestnet, + gasWaiver: { account: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`) }, +}); + +const gw = enterprise.gasWaiver!; +``` + +```text +StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver: undefined } +``` + +The `rpcEndpoints` option is optional. Left unset, the client uses the chain's built-in RPC. + +## 2. Relay a single transaction + +Call `send` with the user's account and the fields that vary. The `gasPrice: 0`, legacy type, `chainId`, and pending nonce are handled for you, so you pass only `to`, and optionally `data`, `value`, and `gas`. + +```ts +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); +``` + +```text +H_inner: 0x8f3a...2d41 +``` + +The user needs no USDT0: the waiver account sponsors the gas. `gas` defaults to `150_000n` (`DEFAULT_INNER_GAS`), which covers a token transfer or approval. Pass an explicit `gas` for heavier calls. + +## 3. Relay a batch + +Call `sendBatch` to relay several transactions from one account. Nonces are auto-sequenced from the account's pending nonce, and you get one result per input, in input order. + +```ts +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}`); +} +``` + +```text +[0] ✔ 0x8f3a...2d41 +[1] ✔ 0x2b7c...9e04 +``` + +A batch reports failures per item in `result.error` instead of throwing, so one bad transaction doesn't sink the rest. + +## 4. Enforce per-partner policy limits + +Restrict what the waiver key may sponsor by adding policy limits to the config. An InnerTx that violates a limit is rejected before broadcast. + +```ts +const enterprise = createStableEnterprise({ + chain: stableTestnet, + gasWaiver: { + account: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`), + maxGasLimit: 500_000n, + maxDataLength: 4_096, + allowedTargets: [ + { address: token, selectors: ["0xa9059cbb"] }, // ERC-20 transfer only + ], + }, +}); +``` + +A transaction to a contract outside `allowedTargets` fails with `TARGET_NOT_ALLOWED`; one over `maxGasLimit` fails with `GAS_LIMIT_EXCEEDED`. Use `"*"` as the `address` to allow any contract, and omit `selectors` to allow any method. + +## 5. Relay a pre-signed transaction + +For a non-custodial flow, the user signs the InnerTx in their own environment and hands you only the signed hex, so you never see their key. Build it with `buildWaiverInnerTx`, then relay it with `relay`. + +```ts +import { buildWaiverInnerTx } from "@stablechain/enterprise"; + +// on the user's side +const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to: token, data, gas: 150_000n, nonce }); + +// on your backend +const { txHash } = await gw.relay(signed); +console.log("H_inner:", txHash); +``` + +```text +H_inner: 0x8f3a...2d41 +``` + +For several pre-signed transactions, use `relayBatch`, which returns one result per input like `sendBatch`. + +## Handle rejections + +`send` and `relay` throw `StableEnterpriseRelayError` on rejection, carrying a `code` you can branch on. + +```ts +import { StableEnterpriseRelayError } from "@stablechain/enterprise"; + +try { + await gw.send(user, { to: token, data }); +} catch (err) { + if (err instanceof StableEnterpriseRelayError && err.code === "TARGET_NOT_ALLOWED") { + // the InnerTx target is outside the configured allowlist + } + throw err; +} +``` + +```text +StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not allowed +``` + +See the full [`ErrorCode`](/en/reference/enterprise-sdk#errorcode) table for every rejection reason. + +## Where to go next + +- [**Send guaranteed transactions**](/en/how-to/send-guaranteed-transactions): Land transactions in reserved Enterprise-lane blockspace, and combine it with gas waiver. +- [**Enterprise SDK reference**](/en/reference/enterprise-sdk#relay-with-gas-waiver): Every method, config option, and error class in full. +- [**Gas waiver**](/en/explanation/gas-waiver): How zero-gas transactions work at the protocol level. diff --git a/docs/pages/en/how-to/send-guaranteed-transactions.mdx b/docs/pages/en/how-to/send-guaranteed-transactions.mdx new file mode 100644 index 0000000..22dc49f --- /dev/null +++ b/docs/pages/en/how-to/send-guaranteed-transactions.mdx @@ -0,0 +1,170 @@ +--- +title: "Send guaranteed transactions" +description: "Land transactions in reserved Enterprise-lane blockspace with the Enterprise SDK, and combine guaranteed blockspace with gas waiver to relay them gas-free." +diataxis: "how-to" +--- + +# Send guaranteed transactions + +Route transactions through reserved Enterprise-lane blockspace with `@stablechain/enterprise`. The `guaranteedBlock` module relays a GuaranteedTx (a type `0x3F` CustomTx) through the Enterprise RPC gateway so it lands in capacity reserved for enterprise workloads. Unlike gas waiver, the signer pays its own gas, so it must be funded. + +You can combine this with gas waiver to get [guaranteed relay transactions](#combine-with-gas-waiver): gas-waived transactions that still land in the Enterprise lane. + +## Prerequisites + +- Node.js 20 or later, and `@stablechain/enterprise` plus `viem` installed. See the [Enterprise SDK reference](/en/reference/enterprise-sdk#install). +- An Enterprise RPC gateway API key. The Enterprise SDK is testnet only for now, and access is gated: [contact Stable](https://discord.gg/stablexyz) to get a gateway endpoint. +- A funded signer, since a GuaranteedTx pays its own gas. + +:::warning +This is a server-side library. Keep the Enterprise RPC gateway URL on your backend: it embeds your API key. +::: + +## 1. Create a client with the guaranteed blockspace module + +Pass `guaranteedBlock` and `enterpriseRpcEndpoints` to `createStableEnterprise`. The gateway is the only endpoint that admits `0x3F` GuaranteedTxs, and it holds your API key. An invalid `laneId` is rejected up front. + +```ts +import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; +import { privateKeyToAccount } from "viem/accounts"; + +const enterprise = createStableEnterprise({ + chain: stableTestnet, + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // the gateway URL Stable provisions + guaranteedBlock: { + account: privateKeyToAccount(process.env.SIGNER_PRIVATE_KEY as `0x${string}`), // must be funded + laneId: 0n, // Enterprise lane + }, +}); + +const gb = enterprise.guaranteedBlock!; +``` + +```text +StableEnterpriseClient { gasWaiver: undefined, guaranteedBlock, guaranteedWaiver: undefined } +``` + +## 2. Send a single transaction + +Call `send` with the signer and the varying fields. The 1559 fee fields are required because the signer pays gas. The `chainId`, the Enterprise `nonceKey`, and the 2D nonce (discovered from the gateway) are handled for you. + +```ts +import { createPublicClient, http } from "viem"; + +const publicClient = createPublicClient({ chain: stableTestnet, transport: http() }); +const gasPrice = await publicClient.getGasPrice(); + +const { txHash } = await gb.send(signer, { + to: recipient, + gas: 21_000n, + gasFeeCap: gasPrice * 2n, + gasTipCap: gasPrice, +}); +console.log("Guaranteed tx:", txHash); +``` + +```text +Guaranteed tx: 0xabcd...7890 +``` + +The signer pays gas, so confirm it holds a balance before relaying. A GuaranteedTx from a zero-balance account fails. + +## 3. Send a batch + +Call `sendBatch` to send several transactions. Nonces are auto-sequenced from a discovered base, and you get one result per input, in input order. A failure strands its successors. + +```ts +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 }, +]); + +for (const r of results) { + console.log(r.success ? `[${r.index}] ✔ ${r.txHash}` : `[${r.index}] ✖ ${r.error?.code}`); +} +``` + +```text +[0] ✔ 0xabcd...7890 +[1] ✔ 0x1f2e...66a1 +``` + +## 4. Send a pre-signed transaction + +For a non-custodial flow, build and sign the GuaranteedTx elsewhere with `buildGuaranteedTx`, then hand the operator only the signed hex. The Enterprise nonce key comes from `nonceKeyForLane`. + +```ts +import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; + +const signed = await buildGuaranteedTx(signer, stableTestnet.id, { + to: recipient, + gas: 21_000n, + gasFeeCap, + gasTipCap, + nonce, // the account's current 2D-lane nonce + nonceKey: nonceKeyForLane(0n), // Enterprise lane 0 +}); + +const { txHash } = await gb.relay(signed); +console.log("Guaranteed tx:", txHash); +``` + +```text +Guaranteed tx: 0xabcd...7890 +``` + +For several pre-signed transactions, use `relayBatch`. + +## Combine with gas waiver + +Guaranteed relay transactions compose both rails: a gas-waived transaction routed through guaranteed blockspace. The user needs no balance and no fee fields, and the transaction still lands in the Enterprise lane. Enable it with `guaranteedWaiver`, which takes the whitelisted waiver account plus the lane. + +```ts +const enterprise = createStableEnterprise({ + chain: stableTestnet, + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], + guaranteedWaiver: { + waiverAccount: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`), + laneId: 0n, + }, +}); + +const gw = enterprise.guaranteedWaiver!; + +// gas is waived, so the user needs no balance and no fee fields +const { txHash } = await gw.send(user, { to: recipient }); +console.log("H_inner:", txHash); +``` + +```text +H_inner: 0x8f3a...2d41 +``` + +Like gas waiver, `send` returns `H_inner`, and `sendBatch`, `relay`, and `relayBatch` work the same way. The `guaranteedWaiver` config also accepts the same `allowedTargets`, `maxGasLimit`, and `maxDataLength` policy limits as `gasWaiver`. + +## Handle rejections + +`send` and `relay` throw `StableEnterpriseRelayError` on rejection. Gateway-specific codes include `GATEWAY_UNAUTHORIZED` (a missing or invalid API key) and `QUOTA_EXCEEDED` (the gateway gas quota is exhausted). + +```ts +import { StableEnterpriseRelayError } from "@stablechain/enterprise"; + +try { + await gb.send(signer, { to: recipient, gas: 21_000n, gasFeeCap, gasTipCap }); +} catch (err) { + if (err instanceof StableEnterpriseRelayError && err.code === "GATEWAY_UNAUTHORIZED") { + // the Enterprise RPC gateway rejected the API key + } + throw err; +} +``` + +```text +StableEnterpriseRelayError: relay failed [GATEWAY_UNAUTHORIZED]: invalid api key +``` + +## Where to go next + +- [**Relay with gas waiver**](/en/how-to/relay-with-gas-waiver): Sponsor a user's gas so they transact without holding USDT0. +- [**Enterprise SDK reference**](/en/reference/enterprise-sdk#guaranteed-blockspace): Every method, config option, and error class in full. +- [**Guaranteed blockspace**](/en/explanation/guaranteed-blockspace): How Stable reserves block capacity for enterprise workloads. diff --git a/docs/pages/en/reference/enterprise-sdk.mdx b/docs/pages/en/reference/enterprise-sdk.mdx index b7063f1..2f9f840 100644 --- a/docs/pages/en/reference/enterprise-sdk.mdx +++ b/docs/pages/en/reference/enterprise-sdk.mdx @@ -6,10 +6,10 @@ diataxis: "reference" # Enterprise SDK reference -Full surface of `@stablechain/enterprise`. This covers the client from [`createStableEnterprise`](#createstableenterpriseconfig), its three modules ([gas waiver](#gaswaiver-module), [guaranteed blockspace](#guaranteedblock-module), and [the composed waiver](#guaranteedwaiver-module)), the low-level build helpers, and the shared result and error types. For what these rails are, see [Stable Enterprise SDK](/en/explanation/enterprise-sdk), [Gas waiver](/en/explanation/gas-waiver), and [Guaranteed blockspace](/en/explanation/guaranteed-blockspace). +Full surface of `@stablechain/enterprise`. This covers the client from [`createStableEnterprise`](#createstableenterpriseconfig), its three features ([relay with gas waiver](#relay-with-gas-waiver), [guaranteed blockspace](#guaranteed-blockspace), and [guaranteed relay transactions](#guaranteed-relay-transactions)), the low-level build helpers, and the shared result and error types. For what these rails are, see [Stable Enterprise SDK](/en/explanation/enterprise-sdk), [Gas waiver](/en/explanation/gas-waiver), and [Guaranteed blockspace](/en/explanation/guaranteed-blockspace). :::note -The Enterprise SDK is available on Stable Testnet only, and both rails are gated. To integrate, [contact Stable](https://discord.gg/stablexyz) to get a governance-registered waiver key and an Enterprise RPC gateway API key. +The Enterprise SDK is available on Stable Testnet only for now, and access is on request. To integrate, [contact Stable](https://discord.gg/stablexyz) to get a governance-registered waiver key and an Enterprise RPC gateway API key. ::: :::warning @@ -54,9 +54,9 @@ StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver | `rpcEndpoints` | `string[]?` | Chain's built-in RPC | One or more Stable RPC endpoints, tried in order on failure. Override only to point at a private endpoint. | | `enterpriseRpcEndpoints` | `string[]?` | | One or more Enterprise RPC gateway endpoints, tried in order on failure. Required for `guaranteedBlock` and `guaranteedWaiver`. | | `batchSizeLimit` | `number?` | `100` | Maximum transactions per batched RPC call. | -| `gasWaiver` | `GasWaiverConfig?` | | Enable the [gas waiver module](#gaswaiver-module). | -| `guaranteedBlock` | `GuaranteedBlockConfig?` | | Enable the [guaranteed blockspace module](#guaranteedblock-module). | -| `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | Enable the [composed waiver module](#guaranteedwaiver-module). | +| `gasWaiver` | `GasWaiverConfig?` | | Enable [relay with gas waiver](#relay-with-gas-waiver). | +| `guaranteedBlock` | `GuaranteedBlockConfig?` | | Enable [guaranteed blockspace](#guaranteed-blockspace). | +| `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | Enable [guaranteed relay transactions](#guaranteed-relay-transactions). | ### `StableEnterpriseClient` @@ -68,9 +68,9 @@ interface StableEnterpriseClient { } ``` -## `gasWaiver` module +## Relay with gas waiver -Relay gas-waived transactions. A whitelisted waiver account wraps a user's zero-gas transaction (the InnerTx) into a WaiverTx and broadcasts it. The user needs no USDT0. Every method returns `H_inner`, the InnerTx hash, not the wrapper hash. +The `gasWaiver` module relays gas-waived transactions. A whitelisted waiver account wraps a user's zero-gas transaction (the InnerTx) into a WaiverTx and broadcasts it. The user needs no USDT0. Every method returns `H_inner`, the InnerTx hash, not the wrapper hash. Enable it with `gasWaiver` in the config: @@ -157,9 +157,9 @@ const results = await gw.relayBatch([signed0, signed1]); [ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: false, error: { code: "TARGET_NOT_ALLOWED", message: "..." } } ] ``` -## `guaranteedBlock` module +## Guaranteed blockspace -Relay GuaranteedTx (type `0x3F` CustomTx) through the Enterprise RPC gateway so they land in reserved Enterprise-lane blockspace. Unlike gas waiver, the signer pays its own gas and must be funded. Each transaction carries a 2D nonce keyed to an Enterprise lane, and broadcasting goes only through the gateway. +The `guaranteedBlock` module relays GuaranteedTx (type `0x3F` CustomTx) through the Enterprise RPC gateway so they land in reserved Enterprise-lane blockspace. Unlike gas waiver, the signer pays its own gas and must be funded. Each transaction carries a 2D nonce keyed to an Enterprise lane, and broadcasting goes only through the gateway. Enable it with `guaranteedBlock` plus `enterpriseRpcEndpoints`: @@ -243,9 +243,9 @@ const { txHash } = await gb.relay(signed); { txHash: "0xabcd...7890" } ``` -## `guaranteedWaiver` module +## Guaranteed relay transactions -The composition of the two rails above: a gas-waived transaction routed through guaranteed blockspace. Both the inner and outer transaction are `0x3F` CustomTxs sharing one Enterprise `nonceKey`, so it broadcasts through the gateway like `guaranteedBlock`. The waiver sponsors gas, so the user needs no balance and no fee fields, like `gasWaiver`. Every method returns `H_inner`. +The `guaranteedWaiver` module combines the two rails above: a gas-waived transaction routed through guaranteed blockspace. Both the inner and outer transaction are `0x3F` CustomTxs sharing one Enterprise `nonceKey`, so it broadcasts through the gateway like `guaranteedBlock`. The waiver sponsors gas, so the user needs no balance and no fee fields, like `gasWaiver`. Every method returns `H_inner`. Enable it with `guaranteedWaiver` plus `enterpriseRpcEndpoints`: diff --git a/docs/sidebar.json b/docs/sidebar.json index 1c05f52..1790ce2 100644 --- a/docs/sidebar.json +++ b/docs/sidebar.json @@ -218,11 +218,11 @@ }, { "text": "Gas Waiver", - "link": "/en/explanation/gas-waiver" + "link": "/en/how-to/relay-with-gas-waiver" }, { "text": "Guaranteed Blockspace", - "link": "/en/explanation/guaranteed-blockspace" + "link": "/en/how-to/send-guaranteed-transactions" }, { "text": "Reference", From c81020a3830fc8b5c008d5371048201269bff1ef Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 13 Jul 2026 15:19:53 +0000 Subject: [PATCH 06/20] i18n: auto-translate cn/ko for changed en content --- docs/pages/cn/explanation/enterprise-sdk.mdx | 38 ++-- .../pages/cn/how-to/relay-with-gas-waiver.mdx | 153 ++++++++++++++ .../how-to/send-guaranteed-transactions.mdx | 172 +++++++++++++++ docs/pages/cn/reference/enterprise-sdk.mdx | 192 ++++++++--------- docs/pages/ko/explanation/enterprise-sdk.mdx | 40 ++-- .../pages/ko/how-to/relay-with-gas-waiver.mdx | 153 ++++++++++++++ .../how-to/send-guaranteed-transactions.mdx | 172 +++++++++++++++ docs/pages/ko/reference/enterprise-sdk.mdx | 198 +++++++++--------- docs/sidebar.json | 138 ++++++------ 9 files changed, 953 insertions(+), 303 deletions(-) create mode 100644 docs/pages/cn/how-to/relay-with-gas-waiver.mdx create mode 100644 docs/pages/cn/how-to/send-guaranteed-transactions.mdx create mode 100644 docs/pages/ko/how-to/relay-with-gas-waiver.mdx create mode 100644 docs/pages/ko/how-to/send-guaranteed-transactions.mdx diff --git a/docs/pages/cn/explanation/enterprise-sdk.mdx b/docs/pages/cn/explanation/enterprise-sdk.mdx index c4feb86..94b585d 100644 --- a/docs/pages/cn/explanation/enterprise-sdk.mdx +++ b/docs/pages/cn/explanation/enterprise-sdk.mdx @@ -1,14 +1,14 @@ --- source_path: explanation/enterprise-sdk.mdx -source_sha: c851ff041a812cf877db582b540a0369d4777566 +source_sha: 3925dc600289afa0a771b5b508728ee1b20bcb01 title: "Stable 企业版 SDK" -description: "通过类型化的 @stablechain/enterprise SDK,从您的后端中继免 gas 费和保证区块空间的交易。" +description: "使用类型化的 @stablechain/enterprise SDK 从您的后端中继免 Gas 费和保证区块空间的交易。" diataxis: "explanation" --- # Stable 企业版 SDK -`@stablechain/enterprise` 是 Stable 企业交易轨道的服务器端 TypeScript 客户端。它签署并中继两种特权交易:免 gas 费交易(您为用户的 gas 费提供担保)和保证区块空间交易(它们进入预留的企业通道)。您可以在一个客户端上启用任一轨道,或两者都启用。 +`@stablechain/enterprise` 是一个用于 Stable 企业级交易轨道的服务器端 TypeScript 客户端。它会签署并中继两种特权交易:一种是免 Gas 费交易,由您为用户支付 Gas 费;另一种是保证区块空间交易,它们会进入预留的企业级通道。您可以在一个客户端上启用其中一个或两个轨道。 ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -26,44 +26,44 @@ const { txHash } = await enterprise.gasWaiver!.send(user, { to: token, data }); txHash: 0x8f3a...2d41 ``` -此调用返回 `H_inner`,即用户交易的哈希值,而不是承载它的包装交易的哈希值。 +此调用返回 `H_inner`,即用户交易的哈希值,而不是承载它的包装器交易的哈希值。 -## SDK 的功能 +## SDK 的作用 -SDK 暴露了三个模块。每个模块都是可选的,可以独立配置,并且每个模块都带有自己的签名账户,因此您可以使用不同的密钥。 +SDK 暴露了三个功能,每个模块一个。每个功能都是可选的,可以独立配置,并且每个功能都有自己的签名账户,因此您可以使用单独的密钥。 -- **`gasWaiver`**:构建、签署并中继免 gas 费交易。一个白名单豁免账户包装了用户的零 gas 交易,因此用户在没有持有任何 USDT0 的情况下进行交易。请参阅[Gas 豁免](/cn/explanation/gas-waiver)。 -- **`guaranteedBlock`**:通过企业 RPC 网关中继 GuaranteedTx,使其进入预留的企业通道区块空间。与 gas 豁免不同,签名者支付自己的 gas 费。请参阅[保证区块空间](/cn/explanation/guaranteed-blockspace)。 -- **`guaranteedWaiver`**:两者的组合。通过保证区块空间路由的免 gas 费交易,因此用户无需余额,且交易仍进入企业通道。 +- **免 Gas 费中继** (`gasWaiver`):构建、签署并中继免 Gas 费交易。一个白名单豁免账户会包装用户的零 Gas 交易,以便用户在不持有任何 USDT0 的情况下进行交易。请参阅[免 Gas 费](/cn/explanation/gas-waiver)。 +- **保证区块空间** (`guaranteedBlock`):通过企业版 RPC 网关中继交易,使其进入预留的企业级通道区块空间。与免 Gas 费不同,签名者支付自己的 Gas 费。请参阅[保证区块空间](/cn/explanation/guaranteed-blockspace)。 +- **保证中继交易** (`guaranteedWaiver`):两者结合。通过保证区块空间路由的免 Gas 费交易,因此用户无需余额,交易仍能进入企业级通道。 -每个模块都提供相同的四种方法:`send` 和 `sendBatch` 用于 SDK 签名的托管路径,`relay` 和 `relayBatch` 用于用户在其他地方签名并只向您提供已签名十六进制的非托管路径。 +每个功能都提供相同的四种方法:`send` 和 `sendBatch` 用于 SDK 签名的托管路径,以及 `relay` 和 `relayBatch` 用于用户在其他地方签名并只向您提供签名十六进制字符串的非托管路径。 ## 访问权限 企业版 SDK 目前仅在 Stable 测试网上可用。 -这两个轨道都受限。Gas 豁免需要一个治理注册的豁免密钥,而保证区块空间需要一个企业 RPC 网关 API 密钥。要进行集成,请[联系 Stable](https://discord.gg/stablexyz) 以获取访问权限。Stable 会提供您所需的豁免密钥和网关端点。 +这两个轨道都受限。免 Gas 费需要治理注册的豁免密钥,而保证区块空间需要企业版 RPC 网关 API 密钥。要进行集成,请[联系 Stable](https://discord.gg/stablexyz) 以获取访问权限。Stable 会提供您需要的豁免密钥和网关端点。 ## 仅限服务器端 :::warning -企业版 SDK 是一个无状态的服务器端库,它使用私钥进行签名。切勿在浏览器中运行它。将豁免密钥和企业 RPC 网关 URL 保存在您的后端。 +企业版 SDK 是一个无状态的服务器端库,使用私钥进行签名。切勿在浏览器中运行它。将豁免密钥和企业版 RPC 网关 URL 保留在您的后端。 ::: -豁免密钥是一个白名单,治理注册的账户:任何持有它的人都可以根据您的策略赞助 gas 费。企业 RPC 网关 URL 嵌入了您的 API 密钥。请将两者都视为秘密。 +豁免密钥是一个白名单的、治理注册的账户:任何持有它的人都可以根据您的策略支付 Gas 费。企业版 RPC 网关 URL 嵌入了您的 API 密钥。请将两者都视为秘密。 ## 何时使用它 -当您运营后端并希望为用户赞助 gas 费或保证您的流量被包含时,请使用企业版 SDK。对于日常转账、桥接、交换和来自后端或浏览器的金库收益,请改用通用[Stable SDK](/cn/explanation/sdk-overview)。 +当您运营后端并希望为用户支付 Gas 费或保证自己的流量包含在区块中时,请使用企业版 SDK。对于日常传输、桥接、交换和来自后端或浏览器的资金池收益,请改用通用的 [Stable SDK](/cn/explanation/sdk-overview)。 ## 从这里开始 +- [**免 Gas 费中继**](/cn/how-to/relay-with-gas-waiver):为用户支付 Gas 费,以便他们在不持有 USDT0 的情况下进行交易。 +- [**发送保证交易**](/cn/how-to/send-guaranteed-transactions):将交易放入预留的企业级通道区块空间,并将其与免 Gas 费结合使用。 - [**企业版 SDK 参考**](/cn/reference/enterprise-sdk):每个模块、方法、配置选项和错误类。 -- [**Gas 豁免**](/cn/explanation/gas-waiver):零 gas 费交易如何在协议层面工作。 -- [**保证区块空间**](/cn/explanation/guaranteed-blockspace):Stable 如何为企业工作负载预留区块容量。 -## 下一步建议 +## 下一步推荐 -- [**Gas 豁免协议**](/cn/reference/gas-waiver-api):交易格式、标记路由和治理控制。 -- [**Stable SDK**](/cn/explanation/sdk-overview):用于转账、桥接、交换和收益的通用客户端。 +- [**免 Gas 费协议**](/cn/reference/gas-waiver-api):交易格式、标记路由和治理控制。 +- [**Stable SDK**](/cn/explanation/sdk-overview):用于传输、桥接、交换和收益的通用客户端。 - [**连接到 Stable**](/cn/reference/connect):测试网的链 ID、RPC 端点和浏览器。 diff --git a/docs/pages/cn/how-to/relay-with-gas-waiver.mdx b/docs/pages/cn/how-to/relay-with-gas-waiver.mdx new file mode 100644 index 0000000..d5c03ba --- /dev/null +++ b/docs/pages/cn/how-to/relay-with-gas-waiver.mdx @@ -0,0 +1,153 @@ +--- +source_path: how-to/relay-with-gas-waiver.mdx +source_sha: b123789598d68061ee8cb4472a3ed8d22153b91c +title: "使用 Gas 代付进行中继" +description: "使用 Enterprise SDK 赞助用户的 gas 费用:中继零 gas 交易、批量中继、强制执行策略限制以及中继预签名交易。" +diataxis: "how-to" +--- + +# 使用 Gas 代付进行中继 + +使用 `@stablechain/enterprise` 赞助用户的 gas 费用。列入白名单的代付账户会封装用户的零 gas 交易(InnerTx)并广播,因此用户无需持有任何 USDT0 即可进行交易。`gasWaiver` 模块在一个调用中完成构建、签名和中继,因此每个操作只需调用一个方法。 + +每个方法都返回 `H_inner`,即用户交易的哈希值,而不是承载它的封装器。 + +## 先决条件 + +- Node.js 20 或更高版本,并已安装 `@stablechain/enterprise` 和 `viem`。请参阅 [Enterprise SDK 参考](/cn/reference/enterprise-sdk#install)。 +- 治理注册的代付密钥。Enterprise SDK 目前仅限测试网使用,并且访问受限:请[联系 Stable](https://discord.gg/stablexyz) 以获取列入白名单的代付密钥。 + +:::warning +这是一个使用私钥进行签名的服务器端库。切勿在浏览器中运行。将代付密钥保留在后端。 +::: + +## 1. 使用 Gas 代付模块创建客户端 + +将 `gasWaiver: { account }` 传递给 `createStableEnterprise`,其中 `account` 是您列入白名单的代付密钥。只有在配置后,模块才会在客户端上存在。 + +```ts +import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; +import { privateKeyToAccount } from "viem/accounts"; + +const enterprise = createStableEnterprise({ + chain: stableTestnet, + gasWaiver: { account: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`) }, +}); + +const gw = enterprise.gasWaiver!; +``` + +```text +StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver: undefined } +``` + +`rpcEndpoints` 选项是可选的。如果未设置,客户端将使用链的内置 RPC。 + +## 2. 中继单个交易 + +使用用户账户和可变字段调用 `send`。`gasPrice: 0`、遗留类型、`chainId` 和待处理 nonce 会为您处理,因此您只需传递 `to`,以及可选的 `data`、`value` 和 `gas`。 + +```ts +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); +``` + +```text +H_inner: 0x8f3a...2d41 +``` + +用户不需要 USDT0:代付账户会赞助 gas 费用。`gas` 默认为 `150_000n` (`DEFAULT_INNER_GAS`),足以覆盖代币转账或批准。对于更复杂的调用,请传递明确的 `gas`。 + +## 3. 中继批次 + +调用 `sendBatch` 可以中继来自同一账户的多个交易。Nonce 会根据账户的待处理 nonce 自动排序,并且您会根据输入顺序获得每个输入的结果。 + +```ts +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}`); +} +``` + +```text +[0] ✔ 0x8f3a...2d41 +[1] ✔ 0x2b7c...9e04 +``` + +批处理会报告每个项目的失败情况,而不是抛出异常,因此一个错误的交易不会影响其余交易。 + +## 4. 强制执行每个合作伙伴的策略限制 + +通过向配置添加策略限制,限制代付密钥可以赞助的内容。违反限制的 InnerTx 会在广播前被拒绝。 + +```ts +const enterprise = createStableEnterprise({ + chain: stableTestnet, + 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` 中继。 + +```ts +import { buildWaiverInnerTx } from "@stablechain/enterprise"; + +// 在用户端 +const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to: token, data, gas: 150_000n, nonce }); + +// 在您的后端 +const { txHash } = await gw.relay(signed); +console.log("H_inner:", txHash); +``` + +```text +H_inner: 0x8f3a...2d41 +``` + +对于多个预签名交易,请使用 `relayBatch`,它像 `sendBatch` 一样为每个输入返回一个结果。 + +## 处理拒绝 + +`send` 和 `relay` 在拒绝时会抛出 `StableEnterpriseRelayError`,其中包含一个可供您分支的 `code`。 + +```ts +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; +} +``` + +```text +StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not allowed +``` + +请参阅完整的 [`ErrorCode`](/cn/reference/enterprise-sdk#errorcode) 表格,了解所有拒绝原因。 + +## 下一步 + +- [**发送保证交易**](/cn/how-to/send-guaranteed-transactions):在预留的企业通道区块空间中进行交易,并将其与 gas 代付结合使用。 +- [**Enterprise SDK 参考**](/cn/reference/enterprise-sdk#relay-with-gas-waiver):所有方法、配置选项和错误类的完整说明。 +- [**Gas 代付**](/cn/explanation/gas-waiver):零 gas 交易在协议层面的工作原理。 diff --git a/docs/pages/cn/how-to/send-guaranteed-transactions.mdx b/docs/pages/cn/how-to/send-guaranteed-transactions.mdx new file mode 100644 index 0000000..d2fdf14 --- /dev/null +++ b/docs/pages/cn/how-to/send-guaranteed-transactions.mdx @@ -0,0 +1,172 @@ +--- +source_path: how-to/send-guaranteed-transactions.mdx +source_sha: 22dc49ff9b3a53eff2271c3e3b8d393f7543446c +title: "发送保障交易" +description: "使用 Enterprise SDK 在预留的企业通道区块空间中进行交易,并将保障区块空间与免 Gas 费结合使用,以实现免 Gas 传输交易。" +diataxis: "how-to" +--- + +# 发送保障交易 + +使用 `@stablechain/enterprise` 通过预留的企业通道区块空间路由交易。`guaranteedBlock` 模块通过企业 RPC 网关中继 GuaranteedTx(一种 `0x3F` 类型的 CustomTx),使其落在企业工作负载预留的容量中。与免 Gas 费不同,签名者支付自己的 Gas,因此必须提供资金。 + +您可以将此功能与免 Gas 费结合使用,以获得[保障中继交易](#combine-with-gas-waiver):免 Gas 费的交易仍可进入企业通道。 + +## 先决条件 + +- Node.js 20 或更高版本,并安装 `@stablechain/enterprise` 和 `viem`。请参阅 [企业 SDK 参考](/cn/reference/enterprise-sdk#install)。 +- 企业 RPC 网关 API 密钥。企业 SDK 目前仅支持测试网,并且访问受限:请[联系 Stable](https://discord.gg/stablexyz) 获取网关端点。 +- 一个有资金的签名者,因为 GuaranteedTx 会支付自己的 Gas。 + +:::warning +这是一个服务器端库。将企业 RPC 网关 URL 保留在您的后端:它会嵌入您的 API 密钥。 +::: + +## 1. 使用保障区块空间模块创建客户端 + +将 `guaranteedBlock` 和 `enterpriseRpcEndpoints` 传递给 `createStableEnterprise`。网关是唯一接受 `0x3F` GuaranteedTxs 的端点,并且它持有您的 API 密钥。无效的 `laneId` 会被立即拒绝。 + +```ts +import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; +import { privateKeyToAccount } from "viem/accounts"; + +const enterprise = createStableEnterprise({ + chain: stableTestnet, + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // the gateway URL Stable provisions + guaranteedBlock: { + account: privateKeyToAccount(process.env.SIGNER_PRIVATE_KEY as `0x${string}`), // must be funded + laneId: 0n, // Enterprise lane + }, +}); + +const gb = enterprise.guaranteedBlock!; +``` + +```text +StableEnterpriseClient { gasWaiver: undefined, guaranteedBlock, guaranteedWaiver: undefined } +``` + +## 2. 发送单笔交易 + +使用签名者和可变字段调用 `send`。由于签名者支付 Gas,因此 1559 费用字段是必需的。`chainId`、企业 `nonceKey` 和 2D nouce(从网关发现)都会为您处理。 + +```ts +import { createPublicClient, http } from "viem"; + +const publicClient = createPublicClient({ chain: stableTestnet, transport: http() }); +const gasPrice = await publicClient.getGasPrice(); + +const { txHash } = await gb.send(signer, { + to: recipient, + gas: 21_000n, + gasFeeCap: gasPrice * 2n, + gasTipCap: gasPrice, +}); +console.log("Guaranteed tx:", txHash); +``` + +```text +Guaranteed tx: 0xabcd...7890 +``` + +签名者支付 Gas,因此在进行中继之前请确认账户余额。零余额账户发出的 GuaranteedTx 会失败。 + +## 3. 发送批量交易 + +调用 `sendBatch` 发送多笔交易。Nonce 会从发现的基数自动排序,并且您会为每个输入获得一个结果,按输入顺序。如果其中一个失败,则其后续交易也会失败。 + +```ts +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 }, +]); + +for (const r of results) { + console.log(r.success ? `[${r.index}] ✔ ${r.txHash}` : `[${r.index}] ✖ ${r.error?.code}`); +} +``` + +```text +[0] ✔ 0xabcd...7890 +[1] ✔ 0x1f2e...66a1 +``` + +## 4. 发送预签名交易 + +对于非托管流程,使用 `buildGuaranteedTx` 在其他地方构建和签署 GuaranteedTx,然后只将签名十六进制交给运营商。企业 nonce 密钥来自 `nonceKeyForLane`。 + +```ts +import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; + +const signed = await buildGuaranteedTx(signer, stableTestnet.id, { + to: recipient, + gas: 21_000n, + gasFeeCap, + gasTipCap, + nonce, // the account's current 2D-lane nonce + nonceKey: nonceKeyForLane(0n), // Enterprise lane 0 +}); + +const { txHash } = await gb.relay(signed); +console.log("Guaranteed tx:", txHash); +``` + +```text +Guaranteed tx: 0xabcd...7890 +``` + +对于多笔预签名交易,请使用 `relayBatch`。 + +## 与免 Gas 费结合使用 + +保障中继交易结合了两种功能:通过保障区块空间路由的免 Gas 费交易。用户无需余额和费用字段,交易仍可进入企业通道。通过 `guaranteedWaiver` 启用此功能,它接受白名单豁免账户和通道。 + +```ts +const enterprise = createStableEnterprise({ + chain: stableTestnet, + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], + guaranteedWaiver: { + waiverAccount: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`), + laneId: 0n, + }, +}); + +const gw = enterprise.guaranteedWaiver!; + +// gas is waived, so the user needs no balance and no fee fields +const { txHash } = await gw.send(user, { to: recipient }); +console.log("H_inner:", txHash); +``` + +```text +H_inner: 0x8f3a...2d41 +``` + +与免 Gas 费类似,`send` 返回 `H_inner`,并且 `sendBatch`、`relay` 和 `relayBatch` 的工作方式相同。`guaranteedWaiver` 配置也接受与 `gasWaiver` 相同的 `allowedTargets`、`maxGasLimit` 和 `maxDataLength` 策略限制。 + +## 处理拒绝 + +`send` 和 `relay` 在拒绝时会抛出 `StableEnterpriseRelayError`。网关特定的代码包括 `GATEWAY_UNAUTHORIZED`(API 密钥缺失或无效)和 `QUOTA_EXCEEDED`(网关 Gas 配额已用尽)。 + +```ts +import { StableEnterpriseRelayError } from "@stablechain/enterprise"; + +try { + await gb.send(signer, { to: recipient, gas: 21_000n, gasFeeCap, gasTipCap }); +} catch (err) { + if (err instanceof StableEnterpriseRelayError && err.code === "GATEWAY_UNAUTHORIZED") { + // the Enterprise RPC gateway rejected the API key + } + throw err; +} +``` + +```text +StableEnterpriseRelayError: relay failed [GATEWAY_UNAUTHORIZED]: invalid api key +``` + +## 接下来去哪儿 + +- [**使用免 Gas 费中继**](/cn/how-to/relay-with-gas-waiver):赞助用户的 Gas 费,让他们无需持有 USDT0 即可进行交易。 +- [**企业 SDK 参考**](/cn/reference/enterprise-sdk#guaranteed-blockspace):所有方法、配置选项和错误类的完整说明。 +- [**保障区块空间**](/cn/explanation/guaranteed-blockspace):Stable 如何为企业工作负载预留区块容量。 diff --git a/docs/pages/cn/reference/enterprise-sdk.mdx b/docs/pages/cn/reference/enterprise-sdk.mdx index 2a80010..313e56d 100644 --- a/docs/pages/cn/reference/enterprise-sdk.mdx +++ b/docs/pages/cn/reference/enterprise-sdk.mdx @@ -1,21 +1,21 @@ --- source_path: reference/enterprise-sdk.mdx -source_sha: b7063f13645d37e2d66b8bb8c87b0dcfaf386a61 -title: "企业级SDK参考" -description: "@stablechain/enterprise 的完整参考:createStableEnterprise、免燃气费和保证区块空间模块、构建助手以及错误类。" +source_sha: 2f9f840d9ea287e27f4642da4f0a219db13edab6 +title: "企业版 SDK 参考" +description: "完整的 @stablechain/enterprise 参考:createStableEnterprise、免燃料费和保证区块空间模块、构建助手以及错误类。" diataxis: "reference" --- -# 企业级SDK参考 +# 企业版 SDK 参考 -`@stablechain/enterprise` 的完整功能。它涵盖了从 [`createStableEnterprise`](#createstableenterpriseconfig) 客户端开始,它的三个模块([免燃气费](#gaswaiver-module)、[保证区块空间](#guaranteedblock-module)和[组合免燃气费](#guaranteedwaiver-module)),低级构建助手,以及共享的结果和错误类型。有关这些机制的详细信息,请参阅[稳定企业版SDK](/cn/explanation/enterprise-sdk)、[免燃气费](/cn/explanation/gas-waiver)和[保证区块空间](/cn/explanation/guaranteed-blockspace)。 +`@stablechain/enterprise` 的完整功能。它涵盖了客户端从 [`createStableEnterprise`](#createstableenterpriseconfig) 到其三个功能([免燃料费中继](#relay-with-gas-waiver)、[保证区块空间](#guaranteed-blockspace)和[保证中继交易](#guaranteed-relay-transactions))、底层构建助手以及共享结果和错误类型。有关这些轨道的详情,请参阅 [Stable 企业版 SDK](/cn/explanation/enterprise-sdk)、[免燃料费](/cn/explanation/gas-waiver)和 [保证区块空间](/cn/explanation/guaranteed-blockspace)。 :::note -企业版SDK仅在Stable测试网上可用,并且两个机制都受到限制。要进行集成,请[联系Stable](https://discord.gg/stablexyz)以获取经治理注册的免燃气费密钥和企业版RPC网关API密钥。 +企业版 SDK 目前仅在 Stable 测试网上提供,且需要申请访问权限。要进行集成,请[联系 Stable](https://discord.gg/stablexyz) 以获取治理注册的豁免密钥和企业版 RPC 网关 API 密钥。 ::: :::warning -这是一个使用私钥进行签名的服务器端库。切勿在浏览器中运行它。请将免燃气费密钥和企业版RPC网关URL保存在您的后端。 +这是一个使用私钥进行签名的服务器端库。切勿在浏览器中运行它。将豁免密钥和企业版 RPC 网关 URL 保留在您的后端。 ::: ## 安装 @@ -32,7 +32,7 @@ added 2 packages, audited 3 packages in 2s ## `createStableEnterprise(config)` -构造一个 `StableEnterpriseClient`。每个模块仅在您配置它时才会存在,因此在使用前请通过 `!` 或空检查进行保护。 +构造一个 `StableEnterpriseClient`。每个模块只有在您配置它时才存在,因此在使用前使用 `!` 或空检查进行防护。 ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -52,13 +52,13 @@ StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | -| `chain` | `StableChain` | | 目标链。传入 `stable` 或 `stableTestnet`(由包重新导出)。必填。 | -| `rpcEndpoints` | `string[]?` | 链的内置RPC | 一个或多个Stable RPC端点,失败时按顺序尝试。仅在指向私有端点时才覆盖。 | -| `enterpriseRpcEndpoints` | `string[]?` | | 一个或多个企业RPC网关端点,失败时按顺序尝试。`guaranteedBlock` 和 `guaranteedWaiver` 所需。 | -| `batchSizeLimit` | `number?` | `100` | 每个批处理RPC调用的最大交易数量。 | -| `gasWaiver` | `GasWaiverConfig?` | | 启用[免燃气费模块](#gaswaiver-module)。 | -| `guaranteedBlock` | `GuaranteedBlockConfig?` | | 启用[保证区块空间模块](#guaranteedblock-module)。 | -| `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | 启用[组合免燃气费模块](#guaranteedwaiver-module)。 | +| `chain` | `StableChain` | | 目标链。传递 `stable` 或 `stableTestnet`(由包重新导出)。必填。 | +| `rpcEndpoints` | `string[]?` | 链的内置 RPC | 一个或多个 Stable RPC 端点,在失败时按顺序尝试。仅当指向私有端点时才覆盖。 | +| `enterpriseRpcEndpoints` | `string[]?` | | 一个或多个企业版 RPC 网关端点,在失败时按顺序尝试。`guaranteedBlock` 和 `guaranteedWaiver` 所必需。 | +| `batchSizeLimit` | `number?` | `100` | 每个批处理 RPC 调用的最大交易数量。 | +| `gasWaiver` | `GasWaiverConfig?` | | 启用[免燃料费中继](#relay-with-gas-waiver)。 | +| `guaranteedBlock` | `GuaranteedBlockConfig?` | | 启用[保证区块空间](#guaranteed-blockspace)。 | +| `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | 启用[保证中继交易](#guaranteed-relay-transactions)。 | ### `StableEnterpriseClient` @@ -70,9 +70,9 @@ interface StableEnterpriseClient { } ``` -## `gasWaiver` 模块 +## 免燃料费中继 -中继免燃气费交易。列入白名单的免燃气费账户将用户的零燃气交易(内部交易)包装成免燃气费交易并进行广播。用户不需要USDT0。每个方法都返回 `H_inner`,即内部交易哈希,而不是包装器哈希。 +`gasWaiver` 模块中继免燃料费交易。一个白名单豁免账户将用户的零燃料费交易(InnerTx)包装成一个 WaiverTx 并广播。用户不需要 USDT0。每个方法都返回 `H_inner`,即 InnerTx 哈希,而不是包装器哈希。 在配置中通过 `gasWaiver` 启用它: @@ -96,14 +96,14 @@ const gw = enterprise.gasWaiver!; | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `account` | `LocalAccount` | 签署每个免燃气费交易的白名单、经治理注册的账户。 | +| `account` | `LocalAccount` | 签署每个 WaiverTx 的白名单、治理注册账户。 | | `maxGasLimit` | `bigint?` | 继承自 `ValidationLimits`。 | | `maxDataLength` | `number?` | 继承自 `ValidationLimits`。 | | `allowedTargets` | `AllowedTarget[]?` | 继承自 `ValidationLimits`。 | ### `send(account, tx)` -从 `account` 构建、签名并中继一个内部交易,一次调用完成。`gasPrice: 0`、遗留类型、`chainId` 和待处理 Nonce 都为您处理。拒绝时抛出 `StableEnterpriseRelayError`。 +在一个调用中构建、签名和中继一个来自 `account` 的 InnerTx。`gasPrice: 0`、旧类型、`chainId` 和待处理 nonce 会为您处理。如果被拒绝,则抛出 `StableEnterpriseRelayError`。 ```ts const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); @@ -113,11 +113,11 @@ const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); { txHash: "0x8f3a...2d41" } ``` -`tx` 参数是一个 [`WaiverInnerTx`](#waiverinnertx) 加上一个可选的 `nonce`。返回 [`RelayResult`](#relayresult)。 +`tx` 参数是 [`WaiverInnerTx`](#waiverinnertx) 加上一个可选的 `nonce`。返回 [`RelayResult`](#relayresult)。 ### `sendBatch(account, txs)` -从一个`account`构建、签名并中继多个内部交易。Nonce会根据账户的待处理Nonce自动排序。按顺序为每个输入返回一个结果。 +构建、签名和中继来自一个 `account` 的多个 InnerTx。Nonce 从账户的待处理 nonce 自动排序。按顺序为每个输入返回一个结果。 ```ts const results = await gw.sendBatch(user, [ @@ -130,11 +130,11 @@ const results = await gw.sendBatch(user, [ [ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: true, txHash: "0x..." } ] ``` -`txs` 是一个只读的 [`WaiverInnerTx`](#waiverinnertx) 数组。返回 [`BatchResultItem[]`](#batchresultitem)。 +`txs` 是一个 [`WaiverInnerTx`](#waiverinnertx) 的只读数组。返回 [`BatchResultItem[]`](#batchresultitem)。 ### `relay(signedInnerTxHex)` -中继一个已预签名的零燃气费内部交易。当用户在自己的环境中签名并只向您提供已签名十六进制数据时,可用于非托管流程,这样免燃气费操作员就永远无法看到用户的私钥。使用 [`buildWaiverInnerTx`](#buildwaiverinnertxaccount-chainid-req) 构建一个。拒绝时抛出错误。 +中继一个预签名的零燃料费 InnerTx。这用于非托管流程,用户在其自己的环境中签名并只向您提供签名的十六进制,因此豁免操作员永远不会看到用户的密钥。使用 [`buildWaiverInnerTx`](#buildwaiverinnertxaccount-chainid-req) 构建一个。拒绝时抛出。 ```ts import { buildWaiverInnerTx } from "@stablechain/enterprise"; @@ -149,7 +149,7 @@ const { txHash } = await gw.relay(signed); ### `relayBatch(signedInnerTxHexes)` -中继一批预签名的内部交易。每个输入都会返回一个 [`BatchResultItem`](#batchresultitem),按顺序排列。 +中继一批预签名的 InnerTx。按顺序为每个输入返回一个 [`BatchResultItem`](#batchresultitem)。 ```ts const results = await gw.relayBatch([signed0, signed1]); @@ -159,16 +159,16 @@ 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),使其进入预留的企业级车道区块空间。与燃气费豁免不同,签名者需要支付自己的燃气费,并且必须有资金。每笔交易都带有与企业级车道关联的2D nonce,并且广播仅通过网关进行。 +`guaranteedBlock` 模块通过企业版 RPC 网关中继 GuaranteedTx(类型 `0x3F` CustomTx),以便它们落在预留的 Enterprise-lane 区块空间中。与免燃料费不同,签名者支付自己的燃料费并且必须有资金。每笔交易都带有与企业版通道关联的二维 nonce,并且仅通过网关广播。 通过 `guaranteedBlock` 和 `enterpriseRpcEndpoints` 启用它: ```ts const enterprise = createStableEnterprise({ chain: stableTestnet, - enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable提供的网关URL + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable 提供的网关 URL guaranteedBlock: { account: privateKeyToAccount("0xFUNDED_SIGNER_KEY"), laneId: 0n, @@ -182,12 +182,12 @@ const gb = enterprise.guaranteedBlock!; | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `account` | `LocalAccount` | 签署每个 GuaranteedTx 并支付其燃气费的已资助账户。 | -| `laneId` | `bigint` | 企业通道ID。必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。无效的ID会提前被拒绝。 | +| `account` | `LocalAccount` | 签署每个 GuaranteedTx 并支付其燃料费的有资金账户。 | +| `laneId` | `bigint` | 企业版通道 ID。必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。无效的 ID 将被立即拒绝。 | ### `send(account, tx)` -构建、签名并中继一个 GuaranteedTx。签名者需要支付燃气费,因此需要1559费率字段。`chainId`、企业 `nonceKey` 和 2D nonce(从网关发现)都为您处理。 +构建、签名和中继一个 GuaranteedTx。需要 1559 费用字段,因为签名者支付燃料费。`chainId`、企业版 `nonceKey` 和二维 nonce(从网关发现)会为您处理。 ```ts const gasPrice = await publicClient.getGasPrice(); @@ -204,11 +204,11 @@ const { txHash } = await gb.send(signer, { { txHash: "0xabcd...7890" } ``` -`tx` 参数是一个 [`GuaranteedTxRequest`](#guaranteedtxrequest) 加上一个可选的 `nonce`。返回 [`RelayResult`](#relayresult)。 +`tx` 参数是 [`GuaranteedTxRequest`](#guaranteedtxrequest) 加上一个可选的 `nonce`。返回 [`RelayResult`](#relayresult)。 ### `sendBatch(account, txs)` -构建、签名并中继多个 GuaranteedTx。Noncce 会从发现的基本 Nonce 自动排序。失败会影响其后续的交易。 +构建、签名和中继多个 GuaranteedTx。Nonce 从发现的基础自动排序。失败会使其后续交易受阻。 ```ts const results = await gb.sendBatch(signer, [ @@ -225,7 +225,7 @@ const results = await gb.sendBatch(signer, [ ### `relay(signedTx)` / `relayBatch(signedTxs)` -中继一个已预签名的 GuaranteedTx,或批量中继。使用 [`nonceKeyForLane`](#noncekeyforlanelaneid) 作为企业 Nonce 密钥,使用 [`buildGuaranteedTx`](#buildguaranteedtxaccount-chainid-req) 在其他地方构建并签名交易,然后只将已签名的十六进制数据交给操作员。 +中继一个预签名的 GuaranteedTx,或一批。使用 [`nonceKeyForLane`](#noncekeyforlanelaneid) 作为企业版 nonce 密钥,使用 [`buildGuaranteedTx`](#buildguaranteedtxaccount-chainid-req) 在其他地方构建和签名交易,然后只将签名的十六进制交给操作员。 ```ts import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; @@ -235,7 +235,7 @@ const signed = await buildGuaranteedTx(signer, stableTestnet.id, { gas: 21_000n, gasFeeCap, gasTipCap, - nonce, // the account's current 2D-lane nonce + nonce, // 账户当前的二维通道 nonce nonceKey: nonceKeyForLane(0n), }); const { txHash } = await gb.relay(signed); @@ -245,16 +245,16 @@ const { txHash } = await gb.relay(signed); { txHash: "0xabcd...7890" } ``` -## `guaranteedWaiver` 模块 +## 保证中继交易 -以上两种机制的组合:通过保证区块空间路由的免燃气费交易。内部和外部交易都是 `0x3F` CustomTx,共享一个企业 `nonceKey`,因此它像 `guaranteedBlock` 一样通过网关广播。免燃气费模块赞助燃气费,所以用户不需要余额,也不需要燃气费字段,就像 `gasWaiver` 一样。每个方法都返回 `H_inner`。 +`guaranteedWaiver` 模块结合了上述两个轨道:通过保证区块空间路由的免燃料费交易。内部和外部交易都是共享一个企业版 `nonceKey` 的 `0x3F` CustomTx,因此它像 `guaranteedBlock` 一样通过网关广播。豁免方支付燃料费,因此用户不需要余额和费用字段,就像 `gasWaiver` 一样。每个方法都返回 `H_inner`。 通过 `guaranteedWaiver` 和 `enterpriseRpcEndpoints` 启用它: ```ts const enterprise = createStableEnterprise({ chain: stableTestnet, - enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable提供的网关URL + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable 提供的网关 URL guaranteedWaiver: { waiverAccount: privateKeyToAccount("0xYOUR_WAIVER_KEY"), laneId: 0n, @@ -270,18 +270,18 @@ const gw = enterprise.guaranteedWaiver!; | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `waiverAccount` | `LocalAccount` | 签署外部包装器的白名单、经治理注册的账户。 | -| `laneId` | `bigint` | 企业通道ID。必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。 | +| `waiverAccount` | `LocalAccount` | 签署外部包装器的白名单、治理注册账户。 | +| `laneId` | `bigint` | 企业版通道 ID。必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。 | ### `send(user, tx)` / `sendBatch(user, txs)` -从 `user` 构建并签名内部 `0x3F` CustomTx,用免燃气费密钥包装,然后中继。无需燃气费字段,因为燃气费已豁免。内部 2D nonce 是从网关发现的,批次从该基础自动排序。 +构建并签名来自 `user` 的内部 `0x3F` CustomTx,用豁免密钥包装它,然后中继。不需要费用字段,因为燃料费已免除。内部二维 nonce 从网关发现,并且批处理从此基础自动排序。 ```ts // 单个 const { txHash } = await gw.send(user, { to: recipient }); -// 批处理 +// 批量 const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); ``` @@ -289,11 +289,11 @@ const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); { txHash: "0x8f3a...2d41" } ``` -`tx` 参数是一个 [`GuaranteedWaiverTxRequest`](#guaranteedwaivertxrequest) 加上一个可选的 `nonce`。`send` 返回 [`RelayResult`](#relayresult);`sendBatch` 返回 [`BatchResultItem[]`](#batchresultitem)。 +`tx` 参数是 [`GuaranteedWaiverTxRequest`](#guaranteedwaivertxrequest) 加上一个可选的 `nonce`。`send` 返回 [`RelayResult`](#relayresult);`sendBatch` 返回 [`BatchResultItem[]`](#batchresultitem)。 ### `relay(signedInnerTx)` / `relayBatch(signedInnerTxs)` -对于非托管流,用户使用 [`buildGuaranteedTx`](#buildguaranteedtxaccount-chainid-req) 签名内部 `0x3F` CustomTx (费用 `0n`,使用 `nonceKeyForLane(laneId)`),然后只将签名的十六进制数据交给操作员。操作员使用免燃气费密钥包装并中继。 +对于非托管流程,用户使用 [`buildGuaranteedTx`](#buildguaranteedtxaccount-chainid-req) 签名内部 `0x3F` CustomTx(费用 `0n`,使用 `nonceKeyForLane(laneId)`),并只将签名的十六进制交给操作员。操作员用豁免密钥包装它并中继。 ```ts import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; @@ -301,12 +301,12 @@ import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; const signedInner = await buildGuaranteedTx(user, stableTestnet.id, { to, gas: 100_000n, - gasFeeCap: 0n, // waived + gasFeeCap: 0n, // 已免除 gasTipCap: 0n, nonce, nonceKey: nonceKeyForLane(0n), }); -const { txHash } = await gw.relay(signedInner); // waiver wraps + broadcasts → H_inner +const { txHash } = await gw.relay(signedInner); // 豁免包装 + 广播 → H_inner ``` ```text @@ -315,11 +315,11 @@ const { txHash } = await gw.relay(signedInner); // waiver wraps + broadcasts → ## 构建助手 -用于非托管 `relay` 路径的低级签名者。每个都返回一个已签名交易作为 `Hex`,不进行 nonce 获取或费用估算。 +用于非托管 `relay` 路径的底层签名器。每个都以 `Hex` 形式返回已签名的交易,不进行 nonce 获取或费用估算。 ### `buildWaiverInnerTx(account, chainId, req)` -使用免燃气费不变式(`gasPrice: 0`、遗留类型和给定 `chainId`)签署一个准备好的内部交易。`req` 是一个 [`WaiverInnerTx`](#waiverinnertx) 加上一个必需的 `nonce`。 +使用预设的豁免不变量(`gasPrice: 0`、旧类型和给定的 `chainId`)签名 waiver-ready InnerTx。`req` 是一个 [`WaiverInnerTx`](#waiverinnertx) 加上一个必需的 `nonce`。 ```ts const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to, data, gas: 150_000n, nonce }); @@ -327,15 +327,15 @@ const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to, data, gas: ### `buildGuaranteedTx(account, chainId, req)` -构建并签署一个 GuaranteedTx (`0x3F` CustomTx)。`req` 是一个 [`GuaranteedTxRequest`](#guaranteedtxrequest) 加上一个必需的 `nonce` 和 `nonceKey`。 +构建并签名一个 GuaranteedTx(`0x3F` CustomTx)。`req` 是一个 [`GuaranteedTxRequest`](#guaranteedtxrequest) 加上一个必需的 `nonce` 和 `nonceKey`。 ### `buildGuaranteedWaiverTx(...)` -将预签名内部交易包装到外部 `0x3F` 免燃气费 CustomTx 中。供 `guaranteedWaiver.relay` 内部使用;为高级流程导出。 +将预签名的内部交易包装到外部 `0x3F` 豁免自定义交易中。供 `guaranteedWaiver.relay` 内部使用;为高级流程导出。 ### `nonceKeyForLane(laneId)` -返回 `laneId` 的企业 `nonceKey`,供 `buildGuaranteedTx` 使用。 +返回用于 `buildGuaranteedTx` 的通道 ID 的企业版 `nonceKey`。 ```ts import { nonceKeyForLane } from "@stablechain/enterprise"; @@ -347,82 +347,82 @@ const nonceKey = nonceKeyForLane(0n); ### `WaiverInnerTx` -每次调用内部交易时会变化的字段。 +每次调用不同的 InnerTx 字段。 | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | -| `to` | `Address` | | 目标地址:用于ERC-20转账的代币合约,或用于原生资产的接收方。 | -| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | 燃气限制。由于 `gasPrice` 为 0,所以一个慷慨的限制是免费的。 | +| `to` | `Address` | | 目标地址:ERC-20 转账的代币合约,原生转账的接收方。 | +| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | 燃料限制。因为 `gasPrice` 为 0,所以慷慨的限制是免费的。 | | `data` | `Hex?` | `"0x"` | 调用数据。 | -| `value` | `bigint?` | `0n` | 要发送的原生价值。 | +| `value` | `bigint?` | `0n` | 要发送的原生值。 | ### `GuaranteedTxRequest` | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | -| `to` | `Address?` | | 目标地址。 | -| `gas` | `bigint` | | 燃气限制。必填。 | -| `gasFeeCap` | `bigint` | | `maxFeePerGas`。必填。 | -| `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`。必填。 | +| `to` | `Address?` | | 目标地址。 | +| `gas` | `bigint` | | 燃料限制。必需。 | +| `gasFeeCap` | `bigint` | | `maxFeePerGas`。必需。 | +| `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`。必需。 | | `data` | `Hex?` | `"0x"` | 调用数据。 | -| `value` | `bigint?` | `0n` | 要发送的原生价值。 | +| `value` | `bigint?` | `0n` | 要发送的原生值。 | ### `GuaranteedWaiverTxRequest` -费用字段始终为 0,因此在此处省略。 +燃料费字段始终为 0,因此此处省略。 | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | -| `to` | `Address` | | 目标地址。 | -| `gas` | `bigint?` | 共享内部燃气默认值 | 燃气限制。 | +| `to` | `Address` | | 目标地址。 | +| `gas` | `bigint?` | 共享的内部燃料默认值 | 燃料限制。 | | `data` | `Hex?` | `"0x"` | 调用数据。 | -| `value` | `bigint?` | `0n` | 要发送的原生价值。允许免燃气费交易进行价值转账。 | +| `value` | `bigint?` | `0n` | 要发送的原生值。豁免允许值转移。 | ### `ValidationLimits` -由 `gasWaiver` 和 `guaranteedWaiver` 应用于每个 InternalTx 的按合作方策略。 +应用于 `gasWaiver` 和 `guaranteedWaiver` 的每个 InnerTx 的每个合作伙伴策略。 | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | -| `maxGasLimit` | `bigint?` | `10_000_000n` | InternalTx 的最大燃气限制。超过此限制将导致 `GAS_LIMIT_EXCEEDED` 失败。 | -| `maxDataLength` | `number?` | `131_072` (128 KB) | 调用数据的最大字节数。超过此限制将导致 `DATA_TOO_LARGE` 失败。 | -| `allowedTargets` | `AllowedTarget[]?` | | 豁免燃气费可能赞助的合约和方法的白名单。设置后,列表之外的目标将导致 `TARGET_NOT_ALLOWED` 失败。 | +| `maxGasLimit` | `bigint?` | `10_000_000n` | InnerTx 的最大燃料限制。超过此限制将导致 `GAS_LIMIT_EXCEEDED` 失败。 | +| `maxDataLength` | `number?` | `131_072` (128 KB) | 调用数据的最大字节大小。超过此限制将导致 `DATA_TOO_LARGE` 失败。 | +| `allowedTargets` | `AllowedTarget[]?` | | 豁免可能赞助的合约和方法的允许列表。设置后,列表之外的目标将导致 `TARGET_NOT_ALLOWED` 失败。 | ### `AllowedTarget` | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `address` | `Address \| "*"` | 内部交易可以调用的合约,或 `"*"` 表示匹配任何合约。 | -| `selectors` | `Hex[]?` | 允许的4字节方法选择器(例如,ERC-20 `transfer` 的 `"0xa9059cbb"`)。省略或留空表示允许 `address` 上的任何方法。 | +| `address` | `Address \| "*"` | InnerTx 可能调用的合约,或 `"*"` 以匹配任何合约。 | +| `selectors` | `Hex[]?` | 允许的 4 字节方法选择器(例如,ERC-20 `transfer` 的 `"0xa9059cbb"`)。省略或留空以允许 `address` 上的任何方法。 | ### `RelayResult` ```ts interface RelayResult { - txHash: Hash; // H_inner 用于豁免,GuaranteedTx 哈希用于独立保证区块 + txHash: Hash; // 豁免的 H_inner,独立保证区块的 GuaranteedTx 哈希 } ``` ### `BatchResultItem` -批次中每个输入的条目,按输入顺序排列。批次不是抛出异常,而是显示每个项目的处理结果。 +批处理中每个输入的一个条目,按输入顺序排列。批处理不会抛出,而是显示每个项目的输出。 | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `index` | `number` | 零基位置,与输入数组匹配。 | -| `success` | `boolean` | 此项是否被中继。 | +| `index` | `number` | 与输入数组匹配的从零开始的位置。 | +| `success` | `boolean` | 此项目是否已中继。 | | `txHash` | `Hash?` | 成功时存在:内部交易哈希。 | | `error` | `{ code: ErrorCode; message: string }?` | 失败时存在。 | ## 错误 -单一交易方法(`send`,`relay`)在拒绝时抛出错误。批量方法则在 [`BatchResultItem.error`](#batchresultitem) 中报告每个项目的失败。所有错误类都扩展自 `StableEnterpriseError`。 +单交易方法(`send`、`relay`)在拒绝时抛出。批处理方法则在 [`BatchResultItem.error`](#batchresultitem) 中报告每个项目的失败。所有错误类都扩展自 `StableEnterpriseError`。 -| **类** | **抛出条件** | **有用字段** | +| **类** | **抛出时机** | **有用字段** | | :--- | :--- | :--- | -| `StableEnterpriseError` | 每个SDK错误的基础类。 | `message` | -| `StableEnterpriseRelayError` | 交易在RPC或中继层被拒绝。 | `code` | -| `WaiverValidationError` | 内部交易在广播前未能通过策略检查(燃气费、数据大小或目标白名单)。 | `code` | +| `StableEnterpriseError` | 所有 SDK 错误的基类。 | `message` | +| `StableEnterpriseRelayError` | 交易在 RPC 或中继层被拒绝。 | `code` | +| `WaiverValidationError` | InnerTx 在广播前未能通过策略检查(燃料、数据大小或目标允许列表)。 | `code` | ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -431,7 +431,7 @@ try { await gw.send(user, { to: token, data }); } catch (err) { if (err instanceof StableEnterpriseRelayError && err.code === "TARGET_NOT_ALLOWED") { - // 内部交易目标不在配置的允许列表内 + // InnerTx 目标不在配置的允许列表之外 } throw err; } @@ -443,33 +443,33 @@ StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not ### `ErrorCode` -抛出的错误或 `BatchResultItem.error` 上的 `code` 之一是: +抛出的错误或 `BatchResultItem.error` 上的 `code` 是以下之一: | **代码** | **含义** | | :--- | :--- | -| `UNKNOWN_ERROR` | 当没有特定代码时回退。 | -| `BROADCAST_FAILED` | 广播在RPC层被拒绝,或网关中继失败。 | -| `INVALID_TRANSACTION` | 内部交易解码或解析失败。 | +| `UNKNOWN_ERROR` | 当没有特定代码可用时的回退。 | +| `BROADCAST_FAILED` | 广播在 RPC 层被拒绝,或网关未能中继。 | +| `INVALID_TRANSACTION` | InnerTx 解码或解析失败。 | | `INVALID_SIGNATURE` | 签名验证失败。 | -| `UNSUPPORTED_TX_TYPE` | 内部交易类型不是 legacy、eip2930 或 eip1559。 | -| `WRONG_CHAIN_ID` | 内部交易 `chainId` 缺失或与目标链不匹配。 | -| `NON_ZERO_GAS_PRICE` | 内部交易携带非零燃气费(豁免时必须为零)。 | -| `GAS_LIMIT_EXCEEDED` | 内部交易燃气限制超过 `maxGasLimit`。 | -| `DATA_TOO_LARGE` | 内部交易调用数据超过 `maxDataLength`。 | -| `TARGET_NOT_ALLOWED` | 内部交易目标不在 `allowedTargets` 中。 | -| `GATEWAY_UNAUTHORIZED` | 企业版RPC网关拒绝了API密钥(缺失、无效或已过期)。 | -| `QUOTA_EXCEEDED` | 企业版RPC网关的燃气配额已用尽。 | +| `UNSUPPORTED_TX_TYPE` | InnerTx 类型不是 legacy、eip2930 或 eip1559。 | +| `WRONG_CHAIN_ID` | InnerTx `chainId` 缺失或与目标链不匹配。 | +| `NON_ZERO_GAS_PRICE` | InnerTx 带有非零燃料价格(豁免必须为零)。 | +| `GAS_LIMIT_EXCEEDED` | InnerTx 燃料限制超过 `maxGasLimit`。 | +| `DATA_TOO_LARGE` | InnerTx 调用数据超过 `maxDataLength`。 | +| `TARGET_NOT_ALLOWED` | InnerTx 目标不在 `allowedTargets` 中。 | +| `GATEWAY_UNAUTHORIZED` | 企业版 RPC 网关拒绝了 API 密钥(缺失、无效或已过期)。 | +| `QUOTA_EXCEEDED` | 企业版 RPC 网关燃料配额已用尽。 | ## 常量 | **常量** | **类型** | **描述** | | :--- | :--- | :--- | -| `DEFAULT_INNER_GAS` | `bigint` | 当 `gas` 省略时,内部交易的默认燃气限制 (`150_000n`)。 | +| `DEFAULT_INNER_GAS` | `bigint` | 当省略 `gas` 时,默认的 InnerTx 燃料限制 (`150_000n`)。 | | `ENTERPRISE_FLAG` | `bigint` | 在通道的 `nonceKey` 上设置的企业位。 | | `ENTERPRISE_MASK` | `bigint` | 通道 ID 的上限:`laneId` 必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。 | -## 下一步建议 +## 下一步推荐 -- [**稳定企业级SDK**](/cn/explanation/enterprise-sdk): 了解这些机制是什么以及何时使用它们。 -- [**燃气费豁免协议**](/cn/reference/gas-waiver-api): 交易格式、标记路由和治理控制。 -- [**保证区块空间**](/cn/explanation/guaranteed-blockspace): Stable如何为企业工作负载预留区块容量。 +- [**Stable 企业版 SDK**](/cn/explanation/enterprise-sdk):轨道的用途以及何时使用它们。 +- [**免燃料费协议**](/cn/reference/gas-waiver-api):交易格式、标记路由和治理控制。 +- [**保证区块空间**](/cn/explanation/guaranteed-blockspace):Stable 如何为企业工作负载预留区块容量。 diff --git a/docs/pages/ko/explanation/enterprise-sdk.mdx b/docs/pages/ko/explanation/enterprise-sdk.mdx index 67f24b7..d9b7f36 100644 --- a/docs/pages/ko/explanation/enterprise-sdk.mdx +++ b/docs/pages/ko/explanation/enterprise-sdk.mdx @@ -1,14 +1,14 @@ --- source_path: explanation/enterprise-sdk.mdx -source_sha: c851ff041a812cf877db582b540a0369d4777566 -title: "Stable 엔터프라이즈 SDK" -description: "유형화된 @stablechain/enterprise SDK를 사용하여 백엔드에서 가스 면제 및 블록 공간 보장 트랜잭션을 릴레이합니다." +source_sha: 3925dc600289afa0a771b5b508728ee1b20bcb01 +title: "Stable Enterprise SDK" +description: "유형화된 @stablechain/enterprise SDK를 사용하여 백엔드에서 가스 면제 및 보장된 블록 공간 트랜잭션을 릴레이합니다." diataxis: "explanation" --- -# Stable 엔터프라이즈 SDK +# Stable Enterprise SDK -`@stablechain/enterprise`는 Stable의 엔터프라이즈 트랜잭션 레일을 위한 서버 측 TypeScript 클라이언트입니다. 가스 면제 트랜잭션(사용자 가스 후원)과 보장된 블록 공간 트랜잭션(예약된 엔터프라이즈 레인에 상륙)의 두 가지 유형의 특권 트랜잭션을 서명하고 릴레이합니다. 한 클라이언트에서 두 레일 중 하나 또는 둘 다를 활성화할 수 있습니다. +`@stablechain/enterprise`는 Stable의 엔터프라이즈 트랜잭션 레일을 위한 서버 측 TypeScript 클라이언트입니다. 가스 면제 트랜잭션(사용자의 가스를 후원하는 경우)과 보장된 블록 공간 트랜잭션(예약된 엔터프라이즈 레인에 도달하는 트랜잭션)의 두 가지 유형의 특권 트랜잭션을 서명하고 릴레이합니다. 한 클라이언트에서 두 레일 중 하나 또는 둘 다를 활성화할 수 있습니다. ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -26,44 +26,44 @@ const { txHash } = await enterprise.gasWaiver!.send(user, { to: token, data }); txHash: 0x8f3a...2d41 ``` -호출은 사용자의 트랜잭션 해시인 `H_inner`를 반환하며, 이를 전달한 래퍼 트랜잭션 해시는 반환하지 않습니다. +호출은 사용자의 트랜잭션 해시인 `H_inner`를 반환하며, 이를 포함하는 래퍼 트랜잭션이 아닙니다. ## SDK의 기능 -SDK는 세 가지 모듈을 노출합니다. 각 모듈은 선택 사항이며 독립적으로 구성되며, 각각 고유한 서명 계정을 가지고 있어 별도의 키를 사용할 수 있습니다. +SDK는 모듈당 하나의 세 가지 기능을 노출합니다. 각 기능은 선택 사항이며 독립적으로 구성되며, 각각 자체 서명 계정을 포함하므로 별도의 키를 사용할 수 있습니다. -- **`gasWaiver`**: 가스 면제 트랜잭션을 빌드, 서명 및 릴레이합니다. 화이트리스트에 있는 면제 계정이 사용자의 제로 가스 트랜잭션을 래핑하여 사용자가 USDT0를 보유하지 않고도 트랜잭션할 수 있도록 합니다. [가스 면제](/ko/explanation/gas-waiver)를 참조하십시오. -- **`guaranteedBlock`**: Enterprise RPC 게이트웨이를 통해 GuaranteedTx를 릴레이하여 예약된 Enterprise-lane 블록 공간에 상륙합니다. 가스 면제와 달리 서명자는 자체 가스를 지불합니다. [보장된 블록 공간](/ko/explanation/guaranteed-blockspace)을 참조하십시오. -- **`guaranteedWaiver`**: 둘의 조합입니다. 보장된 블록 공간을 통해 라우팅되는 가스 면제 트랜잭션이므로 사용자는 잔액이 필요 없고 트랜잭션은 여전히 Enterprise 레인에 상륙합니다. +- **가스 면제 릴레이** (`gasWaiver`): 가스 면제 트랜잭션을 구축, 서명 및 릴레이합니다. 화이트리스트에 등록된 면제 계정은 사용자의 제로 가스 트랜잭션을 래핑하여 사용자가 USDT0를 보유하지 않고도 트랜잭션을 수행할 수 있도록 합니다. [가스 면제](/ko/explanation/gas-waiver)를 참조하십시오. +- **보장된 블록 공간** (`guaranteedBlock`): 트랜잭션을 엔터프라이즈 RPC 게이트웨이를 통해 릴레이하여 예약된 엔터프라이즈 레인 블록 공간에 도달하도록 합니다. 가스 면제와 달리 서명자는 자체 가스를 지불합니다. [보장된 블록 공간](/ko/explanation/guaranteed-blockspace)을 참조하십시오. +- **보장된 릴레이 트랜잭션** (`guaranteedWaiver`): 두 기능을 모두 결합합니다. 보장된 블록 공간을 통해 라우팅되는 가스 면제 트랜잭션으로, 사용자는 잔액이 필요하지 않으며 트랜잭션은 여전히 엔터프라이즈 레인에 도달합니다. -모든 모듈은 동일한 네 가지 메서드를 제공합니다. SDK가 서명하는 관리 경로에는 `send` 및 `sendBatch`, 사용자가 다른 곳에서 서명하고 서명된 헥스만 전달하는 비관리 경로에는 `relay` 및 `relayBatch`가 있습니다. +각 기능은 동일한 네 가지 메서드를 제공합니다. SDK가 서명하는 관리 경로의 경우 `send` 및 `sendBatch`, 그리고 사용자가 다른 곳에서 서명하고 서명된 hex만 전달하는 비관리 경로의 경우 `relay` 및 `relayBatch`가 있습니다. ## 접근 엔터프라이즈 SDK는 현재 Stable Testnet에서만 사용할 수 있습니다. -두 레일 모두 게이트되었습니다. 가스 면제는 거버넌스 등록 면제 키가 필요하고, 보장된 블록 공간은 엔터프라이즈 RPC 게이트웨이 API 키가 필요합니다. 통합하려면 Stable에 문의하여 액세스 권한을 얻으십시오. Stable은 필요한 면제 키와 게이트웨이 엔드포인트를 제공합니다. +두 레일 모두 게이트됩니다. 가스 면제는 거버넌스에 등록된 면제 키를 필요로 하며, 보장된 블록 공간은 엔터프라이즈 RPC 게이트웨이 API 키를 필요로 합니다. 통합하려면 [Stable에 문의](https://discord.gg/stablexyz)하여 액세스 권한을 얻으십시오. Stable은 필요한 면제 키와 게이트웨이 엔드포인트를 제공합니다. ## 서버 측 전용 :::warning -엔터프라이즈 SDK는 개인 키로 서명하는 무상태 서버 측 라이브러리입니다. 브라우저에서 실행하지 마십시오. 면제 키와 엔터프라이즈 RPC 게이트웨이 URL을 백엔드에 보관하십시오. +엔터프라이즈 SDK는 개인 키로 서명하는 상태 비저장 서버 측 라이브러리입니다. 브라우저에서 실행하지 마십시오. 면제 키와 엔터프라이즈 RPC 게이트웨이 URL을 백엔드에 보관하십시오. ::: -면제 키는 화이트리스트에 있는 거버넌스 등록 계정입니다. 이를 보유한 사람은 누구나 귀하의 정책에 따라 가스를 후원할 수 있습니다. 엔터프라이즈 RPC 게이트웨이 URL은 API 키를 포함합니다. 둘 다 비밀로 취급하십시오. +면제 키는 화이트리스트에 등록된 거버넌스 등록 계정입니다. 이를 소유한 누구든지 귀하의 정책에 따라 가스를 후원할 수 있습니다. 엔터프라이즈 RPC 게이트웨이 URL에는 API 키가 포함되어 있습니다. 두 가지 모두 비밀로 취급하십시오. -## 언제 사용해야 하는가 +## 언제 사용해야 할까요? -백엔드를 운영하고 사용자 가스를 후원하거나 자체 트래픽에 대한 포함을 보장하려는 경우 엔터프라이즈 SDK를 사용하십시오. 백엔드 또는 브라우저에서 일상적인 전송, 브릿지, 스왑 및 볼트 수익을 위해서는 일반적인 [Stable SDK](/ko/explanation/sdk-overview)를 대신 사용하십시오. +백엔드를 운영하고 사용자 가스를 후원하거나 자신의 트래픽에 대한 포함을 보장하려는 경우 엔터프라이즈 SDK를 사용하십시오. 백엔드 또는 브라우저에서 일상적인 전송, 브릿지, 스왑 및 볼트 수익률을 위해서는 대신 범용 [Stable SDK](/ko/explanation/sdk-overview)를 사용하십시오. -## 여기부터 시작 +## 여기서 시작하세요 +- [**가스 면제 릴레이**](/ko/how-to/relay-with-gas-waiver): 사용자의 가스를 후원하여 USDT0를 보유하지 않고도 거래할 수 있도록 지원합니다. +- [**보장된 거래 전송**](/ko/how-to/send-guaranteed-transactions): 거래를 예약된 엔터프라이즈 레인 블록 공간에 도착시키고, 가스 면제와 결합합니다. - [**엔터프라이즈 SDK 참조**](/ko/reference/enterprise-sdk): 모든 모듈, 메서드, 구성 옵션 및 오류 클래스. -- [**가스 면제**](/ko/explanation/gas-waiver): 제로 가스 트랜잭션이 프로토콜 수준에서 작동하는 방식. -- [**보장된 블록 공간**](/ko/explanation/guaranteed-blockspace): Stable이 엔터프라이즈 워크로드에 대한 블록 용량을 예약하는 방식. ## 다음 권장 사항 - [**가스 면제 프로토콜**](/ko/reference/gas-waiver-api): 트랜잭션 형식, 마커 라우팅 및 거버넌스 제어. -- [**Stable SDK**](/ko/explanation/sdk-overview): 전송, 브리징, 스왑 및 수익을 위한 일반적인 클라이언트. +- [**Stable SDK**](/ko/explanation/sdk-overview): 전송, 브리징, 스왑 및 수익률을 위한 범용 클라이언트. - [**Stable에 연결**](/ko/reference/connect): 테스트넷용 체인 ID, RPC 엔드포인트 및 탐색기. diff --git a/docs/pages/ko/how-to/relay-with-gas-waiver.mdx b/docs/pages/ko/how-to/relay-with-gas-waiver.mdx new file mode 100644 index 0000000..1d99467 --- /dev/null +++ b/docs/pages/ko/how-to/relay-with-gas-waiver.mdx @@ -0,0 +1,153 @@ +--- +source_path: how-to/relay-with-gas-waiver.mdx +source_sha: b123789598d68061ee8cb4472a3ed8d22153b91c +title: "가스 면제 릴레이(Relay with gas waiver)" +description: "Enterprise SDK로 사용자의 가스를 후원하세요: 제로 가스 트랜잭션을 릴레이하고, 릴레이를 일괄 처리하고, 정책 제한을 적용하고, 미리 서명된 트랜잭션을 릴레이합니다." +diataxis: "how-to" +--- + +# 가스 면제 릴레이(Relay with gas waiver) + +`@stablechain/enterprise`를 사용하여 사용자의 가스를 후원하세요. 화이트리스트에 등록된 면제 계정은 사용자의 제로 가스 트랜잭션(InnerTx)을 래핑하고 브로드캐스트하므로, 사용자는 USDT0를 보유하지 않고도 트랜잭션을 처리할 수 있습니다. `gasWaiver` 모듈은 빌드, 서명 및 릴레이를 한 번의 호출로 처리하므로, 작업마다 하나의 메서드를 호출합니다. + +모든 메서드는 래퍼가 아닌 사용자 트랜잭션의 해시인 `H_inner`를 반환합니다. + +## 전제 조건 + +- Node.js 20 이상, 그리고 `@stablechain/enterprise`와 `viem` 이 설치되어 있어야 합니다. [Enterprise SDK 참조](/ko/reference/enterprise-sdk#install)를 참조하십시오. +- 거버넌스에 등록된 면제 키. 현재 Enterprise SDK는 테스트넷 전용이며 접근이 제한됩니다. 화이트리스트에 등록된 면제 키를 얻으려면 [Stable에 문의](https://discord.gg/stablexyz)하십시오. + +:::warning +이것은 개인 키로 서명하는 서버 측 라이브러리입니다. 브라우저에서 실행하지 마십시오. 면제 키는 백엔드에 보관하십시오. +::: + +## 1. 가스 면제 모듈로 클라이언트 생성 + +`createStableEnterprise`에 `gasWaiver: { account }`를 전달합니다. 여기서 `account`는 화이트리스트에 등록된 면제 키입니다. 모듈은 구성할 때만 클라이언트에 존재합니다. + +```ts +import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; +import { privateKeyToAccount } from "viem/accounts"; + +const enterprise = createStableEnterprise({ + chain: stableTestnet, + gasWaiver: { account: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`) }, +}); + +const gw = enterprise.gasWaiver!; +``` + +```text +StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver: undefined } +``` + +`rpcEndpoints` 옵션은 선택 사항입니다. 설정하지 않으면 클라이언트는 체인의 내장 RPC를 사용합니다. + +## 2. 단일 트랜잭션 릴레이 + +사용자 계정과 변경되는 필드를 사용하여 `send`를 호출합니다. `gasPrice: 0`, 레거시 유형, `chainId`, 보류 중인 nonce는 자동으로 처리되므로, `to`와 선택적으로 `data`, `value`, `gas`만 전달하면 됩니다. + +```ts +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); +``` + +```text +H_inner: 0x8f3a...2d41 +``` + +사용자는 USDT0가 필요하지 않습니다. 면제 계정이 가스를 후원합니다. `gas`는 `150_000n` (`DEFAULT_INNER_GAS`)으로 기본 설정되며, 이는 토큰 전송 또는 승인을 포함합니다. 더 많은 가스가 필요한 호출의 경우 명시적인 `gas`를 전달합니다. + +## 3. 일괄 릴레이 + +여러 계정에서 여러 트랜잭션을 릴레이하려면 `sendBatch`를 호출합니다. Nonce는 계정의 보류 중인 nonce에서 자동으로 순서가 지정되며, 입력 순서대로 입력당 하나의 결과를 얻습니다. + +```ts +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}`); +} +``` + +```text +[0] ✔ 0x8f3a...2d41 +[1] ✔ 0x2b7c...9e04 +``` + +배치(batch)는 오류를 발생시키는 대신 `result.error`에 항목별 실패를 보고하므로, 하나의 잘못된 트랜잭션이 나머지 트랜잭션을 망치지 않습니다. + +## 4. 파트너별 정책 제한 적용 + +설정에 정책 제한을 추가하여 면제 키가 후원할 수 있는 것을 제한할 수 있습니다. 제한을 위반하는 InnerTx는 브로드캐스트 전에 거부됩니다. + +```ts +const enterprise = createStableEnterprise({ + chain: stableTestnet, + 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`로 릴레이합니다. + +```ts +import { buildWaiverInnerTx } from "@stablechain/enterprise"; + +// 사용자 측에서 +const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to: token, data, gas: 150_000n, nonce }); + +// 백엔드에서 +const { txHash } = await gw.relay(signed); +console.log("H_inner:", txHash); +``` + +```text +H_inner: 0x8f3a...2d41 +``` + +여러 개의 미리 서명된 트랜잭션의 경우, `sendBatch`와 같이 입력당 하나의 결과를 반환하는 `relayBatch`를 사용합니다. + +## 거부 처리 + +`send` 및 `relay`는 거부 시 `StableEnterpriseRelayError`를 발생시키며, 분기할 수 있는 `code`를 포함합니다. + +```ts +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; +} +``` + +```text +StableEnterpriseRelayError: 릴레이 실패 [TARGET_NOT_ALLOWED]: 대상 0x... 허용되지 않음 +``` + +모든 거부 이유에 대한 전체 [`ErrorCode`](/ko/reference/enterprise-sdk#errorcode) 표를 참조하십시오. + +## 다음 단계 + +- [**보장된 트랜잭션 보내기**](/ko/how-to/send-guaranteed-transactions): 예약된 엔터프라이즈 레인 블록스페이스에 트랜잭션을 전송하고 가스 면제와 결합합니다. +- [**엔터프라이즈 SDK 참조**](/ko/reference/enterprise-sdk#relay-with-gas-waiver): 모든 메서드, 구성 옵션 및 오류 클래스에 대한 전체 정보. +- [**가스 면제**](/ko/explanation/gas-waiver): 프로토콜 수준에서 제로 가스 트랜잭션이 작동하는 방식. diff --git a/docs/pages/ko/how-to/send-guaranteed-transactions.mdx b/docs/pages/ko/how-to/send-guaranteed-transactions.mdx new file mode 100644 index 0000000..5736f31 --- /dev/null +++ b/docs/pages/ko/how-to/send-guaranteed-transactions.mdx @@ -0,0 +1,172 @@ +--- +source_path: how-to/send-guaranteed-transactions.mdx +source_sha: 22dc49ff9b3a53eff2271c3e3b8d393f7543446c +title: "보장된 트랜잭션 전송" +description: "Enterprise SDK를 사용하여 예약된 엔터프라이즈 레인 블록스페이스에 트랜잭션을 랜딩하고, 보장된 블록스페이스와 가스 면제를 결합하여 가스 없이 트랜잭션을 릴레이합니다." +diataxis: "how-to" +--- + +# 보장된 트랜잭션 전송 + +`@stablechain/enterprise`를 사용하여 예약된 엔터프라이즈 레인 블록스페이스를 통해 트랜잭션을 라우팅합니다. `guaranteedBlock` 모듈은 Enterprise RPC 게이트웨이를 통해 GuaranteedTx(타입 `0x3F` CustomTx)를 릴레이하여 엔터프라이즈 워크로드용으로 예약된 용량에 랜딩합니다. 가스 면제와 달리 서명자는 자체 가스를 지불하므로 자금이 있어야 합니다. + +이를 가스 면제와 결합하여 [보장된 릴레이 트랜잭션](#combine-with-gas-waiver)을 얻을 수 있습니다. 이는 가스가 면제되면서도 엔터프라이즈 레인에 랜딩되는 트랜잭션입니다. + +## 전제 조건 + +- Node.js 20 이상, 그리고 `@stablechain/enterprise`와 `viem`이 설치되어 있어야 합니다. [엔터프라이즈 SDK 참조](/ko/reference/enterprise-sdk#install)를 참조하세요. +- 엔터프라이즈 RPC 게이트웨이 API 키. 엔터프라이즈 SDK는 현재 테스트넷 전용이며, 액세스는 제한되어 있습니다. 게이트웨이 엔드포인트를 얻으려면 [Stable에 문의](https://discord.gg/stablexyz)하세요. +- GuaranteedTx는 자체 가스를 지불하므로 자금이 있는 서명자. + +:::warning +이것은 서버 측 라이브러리입니다. 엔터프라이즈 RPC 게이트웨이 URL은 백엔드에 유지하세요. API 키가 포함되어 있습니다. +::: + +## 1. 보장된 블록스페이스 모듈로 클라이언트 생성 + +`guaranteedBlock` 및 `enterpriseRpcEndpoints`를 `createStableEnterprise`에 전달합니다. 게이트웨이는 `0x3F` GuaranteedTxs를 허용하는 유일한 엔드포인트이며, API 키를 보유합니다. 잘못된 `laneId`는 즉시 거부됩니다. + +```ts +import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; +import { privateKeyToAccount } from "viem/accounts"; + +const enterprise = createStableEnterprise({ + chain: stableTestnet, + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable이 제공하는 게이트웨이 URL + guaranteedBlock: { + account: privateKeyToAccount(process.env.SIGNER_PRIVATE_KEY as `0x${string}`), // 자금이 있어야 함 + laneId: 0n, // 엔터프라이즈 레인 + }, +}); + +const gb = enterprise.guaranteedBlock!; +``` + +```text +StableEnterpriseClient { gasWaiver: undefined, guaranteedBlock, guaranteedWaiver: undefined } +``` + +## 2. 단일 트랜잭션 전송 + +서명자와 변경되는 필드로 `send`를 호출합니다. 서명자가 가스를 지불하므로 1559 수수료 필드가 필요합니다. `chainId`, 엔터프라이즈 `nonceKey`, 그리고 2D nonce(게이트웨이에서 발견됨)는 자동으로 처리됩니다. + +```ts +import { createPublicClient, http } from "viem"; + +const publicClient = createPublicClient({ chain: stableTestnet, transport: http() }); +const gasPrice = await publicClient.getGasPrice(); + +const { txHash } = await gb.send(signer, { + to: recipient, + gas: 21_000n, + gasFeeCap: gasPrice * 2n, + gasTipCap: gasPrice, +}); +console.log("Guaranteed tx:", txHash); +``` + +```text +Guaranteed tx: 0xabcd...7890 +``` + +서명자가 가스를 지불하므로 릴레이 전에 잔액을 확인하십시오. 잔액이 없는 계정에서 보낸 GuaranteedTx는 실패합니다. + +## 3. 배치 전송 + +여러 트랜잭션을 보내려면 `sendBatch`를 호출합니다. Nonce는 발견된 기준에서 자동으로 시퀀싱되며, 입력 순서대로 입력당 하나의 결과를 얻습니다. 실패는 후속 작업에 영향을 줍니다. + +```ts +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 }, +]); + +for (const r of results) { + console.log(r.success ? `[${r.index}] ✔ ${r.txHash}` : `[${r.index}] ✖ ${r.error?.code}`); +} +``` + +```text +[0] ✔ 0xabcd...7890 +[1] ✔ 0x1f2e...66a1 +``` + +## 4. 사전 서명된 트랜잭션 전송 + +비수탁형 흐름의 경우, `buildGuaranteedTx`로 다른 곳에서 GuaranteedTx를 빌드하고 서명한 다음, 운영자에게 서명된 hex만 전달합니다. 엔터프라이즈 nonce 키는 `nonceKeyForLane`에서 가져옵니다. + +```ts +import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; + +const signed = await buildGuaranteedTx(signer, stableTestnet.id, { + to: recipient, + gas: 21_000n, + gasFeeCap, + gasTipCap, + nonce, // 계정의 현재 2D 레인 nonce + nonceKey: nonceKeyForLane(0n), // 엔터프라이즈 레인 0 +}); + +const { txHash } = await gb.relay(signed); +console.log("Guaranteed tx:", txHash); +``` + +```text +Guaranteed tx: 0xabcd...7890 +``` + +여러 사전 서명된 트랜잭션의 경우 `relayBatch`를 사용합니다. + +## 가스 면제와 결합 + +보장된 릴레이 트랜잭션은 두 가지 레일을 모두 구성합니다. 즉, 보장된 블록스페이스를 통해 라우팅되는 가스 면제 트랜잭션입니다. 사용자는 잔액이나 수수료 필드가 필요 없으며, 트랜잭션은 여전히 엔터프라이즈 레인에 랜딩됩니다. 화이트리스트에 등록된 면제 계정과 레인을 사용하는 `guaranteedWaiver`로 이 기능을 활성화할 수 있습니다. + +```ts +const enterprise = createStableEnterprise({ + chain: stableTestnet, + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], + guaranteedWaiver: { + waiverAccount: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`), + laneId: 0n, + }, +}); + +const gw = enterprise.guaranteedWaiver!; + +// 가스가 면제되므로 사용자는 잔액이나 수수료 필드가 필요 없습니다 +const { txHash } = await gw.send(user, { to: recipient }); +console.log("H_inner:", txHash); +``` + +```text +H_inner: 0x8f3a...2d41 +``` + +가스 면제와 마찬가지로 `send`는 `H_inner`를 반환하며, `sendBatch`, `relay`, `relayBatch`도 동일하게 작동합니다. `guaranteedWaiver` 설정은 `gasWaiver`와 동일한 `allowedTargets`, `maxGasLimit`, `maxDataLength` 정책 제한을 허용합니다. + +## 거부 처리 + +`send` 및 `relay`는 거부 시 `StableEnterpriseRelayError`를 발생시킵니다. 게이트웨이별 코드에는 `GATEWAY_UNAUTHORIZED`(누락된 또는 잘못된 API 키) 및 `QUOTA_EXCEEDED`(게이트웨이 가스 할당량 소진)가 포함됩니다. + +```ts +import { StableEnterpriseRelayError } from "@stablechain/enterprise"; + +try { + await gb.send(signer, { to: recipient, gas: 21_000n, gasFeeCap, gasTipCap }); +} catch (err) { + if (err instanceof StableEnterpriseRelayError && err.code === "GATEWAY_UNAUTHORIZED") { + // 엔터프라이즈 RPC 게이트웨이가 API 키를 거부했습니다 + } + throw err; +} +``` + +```text +StableEnterpriseRelayError: relay failed [GATEWAY_UNAUTHORIZED]: invalid api key +``` + +## 다음으로 갈 곳 + +- [**가스 면제로 릴레이**](/ko/how-to/relay-with-gas-waiver): 사용자의 가스를 후원하여 USDT0 없이 트랜잭션을 처리하게 합니다. +- [**엔터프라이즈 SDK 참조**](/ko/reference/enterprise-sdk#guaranteed-blockspace): 모든 메서드, 구성 옵션 및 오류 클래스에 대한 전체 정보입니다. +- [**보장된 블록스페이스**](/ko/explanation/guaranteed-blockspace): Stable이 엔터프라이즈 워크로드를 위해 블록 용량을 예약하는 방법입니다. diff --git a/docs/pages/ko/reference/enterprise-sdk.mdx b/docs/pages/ko/reference/enterprise-sdk.mdx index 565e22f..746160f 100644 --- a/docs/pages/ko/reference/enterprise-sdk.mdx +++ b/docs/pages/ko/reference/enterprise-sdk.mdx @@ -1,6 +1,6 @@ --- source_path: reference/enterprise-sdk.mdx -source_sha: b7063f13645d37e2d66b8bb8c87b0dcfaf386a61 +source_sha: 2f9f840d9ea287e27f4642da4f0a219db13edab6 title: "엔터프라이즈 SDK 참조" description: "@stablechain/enterprise에 대한 완벽한 참조: createStableEnterprise, 가스 면제 및 보장된 블록 공간 모듈, 빌드 헬퍼 및 오류 클래스." diataxis: "reference" @@ -8,14 +8,14 @@ diataxis: "reference" # 엔터프라이즈 SDK 참조 -`@stablechain/enterprise`의 전체 표면입니다. 여기에는 [`createStableEnterprise`](#createstableenterpriseconfig)의 클라이언트, 세 가지 모듈([가스 면제](#gaswaiver-module), [보장된 블록 공간](#guaranteedblock-module), [구성된 면제](#guaranteedwaiver-module)), 저수준 빌드 헬퍼, 공유 결과 및 오류 유형이 포함됩니다. 이러한 레일에 대한 자세한 내용은 [Stable 엔터프라이즈 SDK](/ko/explanation/enterprise-sdk), [가스 면제](/ko/explanation/gas-waiver), [보장된 블록 공간](/ko/explanation/guaranteed-blockspace)을 참조하세요. +`@stablechain/enterprise`의 전체 표면입니다. 여기에는 [`createStableEnterprise`](#createstableenterpriseconfig)를 통한 클라이언트, 세 가지 기능([가스 면제를 통한 릴레이](#relay-with-gas-waiver), [보장된 블록 공간](#guaranteed-blockspace), [보장된 릴레이 트랜잭션](#guaranteed-relay-transactions)), 하위 수준 빌드 헬퍼, 공유 결과 및 오류 유형이 포함됩니다. 이러한 레일에 대한 설명은 [Stable Enterprise SDK](/ko/explanation/enterprise-sdk), [가스 면제](/ko/explanation/gas-waiver), [보장된 블록 공간](/ko/explanation/guaranteed-blockspace)을 참조하십시오. :::note -엔터프라이즈 SDK는 Stable 테스트넷에서만 사용할 수 있으며, 두 레일 모두 게이트됩니다. 통합하려면 [Stable에 문의](https://discord.gg/stablexyz)하여 거버넌스 등록 면제 키와 엔터프라이즈 RPC 게이트웨이 API 키를 받으세요. +엔터프라이즈 SDK는 현재 Stable Testnet에서만 사용할 수 있으며, 요청 시 액세스할 수 있습니다. 통합하려면 [Stable에 문의](https://discord.gg/stablexyz)하여 거버넌스에 등록된 면제 키와 엔터프라이즈 RPC 게이트웨이 API 키를 받으십시오. ::: :::warning -이것은 개인 키로 서명하는 서버 측 라이브러리입니다. 브라우저에서 실행하지 마십시오. 웨이버 키와 엔터프라이즈 RPC 게이트웨이 URL을 백엔드에 보관하십시오. +이것은 개인 키로 서명하는 서버 측 라이브러리입니다. 브라우저에서 절대 실행하지 마십시오. 면제 키와 엔터프라이즈 RPC 게이트웨이 URL을 백엔드에 보관하십시오. ::: ## 설치 @@ -28,11 +28,11 @@ npm install @stablechain/enterprise viem added 2 packages, audited 3 packages in 2s ``` -`viem >= 2.0.0`은 피어 종속성입니다. 이 패키지는 `viem/chains`에서 `stable` 및 `stableTestnet`을 다시 내보내므로 별도로 가져올 필요가 없습니다. +`viem >= 2.0.0`은 피어 의존성입니다. 이 패키지는 `viem/chains`에서 `stable` 및 `stableTestnet`을 다시 내보내므로 별도로 가져올 필요가 없습니다. ## `createStableEnterprise(config)` -`StableEnterpriseClient`를 생성합니다. 각 모듈은 구성할 때만 존재하므로, 사용 전에 `!` 또는 null 검사로 보호하십시오. +`StableEnterpriseClient`를 생성합니다. 각 모듈은 구성할 때만 존재하므로 사용하기 전에 `!` 또는 null 검사를 사용하세요. ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -50,15 +50,15 @@ StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver ### `StableEnterpriseConfig` -| **필드** | **타입** | **기본값** | **설명** | +| **필드** | **유형** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `chain` | `StableChain` | | 대상 체인입니다. `stable` 또는 `stableTestnet`을 전달합니다(패키지에서 다시 내보내기). 필수입니다. | -| `rpcEndpoints` | `string[]?` | 체인의 내장 RPC | 하나 이상의 Stable RPC 엔드포인트로, 실패 시 순서대로 시도됩니다. 개인 엔드포인트를 지정하는 경우에만 재정의합니다. | -| `enterpriseRpcEndpoints` | `string[]?` | | 하나 이상의 엔터프라이즈 RPC 게이트웨이 엔드포인트로, 실패 시 순서대로 시도됩니다. `guaranteedBlock` 및 `guaranteedWaiver`에 필요합니다. | -| `batchSizeLimit` | `number?` | `100` | 일괄 RPC 호출당 최대 트랜잭션 수입니다. | -| `gasWaiver` | `GasWaiverConfig?` | | [가스 면제 모듈](#gaswaiver-module)을 활성화합니다. | -| `guaranteedBlock` | `GuaranteedBlockConfig?` | | [보장된 블록 공간 모듈](#guaranteedblock-module)을 활성화합니다. | -| `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | [구성된 면제 모듈](#guaranteedwaiver-module)을 활성화합니다. | +| `chain` | `StableChain` | | 대상 체인. `stable` 또는 `stableTestnet`(패키지에서 다시 내보냄)을 전달하십시오. 필수. | +| `rpcEndpoints` | `string[]?` | 체인의 내장 RPC | 하나 이상의 Stable RPC 엔드포인트(실패 시 순서대로 시도). 개인 엔드포인트를 지정하는 경우에만 재정의합니다. | +| `enterpriseRpcEndpoints` | `string[]?` | | 하나 이상의 엔터프라이즈 RPC 게이트웨이 엔드포인트(실패 시 순서대로 시도). `guaranteedBlock` 및 `guaranteedWaiver`에 필요합니다. | +| `batchSizeLimit` | `number?` | `100` | 일괄 RPC 호출당 최대 트랜잭션 수. | +| `gasWaiver` | `GasWaiverConfig?` | | [가스 면제를 통한 릴레이](#relay-with-gas-waiver)를 활성화합니다. | +| `guaranteedBlock` | `GuaranteedBlockConfig?` | | [보장된 블록 공간](#guaranteed-blockspace)을 활성화합니다. | +| `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | [보장된 릴레이 트랜잭션](#guaranteed-relay-transactions)을 활성화합니다. | ### `StableEnterpriseClient` @@ -70,11 +70,11 @@ interface StableEnterpriseClient { } ``` -## `gasWaiver` 모듈 +## 가스 면제를 통한 릴레이 -가스 면제 트랜잭션을 릴레이합니다. 화이트리스트에 등록된 면제 계정은 사용자의 제로 가스 트랜잭션(InnerTx)을 WaiverTx로 래핑하고 브로드캐스트합니다. 사용자는 USDT0이 필요하지 않습니다. 모든 메서드는 래퍼 해시가 아닌 InnerTx 해시인 `H_inner`를 반환합니다. +`gasWaiver` 모듈은 가스가 면제된 트랜잭션을 릴레이합니다. 화이트리스트에 등록된 면제 계정은 사용자의 0-가스 트랜잭션(InnerTx)을 WaiverTx로 래핑하고 브로드캐스트합니다. 사용자는 USDT0이 필요하지 않습니다. 모든 메서드는 래퍼 해시가 아닌 InnerTx 해시인 `H_inner`를 반환합니다. -구성에서 `gasWaiver`를 사용하여 활성화하세요. +구성에서 `gasWaiver`로 활성화합니다. ```ts const enterprise = createStableEnterprise({ @@ -94,16 +94,16 @@ const gw = enterprise.gasWaiver!; [`ValidationLimits`](#validationlimits)를 확장합니다. -| **필드** | **타입** | **설명** | +| **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `account` | `LocalAccount` | 각 WaiverTx에 서명하는 화이트리스트에 등록된 거버넌스 계정입니다. | +| `account` | `LocalAccount` | 각 WaiverTx에 서명하는 화이트리스트에 등록된 거버넌스 등록 계정입니다. | | `maxGasLimit` | `bigint?` | `ValidationLimits`에서 상속됩니다. | | `maxDataLength` | `number?` | `ValidationLimits`에서 상속됩니다. | | `allowedTargets` | `AllowedTarget[]?` | `ValidationLimits`에서 상속됩니다. | ### `send(account, tx)` -`account`에서 하나의 InnerTx를 한 번의 호출로 빌드, 서명 및 릴레이합니다. `gasPrice: 0`, 레거시 유형, `chainId`, 보류 중인 nonce는 자동으로 처리됩니다. 거부 시 `StableEnterpriseRelayError`를 throw합니다. +`account`에서 하나의 InnerTx를 빌드, 서명 및 릴레이하는 한 번의 호출입니다. `gasPrice: 0`, 레거시 유형, `chainId`, 대기 중인 논스가 자동으로 처리됩니다. 거부 시 `StableEnterpriseRelayError`를 발생시킵니다. ```ts const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); @@ -113,11 +113,11 @@ const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); { txHash: "0x8f3a...2d41" } ``` -`tx` 인수는 [`WaiverInnerTx`](#waiverinnertx)와 선택적 `nonce`입니다. [`RelayResult`](#relayresult)를 반환합니다. +`tx` 인수는 선택적 `nonce`가 추가된 [`WaiverInnerTx`](#waiverinnertx)입니다. [`RelayResult`](#relayresult)를 반환합니다. ### `sendBatch(account, txs)` -하나의 `account`에서 여러 InnerTx를 빌드, 서명 및 릴레이합니다. Nonce는 계정의 보류 중인 nonce에서 자동으로 순서가 지정됩니다. 입력당 하나의 결과를 순서대로 반환합니다. +하나의 `account`에서 여러 InnerTx를 빌드, 서명 및 릴레이합니다. 논스는 계정의 대기 중인 논스에서 자동으로 시퀀스됩니다. 순서대로 입력당 하나의 결과를 반환합니다. ```ts const results = await gw.sendBatch(user, [ @@ -134,7 +134,7 @@ const results = await gw.sendBatch(user, [ ### `relay(signedInnerTxHex)` -사전 서명된 제로 가스 InnerTx를 릴레이합니다. 사용자 키를 볼 수 없도록 사용자가 자신의 환경에서 서명하고 서명된 hex만 전달하는 비관리형 흐름에 사용하십시오. [`buildWaiverInnerTx`](#buildwaiverinnertxaccount-chainid-req)로 빌드합니다. 거부 시 throw합니다. +미리 서명된 0-가스 InnerTx를 릴레이합니다. 사용자가 자신의 환경에서 서명하고 서명된 헥스만 전달하여 면제 운영자가 사용자의 키를 보지 못하는 비보관 흐름에 이 메서드를 사용하십시오. [`buildWaiverInnerTx`](#buildwaiverinnertxaccount-chainid-req)로 빌드합니다. 거부 시 발생합니다. ```ts import { buildWaiverInnerTx } from "@stablechain/enterprise"; @@ -149,7 +149,7 @@ const { txHash } = await gw.relay(signed); ### `relayBatch(signedInnerTxHexes)` -사전 서명된 InnerTx의 배치를 릴레이합니다. 입력당 하나의 [`BatchResultItem`](#batchresultitem)을 순서대로 반환합니다. +미리 서명된 InnerTx 배치를 릴레이합니다. 입력당 하나의 [`BatchResultItem`](#batchresultitem)을 순서대로 반환합니다. ```ts const results = await gw.relayBatch([signed0, signed1]); @@ -159,11 +159,11 @@ 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)를 릴레이하여 예약된 엔터프라이즈 레인 블록 공간에 착륙시킵니다. 가스 면제와 달리 서명자는 자체 가스를 지불하며 자금이 지원되어야 합니다. 각 트랜잭션은 엔터프라이즈 레인에 키가 지정된 2D 논스를 전달하며, 브로드캐스팅은 게이트웨이를 통해서만 이루어집니다. +`guaranteedBlock` 모듈은 엔터프라이즈 RPC 게이트웨이를 통해 GuaranteedTx(유형 `0x3F` CustomTx)를 릴레이하여 예약된 엔터프라이즈 레인 블록 공간에 배치되도록 합니다. 가스 면제와 달리 서명자는 자체 가스를 지불하며 자금이 있어야 합니다. 각 트랜잭션은 엔터프라이즈 레인에 키가 지정된 2D 논스를 전달하며, 브로드캐스팅은 게이트웨이를 통해서만 이루어집니다. -`guaranteedBlock`과 `enterpriseRpcEndpoints`를 사용하여 활성화하세요. +`guaranteedBlock`과 `enterpriseRpcEndpoints`로 활성화합니다. ```ts const enterprise = createStableEnterprise({ @@ -180,14 +180,14 @@ const gb = enterprise.guaranteedBlock!; ### `GuaranteedBlockConfig` -| **필드** | **타입** | **설명** | +| **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `account` | `LocalAccount` | 각 GuaranteedTx에 서명하고 가스를 지불하는 자금이 지원되는 계정입니다. | -| `laneId` | `bigint` | 엔터프라이즈 레인 ID입니다. `[0, ENTERPRISE_MASK - 1]` 범위 내에 있어야 합니다. 유효하지 않은 ID는 즉시 거부됩니다. | +| `account` | `LocalAccount` | 각 GuaranteedTx에 서명하고 가스를 지불하는 자금이 있는 계정입니다. | +| `laneId` | `bigint` | 엔터프라이즈 레인 ID입니다. `[0, ENTERPRISE_MASK - 1]` 범위에 있어야 합니다. 유효하지 않은 ID는 즉시 거부됩니다. | ### `send(account, tx)` -하나의 GuaranteedTx를 빌드, 서명 및 릴레이합니다. 서명자가 가스를 지불하므로 1559 수수료 필드가 필요합니다. `chainId`, 엔터프라이즈 `nonceKey`, 그리고 2D nonce(게이트웨이에서 검색됨)는 자동으로 처리됩니다. +하나의 GuaranteedTx를 빌드, 서명 및 릴레이합니다. 1559 수수료 필드는 서명자가 가스를 지불하므로 필수입니다. `chainId`, 엔터프라이즈 `nonceKey`, 2D nonce(게이트웨이에서 검색)가 자동으로 처리됩니다. ```ts const gasPrice = await publicClient.getGasPrice(); @@ -204,11 +204,11 @@ const { txHash } = await gb.send(signer, { { txHash: "0xabcd...7890" } ``` -`tx` 인수는 [`GuaranteedTxRequest`](#guaranteedtxrequest)와 선택적 `nonce`입니다. [`RelayResult`](#relayresult)를 반환합니다. +`tx` 인수는 선택적 `nonce`가 추가된 [`GuaranteedTxRequest`](#guaranteedtxrequest)입니다. [`RelayResult`](#relayresult)를 반환합니다. ### `sendBatch(account, txs)` -여러 GuaranteedTx를 빌드, 서명 및 릴레이합니다. Nonce는 검색된 베이스에서 자동으로 순서가 지정됩니다. 실패는 후속 트랜잭션에 영향을 미칩니다. +여러 GuaranteedTx를 빌드, 서명 및 릴레이합니다. 논스는 검색된 기본값에서 자동으로 시퀀스됩니다. 실패는 후속 트랜잭션을 좌초시킵니다. ```ts const results = await gb.sendBatch(signer, [ @@ -225,7 +225,7 @@ const results = await gb.sendBatch(signer, [ ### `relay(signedTx)` / `relayBatch(signedTxs)` -사전 서명된 GuaranteedTx 또는 그 배치들을 릴레이합니다. [`nonceKeyForLane`](#noncekeyforlanelaneid)을 엔터프라이즈 nonce 키로 사용하여 [`buildGuaranteedTx`](#buildguaranteedtxaccount-chainid-req)로 트랜잭션을 다른 곳에서 빌드 및 서명한 다음, 운영자에게 서명된 hex만 전달합니다. +미리 서명된 GuaranteedTx 또는 배치로 릴레이합니다. 엔터프라이즈 nonce 키에는 [`nonceKeyForLane`](#noncekeyforlanelaneid)를 사용하여 [`buildGuaranteedTx`](#buildguaranteedtxaccount-chainid-req)로 트랜잭션을 다른 곳에서 빌드하고 서명한 다음 서명된 헥스만 운영자에게 전달합니다. ```ts import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; @@ -245,11 +245,11 @@ const { txHash } = await gb.relay(signed); { txHash: "0xabcd...7890" } ``` -## `guaranteedWaiver` 모듈 +## 보장된 릴레이 트랜잭션 -위의 두 레일의 결합: 보장된 블록 공간을 통해 라우팅되는 가스 면제 트랜잭션입니다. 내부 및 외부 트랜잭션 모두 하나의 엔터프라이즈 `nonceKey`를 공유하는 `0x3F` CustomTx이므로 `guaranteedBlock`과 같이 게이트웨이를 통해 브로드캐스트됩니다. 면제가 가스를 지원하므로 사용자는 `gasWaiver`와 마찬가지로 잔액이나 수수료 필드가 필요하지 않습니다. 모든 메서드는 `H_inner`를 반환합니다. +`guaranteedWaiver` 모듈은 위 두 가지 레일을 결합합니다. 즉, 보장된 블록 공간을 통해 라우팅되는 가스 면제 트랜잭션입니다. 내부 및 외부 트랜잭션 모두 하나의 엔터프라이즈 `nonceKey`를 공유하는 `0x3F` CustomTx이므로 `guaranteedBlock`과 같이 게이트웨이를 통해 브로드캐스트됩니다. 면제가 가스를 보조하므로 사용자는 `gasWaiver`와 같이 잔액이나 수수료 필드가 필요하지 않습니다. 모든 메서드는 `H_inner`를 반환합니다. -`guaranteedWaiver`와 `enterpriseRpcEndpoints`를 사용하여 활성화하십시오. +`guaranteedWaiver`와 `enterpriseRpcEndpoints`로 활성화합니다. ```ts const enterprise = createStableEnterprise({ @@ -266,22 +266,22 @@ const gw = enterprise.guaranteedWaiver!; ### `GuaranteedWaiverConfig` -[`ValidationLimits`](#validationlimits)를 확장하므로 `GasWaiverConfig`와 동일한 `maxGasLimit`, `maxDataLength`, `allowedTargets` 정책 제어를 허용합니다. +[`ValidationLimits`](#validationlimits)를 확장하므로 `GasWaiverConfig`와 동일한 `maxGasLimit`, `maxDataLength` 및 `allowedTargets` 정책 제어를 허용합니다. -| **필드** | **타입** | **설명** | +| **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `waiverAccount` | `LocalAccount` | 외부 래퍼에 서명하는 화이트리스트에 등록된 거버넌스 계정입니다. | -| `laneId` | `bigint` | 엔터프라이즈 레인 ID입니다. `[0, ENTERPRISE_MASK - 1]` 범위 내에 있어야 합니다. | +| `waiverAccount` | `LocalAccount` | 외부 래퍼에 서명하는 화이트리스트에 등록된 거버넌스 등록 계정입니다. | +| `laneId` | `bigint` | 엔터프라이즈 레인 ID입니다. `[0, ENTERPRISE_MASK - 1]` 범위에 있어야 합니다. | ### `send(user, tx)` / `sendBatch(user, txs)` -`user`에서 내부 `0x3F` CustomTx를 빌드 및 서명하고, 면제 키로 래핑한 다음 릴레이합니다. 가스가 면제되므로 수수료 필드는 필요하지 않습니다. 내부 2D nonce는 게이트웨이에서 감지되며, 일괄 처리는 해당 기준에서 자동으로 시퀀싱됩니다. +`user`로부터 내부 `0x3F` CustomTx를 빌드하고 서명한 다음, 면제 키로 래핑하고 릴레이합니다. 가스가 면제되므로 수수료 필드는 필요하지 않습니다. 내부 2D 논스는 게이트웨이에서 검색되며, 배치는 해당 기본값에서 자동으로 시퀀스됩니다. ```ts // 단일 const { txHash } = await gw.send(user, { to: recipient }); -// 일괄 +// 배치 const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); ``` @@ -289,11 +289,11 @@ const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); { txHash: "0x8f3a...2d41" } ``` -`tx` 인수는 [`GuaranteedWaiverTxRequest`](#guaranteedwaivertxrequest)와 선택적 `nonce`입니다. `send`는 [`RelayResult`](#relayresult)를 반환하고, `sendBatch`는 [`BatchResultItem[]`](#batchresultitem)을 반환합니다. +`tx` 인수는 선택적 `nonce`가 추가된 [`GuaranteedWaiverTxRequest`](#guaranteedwaivertxrequest)입니다. `send`는 [`RelayResult`](#relayresult)를 반환하고, `sendBatch`는 [`BatchResultItem[]`](#batchresultitem)을 반환합니다. ### `relay(signedInnerTx)` / `relayBatch(signedInnerTxs)` -비관리형 흐름의 경우, 사용자는 [`buildGuaranteedTx`](#buildguaranteedtxaccount-chainid-req)로 내부 `0x3F` CustomTx에 서명하고(수수료 `0n`, `nonceKeyForLane(laneId)` 사용), 운영자에게 서명된 Hex 문자열만 전달합니다. 운영자는 이를 면제 키로 래핑하고 릴레이합니다. +비보관 흐름의 경우, 사용자는 [`buildGuaranteedTx`](#buildguaranteedtxaccount-chainid-req)로 내부 `0x3F` CustomTx에 서명(수수료 `0n`, `nonceKeyForLane(laneId)` 사용)하고 서명된 헥스만 운영자에게 전달합니다. 운영자는 면제 키로 래핑하고 릴레이합니다. ```ts import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; @@ -306,7 +306,7 @@ const signedInner = await buildGuaranteedTx(user, stableTestnet.id, { nonce, nonceKey: nonceKeyForLane(0n), }); -const { txHash } = await gw.relay(signedInner); // 면제가 래핑 + 브로드캐스트 → H_inner +const { txHash } = await gw.relay(signedInner); // 면제 래핑 + 브로드캐스트 → H_inner ``` ```text @@ -315,11 +315,11 @@ const { txHash } = await gw.relay(signedInner); // 면제가 래핑 + 브로드 ## 빌드 헬퍼 -비관리형 `relay` 경로를 위한 저수준 서명자입니다. 각 함수는 논스 가져오기 또는 수수료 추정 없이 서명된 트랜잭션을 `Hex`로 반환합니다. +비보관 `relay` 경로에 대한 저수준 서명자입니다. 각각은 논스 가져오기 또는 수수료 예측 없이 서명된 트랜잭션을 `Hex`로 반환합니다. ### `buildWaiverInnerTx(account, chainId, req)` -`gasPrice: 0`, 레거시 유형, 지정된 `chainId`와 같이 웨이버 불변성이 포함된 웨이버 준비 InnerTx에 서명합니다. `req`는 [`WaiverInnerTx`](#waiverinnertx)와 필수 `nonce`입니다. +`gasPrice: 0`, 레거시 유형, 지정된 `chainId`가 포함된 면제 가능 InnerTx에 서명합니다. `req`는 필수 `nonce`와 함께 [`WaiverInnerTx`](#waiverinnertx)입니다. ```ts const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to, data, gas: 150_000n, nonce }); @@ -327,15 +327,15 @@ const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to, data, gas: ### `buildGuaranteedTx(account, chainId, req)` -GuaranteedTx(`0x3F` CustomTx)를 빌드하고 서명합니다. `req`는 [`GuaranteedTxRequest`](#guaranteedtxrequest)와 필수 `nonce` 및 `nonceKey`입니다. +GuaranteedTx(`0x3F` CustomTx)를 빌드하고 서명합니다. `req`는 필수 `nonce`와 `nonceKey`와 함께 [`GuaranteedTxRequest`](#guaranteedtxrequest)입니다. ### `buildGuaranteedWaiverTx(...)` -사전 서명된 내부 트랜잭션을 외부 `0x3F` 웨이버 CustomTx로 래핑합니다. `guaranteedWaiver.relay`에서 내부적으로 사용되며, 고급 흐름을 위해 내보내집니다. +미리 서명된 내부 트랜잭션을 외부 `0x3F` 면제 CustomTx로 래핑합니다. `guaranteedWaiver.relay`에서 내부적으로 사용됩니다. 고급 흐름을 위해 내보내집니다. ### `nonceKeyForLane(laneId)` -`buildGuaranteedTx`에서 사용하기 위한 레인 ID에 대한 엔터프라이즈 `nonceKey`를 반환합니다. +`buildGuaranteedTx`에서 사용할 레인 ID에 대한 엔터프라이즈 `nonceKey`를 반환합니다. ```ts import { nonceKeyForLane } from "@stablechain/enterprise"; @@ -347,82 +347,82 @@ const nonceKey = nonceKeyForLane(0n); ### `WaiverInnerTx` -호출마다 달라지는 InnerTx 필드입니다. +호출당 달라지는 InnerTx의 필드입니다. -| **필드** | **타입** | **기본값** | **설명** | +| **필드** | **유형** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `to` | `Address` | | 대상 주소: ERC-20 전송을 위한 토큰 계약, 기본 전송을 위한 수신자. | -| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | 가스 한도입니다. `gasPrice`가 0이므로 여유 있는 한도는 무료입니다. | -| `data` | `Hex?` | `"0x"` | 칼데이터. | -| `value` | `bigint?` | `0n` | 보낼 기본값입니다. | +| `to` | `Address` | | 대상 주소: ERC-20 전송의 경우 토큰 계약, 네이티브 전송의 경우 수신자. | +| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | 가스 한도. `gasPrice`가 0이므로 관대한 한도는 무료입니다. | +| `data` | `Hex?` | `"0x"` | 콜데이터. | +| `value` | `bigint?` | `0n` | 전송할 네이티브 값. | ### `GuaranteedTxRequest` -| **필드** | **타입** | **기본값** | **설명** | +| **필드** | **유형** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | | `to` | `Address?` | | 대상 주소. | -| `gas` | `bigint` | | 가스 한도. 필수입니다. | -| `gasFeeCap` | `bigint` | | `maxFeePerGas`. 필수입니다. | -| `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`. 필수입니다. | -| `data` | `Hex?` | `"0x"` | 칼데이터. | -| `value` | `bigint?` | `0n` | 보낼 네이티브 값. | +| `gas` | `bigint` | | 가스 한도. 필수. | +| `gasFeeCap` | `bigint` | | `maxFeePerGas`. 필수. | +| `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`. 필수. | +| `data` | `Hex?` | `"0x"` | 콜데이터. | +| `value` | `bigint?` | `0n` | 전송할 네이티브 값. | ### `GuaranteedWaiverTxRequest` -수수료 필드는 항상 0이므로 여기서는 제외됩니다. +수수료 필드는 항상 0이므로 여기서는 생략됩니다. -| **필드** | **타입** | **기본값** | **설명** | +| **필드** | **유형** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | | `to` | `Address` | | 대상 주소. | -| `gas` | `bigint?` | 공유되는 내부 가스 기본값 | 가스 한도. | -| `data` | `Hex?` | `"0x"` | 칼데이터. | -| `value` | `bigint?` | `0n` | 전송할 네이티브 값. 웨이버의 경우 값 전송이 허용됩니다. | +| `gas` | `bigint?` | 공유 내부 가스 기본값 | 가스 한도. | +| `data` | `Hex?` | `"0x"` | 콜데이터. | +| `value` | `bigint?` | `0n` | 전송할 네이티브 값. 면제는 값 전송을 허용합니다. | ### `ValidationLimits` `gasWaiver` 및 `guaranteedWaiver`에 의해 각 InnerTx에 적용되는 파트너별 정책입니다. -| **필드** | **타입** | **기본값** | **설명** | +| **필드** | **유형** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `maxGasLimit` | `bigint?` | `10_000_000n` | InnerTx의 최대 가스 한도. 초과 시 `GAS_LIMIT_EXCEEDED`와 함께 실패합니다. | -| `maxDataLength` | `number?` | `131_072` (128KB) | 칼데이터의 최대 크기(바이트). 초과 시 `DATA_TOO_LARGE`와 함께 실패합니다. | -| `allowedTargets` | `AllowedTarget[]?` | | 웨이버가 지원할 수 있는 계약 및 메서드의 허용 목록입니다. 설정되면 목록 외부의 대상은 `TARGET_NOT_ALLOWED`와 함께 실패합니다. | +| `maxGasLimit` | `bigint?` | `10_000_000n` | InnerTx의 최대 가스 한도. 초과하면 `GAS_LIMIT_EXCEEDED` 오류가 발생합니다. | +| `maxDataLength` | `number?` | `131_072` (128KB) | 바이트 단위로 된 최대 콜데이터 크기. 초과하면 `DATA_TOO_LARGE` 오류가 발생합니다. | +| `allowedTargets` | `AllowedTarget[]?` | | 면제를 후원할 수 있는 계약 및 메서드의 허용 목록. 설정된 경우 목록 외의 대상은 `TARGET_NOT_ALLOWED` 오류가 발생합니다. | ### `AllowedTarget` -| **필드** | **타입** | **설명** | +| **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `address` | `Address \| "*"` | InnerTx가 호출할 수 있는 컨트랙트 또는 모든 컨트랙트와 일치하는 `"*"`. | -| `selectors` | `Hex[]?` | 허용된 4바이트 메서드 셀렉터(예: ERC-20 `transfer`의 `"0xa9059cbb"`). `address`의 모든 메서드를 허용하려면 생략하거나 비워 둡니다. | +| `address` | `Address \| "*"` | InnerTx가 호출할 수 있는 계약, 또는 `"*"`는 모든 계약과 일치합니다. | +| `selectors` | `Hex[]?` | 허용되는 4바이트 메서드 선택자(예: ERC-20 `transfer`의 경우 `"0xa9059cbb"`). `address`에서 모든 메서드를 허용하려면 생략하거나 비워 둡니다. | ### `RelayResult` ```ts interface RelayResult { - txHash: Hash; // 웨이버의 H_inner, 독립형 보장 블록의 GuaranteedTx 해시 + txHash: Hash; // 면제의 경우 H_inner, 독립형 보장된 블록의 경우 GuaranteedTx 해시 } ``` ### `BatchResultItem` -배치에서 입력 순서대로 각 입력에 대한 하나의 항목입니다. throw하는 대신 배치는 항목별 결과를 표시합니다. +배치 내의 입력당 하나의 항목으로 입력 순서대로 정렬됩니다. 발생시키는 대신, 배치는 항목별 결과를 보여줍니다. -| **필드** | **타입** | **설명** | +| **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `index` | `number` | 입력 배열과 일치하는 0부터 시작하는 위치입니다. | +| `index` | `number` | 입력 배열과 일치하는 0부터 시작하는 위치. | | `success` | `boolean` | 이 항목이 릴레이되었는지 여부. | | `txHash` | `Hash?` | 성공 시 존재: 내부 트랜잭션 해시. | | `error` | `{ code: ErrorCode; message: string }?` | 실패 시 존재. | -## 에러 +## 오류 -단일 트랜잭션 메서드(`send`, `relay`)는 거부 시 실패를 throw합니다. 배치 메서드는 [`BatchResultItem.error`](#batchresultitem)에서 항목별 실패를 보고합니다. 모든 오류 클래스는 `StableEnterpriseError`를 확장합니다. +단일 트랜잭션 메서드(`send`, `relay`)는 거부 시 발생합니다. 배치 메서드는 대신 [`BatchResultItem.error`](#batchresultitem)에서 항목별 실패를 보고합니다. 모든 오류 클래스는 `StableEnterpriseError`를 확장합니다. | **클래스** | **발생 시점** | **유용한 필드** | | :--- | :--- | :--- | | `StableEnterpriseError` | 모든 SDK 오류의 기본 클래스. | `message` | -| `StableEnterpriseRelayError` | 트랜잭션이 RPC 또는 릴레이 계층에서 거부되었을 때. | `code` | -| `WaiverValidationError` | InnerTx가 브로드캐스트 전에 정책 검사(가스, 데이터 크기 또는 대상 허용 목록)에 실패했을 때. | `code` | +| `StableEnterpriseRelayError` | RPC 또는 릴레이 계층에서 트랜잭션이 거부됩니다. | `code` | +| `WaiverValidationError` | InnerTx가 브로드캐스트 전에 정책 검사(가스, 데이터 크기 또는 대상 허용 목록)에 실패합니다. | `code` | ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -431,7 +431,7 @@ try { await gw.send(user, { to: token, data }); } catch (err) { if (err instanceof StableEnterpriseRelayError && err.code === "TARGET_NOT_ALLOWED") { - // InnerTx 대상이 구성된 허용 목록 외부에 있음 + // InnerTx 대상이 구성된 허용 목록 외부에 있습니다. } throw err; } @@ -443,33 +443,33 @@ StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not ### `ErrorCode` -throw된 오류 또는 `BatchResultItem.error`의 `code`는 다음 중 하나입니다. +발생된 오류 또는 `BatchResultItem.error`의 `code`는 다음 중 하나입니다. | **코드** | **의미** | | :--- | :--- | -| `UNKNOWN_ERROR` | 특정 코드를 사용할 수 없을 때의 폴백. | +| `UNKNOWN_ERROR` | 특정 코드를 사용할 수 없을 때의 대체. | | `BROADCAST_FAILED` | RPC 계층에서 브로드캐스트가 거부되거나 게이트웨이가 릴레이에 실패했습니다. | -| `INVALID_TRANSACTION` | InnerTx 디코딩 또는 파싱에 실패했습니다. | +| `INVALID_TRANSACTION` | InnerTx 디코딩 또는 구문 분석에 실패했습니다. | | `INVALID_SIGNATURE` | 서명 확인에 실패했습니다. | -| `UNSUPPORTED_TX_TYPE` | InnerTx 유형이 legacy, eip2930 또는 eip1559가 아닙니다. | -| `WRONG_CHAIN_ID` | InnerTx `chainId`가 없거나 대상 체인과 일치하지 않습니다. | -| `NON_ZERO_GAS_PRICE` | InnerTx에 0이 아닌 가스 가격이 포함되어 있습니다(웨이버의 경우 0이어야 함). | +| `UNSUPPORTED_TX_TYPE` | InnerTx 유형이 레거시, eip2930 또는 eip1559가 아닙니다. | +| `WRONG_CHAIN_ID` | InnerTx `chainId`가 누락되었거나 대상 체인과 일치하지 않습니다. | +| `NON_ZERO_GAS_PRICE` | InnerTx에 0이 아닌 가스 가격이 포함되어 있습니다(면제의 경우 0이어야 합니다). | | `GAS_LIMIT_EXCEEDED` | InnerTx 가스 한도가 `maxGasLimit`을 초과합니다. | -| `DATA_TOO_LARGE` | InnerTx calldata가 `maxDataLength`를 초과합니다. | +| `DATA_TOO_LARGE` | InnerTx 콜데이터가 `maxDataLength`를 초과합니다. | | `TARGET_NOT_ALLOWED` | InnerTx 대상이 `allowedTargets`에 없습니다. | | `GATEWAY_UNAUTHORIZED` | 엔터프라이즈 RPC 게이트웨이가 API 키를 거부했습니다(누락, 유효하지 않거나 만료됨). | -| `QUOTA_EXCEEDED` | 엔터프라이즈 RPC 게이트웨이 가스 할당량이 소진되었습니다. | +| `QUOTA_EXCEEDED` | 엔터프라이즈 RPC 게이트웨이 가스 할당량이 초과되었습니다. | ## 상수 -| **상수** | **타입** | **설명** | +| **상수** | **유형** | **설명** | | :--- | :--- | :--- | -| `DEFAULT_INNER_GAS` | `bigint` | `gas`를 생략할 때의 기본 InnerTx 가스 제한(`150_000n`). | -| `ENTERPRISE_FLAG` | `bigint` | 레인의 `nonceKey`에 설정된 엔터프라이즈 비트. | -| `ENTERPRISE_MASK` | `bigint` | 레인 ID의 상한: `laneId`는 `[0, ENTERPRISE_MASK - 1]` 범위 내에 있어야 합니다. | +| `DEFAULT_INNER_GAS` | `bigint` | `gas`가 생략될 때의 기본 InnerTx 가스 한도(`150_000n`). | +| `ENTERPRISE_FLAG` | `bigint` | 레인의 `nonceKey`에 설정된 엔터프라이즈 비트입니다. | +| `ENTERPRISE_MASK` | `bigint` | 레인 ID의 상한: `laneId`는 `[0, ENTERPRISE_MASK - 1]` 범위에 있어야 합니다. | -## 다음 권장 사항 +## 다음으로 권장되는 항목 -- [**Stable 엔터프라이즈 SDK**](/ko/explanation/enterprise-sdk): 레일이 무엇이며 언제 사용해야 하는지. +- [**Stable Enterprise SDK**](/ko/explanation/enterprise-sdk): 레일이 무엇이고 언제 사용해야 하는지. - [**가스 면제 프로토콜**](/ko/reference/gas-waiver-api): 트랜잭션 형식, 마커 라우팅 및 거버넌스 제어. -- [**보장된 블록 공간**](/ko/explanation/guaranteed-blockspace): Stable이 엔터프라이즈 워크로드에 대한 블록 용량을 예약하는 방법. +- [**보장된 블록 공간**](/ko/explanation/guaranteed-blockspace): Stable이 엔터프라이즈 워크로드에 대해 블록 용량을 예약하는 방법. diff --git a/docs/sidebar.json b/docs/sidebar.json index 1790ce2..5c2941e 100644 --- a/docs/sidebar.json +++ b/docs/sidebar.json @@ -709,7 +709,7 @@ "link": "/ko/explanation/core-concepts" }, { - "text": "주요 기능", + "text": "주요 특징", "link": "/ko/explanation/key-features" }, { @@ -739,11 +739,11 @@ ] }, { - "text": "USDT0 기능", + "text": "USDT0 특징", "collapsed": true, "items": [ { - "text": "USDT 기능 개요", + "text": "USDT 특징 개요", "link": "/ko/explanation/usdt-features-overview" }, { @@ -759,7 +759,7 @@ "link": "/ko/explanation/bridge-security" }, { - "text": "Gas 토큰으로서의 USDT", + "text": "가스 토큰으로서의 USDT", "link": "/ko/explanation/usdt-as-gas-token" }, { @@ -775,7 +775,7 @@ "link": "/ko/explanation/guaranteed-blockspace" }, { - "text": "USDT 전송 애그리게이터", + "text": "USDT 전송 Aggregator", "link": "/ko/explanation/usdt-transfer-aggregator" }, { @@ -819,25 +819,25 @@ "collapsed": true, "items": [ { - "text": "결제 사용 사례", + "text": "사용 사례: 결제", "link": "/ko/explanation/use-case-payments" }, { - "text": "급여 사용 사례", + "text": "사용 사례: 급여", "link": "/ko/explanation/use-case-payroll" }, { - "text": "스폰서 사용 사례", + "text": "사용 사례: 스폰서", "link": "/ko/explanation/use-case-sponsored" }, { - "text": "프라이빗 사용 사례", + "text": "사용 사례: 비공개", "link": "/ko/explanation/use-case-private" } ] }, { - "text": "토크노믹스", + "text": "토큰노믹스", "link": "/ko/reference/tokenomics" }, { @@ -875,7 +875,7 @@ "link": "/ko/tutorial/sdk-quickstart" }, { - "text": "참고 자료", + "text": "참조", "link": "/ko/reference/sdk" }, { @@ -902,14 +902,14 @@ }, { "text": "가스 면제", - "link": "/ko/explanation/gas-waiver" + "link": "/ko/how-to/relay-with-gas-waiver" }, { "text": "보장된 블록 공간", - "link": "/ko/explanation/guaranteed-blockspace" + "link": "/ko/how-to/send-guaranteed-transactions" }, { - "text": "참고 자료", + "text": "참조", "link": "/ko/reference/enterprise-sdk" } ] @@ -965,7 +965,7 @@ "link": "/ko/how-to/zero-gas-transactions" }, { - "text": "USDT Gas 작업", + "text": "USDT 가스와 함께 작업", "link": "/ko/how-to/work-with-usdt-gas" }, { @@ -987,7 +987,7 @@ "link": "/ko/how-to/subscribe-and-collect" }, { - "text": "인보이스로 결제", + "text": "송장으로 결제", "link": "/ko/how-to/pay-with-invoice" } ] @@ -1013,15 +1013,15 @@ "link": "/ko/reference/subscriptions" }, { - "text": "인보이스", + "text": "송장", "link": "/ko/reference/invoices" }, { - "text": "호출당 지불", + "text": "통화당 지불", "link": "/ko/reference/pay-per-call" }, { - "text": "예정된 사용 사례", + "text": "향후 사용 사례", "link": "/ko/explanation/upcoming-use-cases" } ] @@ -1029,31 +1029,31 @@ ] }, { - "text": "스마트 컨트랙트 배포", + "text": "계약 배포", "collapsed": true, "items": [ { - "text": "컨트랙트 개요", + "text": "계약 개요", "link": "/ko/explanation/contracts-overview" }, { - "text": "컨트랙트 색인", + "text": "계약 색인", "link": "/ko/explanation/contracts-guides" }, { - "text": "첫 컨트랙트 배포", + "text": "첫 번째 계약 배포", "collapsed": true, "items": [ { - "text": "스마트 컨트랙트", + "text": "스마트 계약", "link": "/ko/tutorial/smart-contract" }, { - "text": "컨트랙트 확인", + "text": "계약 확인", "link": "/ko/how-to/verify-contract" }, { - "text": "컨트랙트 색인", + "text": "계약 색인", "link": "/ko/how-to/index-contract" } ] @@ -1171,7 +1171,7 @@ "link": "/ko/reference/testnet-version-history" }, { - "text": "테스트넷 생태계", + "text": "테스트넷 Ecosystem", "link": "/ko/reference/testnet-ecosystem" } ] @@ -1209,7 +1209,7 @@ "link": "/ko/reference/bridges" }, { - "text": "DEX", + "text": "Dexes", "link": "/ko/reference/dexes" }, { @@ -1225,7 +1225,7 @@ "link": "/ko/reference/network-routing" }, { - "text": "온/오프 램프", + "text": "Ramps", "link": "/ko/reference/ramps" }, { @@ -1233,7 +1233,7 @@ "link": "/ko/reference/wallets" }, { - "text": "커스터디", + "text": "수호", "link": "/ko/reference/custody" }, { @@ -1243,7 +1243,7 @@ ] }, { - "text": "운영 준비 완료", + "text": "프로덕션 준비성", "link": "/ko/how-to/production-readiness" }, { @@ -1251,7 +1251,7 @@ "link": "/ko/reference/developer-assistance" }, { - "text": "리소스", + "text": "자료", "collapsed": true, "items": [ { @@ -1317,7 +1317,7 @@ "link": "/ko/explanation/ai-agents-guides" }, { - "text": "x402 및 MPP로 결제", + "text": "x402 및 MPP를 통한 결제", "collapsed": true, "items": [ { @@ -1333,7 +1333,7 @@ "link": "/ko/explanation/mpp-sessions" }, { - "text": "호출당 지불 구축", + "text": "통화당 지불 구축", "link": "/ko/how-to/build-pay-per-call" }, { @@ -1351,15 +1351,15 @@ "collapsed": true, "items": [ { - "text": "AI로 개발", + "text": "AI 개발", "link": "/ko/how-to/develop-with-ai" }, { - "text": "자율 촉진자", + "text": "Agentic Facilitators", "link": "/ko/reference/agentic-facilitators" }, { - "text": "자율 지갑", + "text": "Agentic Wallets", "link": "/ko/reference/agentic-wallets" } ] @@ -1393,11 +1393,11 @@ "link": "/cn/explanation/core-concepts" }, { - "text": "主要功能", + "text": "主要特点", "link": "/cn/explanation/key-features" }, { - "text": "以太坊对比", + "text": "与以太坊的比较", "link": "/cn/explanation/ethereum-comparison" }, { @@ -1439,7 +1439,7 @@ "link": "/cn/explanation/usdt0-bridging" }, { - "text": "跨链安全", + "text": "桥接安全", "link": "/cn/explanation/bridge-security" }, { @@ -1455,15 +1455,15 @@ "link": "/cn/explanation/gas-waiver" }, { - "text": "保障区块空间", + "text": "保证区块空间", "link": "/cn/explanation/guaranteed-blockspace" }, { - "text": "USDT 传输聚合器", + "text": "USDT 交易聚合器", "link": "/cn/explanation/usdt-transfer-aggregator" }, { - "text": "保密传输", + "text": "保密交易", "link": "/cn/explanation/confidential-transfer" } ] @@ -1507,7 +1507,7 @@ "link": "/cn/explanation/use-case-payments" }, { - "text": "用例:工资", + "text": "用例:薪酬", "link": "/cn/explanation/use-case-payroll" }, { @@ -1543,7 +1543,7 @@ "link": "/cn/explanation/build-overview" }, { - "text": "快速开始", + "text": "快速入门", "link": "/cn/tutorial/quick-start" }, { @@ -1586,11 +1586,11 @@ }, { "text": "Gas 豁免", - "link": "/cn/explanation/gas-waiver" + "link": "/cn/how-to/relay-with-gas-waiver" }, { - "text": "保障区块空间", - "link": "/cn/explanation/guaranteed-blockspace" + "text": "保证区块空间", + "link": "/cn/how-to/send-guaranteed-transactions" }, { "text": "参考", @@ -1599,7 +1599,7 @@ ] }, { - "text": "用户引导", + "text": "用户注册", "collapsed": true, "items": [ { @@ -1625,7 +1625,7 @@ ] }, { - "text": "接受支付", + "text": "接受付款", "collapsed": true, "items": [ { @@ -1671,7 +1671,7 @@ "link": "/cn/how-to/subscribe-and-collect" }, { - "text": "发票支付", + "text": "通过发票支付", "link": "/cn/how-to/pay-with-invoice" } ] @@ -1701,7 +1701,7 @@ "link": "/cn/reference/invoices" }, { - "text": "按次计费", + "text": "按次付费", "link": "/cn/reference/pay-per-call" }, { @@ -1713,7 +1713,7 @@ ] }, { - "text": "发布合约", + "text": "部署合约", "collapsed": true, "items": [ { @@ -1791,7 +1791,7 @@ "link": "/cn/reference/system-transactions-api" }, { - "text": "追踪解绑", + "text": "跟踪解除绑定", "link": "/cn/how-to/track-unbonding" }, { @@ -1893,7 +1893,7 @@ "link": "/cn/reference/bridges" }, { - "text": "DEX", + "text": "DEXes", "link": "/cn/reference/dexes" }, { @@ -1909,7 +1909,7 @@ "link": "/cn/reference/network-routing" }, { - "text": "兑换", + "text": "法币通道", "link": "/cn/reference/ramps" }, { @@ -1931,7 +1931,7 @@ "link": "/cn/how-to/production-readiness" }, { - "text": "开发者协助", + "text": "开发者支持", "link": "/cn/reference/developer-assistance" }, { @@ -1947,11 +1947,11 @@ ] }, { - "text": "运维", + "text": "操作", "collapsed": true, "items": [ { - "text": "节点运维概览", + "text": "节点操作概览", "link": "/cn/reference/node-operations-overview" }, { @@ -1989,15 +1989,15 @@ ] }, { - "text": "[Agents]", + "text": "[代理]", "collapsed": true, "items": [ { - "text": "Agent 结算", + "text": "代理结算", "link": "/cn/explanation/agent-settlement" }, { - "text": "AI Agents 索引", + "text": "AI 代理索引", "link": "/cn/explanation/ai-agents-guides" }, { @@ -2005,7 +2005,7 @@ "collapsed": true, "items": [ { - "text": "X402", + "text": "x402", "link": "/cn/explanation/x402" }, { @@ -2017,7 +2017,7 @@ "link": "/cn/explanation/mpp-sessions" }, { - "text": "构建按次计费", + "text": "构建按次付费", "link": "/cn/how-to/build-pay-per-call" }, { @@ -2025,25 +2025,25 @@ "link": "/cn/how-to/build-mpp-endpoint" }, { - "text": "通过 MCP 支付", + "text": "使用 MCP 支付", "link": "/cn/how-to/pay-with-mcp" } ] }, { - "text": "Agent 基础设施", + "text": "代理基础设施", "collapsed": true, "items": [ { - "text": "使用 AI 进行开发", + "text": "与 AI 开发", "link": "/cn/how-to/develop-with-ai" }, { - "text": "Agentc 协调者", + "text": "代理协调者", "link": "/cn/reference/agentic-facilitators" }, { - "text": "Agentc 钱包", + "text": "代理钱包", "link": "/cn/reference/agentic-wallets" } ] From 61d91183e7a40430dfb62d5d846774442ac6e1f1 Mon Sep 17 00:00:00 2001 From: bastienrp Date: Mon, 13 Jul 2026 17:24:03 +0200 Subject: [PATCH 07/20] docs: add Guaranteed relayed transactions guide Add a dedicated how-to for the combined guaranteedWaiver feature (gas-waived transactions over guaranteed blockspace), modeled on the reference. Add it to the Enterprise SDK menu, and replace the inline "Combine with gas waiver" section in the guaranteed blockspace guide with a pointer to it. Co-Authored-By: Claude Opus 4.8 --- docs/pages/en/explanation/enterprise-sdk.mdx | 3 +- .../guaranteed-relayed-transactions.mdx | 135 ++++++++++++++++++ .../how-to/send-guaranteed-transactions.mdx | 29 +--- docs/sidebar.json | 4 + 4 files changed, 144 insertions(+), 27 deletions(-) create mode 100644 docs/pages/en/how-to/guaranteed-relayed-transactions.mdx diff --git a/docs/pages/en/explanation/enterprise-sdk.mdx b/docs/pages/en/explanation/enterprise-sdk.mdx index 3925dc6..d22b8f5 100644 --- a/docs/pages/en/explanation/enterprise-sdk.mdx +++ b/docs/pages/en/explanation/enterprise-sdk.mdx @@ -57,7 +57,8 @@ Reach for the Enterprise SDK when you operate a backend and want to sponsor user ## Start here - [**Relay with gas waiver**](/en/how-to/relay-with-gas-waiver): Sponsor a user's gas so they transact without holding USDT0. -- [**Send guaranteed transactions**](/en/how-to/send-guaranteed-transactions): Land transactions in reserved Enterprise-lane blockspace, and combine it with gas waiver. +- [**Send guaranteed transactions**](/en/how-to/send-guaranteed-transactions): Land transactions in reserved Enterprise-lane blockspace. +- [**Guaranteed relayed transactions**](/en/how-to/guaranteed-relayed-transactions): Combine both rails: gas-waived transactions in the Enterprise lane. - [**Enterprise SDK reference**](/en/reference/enterprise-sdk): Every module, method, config option, and error class. ## Next recommended diff --git a/docs/pages/en/how-to/guaranteed-relayed-transactions.mdx b/docs/pages/en/how-to/guaranteed-relayed-transactions.mdx new file mode 100644 index 0000000..f17822f --- /dev/null +++ b/docs/pages/en/how-to/guaranteed-relayed-transactions.mdx @@ -0,0 +1,135 @@ +--- +title: "Guaranteed relayed transactions" +description: "Relay gas-waived transactions through guaranteed blockspace with the Enterprise SDK, so users need no balance and still land in the Enterprise lane." +diataxis: "how-to" +--- + +# Guaranteed relayed transactions + +Combine both Enterprise rails with `@stablechain/enterprise`. A guaranteed relayed transaction is a [gas-waived transaction](/en/how-to/relay-with-gas-waiver) routed through [guaranteed blockspace](/en/how-to/send-guaranteed-transactions): the waiver sponsors gas, so the user needs no balance and no fee fields, and the transaction still lands in the reserved Enterprise lane. + +The `guaranteedWaiver` module handles both sides. The user signs an inner `0x3F` CustomTx, the whitelisted waiver account wraps it in an outer `0x3F` CustomTx sharing the same Enterprise `nonceKey`, and it broadcasts through the Enterprise RPC gateway. Every method returns `H_inner`, the user's transaction hash. + +## Prerequisites + +- Node.js 20 or later, and `@stablechain/enterprise` plus `viem` installed. See the [Enterprise SDK reference](/en/reference/enterprise-sdk#install). +- A governance-registered waiver key and an Enterprise RPC gateway API key. The Enterprise SDK is testnet only for now, and access is on request: [contact Stable](https://discord.gg/stablexyz) to get both. + +:::warning +This is a server-side library. Keep the waiver key and the Enterprise RPC gateway URL on your backend: the gateway URL embeds your API key. +::: + +## 1. Create a client with the guaranteed waiver module + +Pass `guaranteedWaiver` and `enterpriseRpcEndpoints` to `createStableEnterprise`. The module takes the whitelisted waiver account (which signs the outer wrapper) plus the Enterprise lane. It also accepts the same `allowedTargets`, `maxGasLimit`, and `maxDataLength` policy limits as `gasWaiver`. + +```ts +import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; +import { privateKeyToAccount } from "viem/accounts"; + +const enterprise = createStableEnterprise({ + chain: stableTestnet, + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // the gateway URL Stable provisions + guaranteedWaiver: { + waiverAccount: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`), + laneId: 0n, // Enterprise lane + }, +}); + +const gw = enterprise.guaranteedWaiver!; +``` + +```text +StableEnterpriseClient { gasWaiver: undefined, guaranteedBlock: undefined, guaranteedWaiver } +``` + +## 2. Relay a single transaction + +Call `send` with the user's account and the fields that vary. Gas is waived, so the user needs no balance and no fee fields. The inner `0x3F` CustomTx, its Enterprise `nonceKey`, and the 2D nonce (discovered from the gateway) are handled for you. + +```ts +const user = privateKeyToAccount(process.env.USER_PRIVATE_KEY as `0x${string}`); + +const { txHash } = await gw.send(user, { to: recipient }); +console.log("H_inner:", txHash); +``` + +```text +H_inner: 0x8f3a...2d41 +``` + +`gas` defaults to the shared inner-gas default; pass it only to override. Value transfers are allowed, so you can also pass `value`. + +## 3. Relay a batch + +Call `sendBatch` to relay several transactions from one user. Inner nonces are auto-sequenced from a discovered base, and you get one result per input, in input order. A failure strands its successors. + +```ts +const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); + +for (const r of results) { + console.log(r.success ? `[${r.index}] ✔ ${r.txHash}` : `[${r.index}] ✖ ${r.error?.code}`); +} +``` + +```text +[0] ✔ 0x8f3a...2d41 +[1] ✔ 0x2b7c...9e04 +``` + +## 4. Relay a pre-signed transaction + +For a non-custodial flow, the user signs the inner `0x3F` CustomTx in their own environment and hands you only the signed hex. Build it with `buildGuaranteedTx`, using `nonceKeyForLane` for the Enterprise nonce key and zero fees (gas is waived). Your backend wraps it with the waiver key and relays it with `relay`. + +```ts +import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; + +// on the user's side +const signedInner = await buildGuaranteedTx(user, stableTestnet.id, { + to: recipient, + gas: 100_000n, + gasFeeCap: 0n, // waived + gasTipCap: 0n, + nonce, // the user's current 2D-lane nonce + nonceKey: nonceKeyForLane(0n), // Enterprise lane 0 +}); + +// on your backend +const { txHash } = await gw.relay(signedInner); // waiver wraps + broadcasts → H_inner +console.log("H_inner:", txHash); +``` + +```text +H_inner: 0x8f3a...2d41 +``` + +For several pre-signed transactions, use `relayBatch`. + +## Handle rejections + +`send` and `relay` throw `StableEnterpriseRelayError` on rejection. Because this flow routes through the gateway, gateway codes like `GATEWAY_UNAUTHORIZED` and `QUOTA_EXCEEDED` apply alongside the waiver policy codes such as `TARGET_NOT_ALLOWED`. + +```ts +import { StableEnterpriseRelayError } from "@stablechain/enterprise"; + +try { + await gw.send(user, { to: recipient }); +} catch (err) { + if (err instanceof StableEnterpriseRelayError && err.code === "GATEWAY_UNAUTHORIZED") { + // the Enterprise RPC gateway rejected the API key + } + throw err; +} +``` + +```text +StableEnterpriseRelayError: relay failed [GATEWAY_UNAUTHORIZED]: invalid api key +``` + +See the full [`ErrorCode`](/en/reference/enterprise-sdk#errorcode) table for every rejection reason. + +## Where to go next + +- [**Relay with gas waiver**](/en/how-to/relay-with-gas-waiver): Sponsor a user's gas without the guaranteed lane. +- [**Send guaranteed transactions**](/en/how-to/send-guaranteed-transactions): Use guaranteed blockspace on its own, where the signer pays gas. +- [**Enterprise SDK reference**](/en/reference/enterprise-sdk#guaranteed-relay-transactions): Every method, config option, and error class in full. diff --git a/docs/pages/en/how-to/send-guaranteed-transactions.mdx b/docs/pages/en/how-to/send-guaranteed-transactions.mdx index 22dc49f..d45aa08 100644 --- a/docs/pages/en/how-to/send-guaranteed-transactions.mdx +++ b/docs/pages/en/how-to/send-guaranteed-transactions.mdx @@ -8,7 +8,7 @@ diataxis: "how-to" Route transactions through reserved Enterprise-lane blockspace with `@stablechain/enterprise`. The `guaranteedBlock` module relays a GuaranteedTx (a type `0x3F` CustomTx) through the Enterprise RPC gateway so it lands in capacity reserved for enterprise workloads. Unlike gas waiver, the signer pays its own gas, so it must be funded. -You can combine this with gas waiver to get [guaranteed relay transactions](#combine-with-gas-waiver): gas-waived transactions that still land in the Enterprise lane. +You can combine this with gas waiver to get [guaranteed relayed transactions](/en/how-to/guaranteed-relayed-transactions): gas-waived transactions that still land in the Enterprise lane. ## Prerequisites @@ -117,30 +117,7 @@ For several pre-signed transactions, use `relayBatch`. ## Combine with gas waiver -Guaranteed relay transactions compose both rails: a gas-waived transaction routed through guaranteed blockspace. The user needs no balance and no fee fields, and the transaction still lands in the Enterprise lane. Enable it with `guaranteedWaiver`, which takes the whitelisted waiver account plus the lane. - -```ts -const enterprise = createStableEnterprise({ - chain: stableTestnet, - enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], - guaranteedWaiver: { - waiverAccount: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`), - laneId: 0n, - }, -}); - -const gw = enterprise.guaranteedWaiver!; - -// gas is waived, so the user needs no balance and no fee fields -const { txHash } = await gw.send(user, { to: recipient }); -console.log("H_inner:", txHash); -``` - -```text -H_inner: 0x8f3a...2d41 -``` - -Like gas waiver, `send` returns `H_inner`, and `sendBatch`, `relay`, and `relayBatch` work the same way. The `guaranteedWaiver` config also accepts the same `allowedTargets`, `maxGasLimit`, and `maxDataLength` policy limits as `gasWaiver`. +To waive the user's gas and still land in the Enterprise lane, compose both rails with the `guaranteedWaiver` module. The user needs no balance and no fee fields, and the transaction routes through the same gateway. See [Guaranteed relayed transactions](/en/how-to/guaranteed-relayed-transactions). ## Handle rejections @@ -165,6 +142,6 @@ StableEnterpriseRelayError: relay failed [GATEWAY_UNAUTHORIZED]: invalid api key ## Where to go next +- [**Guaranteed relayed transactions**](/en/how-to/guaranteed-relayed-transactions): Waive the user's gas and land in the Enterprise lane in one call. - [**Relay with gas waiver**](/en/how-to/relay-with-gas-waiver): Sponsor a user's gas so they transact without holding USDT0. - [**Enterprise SDK reference**](/en/reference/enterprise-sdk#guaranteed-blockspace): Every method, config option, and error class in full. -- [**Guaranteed blockspace**](/en/explanation/guaranteed-blockspace): How Stable reserves block capacity for enterprise workloads. diff --git a/docs/sidebar.json b/docs/sidebar.json index 5c2941e..1b5ad83 100644 --- a/docs/sidebar.json +++ b/docs/sidebar.json @@ -224,6 +224,10 @@ "text": "Guaranteed Blockspace", "link": "/en/how-to/send-guaranteed-transactions" }, + { + "text": "Guaranteed Relayed Transactions", + "link": "/en/how-to/guaranteed-relayed-transactions" + }, { "text": "Reference", "link": "/en/reference/enterprise-sdk" From e17b54f3c1ab8bf8474fe2ffd950ee95be05a509 Mon Sep 17 00:00:00 2001 From: bastienrp Date: Mon, 13 Jul 2026 17:24:51 +0200 Subject: [PATCH 08/20] docs: rename Enterprise SDK menu item Gas Waiver to Relay Transactions Co-Authored-By: Claude Opus 4.8 --- docs/sidebar.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sidebar.json b/docs/sidebar.json index 1b5ad83..0e4f01c 100644 --- a/docs/sidebar.json +++ b/docs/sidebar.json @@ -217,7 +217,7 @@ "link": "/en/explanation/enterprise-sdk" }, { - "text": "Gas Waiver", + "text": "Relay Transactions", "link": "/en/how-to/relay-with-gas-waiver" }, { From 705c03226e76660414d9c6514936740da168078c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 13 Jul 2026 15:26:26 +0000 Subject: [PATCH 09/20] i18n: auto-translate cn/ko for changed en content --- docs/pages/cn/explanation/enterprise-sdk.mdx | 49 ++++--- .../guaranteed-relayed-transactions.mdx | 137 ++++++++++++++++++ .../how-to/send-guaranteed-transactions.mdx | 71 +++------ docs/pages/ko/explanation/enterprise-sdk.mdx | 47 +++--- .../guaranteed-relayed-transactions.mdx | 137 ++++++++++++++++++ .../how-to/send-guaranteed-transactions.mdx | 73 ++++------ docs/sidebar.json | 134 +++++++++-------- 7 files changed, 443 insertions(+), 205 deletions(-) create mode 100644 docs/pages/cn/how-to/guaranteed-relayed-transactions.mdx create mode 100644 docs/pages/ko/how-to/guaranteed-relayed-transactions.mdx diff --git a/docs/pages/cn/explanation/enterprise-sdk.mdx b/docs/pages/cn/explanation/enterprise-sdk.mdx index 94b585d..92779b6 100644 --- a/docs/pages/cn/explanation/enterprise-sdk.mdx +++ b/docs/pages/cn/explanation/enterprise-sdk.mdx @@ -1,14 +1,14 @@ --- source_path: explanation/enterprise-sdk.mdx -source_sha: 3925dc600289afa0a771b5b508728ee1b20bcb01 -title: "Stable 企业版 SDK" -description: "使用类型化的 @stablechain/enterprise SDK 从您的后端中继免 Gas 费和保证区块空间的交易。" +source_sha: d22b8f5b286b6030a0282c7f45a4ef60dd1d928b +title: "Stable 企业级 SDK" +description: "使用类型化的 @stablechain/enterprise SDK,从您的后端中继免 gas 费和保证区块空间的交易。" diataxis: "explanation" --- -# Stable 企业版 SDK +# Stable 企业级 SDK -`@stablechain/enterprise` 是一个用于 Stable 企业级交易轨道的服务器端 TypeScript 客户端。它会签署并中继两种特权交易:一种是免 Gas 费交易,由您为用户支付 Gas 费;另一种是保证区块空间交易,它们会进入预留的企业级通道。您可以在一个客户端上启用其中一个或两个轨道。 +`@stablechain/enterprise` 是一个用于 Stable 企业级交易路由的服务器端 TypeScript 客户端。它签署并中继两种特权交易:免 gas 费交易(您为用户支付 gas 费)和保证区块空间交易(在保留的企业级通道中执行)。您可以在一个客户端上启用任一或同时启用两种路由。 ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -26,44 +26,45 @@ const { txHash } = await enterprise.gasWaiver!.send(user, { to: token, data }); txHash: 0x8f3a...2d41 ``` -此调用返回 `H_inner`,即用户交易的哈希值,而不是承载它的包装器交易的哈希值。 +该调用返回 `H_inner`,即用户交易的哈希值,而不是封装该交易的包装器交易的哈希值。 -## SDK 的作用 +## SDK 的功能 -SDK 暴露了三个功能,每个模块一个。每个功能都是可选的,可以独立配置,并且每个功能都有自己的签名账户,因此您可以使用单独的密钥。 +SDK 暴露了三个功能,每个模块一个。每个功能都是可选且独立配置的,并且每个功能都带自己的签名账户,因此您可以使用不同的密钥。 -- **免 Gas 费中继** (`gasWaiver`):构建、签署并中继免 Gas 费交易。一个白名单豁免账户会包装用户的零 Gas 交易,以便用户在不持有任何 USDT0 的情况下进行交易。请参阅[免 Gas 费](/cn/explanation/gas-waiver)。 -- **保证区块空间** (`guaranteedBlock`):通过企业版 RPC 网关中继交易,使其进入预留的企业级通道区块空间。与免 Gas 费不同,签名者支付自己的 Gas 费。请参阅[保证区块空间](/cn/explanation/guaranteed-blockspace)。 -- **保证中继交易** (`guaranteedWaiver`):两者结合。通过保证区块空间路由的免 Gas 费交易,因此用户无需余额,交易仍能进入企业级通道。 +- **免 gas 费中继** (`gasWaiver`):构建、签署并中继免 gas 费交易。一个白名单豁免账户封装用户的零 gas 交易,因此用户无需持有任何 USDT0 即可交易。请参阅[免 gas 费](/cn/explanation/gas-waiver)。 +- **保证区块空间** (`guaranteedBlock`):通过企业级 RPC 网关中继交易,使其落在保留的企业级通道区块空间中。与免 gas 费不同,签名者支付自己的 gas 费。请参阅[保证区块空间](/cn/explanation/guaranteed-blockspace)。 +- **保证中继交易** (`guaranteedWaiver`):两者结合。通过保证区块空间路由的免 gas 费交易,因此用户无需余额,且交易仍落在企业级通道中。 -每个功能都提供相同的四种方法:`send` 和 `sendBatch` 用于 SDK 签名的托管路径,以及 `relay` 和 `relayBatch` 用于用户在其他地方签名并只向您提供签名十六进制字符串的非托管路径。 +每个功能都提供相同的四种方法:`send` 和 `sendBatch` 用于 SDK 签名的托管路径,`relay` 和 `relayBatch` 用于用户在其他地方签名并只向您提供签名十六进制字符串的非托管路径。 ## 访问权限 -企业版 SDK 目前仅在 Stable 测试网上可用。 +企业级 SDK 目前仅在 Stable Testnet 上可用。 -这两个轨道都受限。免 Gas 费需要治理注册的豁免密钥,而保证区块空间需要企业版 RPC 网关 API 密钥。要进行集成,请[联系 Stable](https://discord.gg/stablexyz) 以获取访问权限。Stable 会提供您需要的豁免密钥和网关端点。 +两种路由都受限制。免 gas 费需要治理注册的豁免密钥,保证区块空间需要企业级 RPC 网关 API 密钥。要进行集成,请[联系 Stable](https://discord.gg/stablexyz) 获取访问权限。Stable 会提供您需要的豁免密钥和网关端点。 ## 仅限服务器端 :::warning -企业版 SDK 是一个无状态的服务器端库,使用私钥进行签名。切勿在浏览器中运行它。将豁免密钥和企业版 RPC 网关 URL 保留在您的后端。 +企业级 SDK 是一个无状态的服务器端库,使用私钥进行签名。切勿在浏览器中运行它。将豁免密钥和企业级 RPC 网关 URL 保留在您的后端。 ::: -豁免密钥是一个白名单的、治理注册的账户:任何持有它的人都可以根据您的策略支付 Gas 费。企业版 RPC 网关 URL 嵌入了您的 API 密钥。请将两者都视为秘密。 +豁免密钥是经过白名单认证、治理注册的账户:任何持有它的人都可以在您的政策下赞助 gas 费。企业级 RPC 网关 URL 嵌入了您的 API 密钥。将两者都视为秘密。 -## 何时使用它 +## 使用场景 -当您运营后端并希望为用户支付 Gas 费或保证自己的流量包含在区块中时,请使用企业版 SDK。对于日常传输、桥接、交换和来自后端或浏览器的资金池收益,请改用通用的 [Stable SDK](/cn/explanation/sdk-overview)。 +当您操作后端并希望赞助用户的 gas 费或保证您的流量被包含时,请使用企业级 SDK。对于来自后端或浏览器的日常转账、桥接、兑换和金库收益,请使用通用型 [Stable SDK](/cn/explanation/sdk-overview)。 ## 从这里开始 -- [**免 Gas 费中继**](/cn/how-to/relay-with-gas-waiver):为用户支付 Gas 费,以便他们在不持有 USDT0 的情况下进行交易。 -- [**发送保证交易**](/cn/how-to/send-guaranteed-transactions):将交易放入预留的企业级通道区块空间,并将其与免 Gas 费结合使用。 -- [**企业版 SDK 参考**](/cn/reference/enterprise-sdk):每个模块、方法、配置选项和错误类。 +- [**免 gas 费中继**](/cn/how-to/relay-with-gas-waiver):赞助用户的 gas 费,使其无需持有 USDT0 即可交易。 +- [**发送保证交易**](/cn/how-to/send-guaranteed-transactions):将交易执行在保留的企业级通道区块空间中。 +- [**保证中继交易**](/cn/how-to/guaranteed-relayed-transactions):结合两种路由:免 gas 费交易在企业级通道中执行。 +- [**企业级 SDK 参考**](/cn/reference/enterprise-sdk):每个模块、方法、配置选项和错误类。 -## 下一步推荐 +## 下一步建议 -- [**免 Gas 费协议**](/cn/reference/gas-waiver-api):交易格式、标记路由和治理控制。 -- [**Stable SDK**](/cn/explanation/sdk-overview):用于传输、桥接、交换和收益的通用客户端。 +- [**免 gas 费协议**](/cn/reference/gas-waiver-api):交易格式、标记路由和治理控制。 +- [**Stable SDK**](/cn/explanation/sdk-overview):用于转账、桥接、兑换和收益的通用客户端。 - [**连接到 Stable**](/cn/reference/connect):测试网的链 ID、RPC 端点和浏览器。 diff --git a/docs/pages/cn/how-to/guaranteed-relayed-transactions.mdx b/docs/pages/cn/how-to/guaranteed-relayed-transactions.mdx new file mode 100644 index 0000000..6a4798f --- /dev/null +++ b/docs/pages/cn/how-to/guaranteed-relayed-transactions.mdx @@ -0,0 +1,137 @@ +--- +source_path: how-to/guaranteed-relayed-transactions.mdx +source_sha: f17822f84d15b62f1ec4a12e262dad94d7343a46 +title: "保证中继交易" +description: "通过带质保的出块空间中继免燃料费交易,用户无需余额即可进入企业版通道,使用 Enterprise SDK。" +diataxis: "how-to" +--- + +# 保证中继交易 + +结合使用 `@stablechain/enterprise` 的企业版通道。保证中继交易是[免燃料费交易](/cn/how-to/relay-with-gas-waiver),通过[保证出块空间](/cn/how-to/send-guaranteed-transactions)进行路由:免除机制支付燃料费,因此用户无需余额和燃料费字段,交易仍会进入预留的企业版通道。 + +`guaranteedWaiver` 模块同时处理两端。用户签署内部 `0x3F` CustomTx,白名单免除帐户将其封装在共享相同 Enterprise `nonceKey` 的外部 `0x3F` CustomTx 中,并通过 Enterprise RPC 网关广播。每个方法都返回 `H_inner`,即用户的交易哈希。 + +## 先决条件 + +- Node.js 20 或更高版本,并安装 `@stablechain/enterprise` 和 `viem`。请参阅 [Enterprise SDK 参考](/cn/reference/enterprise-sdk#install)。 +- 治理注册的免除密钥和企业版 RPC 网关 API 密钥。Enterprise SDK 目前仅限测试网,并按要求提供访问权限:[联系 Stable](https://discord.gg/stablexyz) 以获取两者。 + +:::warning +这是一个服务器端库。将免除密钥和 Enterprise RPC 网关 URL 保存在您的后端:网关 URL 嵌入了您的 API 密钥。 +::: + +## 1. 创建带有保证免除模块的客户端 + +将 `guaranteedWaiver` 和 `enterpriseRpcEndpoints` 传递给 `createStableEnterprise`。该模块接收白名单免除帐户(用于签署外部封装器)以及 Enterprise 通道。它还接受与 `gasWaiver` 相同的 `allowedTargets`、`maxGasLimit` 和 `maxDataLength` 策略限制。 + +```ts +import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; +import { privateKeyToAccount } from "viem/accounts"; + +const enterprise = createStableEnterprise({ + chain: stableTestnet, + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // the gateway URL Stable provisions + guaranteedWaiver: { + waiverAccount: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`), + laneId: 0n, // Enterprise lane + }, +}); + +const gw = enterprise.guaranteedWaiver!; +``` + +```text +StableEnterpriseClient { gasWaiver: undefined, guaranteedBlock: undefined, guaranteedWaiver } +``` + +## 2. 中继单个交易 + +使用用户帐户和变化的字段调用 `send`。燃料费已免除,因此用户不需要余额和燃料费字段。内部 `0x3F` CustomTx、其 Enterprise `nonceKey` 和 2D nonce(从网关发现)都已为您处理。 + +```ts +const user = privateKeyToAccount(process.env.USER_PRIVATE_KEY as `0x${string}`); + +const { txHash } = await gw.send(user, { to: recipient }); +console.log("H_inner:", txHash); +``` + +```text +H_inner: 0x8f3a...2d41 +``` + +`gas` 默认为共享的内部燃料费默认值;仅在需要覆盖时才传递它。允许价值转移,因此您也可以传递 `value`。 + +## 3. 中继批次 + +调用 `sendBatch` 以中继来自一个用户的多个交易。内部 nonce 从发现的基础自动排序,并且您会为每个输入获得一个结果,按输入顺序。一个失败会使其后续成功。 + +```ts +const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); + +for (const r of results) { + console.log(r.success ? `[${r.index}] ✔ ${r.txHash}` : `[${r.index}] ✖ ${r.error?.code}`); +} +``` + +```text +[0] ✔ 0x8f3a...2d41 +[1] ✔ 0x2b7c...9e04 +``` + +## 4. 中继预签署交易 + +对于非托管流程,用户在其自己的环境中签署内部 `0x3F` CustomTx,并仅将签署的十六进制交给您。使用 `buildGuaranteedTx` 构建它,使用 `nonceKeyForLane` 作为 Enterprise nonce 密钥和零燃料费(燃料费已免除)。您的后端使用免除密钥将其封装,并使用 `relay` 中继。 + +```ts +import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; + +// on the user's side +const signedInner = await buildGuaranteedTx(user, stableTestnet.id, { + to: recipient, + gas: 100_000n, + gasFeeCap: 0n, // waived + gasTipCap: 0n, + nonce, // the user's current 2D-lane nonce + nonceKey: nonceKeyForLane(0n), // Enterprise lane 0 +}); + +// on your backend +const { txHash } = await gw.relay(signedInner); // waiver wraps + broadcasts → H_inner +console.log("H_inner:", txHash); +``` + +```text +H_inner: 0x8f3a...2d41 +``` + +对于多个预签署交易,请使用 `relayBatch`。 + +## 处理拒绝 + +`send` 和 `relay` 在拒绝时抛出 `StableEnterpriseRelayError`。由于此流程通过网关路由,因此网关代码(如 `GATEWAY_UNAUTHORIZED` 和 `QUOTA_EXCEEDED`)以及免除策略代码(如 `TARGET_NOT_ALLOWED`)都适用。 + +```ts +import { StableEnterpriseRelayError } from "@stablechain/enterprise"; + +try { + await gw.send(user, { to: recipient }); +} catch (err) { + if (err instanceof StableEnterpriseRelayError && err.code === "GATEWAY_UNAUTHORIZED") { + // the Enterprise RPC gateway rejected the API key + } + throw err; +} +``` + +```text +StableEnterpriseRelayError: relay failed [GATEWAY_UNAUTHORIZED]: invalid api key +``` + +有关每个拒绝原因的完整信息,请参阅完整的 [`ErrorCode`](/cn/reference/enterprise-sdk#errorcode) 表格。 + +## 接下来去哪里 + +- [**免燃料费中继**](/cn/how-to/relay-with-gas-waiver):为用户支付燃料费,无需保证通道。 +- [**发送保证交易**](/cn/how-to/send-guaranteed-transactions):单独使用保证出块空间,由签名者支付燃料费。 +- [**Enterprise SDK 参考**](/cn/reference/enterprise-sdk#guaranteed-relay-transactions):所有方法、配置选项和错误类详情。 diff --git a/docs/pages/cn/how-to/send-guaranteed-transactions.mdx b/docs/pages/cn/how-to/send-guaranteed-transactions.mdx index d2fdf14..3a1ea08 100644 --- a/docs/pages/cn/how-to/send-guaranteed-transactions.mdx +++ b/docs/pages/cn/how-to/send-guaranteed-transactions.mdx @@ -1,30 +1,30 @@ --- source_path: how-to/send-guaranteed-transactions.mdx -source_sha: 22dc49ff9b3a53eff2271c3e3b8d393f7543446c -title: "发送保障交易" -description: "使用 Enterprise SDK 在预留的企业通道区块空间中进行交易,并将保障区块空间与免 Gas 费结合使用,以实现免 Gas 传输交易。" +source_sha: d45aa08b5a1be19855b02d145479697cc0b4bee5 +title: "发送有保证的交易" +description: "使用 Enterprise SDK 在预留的 Enterprise-lane 区块空间中进行交易,并将有保证的区块空间与 Gas 豁免相结合,以实现免 Gas 费用中继。" diataxis: "how-to" --- -# 发送保障交易 +# 发送有保证的交易 -使用 `@stablechain/enterprise` 通过预留的企业通道区块空间路由交易。`guaranteedBlock` 模块通过企业 RPC 网关中继 GuaranteedTx(一种 `0x3F` 类型的 CustomTx),使其落在企业工作负载预留的容量中。与免 Gas 费不同,签名者支付自己的 Gas,因此必须提供资金。 +使用 `@stablechain/enterprise` 通过预留的 Enterprise-lane 区块空间路由交易。`guaranteedBlock` 模块通过 Enterprise RPC 网关中继 GuaranteedTx(一种类型为 `0x3F` 的 CustomTx),使其落在为企业工作负载预留的容量中。与 Gas 豁免不同,签名者支付自己的 Gas 费用,因此必须有足够的资金。 -您可以将此功能与免 Gas 费结合使用,以获得[保障中继交易](#combine-with-gas-waiver):免 Gas 费的交易仍可进入企业通道。 +您可以将其与 Gas 豁免相结合,以获得[有保证的中继交易](/cn/how-to/guaranteed-relayed-transactions):即免 Gas 费用的交易仍会落在 Enterprise-lane 中。 ## 先决条件 -- Node.js 20 或更高版本,并安装 `@stablechain/enterprise` 和 `viem`。请参阅 [企业 SDK 参考](/cn/reference/enterprise-sdk#install)。 -- 企业 RPC 网关 API 密钥。企业 SDK 目前仅支持测试网,并且访问受限:请[联系 Stable](https://discord.gg/stablexyz) 获取网关端点。 -- 一个有资金的签名者,因为 GuaranteedTx 会支付自己的 Gas。 +- Node.js 20 或更高版本,并安装了 `@stablechain/enterprise` 和 `viem`。请参阅 [Enterprise SDK 参考](/cn/reference/enterprise-sdk#install)。 +- 企业 RPC 网关 API 密钥。Enterprise SDK 目前仅限于测试网,访问受限:请[联系 Stable](https://discord.gg/stablexyz) 以获取网关端点。 +- 一个有资金的签名者,因为 GuaranteedTx 支付自己的 Gas。 :::warning -这是一个服务器端库。将企业 RPC 网关 URL 保留在您的后端:它会嵌入您的 API 密钥。 +这是一个服务器端库。将企业 RPC 网关 URL 保留在后端:它嵌入了您的 API 密钥。 ::: -## 1. 使用保障区块空间模块创建客户端 +## 1. 创建一个带有保证区块空间模块的客户端 -将 `guaranteedBlock` 和 `enterpriseRpcEndpoints` 传递给 `createStableEnterprise`。网关是唯一接受 `0x3F` GuaranteedTxs 的端点,并且它持有您的 API 密钥。无效的 `laneId` 会被立即拒绝。 +将 `guaranteedBlock` 和 `enterpriseRpcEndpoints` 传递给 `createStableEnterprise`。网关是唯一接受 `0x3F` GuaranteedTx 的端点,并且它持有您的 API 密钥。无效的 `laneId` 会提前被拒绝。 ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -48,7 +48,7 @@ StableEnterpriseClient { gasWaiver: undefined, guaranteedBlock, guaranteedWaiver ## 2. 发送单笔交易 -使用签名者和可变字段调用 `send`。由于签名者支付 Gas,因此 1559 费用字段是必需的。`chainId`、企业 `nonceKey` 和 2D nouce(从网关发现)都会为您处理。 +使用签名者和可变字段调用 `send`。由于签名者支付 Gas 费用,因此 1559 费用字段是必需的。`chainId`、企业 `nonceKey` 和 2D nonce(从网关发现)都会为您处理。 ```ts import { createPublicClient, http } from "viem"; @@ -69,11 +69,11 @@ console.log("Guaranteed tx:", txHash); Guaranteed tx: 0xabcd...7890 ``` -签名者支付 Gas,因此在进行中继之前请确认账户余额。零余额账户发出的 GuaranteedTx 会失败。 +签名者支付 Gas 费用,因此在进行中继之前请确认其账户有余额。来自零余额账户的 GuaranteedTx 会失败。 -## 3. 发送批量交易 +## 3. 发送一批次 -调用 `sendBatch` 发送多笔交易。Nonce 会从发现的基数自动排序,并且您会为每个输入获得一个结果,按输入顺序。如果其中一个失败,则其后续交易也会失败。 +调用 `sendBatch` 发送多笔交易。Nonce 会从发现的基础自动排序,您会按输入顺序获得每个输入的结果。一次失败会导致其后续交易无法进行。 ```ts const results = await gb.sendBatch(signer, [ @@ -93,7 +93,7 @@ for (const r of results) { ## 4. 发送预签名交易 -对于非托管流程,使用 `buildGuaranteedTx` 在其他地方构建和签署 GuaranteedTx,然后只将签名十六进制交给运营商。企业 nonce 密钥来自 `nonceKeyForLane`。 +对于非托管流程,可在其他地方使用 `buildGuaranteedTx` 构建并签名 GuaranteedTx,然后将签名后的十六进制字符串交给操作员。企业 nonce 密钥来自 `nonceKeyForLane`。 ```ts import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; @@ -117,36 +117,13 @@ Guaranteed tx: 0xabcd...7890 对于多笔预签名交易,请使用 `relayBatch`。 -## 与免 Gas 费结合使用 +## 与 Gas 豁免结合使用 -保障中继交易结合了两种功能:通过保障区块空间路由的免 Gas 费交易。用户无需余额和费用字段,交易仍可进入企业通道。通过 `guaranteedWaiver` 启用此功能,它接受白名单豁免账户和通道。 - -```ts -const enterprise = createStableEnterprise({ - chain: stableTestnet, - enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], - guaranteedWaiver: { - waiverAccount: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`), - laneId: 0n, - }, -}); - -const gw = enterprise.guaranteedWaiver!; - -// gas is waived, so the user needs no balance and no fee fields -const { txHash } = await gw.send(user, { to: recipient }); -console.log("H_inner:", txHash); -``` - -```text -H_inner: 0x8f3a...2d41 -``` - -与免 Gas 费类似,`send` 返回 `H_inner`,并且 `sendBatch`、`relay` 和 `relayBatch` 的工作方式相同。`guaranteedWaiver` 配置也接受与 `gasWaiver` 相同的 `allowedTargets`、`maxGasLimit` 和 `maxDataLength` 策略限制。 +要免除用户的 Gas 费用,并仍进入企业通道,请将两个通道与 `guaranteedWaiver` 模块组合。用户无需余额和费用字段,交易通过相同的网关路由。请参阅[保证中继交易](/cn/how-to/guaranteed-relayed-transactions)。 ## 处理拒绝 -`send` 和 `relay` 在拒绝时会抛出 `StableEnterpriseRelayError`。网关特定的代码包括 `GATEWAY_UNAUTHORIZED`(API 密钥缺失或无效)和 `QUOTA_EXCEEDED`(网关 Gas 配额已用尽)。 +`send` 和 `relay` 在拒绝时抛出 `StableEnterpriseRelayError`。网关特有的代码包括 `GATEWAY_UNAUTHORIZED`(API 密钥缺失或无效)和 `QUOTA_EXCEEDED`(网关 Gas 配额已用尽)。 ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -165,8 +142,8 @@ try { StableEnterpriseRelayError: relay failed [GATEWAY_UNAUTHORIZED]: invalid api key ``` -## 接下来去哪儿 +## 接下来要学习什么 -- [**使用免 Gas 费中继**](/cn/how-to/relay-with-gas-waiver):赞助用户的 Gas 费,让他们无需持有 USDT0 即可进行交易。 -- [**企业 SDK 参考**](/cn/reference/enterprise-sdk#guaranteed-blockspace):所有方法、配置选项和错误类的完整说明。 -- [**保障区块空间**](/cn/explanation/guaranteed-blockspace):Stable 如何为企业工作负载预留区块容量。 +- [**保证中继交易**](/cn/how-to/guaranteed-relayed-transactions):一次调用即可免除用户 Gas 费用并进入企业通道。 +- [**使用 Gas 豁免中继**](/cn/how-to/relay-with-gas-waiver):赞助用户的 Gas 费用,使其无需持有 USDT0 即可进行交易。 +- [**企业 SDK 参考**](/cn/reference/enterprise-sdk#guaranteed-blockspace):全面的方法、配置选项和错误类。 diff --git a/docs/pages/ko/explanation/enterprise-sdk.mdx b/docs/pages/ko/explanation/enterprise-sdk.mdx index d9b7f36..10e09b1 100644 --- a/docs/pages/ko/explanation/enterprise-sdk.mdx +++ b/docs/pages/ko/explanation/enterprise-sdk.mdx @@ -1,14 +1,14 @@ --- source_path: explanation/enterprise-sdk.mdx -source_sha: 3925dc600289afa0a771b5b508728ee1b20bcb01 -title: "Stable Enterprise SDK" -description: "유형화된 @stablechain/enterprise SDK를 사용하여 백엔드에서 가스 면제 및 보장된 블록 공간 트랜잭션을 릴레이합니다." +source_sha: d22b8f5b286b6030a0282c7f45a4ef60dd1d928b +title: "Stable 엔터프라이즈 SDK" +description: "유형화된 @stablechain/enterprise SDK를 사용하여 백엔드에서 가스 면제되고 블록 공간이 보장된 트랜잭션을 릴레이합니다." diataxis: "explanation" --- -# Stable Enterprise SDK +# Stable 엔터프라이즈 SDK -`@stablechain/enterprise`는 Stable의 엔터프라이즈 트랜잭션 레일을 위한 서버 측 TypeScript 클라이언트입니다. 가스 면제 트랜잭션(사용자의 가스를 후원하는 경우)과 보장된 블록 공간 트랜잭션(예약된 엔터프라이즈 레인에 도달하는 트랜잭션)의 두 가지 유형의 특권 트랜잭션을 서명하고 릴레이합니다. 한 클라이언트에서 두 레일 중 하나 또는 둘 다를 활성화할 수 있습니다. +`@stablechain/enterprise`는 Stable의 엔터프라이즈 트랜잭션 레일을 위한 서버 측 TypeScript 클라이언트입니다. 이것은 두 가지 종류의 특권 트랜잭션을 서명하고 릴레이합니다. 즉, 사용자의 가스를 후원하는 가스 면제 트랜잭션과 예약된 엔터프라이즈 레인에 착지하는 블록 공간 보장 트랜잭션입니다. 하나의 클라이언트에서 두 레일 중 하나 또는 둘 다를 활성화할 수 있습니다. ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -26,44 +26,45 @@ const { txHash } = await enterprise.gasWaiver!.send(user, { to: token, data }); txHash: 0x8f3a...2d41 ``` -호출은 사용자의 트랜잭션 해시인 `H_inner`를 반환하며, 이를 포함하는 래퍼 트랜잭션이 아닙니다. +호출은 사용자의 트랜잭션 해시인 `H_inner`를 반환하며, 이를 전달한 래퍼 트랜잭션은 반환하지 않습니다. ## SDK의 기능 -SDK는 모듈당 하나의 세 가지 기능을 노출합니다. 각 기능은 선택 사항이며 독립적으로 구성되며, 각각 자체 서명 계정을 포함하므로 별도의 키를 사용할 수 있습니다. +SDK는 모듈당 세 가지 기능을 노출합니다. 각 기능은 선택 사항이며 독립적으로 구성되며, 자체 서명 계정을 포함하므로 별도의 키를 사용할 수 있습니다. -- **가스 면제 릴레이** (`gasWaiver`): 가스 면제 트랜잭션을 구축, 서명 및 릴레이합니다. 화이트리스트에 등록된 면제 계정은 사용자의 제로 가스 트랜잭션을 래핑하여 사용자가 USDT0를 보유하지 않고도 트랜잭션을 수행할 수 있도록 합니다. [가스 면제](/ko/explanation/gas-waiver)를 참조하십시오. -- **보장된 블록 공간** (`guaranteedBlock`): 트랜잭션을 엔터프라이즈 RPC 게이트웨이를 통해 릴레이하여 예약된 엔터프라이즈 레인 블록 공간에 도달하도록 합니다. 가스 면제와 달리 서명자는 자체 가스를 지불합니다. [보장된 블록 공간](/ko/explanation/guaranteed-blockspace)을 참조하십시오. -- **보장된 릴레이 트랜잭션** (`guaranteedWaiver`): 두 기능을 모두 결합합니다. 보장된 블록 공간을 통해 라우팅되는 가스 면제 트랜잭션으로, 사용자는 잔액이 필요하지 않으며 트랜잭션은 여전히 엔터프라이즈 레인에 도달합니다. +- **가스 면제 릴레이** (`gasWaiver`): 가스 면제 트랜잭션을 구축, 서명 및 릴레이합니다. 화이트리스트에 있는 면제 계정이 사용자의 제로 가스 트랜잭션을 래핑하므로 사용자는 USTYD0을 보유하지 않고도 트랜잭션을 처리합니다. [가스 면제](/ko/explanation/gas-waiver)를 참조하십시오. +- **블록 공간 보장** (`guaranteedBlock`): 엔터프라이즈 RPC 게이트웨이를 통해 트랜잭션을 릴레이하여 예약된 엔터프라이즈 레인 블록 공간에 착지합니다. 가스 면제와 달리 서명자는 자체 가스를 지불합니다. [블록 공간 보장](/ko/explanation/guaranteed-blockspace)을 참조하십시오. +- **보장된 릴레이 트랜잭션** (`guaranteedWaiver`): 둘 다 결합됩니다. 엔터프라이즈 레인을 통해 라우팅되는 가스 면제 트랜잭션이므로 사용자는 잔액이 필요 없고 트랜잭션은 여전히 엔터프라이즈 레인에 착지합니다. -각 기능은 동일한 네 가지 메서드를 제공합니다. SDK가 서명하는 관리 경로의 경우 `send` 및 `sendBatch`, 그리고 사용자가 다른 곳에서 서명하고 서명된 hex만 전달하는 비관리 경로의 경우 `relay` 및 `relayBatch`가 있습니다. +모든 기능은 서명하는 SDK의 관리 경로를 위한 `send` 및 `sendBatch`, 그리고 사용자가 다른 곳에서 서명하고 서명된 헥스만 전달하는 비관리 경로를 위한 `relay` 및 `relayBatch`의 네 가지 동일한 메서드를 제공합니다. -## 접근 +## 액세스 엔터프라이즈 SDK는 현재 Stable Testnet에서만 사용할 수 있습니다. -두 레일 모두 게이트됩니다. 가스 면제는 거버넌스에 등록된 면제 키를 필요로 하며, 보장된 블록 공간은 엔터프라이즈 RPC 게이트웨이 API 키를 필요로 합니다. 통합하려면 [Stable에 문의](https://discord.gg/stablexyz)하여 액세스 권한을 얻으십시오. Stable은 필요한 면제 키와 게이트웨이 엔드포인트를 제공합니다. +두 레일 모두 게이트됩니다. 가스 면제는 거버넌스에 등록된 면제 키를 요구하며, 블록 공간 보장은 엔터프라이즈 RPC 게이트웨이 API 키를 요구합니다. 통합하려면 Stable [Stable에 문의](https://discord.gg/stablexyz)하여 액세스 권한을 얻으십시오. Stable은 필요한 면제 키와 게이트웨이 엔드포인트를 제공합니다. ## 서버 측 전용 :::warning -엔터프라이즈 SDK는 개인 키로 서명하는 상태 비저장 서버 측 라이브러리입니다. 브라우저에서 실행하지 마십시오. 면제 키와 엔터프라이즈 RPC 게이트웨이 URL을 백엔드에 보관하십시오. +엔터프라이즈 SDK는 개인 키로 서명하는 무상태, 서버 측 라이브러리입니다. 브라우저에서 실행하지 마십시오. 면제 키와 엔터프라이즈 RPC 게이트웨이 URL을 백엔드에 보관하십시오. ::: -면제 키는 화이트리스트에 등록된 거버넌스 등록 계정입니다. 이를 소유한 누구든지 귀하의 정책에 따라 가스를 후원할 수 있습니다. 엔터프라이즈 RPC 게이트웨이 URL에는 API 키가 포함되어 있습니다. 두 가지 모두 비밀로 취급하십시오. +면제 키는 화이트리스트에 있는 거버넌스 등록 계정입니다. 이 키를 보유한 사람은 누구나 귀하의 정책에 따라 가스를 후원할 수 있습니다. 엔터프라이즈 RPC 게이트웨이 URL은 API 키를 포함합니다. 둘 다 비밀로 취급하십시오. ## 언제 사용해야 할까요? -백엔드를 운영하고 사용자 가스를 후원하거나 자신의 트래픽에 대한 포함을 보장하려는 경우 엔터프라이즈 SDK를 사용하십시오. 백엔드 또는 브라우저에서 일상적인 전송, 브릿지, 스왑 및 볼트 수익률을 위해서는 대신 범용 [Stable SDK](/ko/explanation/sdk-overview)를 사용하십시오. +백엔드를 운영하고 사용자의 가스를 후원하거나 자체 트래픽에 대한 포함을 보장하려는 경우 엔터프라이즈 SDK를 사용하십시오. 백엔드 또는 브라우저에서 일상적인 전송, 브릿지, 스왑 및 볼트 수익을 위해서는 범용 [Stable SDK](/ko/explanation/sdk-overview)를 대신 사용하십시오. -## 여기서 시작하세요 +## 여기에서 시작하기 -- [**가스 면제 릴레이**](/ko/how-to/relay-with-gas-waiver): 사용자의 가스를 후원하여 USDT0를 보유하지 않고도 거래할 수 있도록 지원합니다. -- [**보장된 거래 전송**](/ko/how-to/send-guaranteed-transactions): 거래를 예약된 엔터프라이즈 레인 블록 공간에 도착시키고, 가스 면제와 결합합니다. -- [**엔터프라이즈 SDK 참조**](/ko/reference/enterprise-sdk): 모든 모듈, 메서드, 구성 옵션 및 오류 클래스. +- [**가스 면제 릴레이**](/ko/how-to/relay-with-gas-waiver): 사용자가 USDT0을 보유하지 않고 거래할 수 있도록 가스를 후원합니다. +- [**보장된 트랜잭션 전송**](/ko/how-to/send-guaranteed-transactions): 예약된 엔터프라이즈 레인 블록 공간에 트랜잭션을 착지합니다. +- [**보장된 릴레이 트랜잭션**](/ko/how-to/guaranteed-relayed-transactions): 두 레일을 결합합니다. 엔터프라이즈 레인의 가스 면제 트랜잭션입니다. +- [**엔터프라이즈 SDK 참조**](/ko/reference/enterprise-sdk): 모든 모듈, 메서드, 구성 옵션 및 오류 클래스입니다. ## 다음 권장 사항 -- [**가스 면제 프로토콜**](/ko/reference/gas-waiver-api): 트랜잭션 형식, 마커 라우팅 및 거버넌스 제어. -- [**Stable SDK**](/ko/explanation/sdk-overview): 전송, 브리징, 스왑 및 수익률을 위한 범용 클라이언트. -- [**Stable에 연결**](/ko/reference/connect): 테스트넷용 체인 ID, RPC 엔드포인트 및 탐색기. +- [**가스 면제 프로토콜**](/ko/reference/gas-waiver-api): 트랜잭션 형식, 마커 라우팅 및 거버넌스 제어입니다. +- [**Stable SDK**](/ko/explanation/sdk-overview): 전송, 브리징, 스왑 및 수익을 위한 범용 클라이언트입니다. +- [**Stable에 연결**](/ko/reference/connect): 테스트넷의 체인 ID, RPC 엔드포인트 및 탐색기입니다. diff --git a/docs/pages/ko/how-to/guaranteed-relayed-transactions.mdx b/docs/pages/ko/how-to/guaranteed-relayed-transactions.mdx new file mode 100644 index 0000000..37f0719 --- /dev/null +++ b/docs/pages/ko/how-to/guaranteed-relayed-transactions.mdx @@ -0,0 +1,137 @@ +--- +source_path: how-to/guaranteed-relayed-transactions.mdx +source_sha: f17822f84d15b62f1ec4a12e262dad94d7343a46 +title: "보장된 릴레이 트랜잭션" +description: "Enterprise SDK를 사용하여 보장된 블록 공간을 통해 가스 면제 트랜잭션을 릴레이하므로, 사용자는 잔고가 없어도 Enterprise 레인에 진입할 수 있습니다." +diataxis: "how-to" +--- + +# 보장된 릴레이 트랜잭션 + +`@stablechain/enterprise`를 사용하여 두 가지 Enterprise 레일을 결합합니다. 보장된 릴레이 트랜잭션은 [보장된 블록 공간](/ko/how-to/send-guaranteed-transactions)을 통해 라우팅되는 [가스 면제 트랜잭션](/ko/how-to/relay-with-gas-waiver)입니다. 면제자가 가스를 후원하므로 사용자는 잔고나 수수료 필드가 필요하지 않으며 트랜잭션은 예약된 Enterprise 레인에 도착합니다. + +`guaranteedWaiver` 모듈은 양쪽을 모두 처리합니다. 사용자는 내부 `0x3F` CustomTx에 서명하고, 화이트리스트에 있는 면제 계정은 동일한 Enterprise `nonceKey`를 공유하는 외부 `0x3F` CustomTx로 래핑하여 Enterprise RPC 게이트웨이를 통해 브로드캐스트합니다. 모든 메소드는 사용자의 트랜잭션 해시인 `H_inner`를 반환합니다. + +## 전제 조건 + +- Node.js 20 이상, 그리고 `@stablechain/enterprise` 및 `viem`이 설치되어 있어야 합니다. [Enterprise SDK 참조](/ko/reference/enterprise-sdk#install)를 참조하십시오. +- 거버넌스에 등록된 면제 키와 Enterprise RPC 게이트웨이 API 키. Enterprise SDK는 현재 테스트넷 전용이며 요청 시 액세스 가능합니다. 둘 다 얻으려면 [Stable에 문의하십시오](https://discord.gg/stablexyz). + +:::warning +이것은 서버 측 라이브러리입니다. 면제 키와 Enterprise RPC 게이트웨이 URL을 백엔드에 보관하십시오. 게이트웨이 URL에는 API 키가 포함되어 있습니다. +::: + +## 1. 보장된 면제 모듈로 클라이언트 생성 + +`guaranteedWaiver` 및 `enterpriseRpcEndpoints`를 `createStableEnterprise`에 전달합니다. 모듈은 화이트리스트에 있는 면제 계정(외부 래퍼에 서명)과 Enterprise 레인을 가져옵니다. 또한 `gasWaiver`와 동일한 `allowedTargets`, `maxGasLimit`, `maxDataLength` 정책 한도를 허용합니다. + +```ts +import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; +import { privateKeyToAccount } from "viem/accounts"; + +const enterprise = createStableEnterprise({ + chain: stableTestnet, + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable이 제공하는 게이트웨이 URL + guaranteedWaiver: { + waiverAccount: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`), + laneId: 0n, // Enterprise 레인 + }, +}); + +const gw = enterprise.guaranteedWaiver!; +``` + +```text +StableEnterpriseClient { gasWaiver: undefined, guaranteedBlock: undefined, guaranteedWaiver } +``` + +## 2. 단일 트랜잭션 릴레이 + +사용자 계정과 변경되는 필드를 사용하여 `send`를 호출합니다. 가스가 면제되므로 사용자는 잔고나 수수료 필드가 필요하지 않습니다. 내부 `0x3F` CustomTx, 해당 Enterprise `nonceKey`, 그리고 2D 논스(게이트웨이에서 발견됨)는 자동으로 처리됩니다. + +```ts +const user = privateKeyToAccount(process.env.USER_PRIVATE_KEY as `0x${string}`); + +const { txHash } = await gw.send(user, { to: recipient }); +console.log("H_inner:", txHash); +``` + +```text +H_inner: 0x8f3a...2d41 +``` + +`gas`는 공유된 내부 가스 기본값으로 설정됩니다. 재정의하려면 이 값을 전달하십시오. 값 전송이 허용되므로 `value`를 전달할 수도 있습니다. + +## 3. 배치 릴레이 + +한 사용자로부터 여러 트랜잭션을 릴레이하려면 `sendBatch`를 호출합니다. 내부 논스는 발견된 기본값에서 자동으로 시퀀싱되며, 입력 순서대로 입력당 하나의 결과가 반환됩니다. 실패는 후속 항목에 영향을 미칩니다. + +```ts +const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); + +for (const r of results) { + console.log(r.success ? `[${r.index}] ✔ ${r.txHash}` : `[${r.index}] ✖ ${r.error?.code}`); +} +``` + +```text +[0] ✔ 0x8f3a...2d41 +[1] ✔ 0x2b7c...9e04 +``` + +## 4. 사전 서명된 트랜잭션 릴레이 + +비수탁적 흐름의 경우, 사용자는 자신의 환경에서 내부 `0x3F` CustomTx에 서명하고 서명된 헥스만 사용자에게 제공합니다. Enterprise 논스 키로 `nonceKeyForLane`을 사용하고 수수료를 0으로 설정하여(`gas`는 면제됨) `buildGuaranteedTx`로 빌드합니다. 백엔드는 면제 키로 래핑하고 `relay`로 릴레이합니다. + +```ts +import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; + +// 사용자 측에서 +const signedInner = await buildGuaranteedTx(user, stableTestnet.id, { + to: recipient, + gas: 100_000n, + gasFeeCap: 0n, // 면제됨 + gasTipCap: 0n, + nonce, // 사용자의 현재 2D-레인 논스 + nonceKey: nonceKeyForLane(0n), // Enterprise 레인 0 +}); + +// 백엔드에서 +const { txHash } = await gw.relay(signedInner); // 면제자가 래핑 + 브로드캐스트 → H_inner +console.log("H_inner:", txHash); +``` + +```text +H_inner: 0x8f3a...2d41 +``` + +여러 사전 서명된 트랜잭션의 경우 `relayBatch`를 사용하십시오. + +## 거부 처리 + +`send` 및 `relay`는 거부 시 `StableEnterpriseRelayError`를 던집니다. 이 흐름은 게이트웨이를 통해 라우팅되므로 `GATEWAY_UNAUTHORIZED` 및 `QUOTA_EXCEEDED`와 같은 게이트웨이 코드가 `TARGET_NOT_ALLOWED`와 같은 면제 정책 코드와 함께 적용됩니다. + +```ts +import { StableEnterpriseRelayError } from "@stablechain/enterprise"; + +try { + await gw.send(user, { to: recipient }); +} catch (err) { + if (err instanceof StableEnterpriseRelayError && err.code === "GATEWAY_UNAUTHORIZED") { + // Enterprise RPC 게이트웨이가 API 키를 거부했습니다. + } + throw err; +} +``` + +```text +StableEnterpriseRelayError: relay failed [GATEWAY_UNAUTHORIZED]: invalid api key +``` + +모든 거부 사유는 전체 [`ErrorCode`](/ko/reference/enterprise-sdk#errorcode) 테이블을 참조하십시오. + +## 다음 단계 + +- [**가스 면제 릴레이**](/ko/how-to/relay-with-gas-waiver): 보장된 레인 없이 사용자 가스를 후원합니다. +- [**보장된 트랜잭션 전송**](/ko/how-to/send-guaranteed-transactions): 서명자가 가스를 지불하는 자체적으로 보장된 블록 공간을 사용합니다. +- [**Enterprise SDK 참조**](/ko/reference/enterprise-sdk#guaranteed-relay-transactions): 모든 메소드, 구성 옵션 및 오류 클래스에 대한 전체 정보. diff --git a/docs/pages/ko/how-to/send-guaranteed-transactions.mdx b/docs/pages/ko/how-to/send-guaranteed-transactions.mdx index 5736f31..7e2d9d7 100644 --- a/docs/pages/ko/how-to/send-guaranteed-transactions.mdx +++ b/docs/pages/ko/how-to/send-guaranteed-transactions.mdx @@ -1,30 +1,30 @@ --- source_path: how-to/send-guaranteed-transactions.mdx -source_sha: 22dc49ff9b3a53eff2271c3e3b8d393f7543446c +source_sha: d45aa08b5a1be19855b02d145479697cc0b4bee5 title: "보장된 트랜잭션 전송" -description: "Enterprise SDK를 사용하여 예약된 엔터프라이즈 레인 블록스페이스에 트랜잭션을 랜딩하고, 보장된 블록스페이스와 가스 면제를 결합하여 가스 없이 트랜잭션을 릴레이합니다." +description: "Enterprise SDK를 사용하여 예약된 Enterprise-레인 블록스페이스에 트랜잭션을 배치하고, 가스 면제와 보장된 블록스페이스를 결합하여 가스 없이 릴레이합니다." diataxis: "how-to" --- # 보장된 트랜잭션 전송 -`@stablechain/enterprise`를 사용하여 예약된 엔터프라이즈 레인 블록스페이스를 통해 트랜잭션을 라우팅합니다. `guaranteedBlock` 모듈은 Enterprise RPC 게이트웨이를 통해 GuaranteedTx(타입 `0x3F` CustomTx)를 릴레이하여 엔터프라이즈 워크로드용으로 예약된 용량에 랜딩합니다. 가스 면제와 달리 서명자는 자체 가스를 지불하므로 자금이 있어야 합니다. +`@stablechain/enterprise`를 사용하여 예약된 Enterprise-레인 블록스페이스를 통해 트랜잭션을 라우팅합니다. `guaranteedBlock` 모듈은 GuaranteedTx (0x3F 유형 CustomTx)를 Enterprise RPC 게이트웨이를 통해 릴레이하여 엔터프라이즈 워크로드용으로 예약된 용량에 트랜잭션을 배치합니다. 가스 면제와 달리 서명자는 자체 가스를 지불하므로 자금이 있어야 합니다. -이를 가스 면제와 결합하여 [보장된 릴레이 트랜잭션](#combine-with-gas-waiver)을 얻을 수 있습니다. 이는 가스가 면제되면서도 엔터프라이즈 레인에 랜딩되는 트랜잭션입니다. +이를 가스 면제와 결합하여 [보장된 릴레이 트랜잭션](/ko/how-to/guaranteed-relayed-transactions)을 얻을 수 있습니다. 이는 여전히 Enterprise 레인에 배치되는 가스 면제 트랜잭션입니다. ## 전제 조건 -- Node.js 20 이상, 그리고 `@stablechain/enterprise`와 `viem`이 설치되어 있어야 합니다. [엔터프라이즈 SDK 참조](/ko/reference/enterprise-sdk#install)를 참조하세요. -- 엔터프라이즈 RPC 게이트웨이 API 키. 엔터프라이즈 SDK는 현재 테스트넷 전용이며, 액세스는 제한되어 있습니다. 게이트웨이 엔드포인트를 얻으려면 [Stable에 문의](https://discord.gg/stablexyz)하세요. -- GuaranteedTx는 자체 가스를 지불하므로 자금이 있는 서명자. +- Node.js 20 이상, 그리고 `@stablechain/enterprise`와 `viem`이 설치되어 있어야 합니다. [Enterprise SDK 참조](/ko/reference/enterprise-sdk#install)를 참조하세요. +- Enterprise RPC 게이트웨이 API 키. Enterprise SDK는 현재 테스트넷 전용이며 접근이 제한됩니다. 게이트웨이 엔드포인트를 얻으려면 [Stable에 문의하세요](https://discord.gg/stablexyz). +- GuaranteedTx는 자체 가스를 지불하므로 자금이 있는 서명자가 필요합니다. :::warning -이것은 서버 측 라이브러리입니다. 엔터프라이즈 RPC 게이트웨이 URL은 백엔드에 유지하세요. API 키가 포함되어 있습니다. +이것은 서버 측 라이브러리입니다. Enterprise RPC 게이트웨이 URL을 백엔드에 유지하세요: API 키가 포함되어 있습니다. ::: ## 1. 보장된 블록스페이스 모듈로 클라이언트 생성 -`guaranteedBlock` 및 `enterpriseRpcEndpoints`를 `createStableEnterprise`에 전달합니다. 게이트웨이는 `0x3F` GuaranteedTxs를 허용하는 유일한 엔드포인트이며, API 키를 보유합니다. 잘못된 `laneId`는 즉시 거부됩니다. +`guaranteedBlock` 및 `enterpriseRpcEndpoints`를 `createStableEnterprise`에 전달합니다. 게이트웨이만이 `0x3F` GuaranteedTx를 허용하는 유일한 엔드포인트이며, API 키를 보유합니다. 유효하지 않은 `laneId`는 즉시 거부됩니다. ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -35,7 +35,7 @@ const enterprise = createStableEnterprise({ enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable이 제공하는 게이트웨이 URL guaranteedBlock: { account: privateKeyToAccount(process.env.SIGNER_PRIVATE_KEY as `0x${string}`), // 자금이 있어야 함 - laneId: 0n, // 엔터프라이즈 레인 + laneId: 0n, // Enterprise 레인 }, }); @@ -48,7 +48,7 @@ StableEnterpriseClient { gasWaiver: undefined, guaranteedBlock, guaranteedWaiver ## 2. 단일 트랜잭션 전송 -서명자와 변경되는 필드로 `send`를 호출합니다. 서명자가 가스를 지불하므로 1559 수수료 필드가 필요합니다. `chainId`, 엔터프라이즈 `nonceKey`, 그리고 2D nonce(게이트웨이에서 발견됨)는 자동으로 처리됩니다. +서명자와 여러 필드를 사용하여 `send`를 호출합니다. 서명자가 가스를 지불하므로 1559 수수료 필드가 필요합니다. `chainId`, Enterprise `nonceKey` 및 2D nonce (게이트웨이에서 발견됨)는 자동으로 처리됩니다. ```ts import { createPublicClient, http } from "viem"; @@ -69,11 +69,11 @@ console.log("Guaranteed tx:", txHash); Guaranteed tx: 0xabcd...7890 ``` -서명자가 가스를 지불하므로 릴레이 전에 잔액을 확인하십시오. 잔액이 없는 계정에서 보낸 GuaranteedTx는 실패합니다. +서명자가 가스를 지불하므로 릴레이 전에 잔액을 확인하십시오. 잔액이 0인 계정에서 GuaranteedTx는 실패합니다. ## 3. 배치 전송 -여러 트랜잭션을 보내려면 `sendBatch`를 호출합니다. Nonce는 발견된 기준에서 자동으로 시퀀싱되며, 입력 순서대로 입력당 하나의 결과를 얻습니다. 실패는 후속 작업에 영향을 줍니다. +여러 트랜잭션을 보내려면 `sendBatch`를 호출합니다. Nonce는 발견된 기준점에서 자동 시퀀싱되며, 입력 순서대로 입력당 하나의 결과를 얻습니다. 실패는 후속 작업에 영향을 미칩니다. ```ts const results = await gb.sendBatch(signer, [ @@ -91,9 +91,9 @@ for (const r of results) { [1] ✔ 0x1f2e...66a1 ``` -## 4. 사전 서명된 트랜잭션 전송 +## 4. 미리 서명된 트랜잭션 전송 -비수탁형 흐름의 경우, `buildGuaranteedTx`로 다른 곳에서 GuaranteedTx를 빌드하고 서명한 다음, 운영자에게 서명된 hex만 전달합니다. 엔터프라이즈 nonce 키는 `nonceKeyForLane`에서 가져옵니다. +비수탁 흐름의 경우, `buildGuaranteedTx`로 GuaranteedTx를 다른 곳에서 빌드하고 서명한 다음 운영자에게 서명된 hex만 전달합니다. Enterprise nonce 키는 `nonceKeyForLane`에서 가져옵니다. ```ts import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; @@ -103,8 +103,8 @@ const signed = await buildGuaranteedTx(signer, stableTestnet.id, { gas: 21_000n, gasFeeCap, gasTipCap, - nonce, // 계정의 현재 2D 레인 nonce - nonceKey: nonceKeyForLane(0n), // 엔터프라이즈 레인 0 + nonce, // 계정의 현재 2D-레인 nonce + nonceKey: nonceKeyForLane(0n), // Enterprise 레인 0 }); const { txHash } = await gb.relay(signed); @@ -115,38 +115,15 @@ console.log("Guaranteed tx:", txHash); Guaranteed tx: 0xabcd...7890 ``` -여러 사전 서명된 트랜잭션의 경우 `relayBatch`를 사용합니다. +미리 서명된 여러 트랜잭션의 경우 `relayBatch`를 사용하십시오. ## 가스 면제와 결합 -보장된 릴레이 트랜잭션은 두 가지 레일을 모두 구성합니다. 즉, 보장된 블록스페이스를 통해 라우팅되는 가스 면제 트랜잭션입니다. 사용자는 잔액이나 수수료 필드가 필요 없으며, 트랜잭션은 여전히 엔터프라이즈 레인에 랜딩됩니다. 화이트리스트에 등록된 면제 계정과 레인을 사용하는 `guaranteedWaiver`로 이 기능을 활성화할 수 있습니다. - -```ts -const enterprise = createStableEnterprise({ - chain: stableTestnet, - enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], - guaranteedWaiver: { - waiverAccount: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`), - laneId: 0n, - }, -}); - -const gw = enterprise.guaranteedWaiver!; - -// 가스가 면제되므로 사용자는 잔액이나 수수료 필드가 필요 없습니다 -const { txHash } = await gw.send(user, { to: recipient }); -console.log("H_inner:", txHash); -``` - -```text -H_inner: 0x8f3a...2d41 -``` - -가스 면제와 마찬가지로 `send`는 `H_inner`를 반환하며, `sendBatch`, `relay`, `relayBatch`도 동일하게 작동합니다. `guaranteedWaiver` 설정은 `gasWaiver`와 동일한 `allowedTargets`, `maxGasLimit`, `maxDataLength` 정책 제한을 허용합니다. +사용자의 가스를 면제하고 Enterprise 레인에 배치하려면 `guaranteedWaiver` 모듈로 두 레일을 구성합니다. 사용자는 잔액이나 수수료 필드가 필요 없으며, 트랜잭션은 동일한 게이트웨이를 통해 라우팅됩니다. [보장된 릴레이 트랜잭션](/ko/how-to/guaranteed-relayed-transactions)을 참조하십시오. ## 거부 처리 -`send` 및 `relay`는 거부 시 `StableEnterpriseRelayError`를 발생시킵니다. 게이트웨이별 코드에는 `GATEWAY_UNAUTHORIZED`(누락된 또는 잘못된 API 키) 및 `QUOTA_EXCEEDED`(게이트웨이 가스 할당량 소진)가 포함됩니다. +`send` 및 `relay`는 거부 시 `StableEnterpriseRelayError`를 발생시킵니다. 게이트웨이별 코드에는 `GATEWAY_UNAUTHORIZED` (누락되었거나 유효하지 않은 API 키) 및 `QUOTA_EXCEEDED` (게이트웨이 가스 할당량이 소진됨)가 포함됩니다. ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -155,7 +132,7 @@ try { await gb.send(signer, { to: recipient, gas: 21_000n, gasFeeCap, gasTipCap }); } catch (err) { if (err instanceof StableEnterpriseRelayError && err.code === "GATEWAY_UNAUTHORIZED") { - // 엔터프라이즈 RPC 게이트웨이가 API 키를 거부했습니다 + // Enterprise RPC 게이트웨이가 API 키를 거부했습니다 } throw err; } @@ -165,8 +142,8 @@ try { StableEnterpriseRelayError: relay failed [GATEWAY_UNAUTHORIZED]: invalid api key ``` -## 다음으로 갈 곳 +## 다음 단계 -- [**가스 면제로 릴레이**](/ko/how-to/relay-with-gas-waiver): 사용자의 가스를 후원하여 USDT0 없이 트랜잭션을 처리하게 합니다. -- [**엔터프라이즈 SDK 참조**](/ko/reference/enterprise-sdk#guaranteed-blockspace): 모든 메서드, 구성 옵션 및 오류 클래스에 대한 전체 정보입니다. -- [**보장된 블록스페이스**](/ko/explanation/guaranteed-blockspace): Stable이 엔터프라이즈 워크로드를 위해 블록 용량을 예약하는 방법입니다. +- [**보장된 릴레이 트랜잭션**](/ko/how-to/guaranteed-relayed-transactions): 사용자의 가스를 면제하고 한 번의 호출로 Enterprise 레인에 배치합니다. +- [**가스 면제로 릴레이**](/ko/how-to/relay-with-gas-waiver): 사용자의 가스를 지원하여 USDT0를 보유하지 않고도 트랜잭션을 수행하도록 합니다. +- [**Enterprise SDK 참조**](/ko/reference/enterprise-sdk#guaranteed-blockspace): 모든 메서드, 구성 옵션 및 오류 클래스에 대한 전체 설명입니다. diff --git a/docs/sidebar.json b/docs/sidebar.json index 0e4f01c..58ce0b0 100644 --- a/docs/sidebar.json +++ b/docs/sidebar.json @@ -713,7 +713,7 @@ "link": "/ko/explanation/core-concepts" }, { - "text": "주요 특징", + "text": "주요 기능", "link": "/ko/explanation/key-features" }, { @@ -743,11 +743,11 @@ ] }, { - "text": "USDT0 특징", + "text": "USDT0 기능", "collapsed": true, "items": [ { - "text": "USDT 특징 개요", + "text": "USDT 기능 개요", "link": "/ko/explanation/usdt-features-overview" }, { @@ -779,7 +779,7 @@ "link": "/ko/explanation/guaranteed-blockspace" }, { - "text": "USDT 전송 Aggregator", + "text": "USDT 전송 애그리게이터", "link": "/ko/explanation/usdt-transfer-aggregator" }, { @@ -793,7 +793,7 @@ "collapsed": true, "items": [ { - "text": "핵심 최적화 개요", + "text": "코어 최적화 개요", "link": "/ko/explanation/core-optimization-overview" }, { @@ -819,7 +819,7 @@ ] }, { - "text": "사용 사례 설명", + "text": "사용 사례 내러티브", "collapsed": true, "items": [ { @@ -831,7 +831,7 @@ "link": "/ko/explanation/use-case-payroll" }, { - "text": "사용 사례: 스폰서", + "text": "사용 사례: 후원", "link": "/ko/explanation/use-case-sponsored" }, { @@ -841,7 +841,7 @@ ] }, { - "text": "토큰노믹스", + "text": "토크노믹스", "link": "/ko/reference/tokenomics" }, { @@ -887,11 +887,11 @@ "link": "/ko/how-to/earn-yield" }, { - "text": "viem 통합", + "text": "Viem 통합", "link": "/ko/how-to/sdk-with-viem" }, { - "text": "wagmi 통합", + "text": "Wagmi 통합", "link": "/ko/how-to/sdk-with-wagmi" } ] @@ -905,13 +905,17 @@ "link": "/ko/explanation/enterprise-sdk" }, { - "text": "가스 면제", + "text": "릴레이 트랜잭션", "link": "/ko/how-to/relay-with-gas-waiver" }, { "text": "보장된 블록 공간", "link": "/ko/how-to/send-guaranteed-transactions" }, + { + "text": "보장된 릴레이 트랜잭션", + "link": "/ko/how-to/guaranteed-relayed-transactions" + }, { "text": "참조", "link": "/ko/reference/enterprise-sdk" @@ -927,7 +931,7 @@ "link": "/ko/explanation/accounts-overview" }, { - "text": "계정 색인", + "text": "계정 인덱스", "link": "/ko/explanation/accounts-guides" }, { @@ -953,7 +957,7 @@ "link": "/ko/explanation/payments-overview" }, { - "text": "결제 색인", + "text": "결제 인덱스", "link": "/ko/explanation/payments-guides" }, { @@ -969,17 +973,17 @@ "link": "/ko/how-to/zero-gas-transactions" }, { - "text": "USDT 가스와 함께 작업", + "text": "USDT 가스 사용", "link": "/ko/how-to/work-with-usdt-gas" }, { - "text": "USDT0 브릿지", + "text": "USDT0 브릿징", "link": "/ko/tutorial/bridge-usdt0" } ] }, { - "text": "사용자에게 청구", + "text": "사용자 청구", "collapsed": true, "items": [ { @@ -991,7 +995,7 @@ "link": "/ko/how-to/subscribe-and-collect" }, { - "text": "송장으로 결제", + "text": "인보이스로 결제", "link": "/ko/how-to/pay-with-invoice" } ] @@ -1017,15 +1021,15 @@ "link": "/ko/reference/subscriptions" }, { - "text": "송장", + "text": "인보이스", "link": "/ko/reference/invoices" }, { - "text": "통화당 지불", + "text": "통화 당 지불", "link": "/ko/reference/pay-per-call" }, { - "text": "향후 사용 사례", + "text": "예정된 사용 사례", "link": "/ko/explanation/upcoming-use-cases" } ] @@ -1041,7 +1045,7 @@ "link": "/ko/explanation/contracts-overview" }, { - "text": "계약 색인", + "text": "계약 인덱스", "link": "/ko/explanation/contracts-guides" }, { @@ -1057,7 +1061,7 @@ "link": "/ko/how-to/verify-contract" }, { - "text": "계약 색인", + "text": "계약 인덱싱", "link": "/ko/how-to/index-contract" } ] @@ -1115,7 +1119,7 @@ "link": "/ko/how-to/track-unbonding" }, { - "text": "검증인 데이터 색인", + "text": "검증인 데이터 인덱싱", "link": "/ko/how-to/index-validator-data" } ] @@ -1141,7 +1145,7 @@ "link": "/ko/reference/connect" }, { - "text": "Faucet 사용", + "text": "파우셋 사용", "link": "/ko/how-to/use-faucet" }, { @@ -1175,7 +1179,7 @@ "link": "/ko/reference/testnet-version-history" }, { - "text": "테스트넷 Ecosystem", + "text": "테스트넷 생태계", "link": "/ko/reference/testnet-ecosystem" } ] @@ -1213,7 +1217,7 @@ "link": "/ko/reference/bridges" }, { - "text": "Dexes", + "text": "덱스", "link": "/ko/reference/dexes" }, { @@ -1229,7 +1233,7 @@ "link": "/ko/reference/network-routing" }, { - "text": "Ramps", + "text": "램프", "link": "/ko/reference/ramps" }, { @@ -1237,7 +1241,7 @@ "link": "/ko/reference/wallets" }, { - "text": "수호", + "text": "수거", "link": "/ko/reference/custody" }, { @@ -1247,7 +1251,7 @@ ] }, { - "text": "프로덕션 준비성", + "text": "생산 준비성", "link": "/ko/how-to/production-readiness" }, { @@ -1275,7 +1279,7 @@ "link": "/ko/reference/node-operations-overview" }, { - "text": "노드 시스템 요구 사항", + "text": "노드 시스템 요구사항", "link": "/ko/reference/node-system-requirements" }, { @@ -1317,7 +1321,7 @@ "link": "/ko/explanation/agent-settlement" }, { - "text": "AI 에이전트 색인", + "text": "AI 에이전트 인덱스", "link": "/ko/explanation/ai-agents-guides" }, { @@ -1325,7 +1329,7 @@ "collapsed": true, "items": [ { - "text": "x402", + "text": "X402", "link": "/ko/explanation/x402" }, { @@ -1337,7 +1341,7 @@ "link": "/ko/explanation/mpp-sessions" }, { - "text": "통화당 지불 구축", + "text": "통화 당 지불 구축", "link": "/ko/how-to/build-pay-per-call" }, { @@ -1355,7 +1359,7 @@ "collapsed": true, "items": [ { - "text": "AI 개발", + "text": "AI를 이용한 개발", "link": "/ko/how-to/develop-with-ai" }, { @@ -1397,11 +1401,11 @@ "link": "/cn/explanation/core-concepts" }, { - "text": "主要特点", + "text": "主要功能", "link": "/cn/explanation/key-features" }, { - "text": "与以太坊的比较", + "text": "以太坊对比", "link": "/cn/explanation/ethereum-comparison" }, { @@ -1431,7 +1435,7 @@ "collapsed": true, "items": [ { - "text": "USDT0 功能概览", + "text": "USDT 功能概览", "link": "/cn/explanation/usdt-features-overview" }, { @@ -1439,7 +1443,7 @@ "link": "/cn/explanation/flow-of-funds" }, { - "text": "USDT0 跨链", + "text": "USDT0 桥接", "link": "/cn/explanation/usdt0-bridging" }, { @@ -1463,11 +1467,11 @@ "link": "/cn/explanation/guaranteed-blockspace" }, { - "text": "USDT 交易聚合器", + "text": "USDT 转移聚合器", "link": "/cn/explanation/usdt-transfer-aggregator" }, { - "text": "保密交易", + "text": "保密转移", "link": "/cn/explanation/confidential-transfer" } ] @@ -1489,7 +1493,7 @@ "link": "/cn/explanation/execution" }, { - "text": "Stable DB", + "text": "Stable 数据库", "link": "/cn/explanation/stable-db" }, { @@ -1511,7 +1515,7 @@ "link": "/cn/explanation/use-case-payments" }, { - "text": "用例:薪酬", + "text": "用例:工资单", "link": "/cn/explanation/use-case-payroll" }, { @@ -1589,13 +1593,17 @@ "link": "/cn/explanation/enterprise-sdk" }, { - "text": "Gas 豁免", + "text": "中继交易", "link": "/cn/how-to/relay-with-gas-waiver" }, { "text": "保证区块空间", "link": "/cn/how-to/send-guaranteed-transactions" }, + { + "text": "保证中继交易", + "link": "/cn/how-to/guaranteed-relayed-transactions" + }, { "text": "参考", "link": "/cn/reference/enterprise-sdk" @@ -1603,7 +1611,7 @@ ] }, { - "text": "用户注册", + "text": "用户引导", "collapsed": true, "items": [ { @@ -1629,7 +1637,7 @@ ] }, { - "text": "接受付款", + "text": "接受支付", "collapsed": true, "items": [ { @@ -1675,7 +1683,7 @@ "link": "/cn/how-to/subscribe-and-collect" }, { - "text": "通过发票支付", + "text": "发票支付", "link": "/cn/how-to/pay-with-invoice" } ] @@ -1705,7 +1713,7 @@ "link": "/cn/reference/invoices" }, { - "text": "按次付费", + "text": "按次计费", "link": "/cn/reference/pay-per-call" }, { @@ -1717,7 +1725,7 @@ ] }, { - "text": "部署合约", + "text": "发布合约", "collapsed": true, "items": [ { @@ -1795,7 +1803,7 @@ "link": "/cn/reference/system-transactions-api" }, { - "text": "跟踪解除绑定", + "text": "追踪解除绑定", "link": "/cn/how-to/track-unbonding" }, { @@ -1805,7 +1813,7 @@ ] }, { - "text": "JSON-RPC API", + "text": "JSON RPC API", "link": "/cn/reference/json-rpc-api" } ] @@ -1897,7 +1905,7 @@ "link": "/cn/reference/bridges" }, { - "text": "DEXes", + "text": "去中心化交易所", "link": "/cn/reference/dexes" }, { @@ -1913,7 +1921,7 @@ "link": "/cn/reference/network-routing" }, { - "text": "法币通道", + "text": "法币出入金", "link": "/cn/reference/ramps" }, { @@ -1935,7 +1943,7 @@ "link": "/cn/how-to/production-readiness" }, { - "text": "开发者支持", + "text": "开发者协助", "link": "/cn/reference/developer-assistance" }, { @@ -1951,11 +1959,11 @@ ] }, { - "text": "操作", + "text": "运营", "collapsed": true, "items": [ { - "text": "节点操作概览", + "text": "节点运维概览", "link": "/cn/reference/node-operations-overview" }, { @@ -2009,27 +2017,27 @@ "collapsed": true, "items": [ { - "text": "x402", + "text": "X402", "link": "/cn/explanation/x402" }, { - "text": "MPP", + "text": "Mpp", "link": "/cn/explanation/mpp" }, { - "text": "MPP 会话", + "text": "Mpp 会话", "link": "/cn/explanation/mpp-sessions" }, { - "text": "构建按次付费", + "text": "构建按次计费", "link": "/cn/how-to/build-pay-per-call" }, { - "text": "构建 MPP 端点", + "text": "构建 Mpp 端点", "link": "/cn/how-to/build-mpp-endpoint" }, { - "text": "使用 MCP 支付", + "text": "使用 Mcp 支付", "link": "/cn/how-to/pay-with-mcp" } ] @@ -2039,11 +2047,11 @@ "collapsed": true, "items": [ { - "text": "与 AI 开发", + "text": "用 AI 开发", "link": "/cn/how-to/develop-with-ai" }, { - "text": "代理协调者", + "text": "代理协调器", "link": "/cn/reference/agentic-facilitators" }, { From 5a589cfdf4a3e7c2e708e4bbe8ec3e17e31eb207 Mon Sep 17 00:00:00 2001 From: bastienrp Date: Tue, 14 Jul 2026 10:02:11 +0200 Subject: [PATCH 10/20] build: raise docs:build heap ceiling to 7168 MB The Cloudflare prerender OOMs at the previous 6144 MB cap: it prerenders all 395 pages (en/cn/ko) sequentially in one process and dies right at the ceiling (peak 6010/6191 MB). The same build passes locally, so the working set is ~6 GB and just tips over. Raise the cap to 7168 MB, which stays under the 8 GB Cloudflare build container. Co-Authored-By: Claude Opus 4.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3159bd7..0348465 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "check": "npm run style:check && npm run i18n:check && npx tsc --noEmit && npm run structured-data:check && npm run docs:build", "check:node": "node docs/lib/check-node.mjs", "docs:dev": "vocs dev", - "docs:build": "NODE_OPTIONS=--max-old-space-size=6144 vocs build", + "docs:build": "NODE_OPTIONS=--max-old-space-size=7168 vocs build", "docs:preview": "vocs preview", "i18n:check": "node docs/lib/verify-i18n.mjs", "i18n:check:strict": "node docs/lib/verify-i18n.mjs --strict", From 9002b0fab924fc00d06827f8a0d621767853e707 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 14 Jul 2026 08:02:54 +0000 Subject: [PATCH 11/20] i18n: auto-translate cn/ko for changed en content --- docs/sidebar.json | 132 +++++++++++++++++++++++----------------------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/docs/sidebar.json b/docs/sidebar.json index 58ce0b0..489c5d1 100644 --- a/docs/sidebar.json +++ b/docs/sidebar.json @@ -793,7 +793,7 @@ "collapsed": true, "items": [ { - "text": "코어 최적화 개요", + "text": "핵심 최적화 개요", "link": "/ko/explanation/core-optimization-overview" }, { @@ -831,7 +831,7 @@ "link": "/ko/explanation/use-case-payroll" }, { - "text": "사용 사례: 후원", + "text": "사용 사례: 스폰서", "link": "/ko/explanation/use-case-sponsored" }, { @@ -887,11 +887,11 @@ "link": "/ko/how-to/earn-yield" }, { - "text": "Viem 통합", + "text": "viem 통합", "link": "/ko/how-to/sdk-with-viem" }, { - "text": "Wagmi 통합", + "text": "wagmi 통합", "link": "/ko/how-to/sdk-with-wagmi" } ] @@ -905,7 +905,7 @@ "link": "/ko/explanation/enterprise-sdk" }, { - "text": "릴레이 트랜잭션", + "text": "트랜잭션 중계", "link": "/ko/how-to/relay-with-gas-waiver" }, { @@ -913,7 +913,7 @@ "link": "/ko/how-to/send-guaranteed-transactions" }, { - "text": "보장된 릴레이 트랜잭션", + "text": "보장된 중계 트랜잭션", "link": "/ko/how-to/guaranteed-relayed-transactions" }, { @@ -931,7 +931,7 @@ "link": "/ko/explanation/accounts-overview" }, { - "text": "계정 인덱스", + "text": "계정 색인", "link": "/ko/explanation/accounts-guides" }, { @@ -957,7 +957,7 @@ "link": "/ko/explanation/payments-overview" }, { - "text": "결제 인덱스", + "text": "결제 색인", "link": "/ko/explanation/payments-guides" }, { @@ -969,7 +969,7 @@ "link": "/ko/tutorial/send-usdt0" }, { - "text": "제로 가스 트랜잭션", + "text": "수수료 없는 트랜잭션", "link": "/ko/how-to/zero-gas-transactions" }, { @@ -977,13 +977,13 @@ "link": "/ko/how-to/work-with-usdt-gas" }, { - "text": "USDT0 브릿징", + "text": "USDT0 브릿지", "link": "/ko/tutorial/bridge-usdt0" } ] }, { - "text": "사용자 청구", + "text": "사용자에게 청구", "collapsed": true, "items": [ { @@ -995,7 +995,7 @@ "link": "/ko/how-to/subscribe-and-collect" }, { - "text": "인보이스로 결제", + "text": "송장으로 결제", "link": "/ko/how-to/pay-with-invoice" } ] @@ -1021,11 +1021,11 @@ "link": "/ko/reference/subscriptions" }, { - "text": "인보이스", + "text": "송장", "link": "/ko/reference/invoices" }, { - "text": "통화 당 지불", + "text": "호출당 지불", "link": "/ko/reference/pay-per-call" }, { @@ -1045,11 +1045,11 @@ "link": "/ko/explanation/contracts-overview" }, { - "text": "계약 인덱스", + "text": "계약 색인", "link": "/ko/explanation/contracts-guides" }, { - "text": "첫 번째 계약 배포", + "text": "첫 번째 계약 배포하기", "collapsed": true, "items": [ { @@ -1083,19 +1083,19 @@ "link": "/ko/reference/system-modules-api-overview" }, { - "text": "뱅크 모듈", + "text": "은행 모듈", "link": "/ko/explanation/bank-module" }, { - "text": "뱅크 모듈 API", + "text": "은행 모듈 API", "link": "/ko/reference/bank-module-api" }, { - "text": "분배 모듈", + "text": "배포 모듈", "link": "/ko/explanation/distribution-module" }, { - "text": "분배 모듈 API", + "text": "배포 모듈 API", "link": "/ko/reference/distribution-module-api" }, { @@ -1115,11 +1115,11 @@ "link": "/ko/reference/system-transactions-api" }, { - "text": "언본딩 추적", + "text": "언바운딩 추적", "link": "/ko/how-to/track-unbonding" }, { - "text": "검증인 데이터 인덱싱", + "text": "검증자 데이터 인덱싱", "link": "/ko/how-to/index-validator-data" } ] @@ -1145,7 +1145,7 @@ "link": "/ko/reference/connect" }, { - "text": "파우셋 사용", + "text": "Faucet 사용", "link": "/ko/how-to/use-faucet" }, { @@ -1217,7 +1217,7 @@ "link": "/ko/reference/bridges" }, { - "text": "덱스", + "text": "DEX", "link": "/ko/reference/dexes" }, { @@ -1241,7 +1241,7 @@ "link": "/ko/reference/wallets" }, { - "text": "수거", + "text": "수탁", "link": "/ko/reference/custody" }, { @@ -1251,7 +1251,7 @@ ] }, { - "text": "생산 준비성", + "text": "운영 준비", "link": "/ko/how-to/production-readiness" }, { @@ -1295,7 +1295,7 @@ "link": "/ko/how-to/use-node-snapshots" }, { - "text": "검증인 실행", + "text": "검증자 실행", "link": "/ko/how-to/run-validator" }, { @@ -1321,11 +1321,11 @@ "link": "/ko/explanation/agent-settlement" }, { - "text": "AI 에이전트 인덱스", + "text": "AI 에이전트 색인", "link": "/ko/explanation/ai-agents-guides" }, { - "text": "x402 및 MPP를 통한 결제", + "text": "x402 및 MPP를 통한 지불", "collapsed": true, "items": [ { @@ -1341,7 +1341,7 @@ "link": "/ko/explanation/mpp-sessions" }, { - "text": "통화 당 지불 구축", + "text": "호출당 지불 구축", "link": "/ko/how-to/build-pay-per-call" }, { @@ -1349,7 +1349,7 @@ "link": "/ko/how-to/build-mpp-endpoint" }, { - "text": "MCP로 결제", + "text": "MCP로 지불", "link": "/ko/how-to/pay-with-mcp" } ] @@ -1359,15 +1359,15 @@ "collapsed": true, "items": [ { - "text": "AI를 이용한 개발", + "text": "AI로 개발", "link": "/ko/how-to/develop-with-ai" }, { - "text": "Agentic Facilitators", + "text": "에이전트 퍼실리테이터", "link": "/ko/reference/agentic-facilitators" }, { - "text": "Agentic Wallets", + "text": "에이전트 지갑", "link": "/ko/reference/agentic-wallets" } ] @@ -1413,7 +1413,7 @@ "link": "/cn/explanation/ethereum-compatibility" }, { - "text": "最终性", + "text": "终结性", "link": "/cn/explanation/finality" }, { @@ -1435,7 +1435,7 @@ "collapsed": true, "items": [ { - "text": "USDT 功能概览", + "text": "USDT0 功能概览", "link": "/cn/explanation/usdt-features-overview" }, { @@ -1443,11 +1443,11 @@ "link": "/cn/explanation/flow-of-funds" }, { - "text": "USDT0 桥接", + "text": "USDT0 跨链", "link": "/cn/explanation/usdt0-bridging" }, { - "text": "桥接安全", + "text": "桥安全性", "link": "/cn/explanation/bridge-security" }, { @@ -1459,7 +1459,7 @@ "link": "/cn/explanation/usdt0-behavior" }, { - "text": "Gas 豁免", + "text": "Gas 减免", "link": "/cn/explanation/gas-waiver" }, { @@ -1467,11 +1467,11 @@ "link": "/cn/explanation/guaranteed-blockspace" }, { - "text": "USDT 转移聚合器", + "text": "USDT 转账聚合器", "link": "/cn/explanation/usdt-transfer-aggregator" }, { - "text": "保密转移", + "text": "隐私转账", "link": "/cn/explanation/confidential-transfer" } ] @@ -1493,7 +1493,7 @@ "link": "/cn/explanation/execution" }, { - "text": "Stable 数据库", + "text": "Stable DB", "link": "/cn/explanation/stable-db" }, { @@ -1515,7 +1515,7 @@ "link": "/cn/explanation/use-case-payments" }, { - "text": "用例:工资单", + "text": "用例:薪资", "link": "/cn/explanation/use-case-payroll" }, { @@ -1637,7 +1637,7 @@ ] }, { - "text": "接受支付", + "text": "接受付款", "collapsed": true, "items": [ { @@ -1683,7 +1683,7 @@ "link": "/cn/how-to/subscribe-and-collect" }, { - "text": "发票支付", + "text": "通过发票支付", "link": "/cn/how-to/pay-with-invoice" } ] @@ -1713,7 +1713,7 @@ "link": "/cn/reference/invoices" }, { - "text": "按次计费", + "text": "按次付费", "link": "/cn/reference/pay-per-call" }, { @@ -1725,7 +1725,7 @@ ] }, { - "text": "发布合约", + "text": "部署合约", "collapsed": true, "items": [ { @@ -1803,17 +1803,17 @@ "link": "/cn/reference/system-transactions-api" }, { - "text": "追踪解除绑定", + "text": "跟踪解绑", "link": "/cn/how-to/track-unbonding" }, { - "text": "索引验证器数据", + "text": "索引验证者数据", "link": "/cn/how-to/index-validator-data" } ] }, { - "text": "JSON RPC API", + "text": "JSON-RPC API", "link": "/cn/reference/json-rpc-api" } ] @@ -1879,19 +1879,19 @@ ] }, { - "text": "Gas 豁免服务", + "text": "Gas 减免服务", "collapsed": true, "items": [ { - "text": "集成 Gas 豁免", + "text": "集成 Gas 减免", "link": "/cn/how-to/integrate-gas-waiver" }, { - "text": "自托管 Gas 豁免", + "text": "自托管 Gas 减免", "link": "/cn/how-to/self-hosted-gas-waiver" }, { - "text": "Gas 豁免 API", + "text": "Gas 减免 API", "link": "/cn/reference/gas-waiver-api" } ] @@ -1905,7 +1905,7 @@ "link": "/cn/reference/bridges" }, { - "text": "去中心化交易所", + "text": "DEX", "link": "/cn/reference/dexes" }, { @@ -1921,7 +1921,7 @@ "link": "/cn/reference/network-routing" }, { - "text": "法币出入金", + "text": "出入金", "link": "/cn/reference/ramps" }, { @@ -1959,11 +1959,11 @@ ] }, { - "text": "运营", + "text": "操作", "collapsed": true, "items": [ { - "text": "节点运维概览", + "text": "节点操作概览", "link": "/cn/reference/node-operations-overview" }, { @@ -1983,7 +1983,7 @@ "link": "/cn/how-to/use-node-snapshots" }, { - "text": "运行验证器", + "text": "运行验证者", "link": "/cn/how-to/run-validator" }, { @@ -2013,7 +2013,7 @@ "link": "/cn/explanation/ai-agents-guides" }, { - "text": "通过 x402 和 MPP 支付", + "text": "通过 x402 和 MPP 付款", "collapsed": true, "items": [ { @@ -2021,23 +2021,23 @@ "link": "/cn/explanation/x402" }, { - "text": "Mpp", + "text": "MPP", "link": "/cn/explanation/mpp" }, { - "text": "Mpp 会话", + "text": "MPP 会话", "link": "/cn/explanation/mpp-sessions" }, { - "text": "构建按次计费", + "text": "构建按次付费", "link": "/cn/how-to/build-pay-per-call" }, { - "text": "构建 Mpp 端点", + "text": "构建 MPP 端点", "link": "/cn/how-to/build-mpp-endpoint" }, { - "text": "使用 Mcp 支付", + "text": "使用 MCP 付款", "link": "/cn/how-to/pay-with-mcp" } ] @@ -2047,7 +2047,7 @@ "collapsed": true, "items": [ { - "text": "用 AI 开发", + "text": "使用 AI 进行开发", "link": "/cn/how-to/develop-with-ai" }, { From ae8da11a42e592115fb3665119bd5c09b289a6c7 Mon Sep 17 00:00:00 2001 From: bastienrp Date: Wed, 15 Jul 2026 10:27:11 +0200 Subject: [PATCH 12/20] docs: document custody signers (AWS KMS) for the Enterprise SDK Reflect the custodian-signing update on the SDK main branch: the waiver modules now source their key from a SignerSource (signer > account > env var). Add a subtle "Signing keys and custody" section to the reference with the awsKmsSigner subpath, document the Signer/SignerSource types and signer helpers, and update the build helpers to take a Signer (toSigner). Fix the renamed guaranteedWaiver key field (waiverAccount -> account) and add custody tips to the how-to guides. Co-Authored-By: Claude Opus 4.8 --- docs/pages/en/explanation/enterprise-sdk.mdx | 2 +- .../guaranteed-relayed-transactions.mdx | 14 +-- .../pages/en/how-to/relay-with-gas-waiver.mdx | 10 ++- .../how-to/send-guaranteed-transactions.mdx | 4 +- docs/pages/en/reference/enterprise-sdk.mdx | 90 +++++++++++++++---- 5 files changed, 91 insertions(+), 29 deletions(-) diff --git a/docs/pages/en/explanation/enterprise-sdk.mdx b/docs/pages/en/explanation/enterprise-sdk.mdx index d22b8f5..c16b058 100644 --- a/docs/pages/en/explanation/enterprise-sdk.mdx +++ b/docs/pages/en/explanation/enterprise-sdk.mdx @@ -48,7 +48,7 @@ Both rails are gated. Gas waiver requires a governance-registered waiver key, an The Enterprise SDK is a stateless, server-side library that signs with private keys. Never run it in a browser. Keep the waiver key and the Enterprise RPC gateway URL on your backend. ::: -The waiver key is a whitelisted, governance-registered account: anyone holding it can sponsor gas under your policy. The Enterprise RPC gateway URL embeds your API key. Treat both as secrets. +The waiver key is a whitelisted, governance-registered account: anyone holding it can sponsor gas under your policy. The Enterprise RPC gateway URL embeds your API key. Treat both as secrets. To keep the waiver key out of process, back it with a custody signer such as AWS KMS. See [Signing keys and custody](/en/reference/enterprise-sdk#signing-keys-and-custody). ## When to use it diff --git a/docs/pages/en/how-to/guaranteed-relayed-transactions.mdx b/docs/pages/en/how-to/guaranteed-relayed-transactions.mdx index f17822f..770f26c 100644 --- a/docs/pages/en/how-to/guaranteed-relayed-transactions.mdx +++ b/docs/pages/en/how-to/guaranteed-relayed-transactions.mdx @@ -21,7 +21,7 @@ This is a server-side library. Keep the waiver key and the Enterprise RPC gatewa ## 1. Create a client with the guaranteed waiver module -Pass `guaranteedWaiver` and `enterpriseRpcEndpoints` to `createStableEnterprise`. The module takes the whitelisted waiver account (which signs the outer wrapper) plus the Enterprise lane. It also accepts the same `allowedTargets`, `maxGasLimit`, and `maxDataLength` policy limits as `gasWaiver`. +Pass `guaranteedWaiver` and `enterpriseRpcEndpoints` to `createStableEnterprise`. The module takes the whitelisted waiver key (which signs the outer wrapper) plus the Enterprise lane. It also accepts the same `allowedTargets`, `maxGasLimit`, and `maxDataLength` policy limits as `gasWaiver`. ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -31,7 +31,7 @@ const enterprise = createStableEnterprise({ chain: stableTestnet, enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // the gateway URL Stable provisions guaranteedWaiver: { - waiverAccount: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`), + account: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`), laneId: 0n, // Enterprise lane }, }); @@ -43,6 +43,10 @@ const gw = enterprise.guaranteedWaiver!; StableEnterpriseClient { gasWaiver: undefined, guaranteedBlock: undefined, guaranteedWaiver } ``` +:::tip +To keep the waiver key in a custody backend, pass `signer` instead of `account`. `awsKmsSigner` from `@stablechain/enterprise/aws-kms` backs it with AWS KMS. See [Signing keys and custody](/en/reference/enterprise-sdk#signing-keys-and-custody). +::: + ## 2. Relay a single transaction Call `send` with the user's account and the fields that vary. Gas is waived, so the user needs no balance and no fee fields. The inner `0x3F` CustomTx, its Enterprise `nonceKey`, and the 2D nonce (discovered from the gateway) are handled for you. @@ -82,10 +86,10 @@ for (const r of results) { For a non-custodial flow, the user signs the inner `0x3F` CustomTx in their own environment and hands you only the signed hex. Build it with `buildGuaranteedTx`, using `nonceKeyForLane` for the Enterprise nonce key and zero fees (gas is waived). Your backend wraps it with the waiver key and relays it with `relay`. ```ts -import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; +import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; -// on the user's side -const signedInner = await buildGuaranteedTx(user, stableTestnet.id, { +// on the user's side — buildGuaranteedTx signs through a Signer; toSigner adapts a viem account +const signedInner = await buildGuaranteedTx(toSigner(user), stableTestnet.id, { to: recipient, gas: 100_000n, gasFeeCap: 0n, // waived diff --git a/docs/pages/en/how-to/relay-with-gas-waiver.mdx b/docs/pages/en/how-to/relay-with-gas-waiver.mdx index b123789..d27d02a 100644 --- a/docs/pages/en/how-to/relay-with-gas-waiver.mdx +++ b/docs/pages/en/how-to/relay-with-gas-waiver.mdx @@ -41,6 +41,10 @@ StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver The `rpcEndpoints` option is optional. Left unset, the client uses the chain's built-in RPC. +:::tip +To keep the waiver key in a custody backend, pass `signer` instead of `account`. `awsKmsSigner` from `@stablechain/enterprise/aws-kms` backs it with AWS KMS. See [Signing keys and custody](/en/reference/enterprise-sdk#signing-keys-and-custody). +::: + ## 2. Relay a single transaction Call `send` with the user's account and the fields that vary. The `gasPrice: 0`, legacy type, `chainId`, and pending nonce are handled for you, so you pass only `to`, and optionally `data`, `value`, and `gas`. @@ -105,10 +109,10 @@ A transaction to a contract outside `allowedTargets` fails with `TARGET_NOT_ALLO For a non-custodial flow, the user signs the InnerTx in their own environment and hands you only the signed hex, so you never see their key. Build it with `buildWaiverInnerTx`, then relay it with `relay`. ```ts -import { buildWaiverInnerTx } from "@stablechain/enterprise"; +import { buildWaiverInnerTx, toSigner } from "@stablechain/enterprise"; -// on the user's side -const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to: token, data, gas: 150_000n, nonce }); +// on the user's side — buildWaiverInnerTx signs through a Signer; toSigner adapts a viem account +const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to: token, data, gas: 150_000n, nonce }); // on your backend const { txHash } = await gw.relay(signed); diff --git a/docs/pages/en/how-to/send-guaranteed-transactions.mdx b/docs/pages/en/how-to/send-guaranteed-transactions.mdx index d45aa08..c59ac1a 100644 --- a/docs/pages/en/how-to/send-guaranteed-transactions.mdx +++ b/docs/pages/en/how-to/send-guaranteed-transactions.mdx @@ -94,9 +94,9 @@ for (const r of results) { For a non-custodial flow, build and sign the GuaranteedTx elsewhere with `buildGuaranteedTx`, then hand the operator only the signed hex. The Enterprise nonce key comes from `nonceKeyForLane`. ```ts -import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; +import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; -const signed = await buildGuaranteedTx(signer, stableTestnet.id, { +const signed = await buildGuaranteedTx(toSigner(signer), stableTestnet.id, { to: recipient, gas: 21_000n, gasFeeCap, diff --git a/docs/pages/en/reference/enterprise-sdk.mdx b/docs/pages/en/reference/enterprise-sdk.mdx index 2f9f840..1415ca3 100644 --- a/docs/pages/en/reference/enterprise-sdk.mdx +++ b/docs/pages/en/reference/enterprise-sdk.mdx @@ -58,6 +58,31 @@ StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver | `guaranteedBlock` | `GuaranteedBlockConfig?` | | Enable [guaranteed blockspace](#guaranteed-blockspace). | | `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | Enable [guaranteed relay transactions](#guaranteed-relay-transactions). | +### Signing keys and custody + +The modules that hold the waiver key (`gasWaiver` and `guaranteedWaiver`) resolve it from a [`SignerSource`](#signersource), in order: `signer` (a custody-grade backend), then `account` (an in-process viem key), then the `STABLE_ENTERPRISE_PRIVATE_KEY` environment variable. `guaranteedBlock` takes a funded `account` directly. + +A `Signer` signs a 32-byte digest, so the key never leaves the custody backend. Use `awsKmsSigner` for AWS KMS, `toSigner(account)` to adapt a viem account, or `privateKeySigner(key)` / `envSigner()` for an in-process key. + +```bash +npm install @aws-sdk/client-kms +``` + +```ts +import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; +import { awsKmsSigner } from "@stablechain/enterprise/aws-kms"; + +// the KMS key must be ECC_SECG_P256K1 (secp256k1); the SDK derives the address from it +const signer = await awsKmsSigner({ keyId: process.env.KMS_KEY_ID! }); + +const enterprise = createStableEnterprise({ + chain: stableTestnet, + gasWaiver: { signer }, // custody-grade waiver key, in place of `account` +}); +``` + +`awsKmsSigner` ships in the `@stablechain/enterprise/aws-kms` subpath so `@aws-sdk/client-kms` stays an optional peer dependency, out of the core install. + ### `StableEnterpriseClient` ```ts @@ -90,11 +115,12 @@ const gw = enterprise.gasWaiver!; ### `GasWaiverConfig` -Extends [`ValidationLimits`](#validationlimits). +Extends [`ValidationLimits`](#validationlimits) and [`SignerSource`](#signersource). | **Field** | **Type** | **Description** | | :--- | :--- | :--- | -| `account` | `LocalAccount` | The whitelisted, governance-registered account that signs each WaiverTx. | +| `signer` | `Signer?` | The whitelisted, governance-registered waiver key as a custody signer (AWS KMS, HSM). See [Signing keys and custody](#signing-keys-and-custody). Takes precedence over `account`. | +| `account` | `LocalAccount?` | The waiver key as an in-process viem account. Falls back to `STABLE_ENTERPRISE_PRIVATE_KEY` when neither is set. | | `maxGasLimit` | `bigint?` | Inherited from `ValidationLimits`. | | `maxDataLength` | `number?` | Inherited from `ValidationLimits`. | | `allowedTargets` | `AllowedTarget[]?` | Inherited from `ValidationLimits`. | @@ -132,12 +158,12 @@ const results = await gw.sendBatch(user, [ ### `relay(signedInnerTxHex)` -Relay a pre-signed zero-gas InnerTx. Use this for the non-custodial flow where the user signs in their own environment and hands you only the signed hex, so the waiver operator never sees the user's key. Build one with [`buildWaiverInnerTx`](#buildwaiverinnertxaccount-chainid-req). Throws on rejection. +Relay a pre-signed zero-gas InnerTx. Use this for the non-custodial flow where the user signs in their own environment and hands you only the signed hex, so the waiver operator never sees the user's key. Build one with [`buildWaiverInnerTx`](#buildwaiverinnertxsigner-chainid-req). Throws on rejection. ```ts -import { buildWaiverInnerTx } from "@stablechain/enterprise"; +import { buildWaiverInnerTx, toSigner } from "@stablechain/enterprise"; -const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to, data, gas: 150_000n, nonce }); +const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to, data, gas: 150_000n, nonce }); const { txHash } = await gw.relay(signed); ``` @@ -223,12 +249,12 @@ Returns [`BatchResultItem[]`](#batchresultitem). ### `relay(signedTx)` / `relayBatch(signedTxs)` -Relay a pre-signed GuaranteedTx, or a batch of them. Build and sign the transaction elsewhere with [`buildGuaranteedTx`](#buildguaranteedtxaccount-chainid-req), using [`nonceKeyForLane`](#noncekeyforlanelaneid) for the Enterprise nonce key, then hand the operator only the signed hex. +Relay a pre-signed GuaranteedTx, or a batch of them. Build and sign the transaction elsewhere with [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req), using [`nonceKeyForLane`](#noncekeyforlanelaneid) for the Enterprise nonce key, then hand the operator only the signed hex. ```ts -import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; +import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; -const signed = await buildGuaranteedTx(signer, stableTestnet.id, { +const signed = await buildGuaranteedTx(toSigner(signer), stableTestnet.id, { to, gas: 21_000n, gasFeeCap, @@ -254,7 +280,7 @@ const enterprise = createStableEnterprise({ chain: stableTestnet, enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // the gateway URL Stable provisions guaranteedWaiver: { - waiverAccount: privateKeyToAccount("0xYOUR_WAIVER_KEY"), + account: privateKeyToAccount("0xYOUR_WAIVER_KEY"), laneId: 0n, }, }); @@ -264,11 +290,12 @@ const gw = enterprise.guaranteedWaiver!; ### `GuaranteedWaiverConfig` -Extends [`ValidationLimits`](#validationlimits), so it accepts the same `maxGasLimit`, `maxDataLength`, and `allowedTargets` policy controls as `GasWaiverConfig`. +Extends [`ValidationLimits`](#validationlimits) and [`SignerSource`](#signersource). It sources the outer-wrapper waiver key exactly like `GasWaiverConfig` (`signer`, then `account`, then the env var) and accepts the same `maxGasLimit`, `maxDataLength`, and `allowedTargets` policy controls. | **Field** | **Type** | **Description** | | :--- | :--- | :--- | -| `waiverAccount` | `LocalAccount` | The whitelisted, governance-registered account that signs the outer wrapper. | +| `signer` | `Signer?` | The whitelisted waiver key (which signs the outer wrapper) as a custody signer. Takes precedence over `account`. See [Signing keys and custody](#signing-keys-and-custody). | +| `account` | `LocalAccount?` | The waiver key as an in-process viem account. Falls back to `STABLE_ENTERPRISE_PRIVATE_KEY` when neither is set. | | `laneId` | `bigint` | Enterprise lane id. Must be in `[0, ENTERPRISE_MASK - 1]`. | ### `send(user, tx)` / `sendBatch(user, txs)` @@ -291,12 +318,12 @@ The `tx` argument is a [`GuaranteedWaiverTxRequest`](#guaranteedwaivertxrequest) ### `relay(signedInnerTx)` / `relayBatch(signedInnerTxs)` -For the non-custodial flow, the user signs the inner `0x3F` CustomTx with [`buildGuaranteedTx`](#buildguaranteedtxaccount-chainid-req) (fees `0n`, using `nonceKeyForLane(laneId)`) and hands the operator only the signed hex. The operator wraps it with the waiver key and relays. +For the non-custodial flow, the user signs the inner `0x3F` CustomTx with [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req) (fees `0n`, using `nonceKeyForLane(laneId)`) and hands the operator only the signed hex. The operator wraps it with the waiver key and relays. ```ts -import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; +import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; -const signedInner = await buildGuaranteedTx(user, stableTestnet.id, { +const signedInner = await buildGuaranteedTx(toSigner(user), stableTestnet.id, { to, gas: 100_000n, gasFeeCap: 0n, // waived @@ -313,17 +340,17 @@ const { txHash } = await gw.relay(signedInner); // waiver wraps + broadcasts → ## Build helpers -Low-level signers for the non-custodial `relay` paths. Each returns a signed transaction as `Hex`, with no nonce fetch or fee estimation. +Low-level signers for the non-custodial `relay` paths. Each returns a signed transaction as `Hex`, with no nonce fetch or fee estimation. The first argument is a [`Signer`](#signing-keys-and-custody): wrap a viem account with `toSigner(account)`, or pass a custody signer such as `awsKmsSigner`. -### `buildWaiverInnerTx(account, chainId, req)` +### `buildWaiverInnerTx(signer, chainId, req)` Sign a waiver-ready InnerTx with the waiver invariants baked in: `gasPrice: 0`, legacy type, and the given `chainId`. `req` is a [`WaiverInnerTx`](#waiverinnertx) plus a required `nonce`. ```ts -const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to, data, gas: 150_000n, nonce }); +const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to, data, gas: 150_000n, nonce }); ``` -### `buildGuaranteedTx(account, chainId, req)` +### `buildGuaranteedTx(signer, chainId, req)` Build and sign a GuaranteedTx (`0x3F` CustomTx). `req` is a [`GuaranteedTxRequest`](#guaranteedtxrequest) plus a required `nonce` and `nonceKey`. @@ -343,6 +370,33 @@ const nonceKey = nonceKeyForLane(0n); ## Types +### `SignerSource` + +The signing-key fields a waiver module (`gasWaiver`, `guaranteedWaiver`) accepts. Resolved in order: `signer`, then `account`, then the `STABLE_ENTERPRISE_PRIVATE_KEY` env var. See [Signing keys and custody](#signing-keys-and-custody). + +| **Field** | **Type** | **Description** | +| :--- | :--- | :--- | +| `signer` | `Signer?` | A custody-grade signer (AWS KMS, HSM, or `privateKeySigner`). Takes precedence over `account`. | +| `account` | `LocalAccount?` | An in-process viem account, adapted to a `Signer` via `toSigner`. | + +### `Signer` + +A pluggable signer the SDK signs a 32-byte digest through, so the key never leaves the custody backend. Construct one with `awsKmsSigner`, `toSigner`, `privateKeySigner`, or `envSigner`. + +```ts +interface Signer { + readonly address: Address; + signDigest(hash: Hex): Promise; +} +``` + +| **Helper** | **Import** | **Description** | +| :--- | :--- | :--- | +| `awsKmsSigner({ keyId, client? })` | `@stablechain/enterprise/aws-kms` | Signer backed by an AWS KMS `ECC_SECG_P256K1` key. Returns a `Promise`. | +| `toSigner(account)` | `@stablechain/enterprise` | Adapt a viem `LocalAccount` to a `Signer`. | +| `privateKeySigner(key)` | `@stablechain/enterprise` | Signer wrapping a raw private key held in process. | +| `envSigner(varName?)` | `@stablechain/enterprise` | Signer reading the key from `STABLE_ENTERPRISE_PRIVATE_KEY` (or `varName`). | + ### `WaiverInnerTx` The fields of an InnerTx that vary per call. From 2602a0bfc7a43049edc05ed2f25b91debaa43792 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 Jul 2026 08:30:11 +0000 Subject: [PATCH 13/20] i18n: auto-translate cn/ko for changed en content --- docs/pages/cn/explanation/enterprise-sdk.mdx | 52 ++-- .../guaranteed-relayed-transactions.mdx | 54 ++-- .../pages/cn/how-to/relay-with-gas-waiver.mdx | 62 +++-- .../how-to/send-guaranteed-transactions.mdx | 52 ++-- docs/pages/cn/reference/enterprise-sdk.mdx | 222 +++++++++------ docs/pages/ko/explanation/enterprise-sdk.mdx | 50 ++-- .../guaranteed-relayed-transactions.mdx | 50 ++-- .../pages/ko/how-to/relay-with-gas-waiver.mdx | 56 ++-- .../how-to/send-guaranteed-transactions.mdx | 46 ++-- docs/pages/ko/reference/enterprise-sdk.mdx | 254 +++++++++++------- docs/sidebar.json | 94 +++---- 11 files changed, 558 insertions(+), 434 deletions(-) diff --git a/docs/pages/cn/explanation/enterprise-sdk.mdx b/docs/pages/cn/explanation/enterprise-sdk.mdx index 92779b6..d2e5235 100644 --- a/docs/pages/cn/explanation/enterprise-sdk.mdx +++ b/docs/pages/cn/explanation/enterprise-sdk.mdx @@ -1,18 +1,18 @@ --- source_path: explanation/enterprise-sdk.mdx -source_sha: d22b8f5b286b6030a0282c7f45a4ef60dd1d928b -title: "Stable 企业级 SDK" -description: "使用类型化的 @stablechain/enterprise SDK,从您的后端中继免 gas 费和保证区块空间的交易。" +source_sha: c16b058331d58a968753ec4877bb47cd7377fe14 +title: "Stable 企业版 SDK" +description: "使用类型化的 @stablechain/enterprise SDK 从后端中继免 gas 和保证区块空间的交易。" diataxis: "explanation" --- -# Stable 企业级 SDK +# Stable 企业版 SDK -`@stablechain/enterprise` 是一个用于 Stable 企业级交易路由的服务器端 TypeScript 客户端。它签署并中继两种特权交易:免 gas 费交易(您为用户支付 gas 费)和保证区块空间交易(在保留的企业级通道中执行)。您可以在一个客户端上启用任一或同时启用两种路由。 +`@stablechain/enterprise` 是一个用于 Stable 企业版交易通道的服务器端 TypeScript 客户端。它签署并中继两种特权交易:免 gas 交易(您为用户支付 gas)和保证区块空间交易(交易进入预留的企业通道)。您可以在一个客户端上启用其中一种或两种通道。 ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; -import { privateKeyToAccount } from "viem/accounts"; +import { privateKeyToAccount } = "viem/accounts"; const enterprise = createStableEnterprise({ chain: stableTestnet, @@ -26,45 +26,45 @@ const { txHash } = await enterprise.gasWaiver!.send(user, { to: token, data }); txHash: 0x8f3a...2d41 ``` -该调用返回 `H_inner`,即用户交易的哈希值,而不是封装该交易的包装器交易的哈希值。 +调用返回 `H_inner`,即用户交易的哈希值,而不是承载它的包装器交易的哈希值。 -## SDK 的功能 +## SDK 的作用 -SDK 暴露了三个功能,每个模块一个。每个功能都是可选且独立配置的,并且每个功能都带自己的签名账户,因此您可以使用不同的密钥。 +该 SDK 暴露了三个功能,每个模块一个。每个功能都是可选的且独立配置的,每个功能都带有自己的签名账户,因此您可以使用不同的密钥。 -- **免 gas 费中继** (`gasWaiver`):构建、签署并中继免 gas 费交易。一个白名单豁免账户封装用户的零 gas 交易,因此用户无需持有任何 USDT0 即可交易。请参阅[免 gas 费](/cn/explanation/gas-waiver)。 -- **保证区块空间** (`guaranteedBlock`):通过企业级 RPC 网关中继交易,使其落在保留的企业级通道区块空间中。与免 gas 费不同,签名者支付自己的 gas 费。请参阅[保证区块空间](/cn/explanation/guaranteed-blockspace)。 -- **保证中继交易** (`guaranteedWaiver`):两者结合。通过保证区块空间路由的免 gas 费交易,因此用户无需余额,且交易仍落在企业级通道中。 +- **免 Gas 中继** (`gasWaiver`):构建、签署和中继免 gas 交易。一个白名单中的免除账户会包装用户的零 gas 交易,这样用户无需持有任何 USDT0 即可进行交易。请参阅[免 Gas](/cn/explanation/gas-waiver)。 +- **保证区块空间** (`guaranteedBlock`):通过企业 RPC 网关中继交易,使其进入预留的企业通道区块空间。与免 gas 不同,签名者支付自己的 gas。请参阅[保证区块空间](/cn/explanation/guaranteed-blockspace)。 +- **保证中继交易** (`guaranteedWaiver`):两者结合。通过保证区块空间路由的免 gas 交易,这样用户无需余额,交易仍会进入企业通道。 -每个功能都提供相同的四种方法:`send` 和 `sendBatch` 用于 SDK 签名的托管路径,`relay` 和 `relayBatch` 用于用户在其他地方签名并只向您提供签名十六进制字符串的非托管路径。 +每个功能都提供相同的四个方法:`send` 和 `sendBatch` 用于 SDK 签名的托管路径,以及 `relay` 和 `relayBatch` 用于用户在其他地方签名并仅将签名后的十六进制数据交给您的非托管路径。 -## 访问权限 +## 访问 -企业级 SDK 目前仅在 Stable Testnet 上可用。 +企业版 SDK 目前仅在 Stable 测试网可用。 -两种路由都受限制。免 gas 费需要治理注册的豁免密钥,保证区块空间需要企业级 RPC 网关 API 密钥。要进行集成,请[联系 Stable](https://discord.gg/stablexyz) 获取访问权限。Stable 会提供您需要的豁免密钥和网关端点。 +两个通道都受限。免 gas 需要治理注册的免除密钥,而保证区块空间需要企业 RPC 网关 API 密钥。要集成,请[联系 Stable](https://discord.gg/stablexyz) 获取访问权限。Stable 会为您提供所需的免除密钥和网关端点。 ## 仅限服务器端 :::warning -企业级 SDK 是一个无状态的服务器端库,使用私钥进行签名。切勿在浏览器中运行它。将豁免密钥和企业级 RPC 网关 URL 保留在您的后端。 +企业版 SDK 是一个无状态的服务器端库,使用私钥进行签名。切勿在浏览器中运行它。将免责密钥和企业 RPC 网关 URL 保留在您的后端。 ::: -豁免密钥是经过白名单认证、治理注册的账户:任何持有它的人都可以在您的政策下赞助 gas 费。企业级 RPC 网关 URL 嵌入了您的 API 密钥。将两者都视为秘密。 +豁免密钥是一个白名单中、由治理注册的账户:任何持有该密钥的人都可以在您的策略下资助 gas。企业 RPC 网关 URL 嵌入了您的 API 密钥。将两者都视为秘密。为了将豁免密钥排除在流程之外,请使用 AWS KMS 等托管签名器对其进行备份。请参阅[签名密钥和托管](/cn/reference/enterprise-sdk#signing-keys-and-custody)。 -## 使用场景 +## 何时使用 -当您操作后端并希望赞助用户的 gas 费或保证您的流量被包含时,请使用企业级 SDK。对于来自后端或浏览器的日常转账、桥接、兑换和金库收益,请使用通用型 [Stable SDK](/cn/explanation/sdk-overview)。 +如果您运营后端并希望为用户支付 gas 费用或保证您的交易能够被包含,请使用企业版 SDK。对于日常转账、桥接、兑换和从后端或浏览器获取的金库收益,请使用通用的 [Stable SDK](/cn/explanation/sdk-overview)。 ## 从这里开始 -- [**免 gas 费中继**](/cn/how-to/relay-with-gas-waiver):赞助用户的 gas 费,使其无需持有 USDT0 即可交易。 -- [**发送保证交易**](/cn/how-to/send-guaranteed-transactions):将交易执行在保留的企业级通道区块空间中。 -- [**保证中继交易**](/cn/how-to/guaranteed-relayed-transactions):结合两种路由:免 gas 费交易在企业级通道中执行。 -- [**企业级 SDK 参考**](/cn/reference/enterprise-sdk):每个模块、方法、配置选项和错误类。 +- [**免 gas 中继**](/cn/how-to/relay-with-gas-waiver):为用户支付 gas 费用,使其无需持有 USDT0 即可进行交易。 +- [**发送保证交易**](/cn/how-to/send-guaranteed-transactions):将交易放入预留的企业级区块空间。 +- [**保证中继交易**](/cn/how-to/guaranteed-relayed-transactions):结合这两种方式:在企业通道中进行免 gas 交易。 +- [**企业版 SDK 参考**](/cn/reference/enterprise-sdk):每个模块、方法、配置选项和错误类。 -## 下一步建议 +## 接下来建议 -- [**免 gas 费协议**](/cn/reference/gas-waiver-api):交易格式、标记路由和治理控制。 +- [**Gas 豁免协议**](/cn/reference/gas-waiver-api):交易格式、标记路由和治理控制。 - [**Stable SDK**](/cn/explanation/sdk-overview):用于转账、桥接、兑换和收益的通用客户端。 - [**连接到 Stable**](/cn/reference/connect):测试网的链 ID、RPC 端点和浏览器。 diff --git a/docs/pages/cn/how-to/guaranteed-relayed-transactions.mdx b/docs/pages/cn/how-to/guaranteed-relayed-transactions.mdx index 6a4798f..db0f74e 100644 --- a/docs/pages/cn/how-to/guaranteed-relayed-transactions.mdx +++ b/docs/pages/cn/how-to/guaranteed-relayed-transactions.mdx @@ -1,29 +1,29 @@ --- source_path: how-to/guaranteed-relayed-transactions.mdx -source_sha: f17822f84d15b62f1ec4a12e262dad94d7343a46 -title: "保证中继交易" -description: "通过带质保的出块空间中继免燃料费交易,用户无需余额即可进入企业版通道,使用 Enterprise SDK。" +source_sha: 770f26cb178bfd6e7b678d524f5148a39a3f9946 +title: "有保障的中继交易" +description: "使用 Enterprise SDK 通过有保障的区块空间中继免燃料费交易,这样用户无需余额即可进入企业通道。" diataxis: "how-to" --- -# 保证中继交易 +# 有保障的中继交易 -结合使用 `@stablechain/enterprise` 的企业版通道。保证中继交易是[免燃料费交易](/cn/how-to/relay-with-gas-waiver),通过[保证出块空间](/cn/how-to/send-guaranteed-transactions)进行路由:免除机制支付燃料费,因此用户无需余额和燃料费字段,交易仍会进入预留的企业版通道。 +将 Enterprise 的功能与 `@stablechain/enterprise` 结合起来。有保障的中继交易是[免燃料费交易](/cn/how-to/relay-with-gas-waiver),它通过[有保障的区块空间](/cn/how-to/send-guaranteed-transactions)进行路由:豁免方支付燃料费,因此用户无需余额和燃料费字段,交易仍能进入预留的企业通道。 -`guaranteedWaiver` 模块同时处理两端。用户签署内部 `0x3F` CustomTx,白名单免除帐户将其封装在共享相同 Enterprise `nonceKey` 的外部 `0x3F` CustomTx 中,并通过 Enterprise RPC 网关广播。每个方法都返回 `H_inner`,即用户的交易哈希。 +`guaranteedWaiver` 模块处理双方。用户签署内部 `0x3F` CustomTx,白名单中的豁免账户将其包装在共享相同企业 `nonceKey` 的外部 `0x3F` CustomTx 中,并通过企业 RPC 网关进行广播。每个方法都返回用户的交易哈希 `H_inner`。 ## 先决条件 - Node.js 20 或更高版本,并安装 `@stablechain/enterprise` 和 `viem`。请参阅 [Enterprise SDK 参考](/cn/reference/enterprise-sdk#install)。 -- 治理注册的免除密钥和企业版 RPC 网关 API 密钥。Enterprise SDK 目前仅限测试网,并按要求提供访问权限:[联系 Stable](https://discord.gg/stablexyz) 以获取两者。 +- 一个在管理中注册的豁免密钥和一个企业 RPC 网关 API 密钥。Enterprise SDK 目前仅支持测试网,并且需要请求才能访问:[联系 Stable](https://discord.gg/stablexyz) 获取两者。 :::warning -这是一个服务器端库。将免除密钥和 Enterprise RPC 网关 URL 保存在您的后端:网关 URL 嵌入了您的 API 密钥。 +这是一个服务器端库。请将豁免密钥和企业 RPC 网关 URL 保留在您的后端:网关 URL 嵌入了您的 API 密钥。 ::: -## 1. 创建带有保证免除模块的客户端 +## 1. 使用有保障的豁免模块创建客户端 -将 `guaranteedWaiver` 和 `enterpriseRpcEndpoints` 传递给 `createStableEnterprise`。该模块接收白名单免除帐户(用于签署外部封装器)以及 Enterprise 通道。它还接受与 `gasWaiver` 相同的 `allowedTargets`、`maxGasLimit` 和 `maxDataLength` 策略限制。 +将 `guaranteedWaiver` 和 `enterpriseRpcEndpoints` 传递给 `createStableEnterprise`。该模块接收白名单中的豁免密钥(用于签署外部包装器)以及企业通道。它还接受与 `gasWaiver` 相同的 `allowedTargets`、`maxGasLimit` 和 `maxDataLength` 策略限制。 ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -33,7 +33,7 @@ const enterprise = createStableEnterprise({ chain: stableTestnet, enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // the gateway URL Stable provisions guaranteedWaiver: { - waiverAccount: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`), + account: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`), laneId: 0n, // Enterprise lane }, }); @@ -45,9 +45,13 @@ const gw = enterprise.guaranteedWaiver!; StableEnterpriseClient { gasWaiver: undefined, guaranteedBlock: undefined, guaranteedWaiver } ``` +:::tip +要将豁免密钥保存在托管后端中,请传递 `signer` 而不是 `account`。`@stablechain/enterprise/aws-kms` 中的 `awsKmsSigner` 支持 AWS KMS。请参阅[签署密钥和托管](/cn/reference/enterprise-sdk#signing-keys-and-custody)。 +::: + ## 2. 中继单个交易 -使用用户帐户和变化的字段调用 `send`。燃料费已免除,因此用户不需要余额和燃料费字段。内部 `0x3F` CustomTx、其 Enterprise `nonceKey` 和 2D nonce(从网关发现)都已为您处理。 +使用用户的账户和变化的字段调用 `send`。燃料费被豁免,因此用户无需余额和燃料费字段。内部的 `0x3F` CustomTx、其企业 `nonceKey` 和 2D nonce(从网关发现)都会为您处理。 ```ts const user = privateKeyToAccount(process.env.USER_PRIVATE_KEY as `0x${string}`); @@ -62,9 +66,9 @@ H_inner: 0x8f3a...2d41 `gas` 默认为共享的内部燃料费默认值;仅在需要覆盖时才传递它。允许价值转移,因此您也可以传递 `value`。 -## 3. 中继批次 +## 3. 中继批处理 -调用 `sendBatch` 以中继来自一个用户的多个交易。内部 nonce 从发现的基础自动排序,并且您会为每个输入获得一个结果,按输入顺序。一个失败会使其后续成功。 +调用 `sendBatch` 中继来自一个用户的多个交易。内部 nonce 从发现的基础自动排序,您会按输入顺序获得每个输入一个结果。一个失败会使其后续的交易中止。 ```ts const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); @@ -79,15 +83,15 @@ for (const r of results) { [1] ✔ 0x2b7c...9e04 ``` -## 4. 中继预签署交易 +## 4. 中继预签名交易 -对于非托管流程,用户在其自己的环境中签署内部 `0x3F` CustomTx,并仅将签署的十六进制交给您。使用 `buildGuaranteedTx` 构建它,使用 `nonceKeyForLane` 作为 Enterprise nonce 密钥和零燃料费(燃料费已免除)。您的后端使用免除密钥将其封装,并使用 `relay` 中继。 +对于非托管流程,用户在其自己的环境中签署内部 `0x3F` CustomTx,并仅将已签署的十六进制字符串交给您。使用 `buildGuaranteedTx` 构建它,其中企业 nonce 密钥使用 `nonceKeyForLane`,燃料费设置为零(燃料费被豁免)。您的后端使用豁免密钥包装它,并使用 `relay` 进行中继。 ```ts -import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; +import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; -// on the user's side -const signedInner = await buildGuaranteedTx(user, stableTestnet.id, { +// on the user's side — buildGuaranteedTx signs through a Signer; toSigner adapts a viem account +const signedInner = await buildGuaranteedTx(toSigner(user), stableTestnet.id, { to: recipient, gas: 100_000n, gasFeeCap: 0n, // waived @@ -105,11 +109,11 @@ console.log("H_inner:", txHash); H_inner: 0x8f3a...2d41 ``` -对于多个预签署交易,请使用 `relayBatch`。 +对于多个预签名交易,请使用 `relayBatch`。 ## 处理拒绝 -`send` 和 `relay` 在拒绝时抛出 `StableEnterpriseRelayError`。由于此流程通过网关路由,因此网关代码(如 `GATEWAY_UNAUTHORIZED` 和 `QUOTA_EXCEEDED`)以及免除策略代码(如 `TARGET_NOT_ALLOWED`)都适用。 +`send` 和 `relay` 在拒绝时会抛出 `StableEnterpriseRelayError`。由于此流程通过网关路由,因此网关代码(如 `GATEWAY_UNAUTHORIZED` 和 `QUOTA_EXCEEDED`)以及豁免策略代码(如 `TARGET_NOT_ALLOWED`)都适用。 ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -128,10 +132,10 @@ try { StableEnterpriseRelayError: relay failed [GATEWAY_UNAUTHORIZED]: invalid api key ``` -有关每个拒绝原因的完整信息,请参阅完整的 [`ErrorCode`](/cn/reference/enterprise-sdk#errorcode) 表格。 +有关所有拒绝原因,请参阅完整的 [`ErrorCode`](/cn/reference/enterprise-sdk#errorcode) 表。 ## 接下来去哪里 -- [**免燃料费中继**](/cn/how-to/relay-with-gas-waiver):为用户支付燃料费,无需保证通道。 -- [**发送保证交易**](/cn/how-to/send-guaranteed-transactions):单独使用保证出块空间,由签名者支付燃料费。 -- [**Enterprise SDK 参考**](/cn/reference/enterprise-sdk#guaranteed-relay-transactions):所有方法、配置选项和错误类详情。 +- [**中继免燃料费交易**](/cn/how-to/relay-with-gas-waiver):为用户提供燃料费,但不使用有保障的通道。 +- [**发送有保障的交易**](/cn/how-to/send-guaranteed-transactions):单独使用有保障的区块空间,由签名者支付燃料费。 +- [**Enterprise SDK 参考**](/cn/reference/enterprise-sdk#guaranteed-relay-transactions):所有方法、配置选项和错误类的完整说明。 diff --git a/docs/pages/cn/how-to/relay-with-gas-waiver.mdx b/docs/pages/cn/how-to/relay-with-gas-waiver.mdx index d5c03ba..d249e64 100644 --- a/docs/pages/cn/how-to/relay-with-gas-waiver.mdx +++ b/docs/pages/cn/how-to/relay-with-gas-waiver.mdx @@ -1,29 +1,29 @@ --- source_path: how-to/relay-with-gas-waiver.mdx -source_sha: b123789598d68061ee8cb4472a3ed8d22153b91c -title: "使用 Gas 代付进行中继" -description: "使用 Enterprise SDK 赞助用户的 gas 费用:中继零 gas 交易、批量中继、强制执行策略限制以及中继预签名交易。" +source_sha: d27d02a1e7956429991b4af81f097719e3eabd34 +title: "使用 Gas Waiver 进行中继" +description: "通过 Enterprise SDK 赞助用户的 gas:中继零 gas 交易,批量中继,强制执行策略限制,以及中继预签名交易。" diataxis: "how-to" --- -# 使用 Gas 代付进行中继 +# 使用 Gas Waiver 进行中继 -使用 `@stablechain/enterprise` 赞助用户的 gas 费用。列入白名单的代付账户会封装用户的零 gas 交易(InnerTx)并广播,因此用户无需持有任何 USDT0 即可进行交易。`gasWaiver` 模块在一个调用中完成构建、签名和中继,因此每个操作只需调用一个方法。 +使用 `@stablechain/enterprise` 赞助用户的 gas。列入白名单的 waiver 账户会封装用户的零 gas 交易(内部交易),并将其广播,这样用户无需持有任何 USDT0 即可进行交易。`gasWaiver` 模块在一个调用中构建、签名和中继,因此您每个操作只需调用一个方法。 每个方法都返回 `H_inner`,即用户交易的哈希值,而不是承载它的封装器。 ## 先决条件 -- Node.js 20 或更高版本,并已安装 `@stablechain/enterprise` 和 `viem`。请参阅 [Enterprise SDK 参考](/cn/reference/enterprise-sdk#install)。 -- 治理注册的代付密钥。Enterprise SDK 目前仅限测试网使用,并且访问受限:请[联系 Stable](https://discord.gg/stablexyz) 以获取列入白名单的代付密钥。 +- Node.js 20 或更高版本,并安装了 `@stablechain/enterprise` 和 `viem`。请参阅 [Enterprise SDK 参考](/cn/reference/enterprise-sdk#install)。 +- 治理注册的 waiver 密钥。Enterprise SDK 目前仅适用于测试网,并且访问受限:请[联系 Stable](https://discord.gg/stablexyz) 以获取白名单 waiver 密钥。 :::warning -这是一个使用私钥进行签名的服务器端库。切勿在浏览器中运行。将代付密钥保留在后端。 +这是一个服务器端库,它使用私钥进行签名。切勿在浏览器中运行它。将 waiver 密钥保存在您的后端。 ::: -## 1. 使用 Gas 代付模块创建客户端 +## 1. 使用 gas waiver 模块创建客户端 -将 `gasWaiver: { account }` 传递给 `createStableEnterprise`,其中 `account` 是您列入白名单的代付密钥。只有在配置后,模块才会在客户端上存在。 +将 `gasWaiver: { account }` 传递给 `createStableEnterprise`,其中 `account` 是您列入白名单的 waiver 密钥。只有在配置后,模块才会在客户端上出现。 ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -43,9 +43,13 @@ StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver `rpcEndpoints` 选项是可选的。如果未设置,客户端将使用链的内置 RPC。 +:::tip +要将 waiver 密钥保存在托管后端中,请传递 `signer` 而不是 `account`。`@stablechain/enterprise/aws-kms` 中的 `awsKmsSigner` 使用 AWS KMS 作为后端。请参阅[签名密钥和托管](/cn/reference/enterprise-sdk#signing-keys-and-custody)。 +::: + ## 2. 中继单个交易 -使用用户账户和可变字段调用 `send`。`gasPrice: 0`、遗留类型、`chainId` 和待处理 nonce 会为您处理,因此您只需传递 `to`,以及可选的 `data`、`value` 和 `gas`。 +使用用户账户和可变字段调用 `send`。`gasPrice: 0`、遗留类型、`chainId` 和待处理 nonce 都已为您处理,因此您只需传递 `to`,以及可选的 `data`、`value` 和 `gas`。 ```ts const user = privateKeyToAccount(process.env.USER_PRIVATE_KEY as `0x${string}`); @@ -58,11 +62,11 @@ console.log("H_inner:", txHash); H_inner: 0x8f3a...2d41 ``` -用户不需要 USDT0:代付账户会赞助 gas 费用。`gas` 默认为 `150_000n` (`DEFAULT_INNER_GAS`),足以覆盖代币转账或批准。对于更复杂的调用,请传递明确的 `gas`。 +用户不需要 USDT0:waiver 账户会赞助 gas。`gas` 默认为 `150_000n` (`DEFAULT_INNER_GAS`),足以覆盖代币转账或批准。对于更繁重的调用,请传递显式的 `gas`。 -## 3. 中继批次 +## 3. 批量中继 -调用 `sendBatch` 可以中继来自同一账户的多个交易。Nonce 会根据账户的待处理 nonce 自动排序,并且您会根据输入顺序获得每个输入的结果。 +调用 `sendBatch` 可以中继来自一个账户的多个交易。Nonce 会自动从账户的待处理 nonce 序列化,并且您会根据输入顺序获得每个输入一个结果。 ```ts const results = await gw.sendBatch(user, [ @@ -80,11 +84,11 @@ for (const r of results) { [1] ✔ 0x2b7c...9e04 ``` -批处理会报告每个项目的失败情况,而不是抛出异常,因此一个错误的交易不会影响其余交易。 +批量处理会在 `result.error` 中报告每个项目的失败,而不是抛出异常,因此一个坏交易不会导致其他交易失败。 -## 4. 强制执行每个合作伙伴的策略限制 +## 4. 执行每合作伙伴策略限制 -通过向配置添加策略限制,限制代付密钥可以赞助的内容。违反限制的 InnerTx 会在广播前被拒绝。 +通过向配置添加策略限制来限制 waiver 密钥可以赞助的内容。违反限制的内部交易将在广播前被拒绝。 ```ts const enterprise = createStableEnterprise({ @@ -100,17 +104,17 @@ const enterprise = createStableEnterprise({ }); ``` -目标合约不在 `allowedTargets` 中的交易将因 `TARGET_NOT_ALLOWED` 而失败;超过 `maxGasLimit` 的交易将因 `GAS_LIMIT_EXCEEDED` 而失败。使用 `"*"` 作为 `address` 允许任何合约,并省略 `selectors` 允许任何方法。 +目标合约不在 `allowedTargets` 中的交易将失败并显示 `TARGET_NOT_ALLOWED`;超过 `maxGasLimit` 的交易将失败并显示 `GAS_LIMIT_EXCEEDED`。使用 `"*"` 作为 `address` 允许任何合约,并省略 `selectors` 允许任何方法。 ## 5. 中继预签名交易 -对于非托管流程,用户在其自己的环境中签名 InnerTx,只将签名十六进制传递给您,这样您就永远看不到他们的密钥。使用 `buildWaiverInnerTx` 构建它,然后使用 `relay` 中继。 +对于非托管流程,用户在其自己的环境中签署内部交易并仅向您提供签名十六进制,因此您永远不会看到他们的密钥。使用 `buildWaiverInnerTx` 构建它,然后使用 `relay` 中继。 ```ts -import { buildWaiverInnerTx } from "@stablechain/enterprise"; +import { buildWaiverInnerTx, toSigner } from "@stablechain/enterprise"; -// 在用户端 -const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to: token, data, gas: 150_000n, nonce }); +// 在用户侧 — buildWaiverInnerTx 通过 Signer 签名;toSigner 适配 viem 账户 +const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to: token, data, gas: 150_000n, nonce }); // 在您的后端 const { txHash } = await gw.relay(signed); @@ -121,11 +125,11 @@ console.log("H_inner:", txHash); H_inner: 0x8f3a...2d41 ``` -对于多个预签名交易,请使用 `relayBatch`,它像 `sendBatch` 一样为每个输入返回一个结果。 +对于多个预签名交易,请使用 `relayBatch`,它会像 `sendBatch` 一样为每个输入返回一个结果。 ## 处理拒绝 -`send` 和 `relay` 在拒绝时会抛出 `StableEnterpriseRelayError`,其中包含一个可供您分支的 `code`。 +`send` 和 `relay` 在拒绝时会抛出 `StableEnterpriseRelayError`,并带有一个您可以分支的 `code`。 ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -134,7 +138,7 @@ try { await gw.send(user, { to: token, data }); } catch (err) { if (err instanceof StableEnterpriseRelayError && err.code === "TARGET_NOT_ALLOWED") { - // InnerTx 目标不在配置的允许列表中 + // 内部交易目标不在配置的允许列表中 } throw err; } @@ -144,10 +148,10 @@ try { StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not allowed ``` -请参阅完整的 [`ErrorCode`](/cn/reference/enterprise-sdk#errorcode) 表格,了解所有拒绝原因。 +有关所有拒绝原因,请参阅完整的 [`ErrorCode`](/cn/reference/enterprise-sdk#errorcode) 表格。 -## 下一步 +## 后续步骤 -- [**发送保证交易**](/cn/how-to/send-guaranteed-transactions):在预留的企业通道区块空间中进行交易,并将其与 gas 代付结合使用。 +- [**发送保证交易**](/cn/how-to/send-guaranteed-transactions):将交易提交到保留的企业通道区块空间,并将其与 gas waiver 结合使用。 - [**Enterprise SDK 参考**](/cn/reference/enterprise-sdk#relay-with-gas-waiver):所有方法、配置选项和错误类的完整说明。 -- [**Gas 代付**](/cn/explanation/gas-waiver):零 gas 交易在协议层面的工作原理。 +- [**Gas waiver**](/cn/explanation/gas-waiver):零 gas 交易如何在协议层面工作。 diff --git a/docs/pages/cn/how-to/send-guaranteed-transactions.mdx b/docs/pages/cn/how-to/send-guaranteed-transactions.mdx index 3a1ea08..8fd0a1f 100644 --- a/docs/pages/cn/how-to/send-guaranteed-transactions.mdx +++ b/docs/pages/cn/how-to/send-guaranteed-transactions.mdx @@ -1,30 +1,30 @@ --- source_path: how-to/send-guaranteed-transactions.mdx -source_sha: d45aa08b5a1be19855b02d145479697cc0b4bee5 -title: "发送有保证的交易" -description: "使用 Enterprise SDK 在预留的 Enterprise-lane 区块空间中进行交易,并将有保证的区块空间与 Gas 豁免相结合,以实现免 Gas 费用中继。" +source_sha: c59ac1a053751e961d75071fa7799dbd9dc4b847 +title: "发送有保障的交易" +description: "使用 Enterprise SDK 在预留的企业通道区块空间中进行交易,并将有保障的区块空间与 Gas 豁免结合,以实现免 Gas 中继交易。" diataxis: "how-to" --- -# 发送有保证的交易 +# 发送有保障的交易 -使用 `@stablechain/enterprise` 通过预留的 Enterprise-lane 区块空间路由交易。`guaranteedBlock` 模块通过 Enterprise RPC 网关中继 GuaranteedTx(一种类型为 `0x3F` 的 CustomTx),使其落在为企业工作负载预留的容量中。与 Gas 豁免不同,签名者支付自己的 Gas 费用,因此必须有足够的资金。 +使用 `@stablechain/enterprise` 通过预留的企业通道区块空间路由交易。`guaranteedBlock` 模块通过 Enterprise RPC 网关中继 GuaranteedTx(一种类型为 `0x3F` 的 CustomTx),使其进入为企业工作负载预留的容量中。与 Gas 豁免不同,签名者支付自己的 Gas,因此必须为其提供资金。 -您可以将其与 Gas 豁免相结合,以获得[有保证的中继交易](/cn/how-to/guaranteed-relayed-transactions):即免 Gas 费用的交易仍会落在 Enterprise-lane 中。 +您可以将其与 Gas 豁免结合,以获得[有保障的中继交易](/cn/how-to/guaranteed-relayed-transactions):即获得 Gas 豁免但仍进入企业通道的交易。 ## 先决条件 -- Node.js 20 或更高版本,并安装了 `@stablechain/enterprise` 和 `viem`。请参阅 [Enterprise SDK 参考](/cn/reference/enterprise-sdk#install)。 -- 企业 RPC 网关 API 密钥。Enterprise SDK 目前仅限于测试网,访问受限:请[联系 Stable](https://discord.gg/stablexyz) 以获取网关端点。 -- 一个有资金的签名者,因为 GuaranteedTx 支付自己的 Gas。 +- Node.js 20 或更高版本,以及已安装的 `@stablechain/enterprise` 和 `viem`。请参阅 [Enterprise SDK 参考](/cn/reference/enterprise-sdk#install)。 +- Enterprise RPC 网关 API 密钥。Enterprise SDK 目前仅限于测试网,并且访问受限:请[联系 Stable](https://discord.gg/stablexyz) 以获取网关端点。 +- 一个有资金的签名者,因为 GuaranteedTx 会支付自己的 Gas。 :::warning -这是一个服务器端库。将企业 RPC 网关 URL 保留在后端:它嵌入了您的 API 密钥。 +这是一个服务器端库。将 Enterprise RPC 网关 URL 保留在您的后端:它嵌入了您的 API 密钥。 ::: -## 1. 创建一个带有保证区块空间模块的客户端 +## 1. 使用有保障的区块空间模块创建客户端 -将 `guaranteedBlock` 和 `enterpriseRpcEndpoints` 传递给 `createStableEnterprise`。网关是唯一接受 `0x3F` GuaranteedTx 的端点,并且它持有您的 API 密钥。无效的 `laneId` 会提前被拒绝。 +将 `guaranteedBlock` 和 `enterpriseRpcEndpoints` 传递给 `createStableEnterprise`。网关是唯一接受 `0x3F` GuaranteedTx 的端点,并且它包含您的 API 密钥。无效的 `laneId` 会被立即拒绝。 ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -48,7 +48,7 @@ StableEnterpriseClient { gasWaiver: undefined, guaranteedBlock, guaranteedWaiver ## 2. 发送单笔交易 -使用签名者和可变字段调用 `send`。由于签名者支付 Gas 费用,因此 1559 费用字段是必需的。`chainId`、企业 `nonceKey` 和 2D nonce(从网关发现)都会为您处理。 +使用签名者和可变字段调用 `send`。由于签名者支付 Gas,因此 1559 费用字段是必需的。`chainId`、Enterprise `nonceKey` 和 2D nonce(从网关发现)都会为您处理。 ```ts import { createPublicClient, http } from "viem"; @@ -69,11 +69,11 @@ console.log("Guaranteed tx:", txHash); Guaranteed tx: 0xabcd...7890 ``` -签名者支付 Gas 费用,因此在进行中继之前请确认其账户有余额。来自零余额账户的 GuaranteedTx 会失败。 +签名者支付 Gas,因此在进行中继之前请确认其持有余额。来自零余额账户的 GuaranteedTx 会失败。 -## 3. 发送一批次 +## 3. 批量发送 -调用 `sendBatch` 发送多笔交易。Nonce 会从发现的基础自动排序,您会按输入顺序获得每个输入的结果。一次失败会导致其后续交易无法进行。 +调用 `sendBatch` 发送多笔交易。Nonce 会从发现的基数自动排序,并且您会按输入顺序获得每个输入的一个结果。失败会中止其后续操作。 ```ts const results = await gb.sendBatch(signer, [ @@ -93,12 +93,12 @@ for (const r of results) { ## 4. 发送预签名交易 -对于非托管流程,可在其他地方使用 `buildGuaranteedTx` 构建并签名 GuaranteedTx,然后将签名后的十六进制字符串交给操作员。企业 nonce 密钥来自 `nonceKeyForLane`。 +对于非托管流程,使用 `buildGuaranteedTx` 在其他地方构建并签署 GuaranteedTx,然后只将签名后的十六进制字符串交给操作员。Enterprise nonce 密钥来自 `nonceKeyForLane`。 ```ts -import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; +import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; -const signed = await buildGuaranteedTx(signer, stableTestnet.id, { +const signed = await buildGuaranteedTx(toSigner(signer), stableTestnet.id, { to: recipient, gas: 21_000n, gasFeeCap, @@ -117,13 +117,13 @@ Guaranteed tx: 0xabcd...7890 对于多笔预签名交易,请使用 `relayBatch`。 -## 与 Gas 豁免结合使用 +## 与 Gas 豁免结合 -要免除用户的 Gas 费用,并仍进入企业通道,请将两个通道与 `guaranteedWaiver` 模块组合。用户无需余额和费用字段,交易通过相同的网关路由。请参阅[保证中继交易](/cn/how-to/guaranteed-relayed-transactions)。 +为了豁免用户的 Gas 并仍然进入企业通道,请将这两个通道与 `guaranteedWaiver` 模块结合使用。用户无需余额和费用字段,并且交易通过同一网关路由。请参阅[有保障的中继交易](/cn/how-to/guaranteed-relayed-transactions)。 ## 处理拒绝 -`send` 和 `relay` 在拒绝时抛出 `StableEnterpriseRelayError`。网关特有的代码包括 `GATEWAY_UNAUTHORIZED`(API 密钥缺失或无效)和 `QUOTA_EXCEEDED`(网关 Gas 配额已用尽)。 +`send` 和 `relay` 在拒绝时会抛出 `StableEnterpriseRelayError`。网关特定的代码包括 `GATEWAY_UNAUTHORIZED`(API 密钥缺失或无效)和 `QUOTA_EXCEEDED`(网关 Gas 配额已用尽)。 ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -142,8 +142,8 @@ try { StableEnterpriseRelayError: relay failed [GATEWAY_UNAUTHORIZED]: invalid api key ``` -## 接下来要学习什么 +## 下一步 -- [**保证中继交易**](/cn/how-to/guaranteed-relayed-transactions):一次调用即可免除用户 Gas 费用并进入企业通道。 -- [**使用 Gas 豁免中继**](/cn/how-to/relay-with-gas-waiver):赞助用户的 Gas 费用,使其无需持有 USDT0 即可进行交易。 -- [**企业 SDK 参考**](/cn/reference/enterprise-sdk#guaranteed-blockspace):全面的方法、配置选项和错误类。 +- [**有保障的中继交易**](/cn/how-to/guaranteed-relayed-transactions):一次调用即可豁免用户的 Gas 并进入企业通道。 +- [**使用 Gas 豁免进行中继**](/cn/how-to/relay-with-gas-waiver):赞助用户的 Gas,让他们无需持有 USDT0 即可进行交易。 +- [**Enterprise SDK 参考**](/cn/reference/enterprise-sdk#guaranteed-blockspace):方法、配置选项和错误类的完整列表。 diff --git a/docs/pages/cn/reference/enterprise-sdk.mdx b/docs/pages/cn/reference/enterprise-sdk.mdx index 313e56d..4434ed9 100644 --- a/docs/pages/cn/reference/enterprise-sdk.mdx +++ b/docs/pages/cn/reference/enterprise-sdk.mdx @@ -1,21 +1,21 @@ --- source_path: reference/enterprise-sdk.mdx -source_sha: 2f9f840d9ea287e27f4642da4f0a219db13edab6 -title: "企业版 SDK 参考" -description: "完整的 @stablechain/enterprise 参考:createStableEnterprise、免燃料费和保证区块空间模块、构建助手以及错误类。" +source_sha: 1415ca3965bbd2c7d362a8e86a728c3a9e6269a7 +title: "企业级 SDK 参考" +description: "@stablechain/enterprise 的完整参考:createStableEnterprise,燃气费豁免和保证区块空间模块,构建帮助器和错误类。" diataxis: "reference" --- -# 企业版 SDK 参考 +# 企业级 SDK 参考 -`@stablechain/enterprise` 的完整功能。它涵盖了客户端从 [`createStableEnterprise`](#createstableenterpriseconfig) 到其三个功能([免燃料费中继](#relay-with-gas-waiver)、[保证区块空间](#guaranteed-blockspace)和[保证中继交易](#guaranteed-relay-transactions))、底层构建助手以及共享结果和错误类型。有关这些轨道的详情,请参阅 [Stable 企业版 SDK](/cn/explanation/enterprise-sdk)、[免燃料费](/cn/explanation/gas-waiver)和 [保证区块空间](/cn/explanation/guaranteed-blockspace)。 +`@stablechain/enterprise` 的完整细节。这包括客户端 [`createStableEnterprise`](#createstableenterpriseconfig) 及其三个功能([燃气费豁免中继](#relay-with-gas-waiver)、[保证区块空间](#guaranteed-blockspace)和[保证中继交易](#guaranteed-relay-transactions)),低级构建帮助程序以及共享结果和错误类型。有关这些通道的详细信息,请参阅 [Stable 企业级 SDK](/cn/explanation/enterprise-sdk)、[燃气费豁免](/cn/explanation/gas-waiver)和 [保证区块空间](/cn/explanation/guaranteed-blockspace)。 :::note -企业版 SDK 目前仅在 Stable 测试网上提供,且需要申请访问权限。要进行集成,请[联系 Stable](https://discord.gg/stablexyz) 以获取治理注册的豁免密钥和企业版 RPC 网关 API 密钥。 +企业级 SDK 目前仅在 Stable 测试网上可用,并且需要申请才能访问。要进行集成,请[联系 Stable](https://discord.gg/stablexyz) 以获取治理注册的豁免密钥和企业级 RPC 网关 API 密钥。 ::: :::warning -这是一个使用私钥进行签名的服务器端库。切勿在浏览器中运行它。将豁免密钥和企业版 RPC 网关 URL 保留在您的后端。 +这是一个使用私钥进行签名的服务器端库。切勿在浏览器中运行。将豁免密钥和企业级 RPC 网关 URL 保存在您的后端。 ::: ## 安装 @@ -28,11 +28,11 @@ npm install @stablechain/enterprise viem added 2 packages, audited 3 packages in 2s ``` -`viem >= 2.0.0` 是一个对等依赖项。该包重新导出 `stable` 和 `stableTestnet` 自 `viem/chains`,因此您无需单独导入它们。 +`viem >= 2.0.0` 是一个对等依赖项。该软件包重新导出来自 `viem/chains` 的 `stable` 和 `stableTestnet`,因此您无需单独导入它们。 ## `createStableEnterprise(config)` -构造一个 `StableEnterpriseClient`。每个模块只有在您配置它时才存在,因此在使用前使用 `!` 或空检查进行防护。 +构造一个 `StableEnterpriseClient`。每个模块仅在您配置它时才存在,因此在使用前请使用 `!` 或空检查进行防护。 ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -52,14 +52,39 @@ StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | -| `chain` | `StableChain` | | 目标链。传递 `stable` 或 `stableTestnet`(由包重新导出)。必填。 | -| `rpcEndpoints` | `string[]?` | 链的内置 RPC | 一个或多个 Stable RPC 端点,在失败时按顺序尝试。仅当指向私有端点时才覆盖。 | -| `enterpriseRpcEndpoints` | `string[]?` | | 一个或多个企业版 RPC 网关端点,在失败时按顺序尝试。`guaranteedBlock` 和 `guaranteedWaiver` 所必需。 | +| `chain` | `StableChain` | | 目标链。传递 `stable` 或 `stableTestnet`(由包重新导出)。必填项。 | +| `rpcEndpoints` | `string[]?` | 链的内置 RPC | 一个或多个 Stable RPC 端点,在失败时按顺序尝试。仅在指向私有端点时覆盖。 | +| `enterpriseRpcEndpoints` | `string[]?` | | 一个或多个企业级 RPC 网关端点,在失败时按顺序尝试。`guaranteedBlock` 和 `guaranteedWaiver` 必填。 | | `batchSizeLimit` | `number?` | `100` | 每个批处理 RPC 调用的最大交易数量。 | -| `gasWaiver` | `GasWaiverConfig?` | | 启用[免燃料费中继](#relay-with-gas-waiver)。 | +| `gasWaiver` | `GasWaiverConfig?` | | 启用[燃气费豁免中继](#relay-with-gas-waiver)。 | | `guaranteedBlock` | `GuaranteedBlockConfig?` | | 启用[保证区块空间](#guaranteed-blockspace)。 | | `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | 启用[保证中继交易](#guaranteed-relay-transactions)。 | +### 签名密钥和托管 + +豁免密钥持有模块(`gasWaiver` 和 `guaranteedWaiver`)从 [`SignerSource`](#signersource) 按顺序解析它:`signer`(托管级别的后端),然后是 `account`(进程中的 viem 密钥),然后是 `STABLE_ENTERPRISE_PRIVATE_KEY` 环境变量。`guaranteedBlock` 直接接受已资助的 `account`。 + +签名者对 32 字节摘要进行签名,因此密钥从不离开托管后端。AWS KMS 使用 `awsKmsSigner`,viem 账户使用 `toSigner(account)`,进程内密钥使用 `privateKeySigner(key)` / `envSigner()`。 + +```bash +npm install @aws-sdk/client-kms +``` + +```ts +import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; +import { awsKmsSigner } from "@stablechain/enterprise/aws-kms"; + +// KMS 密钥必须是 ECC_SECG_P256K1 (secp256k1);SDK 从中派生地址 +const signer = await awsKmsSigner({ keyId: process.env.KMS_KEY_ID! }); + +const enterprise = createStableEnterprise({ + chain: stableTestnet, + gasWaiver: { signer }, // 托管级别的豁免密钥,代替 `account` +}); +``` + +`awsKmsSigner` 在 `@stablechain/enterprise/aws-kms` 子路径中提供,因此 `@aws-sdk/client-kms` 仍然是可选的对等依赖项,不在核心安装中。 + ### `StableEnterpriseClient` ```ts @@ -70,9 +95,9 @@ interface StableEnterpriseClient { } ``` -## 免燃料费中继 +## 燃气费豁免中继 -`gasWaiver` 模块中继免燃料费交易。一个白名单豁免账户将用户的零燃料费交易(InnerTx)包装成一个 WaiverTx 并广播。用户不需要 USDT0。每个方法都返回 `H_inner`,即 InnerTx 哈希,而不是包装器哈希。 +`gasWaiver` 模块中继免燃气费交易。白名单豁免账户将用户的零燃气费交易 (InnerTx) 封装到 WaiverTx 中并广播。用户不需要 USDT0。每个方法都返回 `H_inner`,即 InnerTx 的哈希,而不是包装器哈希。 在配置中通过 `gasWaiver` 启用它: @@ -92,18 +117,19 @@ const gw = enterprise.gasWaiver!; ### `GasWaiverConfig` -扩展 [`ValidationLimits`](#validationlimits)。 +扩展了 [`ValidationLimits`](#validationlimits) 和 [`SignerSource`](#signersource)。 | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `account` | `LocalAccount` | 签署每个 WaiverTx 的白名单、治理注册账户。 | +| `signer` | `Signer?` | 白名单、治理注册的豁免密钥作为托管签名者 (AWS KMS, HSM)。请参阅[签名密钥和托管](#signing-keys-and-custody)。优先于 `account`。 | +| `account` | `LocalAccount?` | 进程中的 viem 账户作为豁免密钥。当两者都未设置时,回退到 `STABLE_ENTERPRISE_PRIVATE_KEY`。 | | `maxGasLimit` | `bigint?` | 继承自 `ValidationLimits`。 | | `maxDataLength` | `number?` | 继承自 `ValidationLimits`。 | | `allowedTargets` | `AllowedTarget[]?` | 继承自 `ValidationLimits`。 | ### `send(account, tx)` -在一个调用中构建、签名和中继一个来自 `account` 的 InnerTx。`gasPrice: 0`、旧类型、`chainId` 和待处理 nonce 会为您处理。如果被拒绝,则抛出 `StableEnterpriseRelayError`。 +在一个调用中构建、签名和中继一个来自 `account` 的 InnerTx。`gasPrice: 0`、旧类型、`chainId` 和待处理 Nonce 将为您处理。拒绝时抛出 `StableEnterpriseRelayError`。 ```ts const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); @@ -117,7 +143,7 @@ const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); ### `sendBatch(account, txs)` -构建、签名和中继来自一个 `account` 的多个 InnerTx。Nonce 从账户的待处理 nonce 自动排序。按顺序为每个输入返回一个结果。 +从一个 `account` 构建、签名和中继多个 InnerTx。Nonce 从账户的待处理 Nonce 自动排序。按顺序为每个输入返回一个结果。 ```ts const results = await gw.sendBatch(user, [ @@ -134,12 +160,12 @@ const results = await gw.sendBatch(user, [ ### `relay(signedInnerTxHex)` -中继一个预签名的零燃料费 InnerTx。这用于非托管流程,用户在其自己的环境中签名并只向您提供签名的十六进制,因此豁免操作员永远不会看到用户的密钥。使用 [`buildWaiverInnerTx`](#buildwaiverinnertxaccount-chainid-req) 构建一个。拒绝时抛出。 +中继预签名的零燃气费 InnerTx。在非托管流程中使用此功能,用户在自己的环境中签名并仅将签名后的十六进制交给您,因此豁免操作员永远不会看到用户的密钥。使用 [`buildWaiverInnerTx`](#buildwaiverinnertxsigner-chainid-req) 构建一个。拒绝时抛出。 ```ts -import { buildWaiverInnerTx } from "@stablechain/enterprise"; +import { buildWaiverInnerTx, toSigner } from "@stablechain/enterprise"; -const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to, data, gas: 150_000n, nonce }); +const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to, data, gas: 150_000n, nonce }); const { txHash } = await gw.relay(signed); ``` @@ -161,7 +187,7 @@ const results = await gw.relayBatch([signed0, signed1]); ## 保证区块空间 -`guaranteedBlock` 模块通过企业版 RPC 网关中继 GuaranteedTx(类型 `0x3F` CustomTx),以便它们落在预留的 Enterprise-lane 区块空间中。与免燃料费不同,签名者支付自己的燃料费并且必须有资金。每笔交易都带有与企业版通道关联的二维 nonce,并且仅通过网关广播。 +`guaranteedBlock` 模块通过企业级 RPC 网关中继 GuaranteedTx(类型 `0x3F` CustomTx),以便它们落在预留的企业级通道区块空间中。与燃气费豁免不同,签名者需要支付自己的燃气费,并且必须有资金。每笔交易都带有与企业级通道关联的 2D Nonce,并且广播仅通过网关进行。 通过 `guaranteedBlock` 和 `enterpriseRpcEndpoints` 启用它: @@ -182,12 +208,12 @@ const gb = enterprise.guaranteedBlock!; | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `account` | `LocalAccount` | 签署每个 GuaranteedTx 并支付其燃料费的有资金账户。 | -| `laneId` | `bigint` | 企业版通道 ID。必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。无效的 ID 将被立即拒绝。 | +| `account` | `LocalAccount` | 签署每笔 GuaranteedTx 并支付其燃气费的已资助账户。 | +| `laneId` | `bigint` | 企业级通道 ID。必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。无效 ID 将被提前拒绝。 | ### `send(account, tx)` -构建、签名和中继一个 GuaranteedTx。需要 1559 费用字段,因为签名者支付燃料费。`chainId`、企业版 `nonceKey` 和二维 nonce(从网关发现)会为您处理。 +构建、签名和中继一个 GuaranteedTx。签名者需要支付燃气费,因此 1559 费用字段是必需的。`chainId`、企业级 `nonceKey` 和 2D Nonce(从网关发现)将为您处理。 ```ts const gasPrice = await publicClient.getGasPrice(); @@ -204,11 +230,11 @@ const { txHash } = await gb.send(signer, { { txHash: "0xabcd...7890" } ``` -`tx` 参数是 [`GuaranteedTxRequest`](#guaranteedtxrequest) 加上一个可选的 `nonce`。返回 [`RelayResult`](#relayresult)。 +`tx` 参数是一个 [`GuaranteedTxRequest`](#guaranteedtxrequest) 加上一个可选的 `nonce`。返回 [`RelayResult`](#relayresult)。 ### `sendBatch(account, txs)` -构建、签名和中继多个 GuaranteedTx。Nonce 从发现的基础自动排序。失败会使其后续交易受阻。 +构建、签名和中继多笔 GuaranteedTx。Nonce 从发现的基数自动排序。失败会导致其后续交易无法进行。 ```ts const results = await gb.sendBatch(signer, [ @@ -225,17 +251,17 @@ const results = await gb.sendBatch(signer, [ ### `relay(signedTx)` / `relayBatch(signedTxs)` -中继一个预签名的 GuaranteedTx,或一批。使用 [`nonceKeyForLane`](#noncekeyforlanelaneid) 作为企业版 nonce 密钥,使用 [`buildGuaranteedTx`](#buildguaranteedtxaccount-chainid-req) 在其他地方构建和签名交易,然后只将签名的十六进制交给操作员。 +中继一个预签名的 GuaranteedTx,或一批预签名的 GuaranteedTx。使用 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req) 构建和签署交易,[`nonceKeyForLane`](#noncekeyforlanelaneid) 用于企业 Nonce 密钥,然后只向操作员提供签名十六进制。 ```ts -import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; +import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; -const signed = await buildGuaranteedTx(signer, stableTestnet.id, { +const signed = await buildGuaranteedTx(toSigner(signer), stableTestnet.id, { to, gas: 21_000n, gasFeeCap, gasTipCap, - nonce, // 账户当前的二维通道 nonce + nonce, // 账户当前的 2D 通道 Nonce nonceKey: nonceKeyForLane(0n), }); const { txHash } = await gb.relay(signed); @@ -247,7 +273,7 @@ const { txHash } = await gb.relay(signed); ## 保证中继交易 -`guaranteedWaiver` 模块结合了上述两个轨道:通过保证区块空间路由的免燃料费交易。内部和外部交易都是共享一个企业版 `nonceKey` 的 `0x3F` CustomTx,因此它像 `guaranteedBlock` 一样通过网关广播。豁免方支付燃料费,因此用户不需要余额和费用字段,就像 `gasWaiver` 一样。每个方法都返回 `H_inner`。 +`guaranteedWaiver` 模块结合了上述两条通道:通过保证区块空间路由的燃气费豁免交易。内部和外部交易都是 `0x3F` CustomTx,共享一个企业级 `nonceKey`,因此它通过网关广播,就像 `guaranteedBlock` 一样。豁免方支付燃气费,因此用户不需要余额和费用字段,就像 `gasWaiver` 一样。每个方法都返回 `H_inner`。 通过 `guaranteedWaiver` 和 `enterpriseRpcEndpoints` 启用它: @@ -256,7 +282,7 @@ const enterprise = createStableEnterprise({ chain: stableTestnet, enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable 提供的网关 URL guaranteedWaiver: { - waiverAccount: privateKeyToAccount("0xYOUR_WAIVER_KEY"), + account: privateKeyToAccount("0xYOUR_WAIVER_KEY"), laneId: 0n, }, }); @@ -266,19 +292,20 @@ const gw = enterprise.guaranteedWaiver!; ### `GuaranteedWaiverConfig` -扩展 [`ValidationLimits`](#validationlimits),因此它接受与 `GasWaiverConfig` 相同的 `maxGasLimit`、`maxDataLength` 和 `allowedTargets` 策略控制。 +扩展了 [`ValidationLimits`](#validationlimits) 和 [`SignerSource`](#signersource)。它从外部包装器豁免密钥中获取密钥的方式与 `GasWaiverConfig` (先是 `signer`,然后是 `account`,然后是环境变量) 完全相同,并且接受相同的 `maxGasLimit`、`maxDataLength` 和 `allowedTargets` 策略控制。 | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `waiverAccount` | `LocalAccount` | 签署外部包装器的白名单、治理注册账户。 | -| `laneId` | `bigint` | 企业版通道 ID。必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。 | +| `signer` | `Signer?` | 白名单豁免密钥(签署外部包装器)作为托管签名者。优先于 `account`。请参阅 [签名密钥和托管](#signing-keys-and-custody)。 | +| `account` | `LocalAccount?` | 进程中的 viem 账户作为豁免密钥。当两者都未设置时,回退到 `STABLE_ENTERPRISE_PRIVATE_KEY`。 | +| `laneId` | `bigint` | 企业级通道 ID。必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。 | ### `send(user, tx)` / `sendBatch(user, txs)` -构建并签名来自 `user` 的内部 `0x3F` CustomTx,用豁免密钥包装它,然后中继。不需要费用字段,因为燃料费已免除。内部二维 nonce 从网关发现,并且批处理从此基础自动排序。 +构建并从 `user` 签署内部 `0x3F` CustomTx,用豁免密钥封装,然后中继。由于燃气费已豁免,因此不需要费用字段。内部 2D Nonce 从网关发现,并且批次从此基数自动排序。 ```ts -// 单个 +// 单笔 const { txHash } = await gw.send(user, { to: recipient }); // 批量 @@ -289,24 +316,24 @@ const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); { txHash: "0x8f3a...2d41" } ``` -`tx` 参数是 [`GuaranteedWaiverTxRequest`](#guaranteedwaivertxrequest) 加上一个可选的 `nonce`。`send` 返回 [`RelayResult`](#relayresult);`sendBatch` 返回 [`BatchResultItem[]`](#batchresultitem)。 +`tx` 参数是一个 [`GuaranteedWaiverTxRequest`](#guaranteedwaivertxrequest) 加上一个可选的 `nonce`。`send` 返回 [`RelayResult`](#relayresult);`sendBatch` 返回 [`BatchResultItem[]`](#batchresultitem)。 ### `relay(signedInnerTx)` / `relayBatch(signedInnerTxs)` -对于非托管流程,用户使用 [`buildGuaranteedTx`](#buildguaranteedtxaccount-chainid-req) 签名内部 `0x3F` CustomTx(费用 `0n`,使用 `nonceKeyForLane(laneId)`),并只将签名的十六进制交给操作员。操作员用豁免密钥包装它并中继。 +对于非托管流,用户使用 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req) 签署内部 `0x3F` CustomTx(费用 `0n`,使用 `nonceKeyForLane(laneId)`),并仅向操作员提供签名十六进制。操作员使用豁免密钥封装并中继。 ```ts -import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; +import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; -const signedInner = await buildGuaranteedTx(user, stableTestnet.id, { +const signedInner = await buildGuaranteedTx(toSigner(user), stableTestnet.id, { to, gas: 100_000n, - gasFeeCap: 0n, // 已免除 + gasFeeCap: 0n, // 豁免 gasTipCap: 0n, nonce, nonceKey: nonceKeyForLane(0n), }); -const { txHash } = await gw.relay(signedInner); // 豁免包装 + 广播 → H_inner +const { txHash } = await gw.relay(signedInner); // 豁免方封装 + 广播 → H_inner ``` ```text @@ -315,27 +342,27 @@ const { txHash } = await gw.relay(signedInner); // 豁免包装 + 广播 → H_i ## 构建助手 -用于非托管 `relay` 路径的底层签名器。每个都以 `Hex` 形式返回已签名的交易,不进行 nonce 获取或费用估算。 +用于非托管 `relay` 路径的低级签名者。每个都返回一个已签名的交易作为 `Hex`,不进行 Nonce 获取或费用估算。第一个参数是 [`Signer`](#signing-keys-and-custody):用 `toSigner(account)` 包装一个 viem 账户,或传递一个托管签名者,例如 `awsKmsSigner`。 -### `buildWaiverInnerTx(account, chainId, req)` +### `buildWaiverInnerTx(signer, chainId, req)` -使用预设的豁免不变量(`gasPrice: 0`、旧类型和给定的 `chainId`)签名 waiver-ready InnerTx。`req` 是一个 [`WaiverInnerTx`](#waiverinnertx) 加上一个必需的 `nonce`。 +签署一个豁免就绪的 InnerTx,其中包含豁免不变性:`gasPrice: 0`、旧类型和给定的 `chainId`。`req` 是一个 [`WaiverInnerTx`](#waiverinnertx) 加上一个必需的 `nonce`。 ```ts -const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to, data, gas: 150_000n, nonce }); +const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to, data, gas: 150_000n, nonce }); ``` -### `buildGuaranteedTx(account, chainId, req)` +### `buildGuaranteedTx(signer, chainId, req)` -构建并签名一个 GuaranteedTx(`0x3F` CustomTx)。`req` 是一个 [`GuaranteedTxRequest`](#guaranteedtxrequest) 加上一个必需的 `nonce` 和 `nonceKey`。 +构建并签署一个 GuaranteedTx (`0x3F` CustomTx)。`req` 是一个 [`GuaranteedTxRequest`](#guaranteedtxrequest) 加上一个必需的 `nonce` 和 `nonceKey`。 ### `buildGuaranteedWaiverTx(...)` -将预签名的内部交易包装到外部 `0x3F` 豁免自定义交易中。供 `guaranteedWaiver.relay` 内部使用;为高级流程导出。 +将预签名内部交易封装到外部 `0x3F` 豁免 CustomTx 中。由 `guaranteedWaiver.relay` 内部使用;为高级流程导出。 ### `nonceKeyForLane(laneId)` -返回用于 `buildGuaranteedTx` 的通道 ID 的企业版 `nonceKey`。 +返回用于 `buildGuaranteedTx` 的通道 ID 的企业 `nonceKey`。 ```ts import { nonceKeyForLane } from "@stablechain/enterprise"; @@ -345,84 +372,111 @@ const nonceKey = nonceKeyForLane(0n); ## 类型 +### `SignerSource` + +豁免模块 (`gasWaiver`, `guaranteedWaiver`) 接受的签名密钥字段。按顺序解析:`signer`,然后 `account`,然后是 `STABLE_ENTERPRISE_PRIVATE_KEY` 环境变量。请参阅 [签名密钥和托管](#signing-keys-and-custody)。 + +| **字段** | **类型** | **描述** | +| :--- | :--- | :--- | +| `signer` | `Signer?` | 托管级别的签名者(AWS KMS、HSM 或 `privateKeySigner`)。优先于 `account`。 | +| `account` | `LocalAccount?` | 进程中的 viem 账户,通过 `toSigner` 转换为 `Signer`。 | + +### `Signer` + +一个可插拔的签名器,SDK 通过它签署 32 字节摘要,因此密钥不会离开托管后端。使用 `awsKmsSigner`、`toSigner`、`privateKeySigner` 或 `envSigner` 构建一个。 + +```ts +interface Signer { + readonly address: Address; + signDigest(hash: Hex): Promise; +} +``` + +| **助手** | **导入** | **描述** | +| :--- | :--- | :--- | +| `awsKmsSigner({ keyId, client? })` | `@stablechain/enterprise/aws-kms` | 由 AWS KMS `ECC_SECG_P256K1` 密钥支持的签名器。返回 `Promise`。 | +| `toSigner(account)` | `@stablechain/enterprise` | 将 viem `LocalAccount` 转换为 `Signer`。 | +| `privateKeySigner(key)` | `@stablechain/enterprise` | 包装进程中持有的原始私钥的签名器。 | +| `envSigner(varName?)` | `@stablechain/enterprise` | 从 `STABLE_ENTERPRISE_PRIVATE_KEY`(或 `varName`)读取密钥的签名器。 | + ### `WaiverInnerTx` -每次调用不同的 InnerTx 字段。 +每次调用 InnerTx 中变化的字段。 | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | -| `to` | `Address` | | 目标地址:ERC-20 转账的代币合约,原生转账的接收方。 | -| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | 燃料限制。因为 `gasPrice` 为 0,所以慷慨的限制是免费的。 | +| `to` | `Address` | | 目标地址:用于 ERC-20 转账的代币合约,用于原生代币的接收者。 | +| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | 燃气限制。因为 `gasPrice` 为 0,所以慷慨的限制是免费的。 | | `data` | `Hex?` | `"0x"` | 调用数据。 | -| `value` | `bigint?` | `0n` | 要发送的原生值。 | +| `value` | `bigint?` | `0n` | 要发送的原生价值。 | ### `GuaranteedTxRequest` | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | | `to` | `Address?` | | 目标地址。 | -| `gas` | `bigint` | | 燃料限制。必需。 | +| `gas` | `bigint` | | 燃气限制。必需。 | | `gasFeeCap` | `bigint` | | `maxFeePerGas`。必需。 | | `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`。必需。 | | `data` | `Hex?` | `"0x"` | 调用数据。 | -| `value` | `bigint?` | `0n` | 要发送的原生值。 | +| `value` | `bigint?` | `0n` | 要发送的原生价值。 | ### `GuaranteedWaiverTxRequest` -燃料费字段始终为 0,因此此处省略。 +费用字段始终为 0,因此此处省略。 | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | | `to` | `Address` | | 目标地址。 | -| `gas` | `bigint?` | 共享的内部燃料默认值 | 燃料限制。 | +| `gas` | `bigint?` | 共享的内部燃气默认值 | 燃气限制。 | | `data` | `Hex?` | `"0x"` | 调用数据。 | -| `value` | `bigint?` | `0n` | 要发送的原生值。豁免允许值转移。 | +| `value` | `bigint?` | `0n` | 要发送的原生价值。燃气费豁免允许价值转移。 | ### `ValidationLimits` -应用于 `gasWaiver` 和 `guaranteedWaiver` 的每个 InnerTx 的每个合作伙伴策略。 +由 `gasWaiver` 和 `guaranteedWaiver` 应用于每个 InnerTx 的每合作伙伴策略。 | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | -| `maxGasLimit` | `bigint?` | `10_000_000n` | InnerTx 的最大燃料限制。超过此限制将导致 `GAS_LIMIT_EXCEEDED` 失败。 | -| `maxDataLength` | `number?` | `131_072` (128 KB) | 调用数据的最大字节大小。超过此限制将导致 `DATA_TOO_LARGE` 失败。 | -| `allowedTargets` | `AllowedTarget[]?` | | 豁免可能赞助的合约和方法的允许列表。设置后,列表之外的目标将导致 `TARGET_NOT_ALLOWED` 失败。 | +| `maxGasLimit` | `bigint?` | `10_000_000n` | InnerTx 的最大燃气限制。超出此限制将因 `GAS_LIMIT_EXCEEDED` 而失败。 | +| `maxDataLength` | `number?` | `131_072` (128 KB) | 调用数据的最大大小(字节)。超出此限制将因 `DATA_TOO_LARGE` 而失败。 | +| `allowedTargets` | `AllowedTarget[]?` | | 豁免可能赞助的合约和方法的白名单。设置后,不在列表中的目标将因 `TARGET_NOT_ALLOWED` 而失败。 | ### `AllowedTarget` | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `address` | `Address \| "*"` | InnerTx 可能调用的合约,或 `"*"` 以匹配任何合约。 | +| `address` | `Address \| "*"` | InnerTx 可以调用的合约,或者 `"*" `表示匹配任何合约。 | | `selectors` | `Hex[]?` | 允许的 4 字节方法选择器(例如,ERC-20 `transfer` 的 `"0xa9059cbb"`)。省略或留空以允许 `address` 上的任何方法。 | ### `RelayResult` ```ts interface RelayResult { - txHash: Hash; // 豁免的 H_inner,独立保证区块的 GuaranteedTx 哈希 + txHash: Hash; // 燃气费豁免的 H_inner,独立保证区块的 GuaranteedTx 哈希 } ``` ### `BatchResultItem` -批处理中每个输入的一个条目,按输入顺序排列。批处理不会抛出,而是显示每个项目的输出。 +批处理中每个输入的条目,按输入顺序。批处理不是抛出错误,而是显示每个项目的处理结果。 | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `index` | `number` | 与输入数组匹配的从零开始的位置。 | +| `index` | `number` | 零基位置,与输入数组匹配。 | | `success` | `boolean` | 此项目是否已中继。 | | `txHash` | `Hash?` | 成功时存在:内部交易哈希。 | | `error` | `{ code: ErrorCode; message: string }?` | 失败时存在。 | ## 错误 -单交易方法(`send`、`relay`)在拒绝时抛出。批处理方法则在 [`BatchResultItem.error`](#batchresultitem) 中报告每个项目的失败。所有错误类都扩展自 `StableEnterpriseError`。 +单个交易方法 (`send`, `relay`) 在拒绝时会抛出错误。批量方法则在 [`BatchResultItem.error`](#batchresultitem) 中报告每个项目的失败。所有错误类都扩展自 `StableEnterpriseError`。 | **类** | **抛出时机** | **有用字段** | | :--- | :--- | :--- | | `StableEnterpriseError` | 所有 SDK 错误的基类。 | `message` | | `StableEnterpriseRelayError` | 交易在 RPC 或中继层被拒绝。 | `code` | -| `WaiverValidationError` | InnerTx 在广播前未能通过策略检查(燃料、数据大小或目标允许列表)。 | `code` | +| `WaiverValidationError` | InnerTx 在广播前未能通过策略检查(燃气费、数据大小或目标白名单)。 | `code` | ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -431,7 +485,7 @@ try { await gw.send(user, { to: token, data }); } catch (err) { if (err instanceof StableEnterpriseRelayError && err.code === "TARGET_NOT_ALLOWED") { - // InnerTx 目标不在配置的允许列表之外 + // InnerTx 目标不在配置的白名单中 } throw err; } @@ -447,29 +501,29 @@ StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not | **代码** | **含义** | | :--- | :--- | -| `UNKNOWN_ERROR` | 当没有特定代码可用时的回退。 | -| `BROADCAST_FAILED` | 广播在 RPC 层被拒绝,或网关未能中继。 | +| `UNKNOWN_ERROR` | 没有可用特定代码时的回退。 | +| `BROADCAST_FAILED` | 广播在 RPC 层被拒绝,或者网关未能中继。 | | `INVALID_TRANSACTION` | InnerTx 解码或解析失败。 | | `INVALID_SIGNATURE` | 签名验证失败。 | | `UNSUPPORTED_TX_TYPE` | InnerTx 类型不是 legacy、eip2930 或 eip1559。 | | `WRONG_CHAIN_ID` | InnerTx `chainId` 缺失或与目标链不匹配。 | -| `NON_ZERO_GAS_PRICE` | InnerTx 带有非零燃料价格(豁免必须为零)。 | -| `GAS_LIMIT_EXCEEDED` | InnerTx 燃料限制超过 `maxGasLimit`。 | +| `NON_ZERO_GAS_PRICE` | InnerTx 带有非零燃气费(豁免必须为零)。 | +| `GAS_LIMIT_EXCEEDED` | InnerTx 燃气限制超过 `maxGasLimit`。 | | `DATA_TOO_LARGE` | InnerTx 调用数据超过 `maxDataLength`。 | | `TARGET_NOT_ALLOWED` | InnerTx 目标不在 `allowedTargets` 中。 | -| `GATEWAY_UNAUTHORIZED` | 企业版 RPC 网关拒绝了 API 密钥(缺失、无效或已过期)。 | -| `QUOTA_EXCEEDED` | 企业版 RPC 网关燃料配额已用尽。 | +| `GATEWAY_UNAUTHORIZED` | 企业级 RPC 网关拒绝了 API 密钥(缺失、无效或过期)。 | +| `QUOTA_EXCEEDED` | 企业级 RPC 网关燃气配额已用尽。 | ## 常量 | **常量** | **类型** | **描述** | | :--- | :--- | :--- | -| `DEFAULT_INNER_GAS` | `bigint` | 当省略 `gas` 时,默认的 InnerTx 燃料限制 (`150_000n`)。 | -| `ENTERPRISE_FLAG` | `bigint` | 在通道的 `nonceKey` 上设置的企业位。 | +| `DEFAULT_INNER_GAS` | `bigint` | InnerTx 的默认燃气限制 (`150_000n`),当省略 `gas` 时使用。 | +| `ENTERPRISE_FLAG` | `bigint` | 设置在通道 `nonceKey` 上的企业位。 | | `ENTERPRISE_MASK` | `bigint` | 通道 ID 的上限:`laneId` 必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。 | -## 下一步推荐 +## 接下来的建议 -- [**Stable 企业版 SDK**](/cn/explanation/enterprise-sdk):轨道的用途以及何时使用它们。 -- [**免燃料费协议**](/cn/reference/gas-waiver-api):交易格式、标记路由和治理控制。 +- [**Stable 企业级 SDK**](/cn/explanation/enterprise-sdk):这些通道是什么以及何时使用它们。 +- [**燃气费豁免协议**](/cn/reference/gas-waiver-api):交易格式、标记路由和治理控制。 - [**保证区块空间**](/cn/explanation/guaranteed-blockspace):Stable 如何为企业工作负载预留区块容量。 diff --git a/docs/pages/ko/explanation/enterprise-sdk.mdx b/docs/pages/ko/explanation/enterprise-sdk.mdx index 10e09b1..9b4dab6 100644 --- a/docs/pages/ko/explanation/enterprise-sdk.mdx +++ b/docs/pages/ko/explanation/enterprise-sdk.mdx @@ -1,14 +1,14 @@ --- source_path: explanation/enterprise-sdk.mdx -source_sha: d22b8f5b286b6030a0282c7f45a4ef60dd1d928b -title: "Stable 엔터프라이즈 SDK" -description: "유형화된 @stablechain/enterprise SDK를 사용하여 백엔드에서 가스 면제되고 블록 공간이 보장된 트랜잭션을 릴레이합니다." +source_sha: c16b058331d58a968753ec4877bb47cd7377fe14 +title: "Stable Enterprise SDK" +description: "유형화된 @stablechain/enterprise SDK를 사용하여 백엔드에서 가스 면제 및 블록 공간 보장 트랜잭션을 릴레이하세요." diataxis: "explanation" --- -# Stable 엔터프라이즈 SDK +# Stable Enterprise SDK -`@stablechain/enterprise`는 Stable의 엔터프라이즈 트랜잭션 레일을 위한 서버 측 TypeScript 클라이언트입니다. 이것은 두 가지 종류의 특권 트랜잭션을 서명하고 릴레이합니다. 즉, 사용자의 가스를 후원하는 가스 면제 트랜잭션과 예약된 엔터프라이즈 레인에 착지하는 블록 공간 보장 트랜잭션입니다. 하나의 클라이언트에서 두 레일 중 하나 또는 둘 다를 활성화할 수 있습니다. +`@stablechain/enterprise`는 Stable의 엔터프라이즈 트랜잭션 레일을 위한 서버 측 타입스크립트 클라이언트입니다. 이는 두 가지 종류의 특권 트랜잭션, 즉 사용자의 가스를 후원하는 가스 면제 트랜잭션과 예약된 엔터프라이즈 레인에 도달하는 블록 공간 보장 트랜잭션을 서명하고 릴레이합니다. 하나의 클라이언트에서 두 레일 중 하나 또는 둘 다를 활성화할 수 있습니다. ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -26,45 +26,45 @@ const { txHash } = await enterprise.gasWaiver!.send(user, { to: token, data }); txHash: 0x8f3a...2d41 ``` -호출은 사용자의 트랜잭션 해시인 `H_inner`를 반환하며, 이를 전달한 래퍼 트랜잭션은 반환하지 않습니다. +이 호출은 사용자 트랜잭션의 해시(`H_inner`)를 반환하며, 이를 전달한 래퍼 트랜잭션이 아닙니다. ## SDK의 기능 -SDK는 모듈당 세 가지 기능을 노출합니다. 각 기능은 선택 사항이며 독립적으로 구성되며, 자체 서명 계정을 포함하므로 별도의 키를 사용할 수 있습니다. +SDK는 모듈당 세 가지 기능을 제공합니다. 각 기능은 선택 사항이며 독립적으로 구성되며, 자체 서명 계정을 포함하므로 별도의 키를 사용할 수 있습니다. -- **가스 면제 릴레이** (`gasWaiver`): 가스 면제 트랜잭션을 구축, 서명 및 릴레이합니다. 화이트리스트에 있는 면제 계정이 사용자의 제로 가스 트랜잭션을 래핑하므로 사용자는 USTYD0을 보유하지 않고도 트랜잭션을 처리합니다. [가스 면제](/ko/explanation/gas-waiver)를 참조하십시오. -- **블록 공간 보장** (`guaranteedBlock`): 엔터프라이즈 RPC 게이트웨이를 통해 트랜잭션을 릴레이하여 예약된 엔터프라이즈 레인 블록 공간에 착지합니다. 가스 면제와 달리 서명자는 자체 가스를 지불합니다. [블록 공간 보장](/ko/explanation/guaranteed-blockspace)을 참조하십시오. -- **보장된 릴레이 트랜잭션** (`guaranteedWaiver`): 둘 다 결합됩니다. 엔터프라이즈 레인을 통해 라우팅되는 가스 면제 트랜잭션이므로 사용자는 잔액이 필요 없고 트랜잭션은 여전히 엔터프라이즈 레인에 착지합니다. +- **가스 면제와 함께 릴레이** (`gasWaiver`): 가스 면제 트랜잭션을 빌드, 서명 및 릴레이합니다. 화이트리스트에 등록된 면제 계정이 사용자의 제로 가스 트랜잭션을 래핑하므로 사용자는 USDT0을 보유하지 않고 거래할 수 있습니다. [가스 면제](/ko/explanation/gas-waiver)를 참조하세요. +- **블록 공간 보장** (`guaranteedBlock`): 엔터프라이즈 RPC 게이트웨이를 통해 트랜잭션을 릴레이하므로 예약된 엔터프라이즈 레인 블록 공간에 도달합니다. 가스 면제와 달리 서명자는 자체 가스를 지불합니다. [블록 공간 보장](/ko/explanation/guaranteed-blockspace)을 참조하세요. +- **보장된 릴레이 트랜잭션** (`guaranteedWaiver`): 두 기능을 모두 결합합니다. 엔터프라이즈 레인을 통해 라우팅되는 가스 면제 트랜잭션이므로 사용자는 잔액이 필요 없으며 트랜잭션은 엔터프라이즈 레인에 도달합니다. -모든 기능은 서명하는 SDK의 관리 경로를 위한 `send` 및 `sendBatch`, 그리고 사용자가 다른 곳에서 서명하고 서명된 헥스만 전달하는 비관리 경로를 위한 `relay` 및 `relayBatch`의 네 가지 동일한 메서드를 제공합니다. +모든 기능은 동일한 네 가지 메서드를 제공합니다. SDK가 서명하는 관리 경로의 경우 `send` 및 `sendBatch`를, 사용자가 다른 곳에서 서명하고 서명된 헥스만 전달하는 비관리 경로의 경우 `relay` 및 `relayBatch`를 제공합니다. -## 액세스 +## 접근 엔터프라이즈 SDK는 현재 Stable Testnet에서만 사용할 수 있습니다. -두 레일 모두 게이트됩니다. 가스 면제는 거버넌스에 등록된 면제 키를 요구하며, 블록 공간 보장은 엔터프라이즈 RPC 게이트웨이 API 키를 요구합니다. 통합하려면 Stable [Stable에 문의](https://discord.gg/stablexyz)하여 액세스 권한을 얻으십시오. Stable은 필요한 면제 키와 게이트웨이 엔드포인트를 제공합니다. +두 레일 모두 게이트로 보호됩니다. 가스 면제는 거버넌스 등록 면제 키를 요구하고, 보장된 블록 공간은 엔터프라이즈 RPC 게이트웨이 API 키를 요구합니다. 통합하려면, 접근 권한을 얻기 위해 [Stable에 문의](https://discord.gg/stablexyz)하세요. Stable은 필요한 면제 키와 게이트웨이 엔드포인트를 제공합니다. ## 서버 측 전용 :::warning -엔터프라이즈 SDK는 개인 키로 서명하는 무상태, 서버 측 라이브러리입니다. 브라우저에서 실행하지 마십시오. 면제 키와 엔터프라이즈 RPC 게이트웨이 URL을 백엔드에 보관하십시오. +엔터프라이즈 SDK는 개인 키로 서명하는 상태 비저장 서버 측 라이브러리입니다. 브라우저에서 실행하지 마세요. 면제 키와 엔터프라이즈 RPC 게이트웨이 URL을 백엔드에 보관하세요. ::: -면제 키는 화이트리스트에 있는 거버넌스 등록 계정입니다. 이 키를 보유한 사람은 누구나 귀하의 정책에 따라 가스를 후원할 수 있습니다. 엔터프라이즈 RPC 게이트웨이 URL은 API 키를 포함합니다. 둘 다 비밀로 취급하십시오. +면제 키는 화이트리스트에 등록된 거버넌스 등록 계정입니다. 이를 보유한 누구든지 정책에 따라 가스를 후원할 수 있습니다. 기업 RPC 게이트웨이 URL에는 API 키가 포함되어 있습니다. 둘 다 비밀로 취급해야 합니다. 면제 키를 프로세스 외부에 보관하려면 AWS KMS와 같은 보관 서명자로 백업하십시오. [서명 키 및 보관](/ko/reference/enterprise-sdk#signing-keys-and-custody)를 참조하십시오. -## 언제 사용해야 할까요? +## 언제 사용해야 하는가 -백엔드를 운영하고 사용자의 가스를 후원하거나 자체 트래픽에 대한 포함을 보장하려는 경우 엔터프라이즈 SDK를 사용하십시오. 백엔드 또는 브라우저에서 일상적인 전송, 브릿지, 스왑 및 볼트 수익을 위해서는 범용 [Stable SDK](/ko/explanation/sdk-overview)를 대신 사용하십시오. +백엔드를 운영하며 사용자의 가스를 후원하거나 자체 트래픽에 대한 포함을 보장하려는 경우 엔터프라이즈 SDK를 사용하십시오. 백엔드 또는 브라우저에서 일상적인 전송, 브리지, 스왑 및 볼트 수익을 위해서는 일반적인 목적의 [Stable SDK](/ko/explanation/sdk-overview)를 대신 사용하십시오. -## 여기에서 시작하기 +## 여기서 시작 -- [**가스 면제 릴레이**](/ko/how-to/relay-with-gas-waiver): 사용자가 USDT0을 보유하지 않고 거래할 수 있도록 가스를 후원합니다. -- [**보장된 트랜잭션 전송**](/ko/how-to/send-guaranteed-transactions): 예약된 엔터프라이즈 레인 블록 공간에 트랜잭션을 착지합니다. -- [**보장된 릴레이 트랜잭션**](/ko/how-to/guaranteed-relayed-transactions): 두 레일을 결합합니다. 엔터프라이즈 레인의 가스 면제 트랜잭션입니다. -- [**엔터프라이즈 SDK 참조**](/ko/reference/enterprise-sdk): 모든 모듈, 메서드, 구성 옵션 및 오류 클래스입니다. +- [**가스 면제와 함께 릴레이**](/ko/how-to/relay-with-gas-waiver): 사용자가 USDT0를 보유하지 않고 거래할 수 있도록 가스를 후원합니다. +- [**보장된 트랜잭션 전송**](/ko/how-to/send-guaranteed-transactions): 예약된 엔터프라이즈 레인 블록 공간에 트랜잭션을 실현합니다. +- [**보장된 릴레이 트랜잭션**](/ko/how-to/guaranteed-relayed-transactions): 두 레일을 모두 결합합니다: 엔터프라이즈 레인의 가스 면제 트랜잭션. +- [**엔터프라이즈 SDK 참조**](/ko/reference/enterprise-sdk): 모든 모듈, 메서드, 구성 옵션 및 오류 클래스. ## 다음 권장 사항 -- [**가스 면제 프로토콜**](/ko/reference/gas-waiver-api): 트랜잭션 형식, 마커 라우팅 및 거버넌스 제어입니다. -- [**Stable SDK**](/ko/explanation/sdk-overview): 전송, 브리징, 스왑 및 수익을 위한 범용 클라이언트입니다. -- [**Stable에 연결**](/ko/reference/connect): 테스트넷의 체인 ID, RPC 엔드포인트 및 탐색기입니다. +- [**가스 면제 프로토콜**](/ko/reference/gas-waiver-api): 트랜잭션 형식, 마커 라우팅 및 거버넌스 제어. +- [**Stable SDK**](/ko/explanation/sdk-overview): 전송, 브리징, 스왑 및 수익을 위한 범용 클라이언트. +- [**Stable에 연결**](/ko/reference/connect): 테스트넷용 체인 ID, RPC 엔드포인트 및 탐색기. diff --git a/docs/pages/ko/how-to/guaranteed-relayed-transactions.mdx b/docs/pages/ko/how-to/guaranteed-relayed-transactions.mdx index 37f0719..5fe7918 100644 --- a/docs/pages/ko/how-to/guaranteed-relayed-transactions.mdx +++ b/docs/pages/ko/how-to/guaranteed-relayed-transactions.mdx @@ -1,29 +1,29 @@ --- source_path: how-to/guaranteed-relayed-transactions.mdx -source_sha: f17822f84d15b62f1ec4a12e262dad94d7343a46 +source_sha: 770f26cb178bfd6e7b678d524f5148a39a3f9946 title: "보장된 릴레이 트랜잭션" -description: "Enterprise SDK를 사용하여 보장된 블록 공간을 통해 가스 면제 트랜잭션을 릴레이하므로, 사용자는 잔고가 없어도 Enterprise 레인에 진입할 수 있습니다." +description: "Enterprise SDK를 통해 보장된 블록 공간으로 가스가 면제된 트랜잭션을 릴레이하여 사용자는 잔액이 없어도 Enterprise 라인에 접속할 수 있습니다." diataxis: "how-to" --- # 보장된 릴레이 트랜잭션 -`@stablechain/enterprise`를 사용하여 두 가지 Enterprise 레일을 결합합니다. 보장된 릴레이 트랜잭션은 [보장된 블록 공간](/ko/how-to/send-guaranteed-transactions)을 통해 라우팅되는 [가스 면제 트랜잭션](/ko/how-to/relay-with-gas-waiver)입니다. 면제자가 가스를 후원하므로 사용자는 잔고나 수수료 필드가 필요하지 않으며 트랜잭션은 예약된 Enterprise 레인에 도착합니다. +`@stablechain/enterprise`와 함께 두 가지 Enterprise 레일을 결합하세요. 보장된 릴레이 트랜잭션은 [가스가 면제된 트랜잭션](/ko/how-to/relay-with-gas-waiver)을 [보장된 블록 공간](/ko/how-to/send-guaranteed-transactions)을 통해 라우팅하는 것입니다. 즉, 면제는 가스를 후원하므로 사용자는 잔액이나 수수료 필드가 필요 없으며, 트랜잭션은 예약된 Enterprise 레인에 도착합니다. -`guaranteedWaiver` 모듈은 양쪽을 모두 처리합니다. 사용자는 내부 `0x3F` CustomTx에 서명하고, 화이트리스트에 있는 면제 계정은 동일한 Enterprise `nonceKey`를 공유하는 외부 `0x3F` CustomTx로 래핑하여 Enterprise RPC 게이트웨이를 통해 브로드캐스트합니다. 모든 메소드는 사용자의 트랜잭션 해시인 `H_inner`를 반환합니다. +`guaranteedWaiver` 모듈은 양쪽을 모두 처리합니다. 사용자는 내부 `0x3F` CustomTx에 서명하고, 화이트리스트에 있는 면제 계정은 동일한 Enterprise `nonceKey`를 공유하는 외부 `0x3F` CustomTx로 래핑한 다음, Enterprise RPC 게이트웨이를 통해 브로드캐스트합니다. 모든 메소드는 사용자 트랜잭션 해시인 `H_inner`를 반환합니다. ## 전제 조건 -- Node.js 20 이상, 그리고 `@stablechain/enterprise` 및 `viem`이 설치되어 있어야 합니다. [Enterprise SDK 참조](/ko/reference/enterprise-sdk#install)를 참조하십시오. -- 거버넌스에 등록된 면제 키와 Enterprise RPC 게이트웨이 API 키. Enterprise SDK는 현재 테스트넷 전용이며 요청 시 액세스 가능합니다. 둘 다 얻으려면 [Stable에 문의하십시오](https://discord.gg/stablexyz). +- Node.js 20 이상, `@stablechain/enterprise` 및 `viem` 설치. [Enterprise SDK 참조](/ko/reference/enterprise-sdk#install)를 참조하세요. +- 거버넌스에 등록된 면제 키와 Enterprise RPC 게이트웨이 API 키. 현재 Enterprise SDK는 테스트넷 전용이며 요청 시 액세스할 수 있습니다. 둘 다 [Stable에 문의](https://discord.gg/stablexyz)하여 얻으세요. :::warning -이것은 서버 측 라이브러리입니다. 면제 키와 Enterprise RPC 게이트웨이 URL을 백엔드에 보관하십시오. 게이트웨이 URL에는 API 키가 포함되어 있습니다. +이것은 서버 측 라이브러리입니다. 면제 키와 Enterprise RPC 게이트웨이 URL을 백엔드에 보관하세요. 게이트웨이 URL에는 API 키가 포함되어 있습니다. ::: ## 1. 보장된 면제 모듈로 클라이언트 생성 -`guaranteedWaiver` 및 `enterpriseRpcEndpoints`를 `createStableEnterprise`에 전달합니다. 모듈은 화이트리스트에 있는 면제 계정(외부 래퍼에 서명)과 Enterprise 레인을 가져옵니다. 또한 `gasWaiver`와 동일한 `allowedTargets`, `maxGasLimit`, `maxDataLength` 정책 한도를 허용합니다. +`guaranteedWaiver` 및 `enterpriseRpcEndpoints`를 `createStableEnterprise`에 전달합니다. 이 모듈은 화이트리스트에 있는 면제 키(외부 래퍼에 서명)와 Enterprise 레인을 가져옵니다. 또한 `gasWaiver`와 동일한 `allowedTargets`, `maxGasLimit`, `maxDataLength` 정책 제한도 허용합니다. ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -33,7 +33,7 @@ const enterprise = createStableEnterprise({ chain: stableTestnet, enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable이 제공하는 게이트웨이 URL guaranteedWaiver: { - waiverAccount: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`), + account: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`), laneId: 0n, // Enterprise 레인 }, }); @@ -45,9 +45,13 @@ const gw = enterprise.guaranteedWaiver!; StableEnterpriseClient { gasWaiver: undefined, guaranteedBlock: undefined, guaranteedWaiver } ``` +:::tip +면제 키를 보관 백엔드에 보관하려면 `account` 대신 `signer`를 전달합니다. `@stablechain/enterprise/aws-kms`의 `awsKmsSigner`는 AWS KMS로 이를 지원합니다. [서명 키 및 보관](/ko/reference/enterprise-sdk#signing-keys-and-custody)을 참조하세요. +::: + ## 2. 단일 트랜잭션 릴레이 -사용자 계정과 변경되는 필드를 사용하여 `send`를 호출합니다. 가스가 면제되므로 사용자는 잔고나 수수료 필드가 필요하지 않습니다. 내부 `0x3F` CustomTx, 해당 Enterprise `nonceKey`, 그리고 2D 논스(게이트웨이에서 발견됨)는 자동으로 처리됩니다. +사용자 계정과 변하는 필드를 사용하여 `send`를 호출합니다. 가스가 면제되므로 사용자에게는 잔액이나 수수료 필드가 필요 없습니다. 내부 `0x3F` CustomTx, 해당 Enterprise `nonceKey`, 그리고 게이트웨이에서 발견된 2D 논스는 자동으로 처리됩니다. ```ts const user = privateKeyToAccount(process.env.USER_PRIVATE_KEY as `0x${string}`); @@ -60,11 +64,11 @@ console.log("H_inner:", txHash); H_inner: 0x8f3a...2d41 ``` -`gas`는 공유된 내부 가스 기본값으로 설정됩니다. 재정의하려면 이 값을 전달하십시오. 값 전송이 허용되므로 `value`를 전달할 수도 있습니다. +`gas`는 공유된 내부 가스 기본값으로 설정됩니다. 재정의하려면 전달합니다. 값 전송이 허용되므로 `value`를 전달할 수도 있습니다. ## 3. 배치 릴레이 -한 사용자로부터 여러 트랜잭션을 릴레이하려면 `sendBatch`를 호출합니다. 내부 논스는 발견된 기본값에서 자동으로 시퀀싱되며, 입력 순서대로 입력당 하나의 결과가 반환됩니다. 실패는 후속 항목에 영향을 미칩니다. +한 사용자로부터 여러 트랜잭션을 릴레이하려면 `sendBatch`를 호출합니다. 내부 논스는 발견된 기본값에서 자동으로 시퀀싱되며, 입력 순서대로 입력당 하나의 결과를 얻습니다. 실패는 후속 트랜잭션을 중단시킵니다. ```ts const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); @@ -81,13 +85,13 @@ for (const r of results) { ## 4. 사전 서명된 트랜잭션 릴레이 -비수탁적 흐름의 경우, 사용자는 자신의 환경에서 내부 `0x3F` CustomTx에 서명하고 서명된 헥스만 사용자에게 제공합니다. Enterprise 논스 키로 `nonceKeyForLane`을 사용하고 수수료를 0으로 설정하여(`gas`는 면제됨) `buildGuaranteedTx`로 빌드합니다. 백엔드는 면제 키로 래핑하고 `relay`로 릴레이합니다. +비보관 플로우의 경우, 사용자는 자신의 환경에서 내부 `0x3F` CustomTx에 서명하고 서명된 헥스만 전달합니다. `nonceKeyForLane`을 Enterprise 논스 키로 사용하고 수수료를 0으로 설정하여 (가스가 면제됨) `buildGuaranteedTx`로 빌드합니다. 백엔드는 이를 면제 키로 래핑하고 `relay`로 릴레이합니다. ```ts -import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; +import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; -// 사용자 측에서 -const signedInner = await buildGuaranteedTx(user, stableTestnet.id, { +// 사용자 측 — buildGuaranteedTx는 Signer를 통해 서명합니다. toSigner는 viem 계정을 조정합니다. +const signedInner = await buildGuaranteedTx(toSigner(user), stableTestnet.id, { to: recipient, gas: 100_000n, gasFeeCap: 0n, // 면제됨 @@ -97,7 +101,7 @@ const signedInner = await buildGuaranteedTx(user, stableTestnet.id, { }); // 백엔드에서 -const { txHash } = await gw.relay(signedInner); // 면제자가 래핑 + 브로드캐스트 → H_inner +const { txHash } = await gw.relay(signedInner); // 면제 래핑 + 브로드캐스트 → H_inner console.log("H_inner:", txHash); ``` @@ -105,11 +109,11 @@ console.log("H_inner:", txHash); H_inner: 0x8f3a...2d41 ``` -여러 사전 서명된 트랜잭션의 경우 `relayBatch`를 사용하십시오. +여러 사전 서명된 트랜잭션의 경우 `relayBatch`를 사용합니다. ## 거부 처리 -`send` 및 `relay`는 거부 시 `StableEnterpriseRelayError`를 던집니다. 이 흐름은 게이트웨이를 통해 라우팅되므로 `GATEWAY_UNAUTHORIZED` 및 `QUOTA_EXCEEDED`와 같은 게이트웨이 코드가 `TARGET_NOT_ALLOWED`와 같은 면제 정책 코드와 함께 적용됩니다. +`send` 및 `relay`는 거부 시 `StableEnterpriseRelayError`를 발생시킵니다. 이 플로우는 게이트웨이를 통해 라우팅되므로 `GATEWAY_UNAUTHORIZED` 및 `QUOTA_EXCEEDED`와 같은 게이트웨이 코드가 `TARGET_NOT_ALLOWED`와 같은 면제 정책 코드와 함께 적용됩니다. ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -128,10 +132,10 @@ try { StableEnterpriseRelayError: relay failed [GATEWAY_UNAUTHORIZED]: invalid api key ``` -모든 거부 사유는 전체 [`ErrorCode`](/ko/reference/enterprise-sdk#errorcode) 테이블을 참조하십시오. +모든 거부 이유에 대한 전체 [`ErrorCode`](/ko/reference/enterprise-sdk#errorcode) 표를 참조하세요. ## 다음 단계 -- [**가스 면제 릴레이**](/ko/how-to/relay-with-gas-waiver): 보장된 레인 없이 사용자 가스를 후원합니다. -- [**보장된 트랜잭션 전송**](/ko/how-to/send-guaranteed-transactions): 서명자가 가스를 지불하는 자체적으로 보장된 블록 공간을 사용합니다. -- [**Enterprise SDK 참조**](/ko/reference/enterprise-sdk#guaranteed-relay-transactions): 모든 메소드, 구성 옵션 및 오류 클래스에 대한 전체 정보. +- [**가스 면제로 릴레이**](/ko/how-to/relay-with-gas-waiver): 보장된 레인 없이 사용자의 가스를 후원합니다. +- [**보장된 트랜잭션 전송**](/ko/how-to/send-guaranteed-transactions): 서명자가 가스를 지불하는 경우, 보장된 블록 공간을 단독으로 사용합니다. +- [**Enterprise SDK 참조**](/ko/reference/enterprise-sdk#guaranteed-relay-transactions): 모든 메소드, 구성 옵션 및 오류 클래스에 대한 전체 설명입니다. diff --git a/docs/pages/ko/how-to/relay-with-gas-waiver.mdx b/docs/pages/ko/how-to/relay-with-gas-waiver.mdx index 1d99467..e94fd33 100644 --- a/docs/pages/ko/how-to/relay-with-gas-waiver.mdx +++ b/docs/pages/ko/how-to/relay-with-gas-waiver.mdx @@ -1,21 +1,21 @@ --- source_path: how-to/relay-with-gas-waiver.mdx -source_sha: b123789598d68061ee8cb4472a3ed8d22153b91c -title: "가스 면제 릴레이(Relay with gas waiver)" -description: "Enterprise SDK로 사용자의 가스를 후원하세요: 제로 가스 트랜잭션을 릴레이하고, 릴레이를 일괄 처리하고, 정책 제한을 적용하고, 미리 서명된 트랜잭션을 릴레이합니다." +source_sha: d27d02a1e7956429991b4af81f097719e3eabd34 +title: "가스 면제 릴레이" +description: "Enterprise SDK로 사용자의 가스를 후원하세요: 제로 가스 트랜잭션을 릴레이하고, 릴레이를 일괄 처리하고, 정책 제한을 적용하고, 사전 서명된 트랜잭션을 릴레이합니다." diataxis: "how-to" --- -# 가스 면제 릴레이(Relay with gas waiver) +# 가스 면제 릴레이 -`@stablechain/enterprise`를 사용하여 사용자의 가스를 후원하세요. 화이트리스트에 등록된 면제 계정은 사용자의 제로 가스 트랜잭션(InnerTx)을 래핑하고 브로드캐스트하므로, 사용자는 USDT0를 보유하지 않고도 트랜잭션을 처리할 수 있습니다. `gasWaiver` 모듈은 빌드, 서명 및 릴레이를 한 번의 호출로 처리하므로, 작업마다 하나의 메서드를 호출합니다. +`@stablechain/enterprise`를 사용하여 사용자의 가스를 후원하세요. 화이트리스트에 등록된 면제 계정은 사용자의 제로 가스 트랜잭션(InnerTx)을 래핑하고 브로드캐스트하여 사용자가 USDT0를 보유하지 않고도 트랜잭션할 수 있도록 합니다. `gasWaiver` 모듈은 한 번의 호출로 빌드, 서명 및 릴레이를 수행하므로 작업당 하나의 메서드를 호출합니다. -모든 메서드는 래퍼가 아닌 사용자 트랜잭션의 해시인 `H_inner`를 반환합니다. +모든 메서드는 트랜잭션을 전달한 래퍼가 아닌, 사용자 트랜잭션의 해시인 `H_inner`를 반환합니다. ## 전제 조건 -- Node.js 20 이상, 그리고 `@stablechain/enterprise`와 `viem` 이 설치되어 있어야 합니다. [Enterprise SDK 참조](/ko/reference/enterprise-sdk#install)를 참조하십시오. -- 거버넌스에 등록된 면제 키. 현재 Enterprise SDK는 테스트넷 전용이며 접근이 제한됩니다. 화이트리스트에 등록된 면제 키를 얻으려면 [Stable에 문의](https://discord.gg/stablexyz)하십시오. +- Node.js 20 이상, 그리고 `@stablechain/enterprise`와 `viem` 설치. [Enterprise SDK 참조](/ko/reference/enterprise-sdk#install)를 참조하세요. +- 거버넌스에 등록된 면제 키. Enterprise SDK는 현재 테스트넷 전용이며 접근이 제한됩니다: 화이트리스트에 등록된 면제 키를 받으려면 [Stable에 문의](https://discord.gg/stablexyz)하세요. :::warning 이것은 개인 키로 서명하는 서버 측 라이브러리입니다. 브라우저에서 실행하지 마십시오. 면제 키는 백엔드에 보관하십시오. @@ -43,9 +43,13 @@ StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver `rpcEndpoints` 옵션은 선택 사항입니다. 설정하지 않으면 클라이언트는 체인의 내장 RPC를 사용합니다. +:::tip +면제 키를 보관 백엔드에 보관하려면 `account` 대신 `signer`를 전달하세요. `@stablechain/enterprise/aws-kms`의 `awsKmsSigner`는 AWS KMS로 이를 지원합니다. [서명 키 및 보관](/ko/reference/enterprise-sdk#signing-keys-and-custody)을 참조하십시오. +::: + ## 2. 단일 트랜잭션 릴레이 -사용자 계정과 변경되는 필드를 사용하여 `send`를 호출합니다. `gasPrice: 0`, 레거시 유형, `chainId`, 보류 중인 nonce는 자동으로 처리되므로, `to`와 선택적으로 `data`, `value`, `gas`만 전달하면 됩니다. +사용자 계정과 변경되는 필드를 사용하여 `send`를 호출합니다. `gasPrice: 0`, 레거시 유형, `chainId`, 보류 중인 nonce는 자동으로 처리되므로, `to`, 그리고 선택적으로 `data`, `value`, `gas`만 전달하면 됩니다. ```ts const user = privateKeyToAccount(process.env.USER_PRIVATE_KEY as `0x${string}`); @@ -58,11 +62,11 @@ console.log("H_inner:", txHash); H_inner: 0x8f3a...2d41 ``` -사용자는 USDT0가 필요하지 않습니다. 면제 계정이 가스를 후원합니다. `gas`는 `150_000n` (`DEFAULT_INNER_GAS`)으로 기본 설정되며, 이는 토큰 전송 또는 승인을 포함합니다. 더 많은 가스가 필요한 호출의 경우 명시적인 `gas`를 전달합니다. +사용자는 USDT0가 필요하지 않습니다. 면제 계정이 가스를 후원합니다. `gas`는 기본적으로 `150_000n`(`DEFAULT_INNER_GAS`)이며, 이는 토큰 전송 또는 승인을 포함합니다. 더 무거운 호출에는 명시적인 `gas`를 전달하십시오. -## 3. 일괄 릴레이 +## 3. 배치 릴레이 -여러 계정에서 여러 트랜잭션을 릴레이하려면 `sendBatch`를 호출합니다. Nonce는 계정의 보류 중인 nonce에서 자동으로 순서가 지정되며, 입력 순서대로 입력당 하나의 결과를 얻습니다. +하나의 계정에서 여러 트랜잭션을 릴레이하려면 `sendBatch`를 호출합니다. Nonce는 계정의 보류 중인 nonce에서 자동으로 시퀀싱되며, 입력 순서대로 입력당 하나의 결과를 얻습니다. ```ts const results = await gw.sendBatch(user, [ @@ -80,11 +84,11 @@ for (const r of results) { [1] ✔ 0x2b7c...9e04 ``` -배치(batch)는 오류를 발생시키는 대신 `result.error`에 항목별 실패를 보고하므로, 하나의 잘못된 트랜잭션이 나머지 트랜잭션을 망치지 않습니다. +배치는 실패를 스로우하는 대신 `result.error`의 항목별로 보고하므로, 하나의 잘못된 트랜잭션이 나머지 트랜잭션을 망치지 않습니다. ## 4. 파트너별 정책 제한 적용 -설정에 정책 제한을 추가하여 면제 키가 후원할 수 있는 것을 제한할 수 있습니다. 제한을 위반하는 InnerTx는 브로드캐스트 전에 거부됩니다. +설정에 정책 제한을 추가하여 면제 키가 후원할 수 있는 것을 제한합니다. 제한을 위반하는 InnerTx는 브로드캐스트 전에 거부됩니다. ```ts const enterprise = createStableEnterprise({ @@ -94,23 +98,23 @@ const enterprise = createStableEnterprise({ maxGasLimit: 500_000n, maxDataLength: 4_096, allowedTargets: [ - { address: token, selectors: ["0xa9059cbb"] }, // ERC-20 전송만 허용 + { address: token, selectors: ["0xa9059cbb"] }, // ERC-20 전송만 ], }, }); ``` -`allowedTargets` 외부에 있는 계약에 대한 트랜잭션은 `TARGET_NOT_ALLOWED` 오류로 실패하고, `maxGasLimit`을 초과하는 트랜잭션은 `GAS_LIMIT_EXCEEDED` 오류로 실패합니다. 특정 계약을 허용하려면 `address`를 `"*"`로 사용하고, 모든 메서드를 허용하려면 `selectors`를 생략합니다. +`allowedTargets` 외부의 컨트랙트로의 트랜잭션은 `TARGET_NOT_ALLOWED`와 함께 실패하고, `maxGasLimit`을 초과하는 트랜잭션은 `GAS_LIMIT_EXCEEDED`와 함께 실패합니다. 어떤 컨트랙트든 허용하려면 `address`로 `"*"를 사용하고, 어떤 메서드든 허용하려면 `selectors`를 생략합니다. -## 5. 미리 서명된 트랜잭션 릴레이 +## 5. 사전 서명된 트랜잭션 릴레이 -비수탁 흐름의 경우, 사용자는 자신의 환경에서 InnerTx에 서명하고 서명된 헥스만 전달하므로 키가 노출되지 않습니다. `buildWaiverInnerTx`로 빌드한 다음 `relay`로 릴레이합니다. +비수탁 흐름의 경우, 사용자는 자신의 환경에서 InnerTx에 서명하고 서명된 16진수만 제공하므로 사용자의 키를 볼 수 없습니다. `buildWaiverInnerTx`로 빌드한 다음 `relay`로 릴레이합니다. ```ts -import { buildWaiverInnerTx } from "@stablechain/enterprise"; +import { buildWaiverInnerTx, toSigner } from "@stablechain/enterprise"; -// 사용자 측에서 -const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to: token, data, gas: 150_000n, nonce }); +// 사용자 측에서 — buildWaiverInnerTx는 Signer를 통해 서명합니다. toSigner는 viem 계정을 조정합니다. +const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to: token, data, gas: 150_000n, nonce }); // 백엔드에서 const { txHash } = await gw.relay(signed); @@ -121,11 +125,11 @@ console.log("H_inner:", txHash); H_inner: 0x8f3a...2d41 ``` -여러 개의 미리 서명된 트랜잭션의 경우, `sendBatch`와 같이 입력당 하나의 결과를 반환하는 `relayBatch`를 사용합니다. +여러 개의 사전 서명된 트랜잭션의 경우, `sendBatch`와 같이 입력당 하나의 결과를 반환하는 `relayBatch`를 사용합니다. ## 거부 처리 -`send` 및 `relay`는 거부 시 `StableEnterpriseRelayError`를 발생시키며, 분기할 수 있는 `code`를 포함합니다. +`send` 및 `relay`는 거부 시 `StableEnterpriseRelayError`를 던지며, 분기할 수 있는 `code`를 포함합니다. ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -144,10 +148,10 @@ try { StableEnterpriseRelayError: 릴레이 실패 [TARGET_NOT_ALLOWED]: 대상 0x... 허용되지 않음 ``` -모든 거부 이유에 대한 전체 [`ErrorCode`](/ko/reference/enterprise-sdk#errorcode) 표를 참조하십시오. +모든 거부 이유에 대한 전체 [`ErrorCode`](/ko/reference/enterprise-sdk#errorcode) 테이블을 참조하십시오. ## 다음 단계 -- [**보장된 트랜잭션 보내기**](/ko/how-to/send-guaranteed-transactions): 예약된 엔터프라이즈 레인 블록스페이스에 트랜잭션을 전송하고 가스 면제와 결합합니다. -- [**엔터프라이즈 SDK 참조**](/ko/reference/enterprise-sdk#relay-with-gas-waiver): 모든 메서드, 구성 옵션 및 오류 클래스에 대한 전체 정보. +- [**보장된 트랜잭션 보내기**](/ko/how-to/send-guaranteed-transactions): 예약된 Enterprise-lane 블록스페이스에 트랜잭션을 전송하고 가스 면제와 결합합니다. +- [**Enterprise SDK 참조**](/ko/reference/enterprise-sdk#relay-with-gas-waiver): 모든 메서드, 구성 옵션 및 오류 클래스 전체. - [**가스 면제**](/ko/explanation/gas-waiver): 프로토콜 수준에서 제로 가스 트랜잭션이 작동하는 방식. diff --git a/docs/pages/ko/how-to/send-guaranteed-transactions.mdx b/docs/pages/ko/how-to/send-guaranteed-transactions.mdx index 7e2d9d7..61e7c3c 100644 --- a/docs/pages/ko/how-to/send-guaranteed-transactions.mdx +++ b/docs/pages/ko/how-to/send-guaranteed-transactions.mdx @@ -1,30 +1,30 @@ --- source_path: how-to/send-guaranteed-transactions.mdx -source_sha: d45aa08b5a1be19855b02d145479697cc0b4bee5 +source_sha: c59ac1a053751e961d75071fa7799dbd9dc4b847 title: "보장된 트랜잭션 전송" -description: "Enterprise SDK를 사용하여 예약된 Enterprise-레인 블록스페이스에 트랜잭션을 배치하고, 가스 면제와 보장된 블록스페이스를 결합하여 가스 없이 릴레이합니다." +description: "Enterprise SDK를 사용하여 예약된 Enterprise-레인 블록 공간에 트랜잭션을 배치하고, 보장된 블록 공간과 가스 면제를 결합하여 가스 없이 전송합니다." diataxis: "how-to" --- # 보장된 트랜잭션 전송 -`@stablechain/enterprise`를 사용하여 예약된 Enterprise-레인 블록스페이스를 통해 트랜잭션을 라우팅합니다. `guaranteedBlock` 모듈은 GuaranteedTx (0x3F 유형 CustomTx)를 Enterprise RPC 게이트웨이를 통해 릴레이하여 엔터프라이즈 워크로드용으로 예약된 용량에 트랜잭션을 배치합니다. 가스 면제와 달리 서명자는 자체 가스를 지불하므로 자금이 있어야 합니다. +`@stablechain/enterprise`를 사용하여 예약된 엔터프라이즈 레인 블록 공간을 통해 트랜잭션을 라우팅합니다. `guaranteedBlock` 모듈은 엔터프라이즈 RPC 게이트웨이를 통해 GuaranteedTx(유형 `0x3F` CustomTx)를 중계하여 엔터프라이즈 워크로드용으로 예약된 용량에 트랜잭션을 배치합니다. 가스 면제와 달리 서명자는 자체 가스를 지불하므로 자금이 충분해야 합니다. -이를 가스 면제와 결합하여 [보장된 릴레이 트랜잭션](/ko/how-to/guaranteed-relayed-transactions)을 얻을 수 있습니다. 이는 여전히 Enterprise 레인에 배치되는 가스 면제 트랜잭션입니다. +이를 가스 면제와 결합하여 [보장된 릴레이 트랜잭션](/ko/how-to/guaranteed-relayed-transactions)을 얻을 수 있습니다. 이는 엔터프라이즈 레인에 배치되는 가스 면제 트랜잭션입니다. ## 전제 조건 -- Node.js 20 이상, 그리고 `@stablechain/enterprise`와 `viem`이 설치되어 있어야 합니다. [Enterprise SDK 참조](/ko/reference/enterprise-sdk#install)를 참조하세요. -- Enterprise RPC 게이트웨이 API 키. Enterprise SDK는 현재 테스트넷 전용이며 접근이 제한됩니다. 게이트웨이 엔드포인트를 얻으려면 [Stable에 문의하세요](https://discord.gg/stablexyz). -- GuaranteedTx는 자체 가스를 지불하므로 자금이 있는 서명자가 필요합니다. +- Node.js 20 이상, 그리고 `@stablechain/enterprise` 및 `viem`이 설치되어 있어야 합니다. [Enterprise SDK 참조](/ko/reference/enterprise-sdk#install)를 참조하십시오. +- Enterprise RPC 게이트웨이 API 키. Enterprise SDK는 현재 테스트넷 전용이며, 접근이 제한됩니다. 게이트웨이 엔드포인트를 얻으려면 [Stable에 문의](https://discord.gg/stablexyz)하십시오. +- GuaranteedTx가 자체 가스를 지불하므로 자금이 충분한 서명자가 필요합니다. :::warning -이것은 서버 측 라이브러리입니다. Enterprise RPC 게이트웨이 URL을 백엔드에 유지하세요: API 키가 포함되어 있습니다. +이것은 서버 측 라이브러리입니다. Enterprise RPC 게이트웨이 URL을 백엔드에 보관하십시오. 여기에는 API 키가 포함되어 있습니다. ::: -## 1. 보장된 블록스페이스 모듈로 클라이언트 생성 +## 1. 보장된 블록 공간 모듈로 클라이언트 생성 -`guaranteedBlock` 및 `enterpriseRpcEndpoints`를 `createStableEnterprise`에 전달합니다. 게이트웨이만이 `0x3F` GuaranteedTx를 허용하는 유일한 엔드포인트이며, API 키를 보유합니다. 유효하지 않은 `laneId`는 즉시 거부됩니다. +`guaranteedBlock` 및 `enterpriseRpcEndpoints`를 `createStableEnterprise`에 전달합니다. 게이트웨이는 `0x3F` GuaranteedTxs를 허용하는 유일한 엔드포인트이며, API 키를 보유합니다. 잘못된 `laneId`는 즉시 거부됩니다. ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -34,7 +34,7 @@ const enterprise = createStableEnterprise({ chain: stableTestnet, enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable이 제공하는 게이트웨이 URL guaranteedBlock: { - account: privateKeyToAccount(process.env.SIGNER_PRIVATE_KEY as `0x${string}`), // 자금이 있어야 함 + account: privateKeyToAccount(process.env.SIGNER_PRIVATE_KEY as `0x${string}`), // 자금이 충분해야 함 laneId: 0n, // Enterprise 레인 }, }); @@ -48,7 +48,7 @@ StableEnterpriseClient { gasWaiver: undefined, guaranteedBlock, guaranteedWaiver ## 2. 단일 트랜잭션 전송 -서명자와 여러 필드를 사용하여 `send`를 호출합니다. 서명자가 가스를 지불하므로 1559 수수료 필드가 필요합니다. `chainId`, Enterprise `nonceKey` 및 2D nonce (게이트웨이에서 발견됨)는 자동으로 처리됩니다. +서명자와 다양한 필드를 사용하여 `send`를 호출합니다. 서명자가 가스를 지불하므로 1559 수수료 필드가 필요합니다. `chainId`, Enterprise `nonceKey`, 그리고 2D 논스(게이트웨이에서 발견됨)는 자동으로 처리됩니다. ```ts import { createPublicClient, http } from "viem"; @@ -69,11 +69,11 @@ console.log("Guaranteed tx:", txHash); Guaranteed tx: 0xabcd...7890 ``` -서명자가 가스를 지불하므로 릴레이 전에 잔액을 확인하십시오. 잔액이 0인 계정에서 GuaranteedTx는 실패합니다. +서명자가 가스를 지불하므로 릴레이하기 전에 잔액이 충분한지 확인하십시오. 잔액이 0인 계정에서 보장된 트랜잭션은 실패합니다. ## 3. 배치 전송 -여러 트랜잭션을 보내려면 `sendBatch`를 호출합니다. Nonce는 발견된 기준점에서 자동 시퀀싱되며, 입력 순서대로 입력당 하나의 결과를 얻습니다. 실패는 후속 작업에 영향을 미칩니다. +여러 트랜잭션을 보내려면 `sendBatch`를 호출합니다. 논스는 발견된 베이스에서 자동으로 순서가 지정되며, 입력 순서대로 입력당 하나의 결과를 얻습니다. 실패하면 후속 작업이 중단됩니다. ```ts const results = await gb.sendBatch(signer, [ @@ -91,19 +91,19 @@ for (const r of results) { [1] ✔ 0x1f2e...66a1 ``` -## 4. 미리 서명된 트랜잭션 전송 +## 4. 사전 서명된 트랜잭션 전송 -비수탁 흐름의 경우, `buildGuaranteedTx`로 GuaranteedTx를 다른 곳에서 빌드하고 서명한 다음 운영자에게 서명된 hex만 전달합니다. Enterprise nonce 키는 `nonceKeyForLane`에서 가져옵니다. +비수탁 흐름의 경우 `buildGuaranteedTx`를 사용하여 다른 곳에서 GuaranteedTx를 빌드하고 서명한 다음, 서명된 헥스만 운영자에게 전달합니다. Enterprise 논스 키는 `nonceKeyForLane`에서 가져옵니다. ```ts -import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; +import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; -const signed = await buildGuaranteedTx(signer, stableTestnet.id, { +const signed = await buildGuaranteedTx(toSigner(signer), stableTestnet.id, { to: recipient, gas: 21_000n, gasFeeCap, gasTipCap, - nonce, // 계정의 현재 2D-레인 nonce + nonce, // 계정의 현재 2D 레인 논스 nonceKey: nonceKeyForLane(0n), // Enterprise 레인 0 }); @@ -115,7 +115,7 @@ console.log("Guaranteed tx:", txHash); Guaranteed tx: 0xabcd...7890 ``` -미리 서명된 여러 트랜잭션의 경우 `relayBatch`를 사용하십시오. +사전 서명된 여러 트랜잭션의 경우 `relayBatch`를 사용하십시오. ## 가스 면제와 결합 @@ -123,7 +123,7 @@ Guaranteed tx: 0xabcd...7890 ## 거부 처리 -`send` 및 `relay`는 거부 시 `StableEnterpriseRelayError`를 발생시킵니다. 게이트웨이별 코드에는 `GATEWAY_UNAUTHORIZED` (누락되었거나 유효하지 않은 API 키) 및 `QUOTA_EXCEEDED` (게이트웨이 가스 할당량이 소진됨)가 포함됩니다. +`send` 및 `relay`는 거부 시 `StableEnterpriseRelayError`를 발생시킵니다. 게이트웨이 특정 코드는 `GATEWAY_UNAUTHORIZED`(누락되거나 잘못된 API 키) 및 `QUOTA_EXCEEDED`(게이트웨이 가스 할당량 소진)를 포함합니다. ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -142,8 +142,8 @@ try { StableEnterpriseRelayError: relay failed [GATEWAY_UNAUTHORIZED]: invalid api key ``` -## 다음 단계 +## 다음으로 이동할 곳 - [**보장된 릴레이 트랜잭션**](/ko/how-to/guaranteed-relayed-transactions): 사용자의 가스를 면제하고 한 번의 호출로 Enterprise 레인에 배치합니다. -- [**가스 면제로 릴레이**](/ko/how-to/relay-with-gas-waiver): 사용자의 가스를 지원하여 USDT0를 보유하지 않고도 트랜잭션을 수행하도록 합니다. +- [**가스 면제로 릴레이**](/ko/how-to/relay-with-gas-waiver): 사용자가 USDT0를 보유하지 않고도 트랜잭션을 할 수 있도록 가스를 후원합니다. - [**Enterprise SDK 참조**](/ko/reference/enterprise-sdk#guaranteed-blockspace): 모든 메서드, 구성 옵션 및 오류 클래스에 대한 전체 설명입니다. diff --git a/docs/pages/ko/reference/enterprise-sdk.mdx b/docs/pages/ko/reference/enterprise-sdk.mdx index 746160f..026348f 100644 --- a/docs/pages/ko/reference/enterprise-sdk.mdx +++ b/docs/pages/ko/reference/enterprise-sdk.mdx @@ -1,21 +1,21 @@ --- source_path: reference/enterprise-sdk.mdx -source_sha: 2f9f840d9ea287e27f4642da4f0a219db13edab6 +source_sha: 1415ca3965bbd2c7d362a8e86a728c3a9e6269a7 title: "엔터프라이즈 SDK 참조" -description: "@stablechain/enterprise에 대한 완벽한 참조: createStableEnterprise, 가스 면제 및 보장된 블록 공간 모듈, 빌드 헬퍼 및 오류 클래스." +description: "@stablechain/enterprise에 대한 전체 참조: createStableEnterprise, 가스 웨이버 및 보장 블록 공간 모듈, 빌드 헬퍼 및 오류 클래스." diataxis: "reference" --- # 엔터프라이즈 SDK 참조 -`@stablechain/enterprise`의 전체 표면입니다. 여기에는 [`createStableEnterprise`](#createstableenterpriseconfig)를 통한 클라이언트, 세 가지 기능([가스 면제를 통한 릴레이](#relay-with-gas-waiver), [보장된 블록 공간](#guaranteed-blockspace), [보장된 릴레이 트랜잭션](#guaranteed-relay-transactions)), 하위 수준 빌드 헬퍼, 공유 결과 및 오류 유형이 포함됩니다. 이러한 레일에 대한 설명은 [Stable Enterprise SDK](/ko/explanation/enterprise-sdk), [가스 면제](/ko/explanation/gas-waiver), [보장된 블록 공간](/ko/explanation/guaranteed-blockspace)을 참조하십시오. +`@stablechain/enterprise`의 전체 표면입니다. 여기에는 [`createStableEnterprise`](#createstableenterpriseconfig)에서 가져오는 클라이언트, 세 가지 기능([가스 웨이버 대행](#relay-with-gas-waiver), [보장 블록 공간](#guaranteed-blockspace), [보장 릴레이 트랜잭션](#guaranteed-relay-transactions)), 하위 수준 빌드 헬퍼, 공유 결과 및 오류 유형이 포함됩니다. 이러한 레일이 무엇인지는 [Stable Enterprise SDK](/ko/explanation/enterprise-sdk), [가스 웨이버](/ko/explanation/gas-waiver), [보장 블록 공간](/ko/explanation/guaranteed-blockspace)을 참조하세요. :::note -엔터프라이즈 SDK는 현재 Stable Testnet에서만 사용할 수 있으며, 요청 시 액세스할 수 있습니다. 통합하려면 [Stable에 문의](https://discord.gg/stablexyz)하여 거버넌스에 등록된 면제 키와 엔터프라이즈 RPC 게이트웨이 API 키를 받으십시오. +엔터프라이즈 SDK는 현재 Stable Testnet에서만 사용할 수 있으며, 액세스는 요청 시에만 가능합니다. 통합하려면 Stable에 [문의](https://discord.gg/stablexyz)하여 거버넌스 등록 웨이버 키 및 엔터프라이즈 RPC 게이트웨이 API 키를 받으세요. ::: :::warning -이것은 개인 키로 서명하는 서버 측 라이브러리입니다. 브라우저에서 절대 실행하지 마십시오. 면제 키와 엔터프라이즈 RPC 게이트웨이 URL을 백엔드에 보관하십시오. +이것은 개인 키로 서명하는 서버 측 라이브러리입니다. 브라우저에서 실행하지 마세요. 웨이버 키와 엔터프라이즈 RPC 게이트웨이 URL을 백엔드에 보관하세요. ::: ## 설치 @@ -32,7 +32,7 @@ added 2 packages, audited 3 packages in 2s ## `createStableEnterprise(config)` -`StableEnterpriseClient`를 생성합니다. 각 모듈은 구성할 때만 존재하므로 사용하기 전에 `!` 또는 null 검사를 사용하세요. +`StableEnterpriseClient`를 생성합니다. 각 모듈은 구성할 때만 존재하므로 사용하기 전에 `!` 또는 null 검사로 보호하세요. ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -52,13 +52,38 @@ StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver | **필드** | **유형** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `chain` | `StableChain` | | 대상 체인. `stable` 또는 `stableTestnet`(패키지에서 다시 내보냄)을 전달하십시오. 필수. | -| `rpcEndpoints` | `string[]?` | 체인의 내장 RPC | 하나 이상의 Stable RPC 엔드포인트(실패 시 순서대로 시도). 개인 엔드포인트를 지정하는 경우에만 재정의합니다. | -| `enterpriseRpcEndpoints` | `string[]?` | | 하나 이상의 엔터프라이즈 RPC 게이트웨이 엔드포인트(실패 시 순서대로 시도). `guaranteedBlock` 및 `guaranteedWaiver`에 필요합니다. | -| `batchSizeLimit` | `number?` | `100` | 일괄 RPC 호출당 최대 트랜잭션 수. | -| `gasWaiver` | `GasWaiverConfig?` | | [가스 면제를 통한 릴레이](#relay-with-gas-waiver)를 활성화합니다. | -| `guaranteedBlock` | `GuaranteedBlockConfig?` | | [보장된 블록 공간](#guaranteed-blockspace)을 활성화합니다. | -| `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | [보장된 릴레이 트랜잭션](#guaranteed-relay-transactions)을 활성화합니다. | +| `chain` | `StableChain` | | 대상 체인. `stable` 또는 `stableTestnet` (패키지에서 다시 내보냄)을 전달합니다. 필수입니다. | +| `rpcEndpoints` | `string[]?` | 체인의 내장 RPC | 하나 이상의 Stable RPC 엔드포인트이며, 실패 시 순서대로 시도됩니다. 개인 엔드포인트를 가리키는 경우에만 재정의합니다. | +| `enterpriseRpcEndpoints` | `string[]?` | | 하나 이상의 엔터프라이즈 RPC 게이트웨이 엔드포인트이며, 실패 시 순서대로 시도됩니다. `guaranteedBlock` 및 `guaranteedWaiver`에 필요합니다. | +| `batchSizeLimit` | `number?` | `100` | 일괄 RPC 호출당 최대 트랜잭션 수입니다. | +| `gasWaiver` | `GasWaiverConfig?` | | [가스 웨이버 대행](#relay-with-gas-waiver)을 활성화합니다. | +| `guaranteedBlock` | `GuaranteedBlockConfig?` | | [보장 블록 공간](#guaranteed-blockspace)을 활성화합니다. | +| `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | [보장 릴레이 트랜잭션](#guaranteed-relay-transactions)을 활성화합니다. | + +### 서명 키 및 Custody + +웨이버 키(`gasWaiver` 및 `guaranteedWaiver`)를 보유하는 모듈은 [`SignerSource`](#signersource)에서 순서대로 해결됩니다: `signer`(custody 등급 백엔드), 그 다음 `account`(인-프로세스 viem 키), 그 다음 `STABLE_ENTERPRISE_PRIVATE_KEY` 환경 변수. `guaranteedBlock`은 자금이 지원되는 `account`를 직접 사용합니다. + +`Signer`는 32바이트 다이제스트에 서명하므로 키는 custody 백엔드를 벗어나지 않습니다. AWS KMS의 경우 `awsKmsSigner`를 사용하고, viem 계정을 적용하기 위해 `toSigner(account)`를 사용하거나, 인-프로세스 키의 경우 `privateKeySigner(key)` / `envSigner()`를 사용합니다. + +```bash +npm install @aws-sdk/client-kms +``` + +```ts +import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; +import { awsKmsSigner } from "@stablechain/enterprise/aws-kms"; + +// KMS 키는 ECC_SECG_P256K1 (secp256k1)이어야 합니다. SDK가 주소를 거기서 파생합니다. +const signer = await awsKmsSigner({ keyId: process.env.KMS_KEY_ID! }); + +const enterprise = createStableEnterprise({ + chain: stableTestnet, + gasWaiver: { signer }, // `account` 대신 custody 등급 웨이버 키 +}); +``` + +`awsKmsSigner`는 `@stablechain/enterprise/aws-kms` 하위 경로에 제공되므로 `@aws-sdk/client-kms`는 핵심 설치에서 제외된 선택적 피어 의존성으로 유지됩니다. ### `StableEnterpriseClient` @@ -70,11 +95,11 @@ interface StableEnterpriseClient { } ``` -## 가스 면제를 통한 릴레이 +## 가스 웨이버 대행 -`gasWaiver` 모듈은 가스가 면제된 트랜잭션을 릴레이합니다. 화이트리스트에 등록된 면제 계정은 사용자의 0-가스 트랜잭션(InnerTx)을 WaiverTx로 래핑하고 브로드캐스트합니다. 사용자는 USDT0이 필요하지 않습니다. 모든 메서드는 래퍼 해시가 아닌 InnerTx 해시인 `H_inner`를 반환합니다. +`gasWaiver` 모듈은 가스 면제 트랜잭션을 릴레이합니다. 화이트리스트에 등록된 웨이버 계정은 사용자의 제로 가스 트랜잭션(InnerTx)을 WaiverTx로 묶어 브로드캐스트합니다. 사용자는 USDT0이 필요하지 않습니다. 모든 메서드는 래퍼 해시가 아닌 InnerTx 해시인 `H_inner`를 반환합니다. -구성에서 `gasWaiver`로 활성화합니다. +구성에서 `gasWaiver`를 사용하여 활성화합니다. ```ts const enterprise = createStableEnterprise({ @@ -92,18 +117,19 @@ const gw = enterprise.gasWaiver!; ### `GasWaiverConfig` -[`ValidationLimits`](#validationlimits)를 확장합니다. +[`ValidationLimits`](#validationlimits) 및 [`SignerSource`](#signersource)를 확장합니다. | **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `account` | `LocalAccount` | 각 WaiverTx에 서명하는 화이트리스트에 등록된 거버넌스 등록 계정입니다. | +| `signer` | `Signer?` | custody 서명자(AWS KMS, HSM)로서 화이트리스트에 등록된 거버넌스 등록 웨이버 키입니다. [서명 키 및 Custody](#signing-keys-and-custody)를 참조하세요. `account`보다 우선합니다. | +| `account` | `LocalAccount?` | 인-프로세스 viem 계정으로서의 웨이버 키입니다. 둘 다 설정되지 않은 경우 `STABLE_ENTERPRISE_PRIVATE_KEY`로 폴백합니다. | | `maxGasLimit` | `bigint?` | `ValidationLimits`에서 상속됩니다. | | `maxDataLength` | `number?` | `ValidationLimits`에서 상속됩니다. | | `allowedTargets` | `AllowedTarget[]?` | `ValidationLimits`에서 상속됩니다. | ### `send(account, tx)` -`account`에서 하나의 InnerTx를 빌드, 서명 및 릴레이하는 한 번의 호출입니다. `gasPrice: 0`, 레거시 유형, `chainId`, 대기 중인 논스가 자동으로 처리됩니다. 거부 시 `StableEnterpriseRelayError`를 발생시킵니다. +`account`에서 하나의 InnerTx를 한 번의 호출로 빌드, 서명하고 릴레이합니다. `gasPrice: 0`, 레거시 유형, `chainId`, 보류 중인 nonce가 자동으로 처리됩니다. 거부 시 `StableEnterpriseRelayError`가 발생합니다. ```ts const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); @@ -117,7 +143,7 @@ const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); ### `sendBatch(account, txs)` -하나의 `account`에서 여러 InnerTx를 빌드, 서명 및 릴레이합니다. 논스는 계정의 대기 중인 논스에서 자동으로 시퀀스됩니다. 순서대로 입력당 하나의 결과를 반환합니다. +하나의 `account`에서 여러 InnerTx를 빌드, 서명하고 릴레이합니다. Nonce는 계정의 보류 중인 nonce에서 자동으로 순서가 지정됩니다. 입력당 하나의 결과를 순서대로 반환합니다. ```ts const results = await gw.sendBatch(user, [ @@ -130,16 +156,16 @@ const results = await gw.sendBatch(user, [ [ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: true, txHash: "0x..." } ] ``` -`txs`는 [`WaiverInnerTx`](#waiverinnertx)의 읽기 전용 배열입니다. [`BatchResultItem[]`](#batchresultitem)을 반환합니다. +`txs`는 [`WaiverInnerTx`](#waiverinnertx)의 읽기 전용 배열입니다. [`BatchResultItem[]`](#batchresultitem)를 반환합니다. ### `relay(signedInnerTxHex)` -미리 서명된 0-가스 InnerTx를 릴레이합니다. 사용자가 자신의 환경에서 서명하고 서명된 헥스만 전달하여 면제 운영자가 사용자의 키를 보지 못하는 비보관 흐름에 이 메서드를 사용하십시오. [`buildWaiverInnerTx`](#buildwaiverinnertxaccount-chainid-req)로 빌드합니다. 거부 시 발생합니다. +미리 서명된 제로 가스 InnerTx를 릴레이합니다. 사용자가 자신의 환경에서 서명하고 서명된 헥스만 전달하여 웨이버 운영자가 사용자 키를 볼 수 없는 비보관 흐름에 사용합니다. [`buildWaiverInnerTx`](#buildwaiverinnertxsigner-chainid-req)로 빌드합니다. 거부 시 오류가 발생합니다. ```ts -import { buildWaiverInnerTx } from "@stablechain/enterprise"; +import { buildWaiverInnerTx, toSigner } from "@stablechain/enterprise"; -const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to, data, gas: 150_000n, nonce }); +const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to, data, gas: 150_000n, nonce }); const { txHash } = await gw.relay(signed); ``` @@ -149,7 +175,7 @@ const { txHash } = await gw.relay(signed); ### `relayBatch(signedInnerTxHexes)` -미리 서명된 InnerTx 배치를 릴레이합니다. 입력당 하나의 [`BatchResultItem`](#batchresultitem)을 순서대로 반환합니다. +미리 서명된 InnerTx의 배치를 릴레이합니다. 입력당 하나의 [`BatchResultItem`](#batchresultitem)을 순서대로 반환합니다. ```ts const results = await gw.relayBatch([signed0, signed1]); @@ -159,11 +185,11 @@ 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)를 릴레이하여 예약된 엔터프라이즈 레인 블록 공간에 배치되도록 합니다. 가스 면제와 달리 서명자는 자체 가스를 지불하며 자금이 있어야 합니다. 각 트랜잭션은 엔터프라이즈 레인에 키가 지정된 2D 논스를 전달하며, 브로드캐스팅은 게이트웨이를 통해서만 이루어집니다. +`guaranteedBlock` 모듈은 엔터프라이즈 RPC 게이트웨이를 통해 GuaranteedTx(유형 `0x3F` CustomTx)를 릴레이하여 예약된 엔터프라이즈 레인 블록 공간에 배치합니다. 가스 웨이버와 달리 서명자는 자체 가스를 지불하며 자금이 지원되어야 합니다. 각 트랜잭션은 엔터프라이즈 레인에 키가 지정된 2D nonce를 가지고 있으며, 브로드캐스트는 게이트웨이를 통해서만 이루어집니다. -`guaranteedBlock`과 `enterpriseRpcEndpoints`로 활성화합니다. +`guaranteedBlock`과 `enterpriseRpcEndpoints`를 사용하여 활성화합니다. ```ts const enterprise = createStableEnterprise({ @@ -182,12 +208,12 @@ const gb = enterprise.guaranteedBlock!; | **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `account` | `LocalAccount` | 각 GuaranteedTx에 서명하고 가스를 지불하는 자금이 있는 계정입니다. | -| `laneId` | `bigint` | 엔터프라이즈 레인 ID입니다. `[0, ENTERPRISE_MASK - 1]` 범위에 있어야 합니다. 유효하지 않은 ID는 즉시 거부됩니다. | +| `account` | `LocalAccount` | 각 GuaranteedTx에 서명하고 가스를 지불하는 자금이 지원되는 계정입니다. | +| `laneId` | `bigint` | 엔터프라이즈 레인 ID입니다. `[0, ENTERPRISE_MASK - 1]` 범위 내에 있어야 합니다. 유효하지 않은 ID는 즉시 거부됩니다. | ### `send(account, tx)` -하나의 GuaranteedTx를 빌드, 서명 및 릴레이합니다. 1559 수수료 필드는 서명자가 가스를 지불하므로 필수입니다. `chainId`, 엔터프라이즈 `nonceKey`, 2D nonce(게이트웨이에서 검색)가 자동으로 처리됩니다. +하나의 GuaranteedTx를 빌드, 서명하고 릴레이합니다. 서명자가 가스를 지불하므로 1559 수수료 필드는 필수입니다. `chainId`, 엔터프라이즈 `nonceKey`, 그리고 (게이트웨이에서 발견된) 2D nonce가 자동으로 처리됩니다. ```ts const gasPrice = await publicClient.getGasPrice(); @@ -208,7 +234,7 @@ const { txHash } = await gb.send(signer, { ### `sendBatch(account, txs)` -여러 GuaranteedTx를 빌드, 서명 및 릴레이합니다. 논스는 검색된 기본값에서 자동으로 시퀀스됩니다. 실패는 후속 트랜잭션을 좌초시킵니다. +여러 GuaranteedTx를 빌드, 서명하고 릴레이합니다. Nonce는 발견된 기본값에서 자동으로 순서가 지정됩니다. 실패는 후속 처리됩니다. ```ts const results = await gb.sendBatch(signer, [ @@ -221,21 +247,21 @@ const results = await gb.sendBatch(signer, [ [ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: true, txHash: "0x..." } ] ``` -[`BatchResultItem[]`](#batchresultitem)을 반환합니다. +[`BatchResultItem[]`](#batchresultitem)를 반환합니다. ### `relay(signedTx)` / `relayBatch(signedTxs)` -미리 서명된 GuaranteedTx 또는 배치로 릴레이합니다. 엔터프라이즈 nonce 키에는 [`nonceKeyForLane`](#noncekeyforlanelaneid)를 사용하여 [`buildGuaranteedTx`](#buildguaranteedtxaccount-chainid-req)로 트랜잭션을 다른 곳에서 빌드하고 서명한 다음 서명된 헥스만 운영자에게 전달합니다. +미리 서명된 GuaranteedTx 또는 배치로 릴레이합니다. [`nonceKeyForLane`](#noncekeyforlanelaneid)를 엔터프라이즈 nonce 키로 사용하여 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req)로 다른 곳에서 트랜잭션을 빌드하고 서명한 다음, 운영자에게 서명된 헥스만 전달합니다. ```ts -import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; +import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; -const signed = await buildGuaranteedTx(signer, stableTestnet.id, { +const signed = await buildGuaranteedTx(toSigner(signer), stableTestnet.id, { to, gas: 21_000n, gasFeeCap, gasTipCap, - nonce, // 계정의 현재 2D 레인 nonce + nonce, // 계정의 현재 2D-레인 nonce nonceKey: nonceKeyForLane(0n), }); const { txHash } = await gb.relay(signed); @@ -245,18 +271,18 @@ const { txHash } = await gb.relay(signed); { txHash: "0xabcd...7890" } ``` -## 보장된 릴레이 트랜잭션 +## 보장 릴레이 트랜잭션 -`guaranteedWaiver` 모듈은 위 두 가지 레일을 결합합니다. 즉, 보장된 블록 공간을 통해 라우팅되는 가스 면제 트랜잭션입니다. 내부 및 외부 트랜잭션 모두 하나의 엔터프라이즈 `nonceKey`를 공유하는 `0x3F` CustomTx이므로 `guaranteedBlock`과 같이 게이트웨이를 통해 브로드캐스트됩니다. 면제가 가스를 보조하므로 사용자는 `gasWaiver`와 같이 잔액이나 수수료 필드가 필요하지 않습니다. 모든 메서드는 `H_inner`를 반환합니다. +`guaranteedWaiver` 모듈은 위 두 가지 레일을 결합합니다. 즉, 보장된 블록 공간을 통해 라우팅되는 가스 면제 트랜잭션입니다. 내부 및 외부 트랜잭션 모두 하나의 엔터프라이즈 `nonceKey`를 공유하는 `0x3F` CustomTx이므로 `guaranteedBlock`처럼 게이트웨이를 통해 브로드캐스트됩니다. 웨이버가 가스를 지원하므로 사용자는 `gasWaiver`처럼 잔액이나 수수료 필드가 필요하지 않습니다. 모든 메서드는 `H_inner`를 반환합니다. -`guaranteedWaiver`와 `enterpriseRpcEndpoints`로 활성화합니다. +`guaranteedWaiver`와 `enterpriseRpcEndpoints`를 사용하여 활성화합니다. ```ts const enterprise = createStableEnterprise({ chain: stableTestnet, enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable이 제공하는 게이트웨이 URL guaranteedWaiver: { - waiverAccount: privateKeyToAccount("0xYOUR_WAIVER_KEY"), + account: privateKeyToAccount("0xYOUR_WAIVER_KEY"), laneId: 0n, }, }); @@ -266,16 +292,17 @@ const gw = enterprise.guaranteedWaiver!; ### `GuaranteedWaiverConfig` -[`ValidationLimits`](#validationlimits)를 확장하므로 `GasWaiverConfig`와 동일한 `maxGasLimit`, `maxDataLength` 및 `allowedTargets` 정책 제어를 허용합니다. +[`ValidationLimits`](#validationlimits) 및 [`SignerSource`](#signersource)를 확장합니다. `GasWaiverConfig`와 정확히 동일하게 Outer-wrapper 웨이버 키를 소싱(`signer`, 그 다음 `account`, 그 다음 환경 변수)하고 동일한 `maxGasLimit`, `maxDataLength` 및 `allowedTargets` 정책 제어를 허용합니다. | **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `waiverAccount` | `LocalAccount` | 외부 래퍼에 서명하는 화이트리스트에 등록된 거버넌스 등록 계정입니다. | -| `laneId` | `bigint` | 엔터프라이즈 레인 ID입니다. `[0, ENTERPRISE_MASK - 1]` 범위에 있어야 합니다. | +| `signer` | `Signer?` | custody 서명자로서 화이트리스트에 등록된 웨이버 키(외부 래퍼에 서명). `account`보다 우선합니다. [서명 키 및 Custody](#signing-keys-and-custody)를 참조하세요. | +| `account` | `LocalAccount?` | 인-프로세스 viem 계정으로서의 웨이버 키입니다. 둘 다 설정되지 않은 경우 `STABLE_ENTERPRISE_PRIVATE_KEY`로 폴백합니다. | +| `laneId` | `bigint` | 엔터프라이즈 레인 ID입니다. `[0, ENTERPRISE_MASK - 1]` 범위 내에 있어야 합니다. | ### `send(user, tx)` / `sendBatch(user, txs)` -`user`로부터 내부 `0x3F` CustomTx를 빌드하고 서명한 다음, 면제 키로 래핑하고 릴레이합니다. 가스가 면제되므로 수수료 필드는 필요하지 않습니다. 내부 2D 논스는 게이트웨이에서 검색되며, 배치는 해당 기본값에서 자동으로 시퀀스됩니다. +`user`에서 내부 `0x3F` CustomTx를 빌드 및 서명하고, 웨이버 키로 래핑하여 릴레이합니다. 가스가 면제되므로 수수료 필드는 필요하지 않습니다. 내부 2D nonce는 게이트웨이에서 발견되며, 배치는 해당 기본값에서 자동으로 순서가 지정됩니다. ```ts // 단일 @@ -289,24 +316,24 @@ const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); { txHash: "0x8f3a...2d41" } ``` -`tx` 인수는 선택적 `nonce`가 추가된 [`GuaranteedWaiverTxRequest`](#guaranteedwaivertxrequest)입니다. `send`는 [`RelayResult`](#relayresult)를 반환하고, `sendBatch`는 [`BatchResultItem[]`](#batchresultitem)을 반환합니다. +`tx` 인수는 선택적 `nonce`가 추가된 [`GuaranteedWaiverTxRequest`](#guaranteedwaivertxrequest)입니다. `send`는 [`RelayResult`](#relayresult)를 반환하고, `sendBatch`는 [`BatchResultItem[]`](#batchresultitem)를 반환합니다. ### `relay(signedInnerTx)` / `relayBatch(signedInnerTxs)` -비보관 흐름의 경우, 사용자는 [`buildGuaranteedTx`](#buildguaranteedtxaccount-chainid-req)로 내부 `0x3F` CustomTx에 서명(수수료 `0n`, `nonceKeyForLane(laneId)` 사용)하고 서명된 헥스만 운영자에게 전달합니다. 운영자는 면제 키로 래핑하고 릴레이합니다. +비 custody 흐름의 경우, 사용자는 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req) (수수료 `0n`, `nonceKeyForLane(laneId)` 사용)로 내부 `0x3F` CustomTx에 서명하고 운영자에게 서명된 헥스만 전달합니다. 운영자는 웨이버 키로 래핑하고 릴레이합니다. ```ts -import { buildGuaranteedTx, nonceKeyForLane } from "@stablechain/enterprise"; +import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; -const signedInner = await buildGuaranteedTx(user, stableTestnet.id, { +const signedInner = await buildGuaranteedTx(toSigner(user), stableTestnet.id, { to, gas: 100_000n, - gasFeeCap: 0n, // 면제됨 + gasFeeCap: 0n, // 면제 gasTipCap: 0n, nonce, nonceKey: nonceKeyForLane(0n), }); -const { txHash } = await gw.relay(signedInner); // 면제 래핑 + 브로드캐스트 → H_inner +const { txHash } = await gw.relay(signedInner); // 웨이버는 래핑 + 브로드캐스트 → H_inner ``` ```text @@ -315,27 +342,27 @@ const { txHash } = await gw.relay(signedInner); // 면제 래핑 + 브로드캐 ## 빌드 헬퍼 -비보관 `relay` 경로에 대한 저수준 서명자입니다. 각각은 논스 가져오기 또는 수수료 예측 없이 서명된 트랜잭션을 `Hex`로 반환합니다. +비 custody `relay` 경로를 위한 하위 수준 서명자입니다. 각각 서명된 트랜잭션을 `Hex`로 반환하며, nonce 가져오기 또는 수수료 추정은 없습니다. 첫 번째 인수는 [`Signer`](#signing-keys-and-custody)입니다. `toSigner(account)`로 viem 계정을 래핑하거나 `awsKmsSigner`와 같은 custody 서명자를 전달합니다. -### `buildWaiverInnerTx(account, chainId, req)` +### `buildWaiverInnerTx(signer, chainId, req)` -`gasPrice: 0`, 레거시 유형, 지정된 `chainId`가 포함된 면제 가능 InnerTx에 서명합니다. `req`는 필수 `nonce`와 함께 [`WaiverInnerTx`](#waiverinnertx)입니다. +웨이버 고정값(`gasPrice: 0`, 레거시 유형 및 지정된 `chainId`)이 포함된 웨이버 준비 InnerTx에 서명합니다. `req`는 필수 `nonce`가 추가된 [`WaiverInnerTx`](#waiverinnertx)입니다. ```ts -const signed = await buildWaiverInnerTx(user, stableTestnet.id, { to, data, gas: 150_000n, nonce }); +const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to, data, gas: 150_000n, nonce }); ``` -### `buildGuaranteedTx(account, chainId, req)` +### `buildGuaranteedTx(signer, chainId, req)` -GuaranteedTx(`0x3F` CustomTx)를 빌드하고 서명합니다. `req`는 필수 `nonce`와 `nonceKey`와 함께 [`GuaranteedTxRequest`](#guaranteedtxrequest)입니다. +GuaranteedTx(`0x3F` CustomTx)를 빌드하고 서명합니다. `req`는 필수 `nonce` 및 `nonceKey`가 추가된 [`GuaranteedTxRequest`](#guaranteedtxrequest)입니다. ### `buildGuaranteedWaiverTx(...)` -미리 서명된 내부 트랜잭션을 외부 `0x3F` 면제 CustomTx로 래핑합니다. `guaranteedWaiver.relay`에서 내부적으로 사용됩니다. 고급 흐름을 위해 내보내집니다. +미리 서명된 내부 트랜잭션을 외부 `0x3F` 웨이버 CustomTx로 래핑합니다. `guaranteedWaiver.relay`에서 내부적으로 사용됩니다. 고급 흐름을 위해 내보내집니다. ### `nonceKeyForLane(laneId)` -`buildGuaranteedTx`에서 사용할 레인 ID에 대한 엔터프라이즈 `nonceKey`를 반환합니다. +`buildGuaranteedTx`에서 사용하기 위한 레인 ID의 엔터프라이즈 `nonceKey`를 반환합니다. ```ts import { nonceKeyForLane } from "@stablechain/enterprise"; @@ -345,27 +372,54 @@ const nonceKey = nonceKeyForLane(0n); ## 유형 +### `SignerSource` + +웨이버 모듈(`gasWaiver`, `guaranteedWaiver`)이 수락하는 서명 키 필드입니다. `signer`, 그 다음 `account`, 그 다음 `STABLE_ENTERPRISE_PRIVATE_KEY` 환경 변수 순으로 해결됩니다. [서명 키 및 Custody](#signing-keys-and-custody)를 참조하세요. + +| **필드** | **유형** | **설명** | +| :--- | :--- | :--- | +| `signer` | `Signer?` | custody 등급 서명자(AWS KMS, HSM 또는 `privateKeySigner`). `account`보다 우선합니다. | +| `account` | `LocalAccount?` | `toSigner`를 통해 `Signer`로 적용된 인-프로세스 viem 계정입니다. | + +### `Signer` + +SDK가 32바이트 다이제스트를 통해 서명하는 플러그인 가능한 서명자이므로 키는 custody 백엔드를 벗어나지 않습니다. `awsKmsSigner`, `toSigner`, `privateKeySigner` 또는 `envSigner`로 생성합니다. + +```ts +interface Signer { + readonly address: Address; + signDigest(hash: Hex): Promise; +} +``` + +| **헬퍼** | **가져오기** | **설명** | +| :--- | :--- | :--- | +| `awsKmsSigner({ keyId, client? })` | `@stablechain/enterprise/aws-kms` | AWS KMS `ECC_SECG_P256K1` 키가 지원하는 서명자입니다. `Promise`를 반환합니다. | +| `toSigner(account)` | `@stablechain/enterprise` | viem `LocalAccount`를 `Signer`에 적용합니다. | +| `privateKeySigner(key)` | `@stablechain/enterprise` | 프로세스에 보관된 원시 개인 키를 래핑하는 서명자입니다. | +| `envSigner(varName?)` | `@stablechain/enterprise` | `STABLE_ENTERPRISE_PRIVATE_KEY` (또는 `varName`)에서 키를 읽는 서명자입니다. | + ### `WaiverInnerTx` -호출당 달라지는 InnerTx의 필드입니다. +호출당 변동하는 InnerTx의 필드입니다. | **필드** | **유형** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `to` | `Address` | | 대상 주소: ERC-20 전송의 경우 토큰 계약, 네이티브 전송의 경우 수신자. | -| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | 가스 한도. `gasPrice`가 0이므로 관대한 한도는 무료입니다. | -| `data` | `Hex?` | `"0x"` | 콜데이터. | -| `value` | `bigint?` | `0n` | 전송할 네이티브 값. | +| `to` | `Address` | | 대상 주소: ERC-20 전송을 위한 토큰 계약, 네이티브 전송을 위한 수신자입니다. | +| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | 가스 한도입니다. `gasPrice`가 0이므로 관대한 한도는 무료입니다. | +| `data` | `Hex?` | `"0x"` | Calldata입니다. | +| `value` | `bigint?` | `0n` | 전송할 네이티브 값입니다. | ### `GuaranteedTxRequest` | **필드** | **유형** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `to` | `Address?` | | 대상 주소. | -| `gas` | `bigint` | | 가스 한도. 필수. | -| `gasFeeCap` | `bigint` | | `maxFeePerGas`. 필수. | -| `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`. 필수. | -| `data` | `Hex?` | `"0x"` | 콜데이터. | -| `value` | `bigint?` | `0n` | 전송할 네이티브 값. | +| `to` | `Address?` | | 대상 주소입니다. | +| `gas` | `bigint` | | 가스 한도입니다. 필수입니다. | +| `gasFeeCap` | `bigint` | | `maxFeePerGas`입니다. 필수입니다. | +| `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`입니다. 필수입니다. | +| `data` | `Hex?` | `"0x"` | Calldata입니다. | +| `value` | `bigint?` | `0n` | 전송할 네이티브 값입니다. | ### `GuaranteedWaiverTxRequest` @@ -373,10 +427,10 @@ const nonceKey = nonceKeyForLane(0n); | **필드** | **유형** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `to` | `Address` | | 대상 주소. | -| `gas` | `bigint?` | 공유 내부 가스 기본값 | 가스 한도. | -| `data` | `Hex?` | `"0x"` | 콜데이터. | -| `value` | `bigint?` | `0n` | 전송할 네이티브 값. 면제는 값 전송을 허용합니다. | +| `to` | `Address` | | 대상 주소입니다. | +| `gas` | `bigint?` | 공유 내부 가스 기본값 | 가스 한도입니다. | +| `data` | `Hex?` | `"0x"` | Calldata입니다. | +| `value` | `bigint?` | `0n` | 전송할 네이티브 값입니다. 웨이버의 경우 값 전송이 허용됩니다. | ### `ValidationLimits` @@ -384,43 +438,43 @@ const nonceKey = nonceKeyForLane(0n); | **필드** | **유형** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `maxGasLimit` | `bigint?` | `10_000_000n` | InnerTx의 최대 가스 한도. 초과하면 `GAS_LIMIT_EXCEEDED` 오류가 발생합니다. | -| `maxDataLength` | `number?` | `131_072` (128KB) | 바이트 단위로 된 최대 콜데이터 크기. 초과하면 `DATA_TOO_LARGE` 오류가 발생합니다. | -| `allowedTargets` | `AllowedTarget[]?` | | 면제를 후원할 수 있는 계약 및 메서드의 허용 목록. 설정된 경우 목록 외의 대상은 `TARGET_NOT_ALLOWED` 오류가 발생합니다. | +| `maxGasLimit` | `bigint?` | `10_000_000n` | InnerTx의 최대 가스 한도입니다. 초과하면 `GAS_LIMIT_EXCEEDED`와 함께 실패합니다. | +| `maxDataLength` | `number?` | `131_072` (128KB) | 바이트 단위의 최대 calldata 크기입니다. 초과하면 `DATA_TOO_LARGE`와 함께 실패합니다. | +| `allowedTargets` | `AllowedTarget[]?` | | 웨이버가 후원할 수 있는 허용된 계약 및 메서드의 화이트리스트입니다. 설정된 경우 목록 외부의 대상은 `TARGET_NOT_ALLOWED`와 함께 실패합니다. | ### `AllowedTarget` | **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `address` | `Address \| "*"` | InnerTx가 호출할 수 있는 계약, 또는 `"*"`는 모든 계약과 일치합니다. | -| `selectors` | `Hex[]?` | 허용되는 4바이트 메서드 선택자(예: ERC-20 `transfer`의 경우 `"0xa9059cbb"`). `address`에서 모든 메서드를 허용하려면 생략하거나 비워 둡니다. | +| `address` | `Address \| "*"` | InnerTx가 호출할 수 있는 계약 또는 모든 계약과 일치하는 `"*"`입니다. | +| `selectors` | `Hex[]?` | 허용된 4바이트 메서드 선택기 (예: ERC-20 `transfer`의 `"0xa9059cbb"`). `address`의 모든 메서드를 허용하려면 생략하거나 비워 둡니다. | ### `RelayResult` ```ts interface RelayResult { - txHash: Hash; // 면제의 경우 H_inner, 독립형 보장된 블록의 경우 GuaranteedTx 해시 + txHash: Hash; // 웨이버의 경우 H_inner, 독립형 보장 블록의 경우 GuaranteedTx 해시 } ``` ### `BatchResultItem` -배치 내의 입력당 하나의 항목으로 입력 순서대로 정렬됩니다. 발생시키는 대신, 배치는 항목별 결과를 보여줍니다. +배치의 입력당 하나씩, 입력 순서대로 항목입니다. 단일 결과로 반환되는 경우 발생하는 대신, 일괄 처리된 결과는 각 항목별 결과를 표시합니다. | **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `index` | `number` | 입력 배열과 일치하는 0부터 시작하는 위치. | -| `success` | `boolean` | 이 항목이 릴레이되었는지 여부. | -| `txHash` | `Hash?` | 성공 시 존재: 내부 트랜잭션 해시. | -| `error` | `{ code: ErrorCode; message: string }?` | 실패 시 존재. | +| `index` | `number` | 입력 배열과 일치하는 0부터 시작하는 위치입니다. | +| `success` | `boolean` | 이 항목이 릴레이되었는지 여부입니다. | +| `txHash` | `Hash?` | 성공 시 존재: 내부 트랜잭션 해시입니다. | +| `error` | `{ code: ErrorCode; message: string }?` | 실패 시 존재합니다. | ## 오류 -단일 트랜잭션 메서드(`send`, `relay`)는 거부 시 발생합니다. 배치 메서드는 대신 [`BatchResultItem.error`](#batchresultitem)에서 항목별 실패를 보고합니다. 모든 오류 클래스는 `StableEnterpriseError`를 확장합니다. +단일 트랜잭션 메서드(`send`, `relay`)는 거부 시 오류를 발생시킵니다. 일괄 처리 메서드는 대신 [`BatchResultItem.error`](#batchresultitem)에서 항목당 실패를 보고합니다. 모든 오류 클래스는 `StableEnterpriseError`를 확장합니다. -| **클래스** | **발생 시점** | **유용한 필드** | +| **클래스** | **오류 발생 시** | **유용한 필드** | | :--- | :--- | :--- | -| `StableEnterpriseError` | 모든 SDK 오류의 기본 클래스. | `message` | +| `StableEnterpriseError` | 모든 SDK 오류의 기본 클래스입니다. | `message` | | `StableEnterpriseRelayError` | RPC 또는 릴레이 계층에서 트랜잭션이 거부됩니다. | `code` | | `WaiverValidationError` | InnerTx가 브로드캐스트 전에 정책 검사(가스, 데이터 크기 또는 대상 허용 목록)에 실패합니다. | `code` | @@ -443,33 +497,33 @@ StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not ### `ErrorCode` -발생된 오류 또는 `BatchResultItem.error`의 `code`는 다음 중 하나입니다. +발생한 오류 또는 `BatchResultItem.error`의 `code`는 다음 중 하나입니다. | **코드** | **의미** | | :--- | :--- | -| `UNKNOWN_ERROR` | 특정 코드를 사용할 수 없을 때의 대체. | +| `UNKNOWN_ERROR` | 특정 코드를 사용할 수 없는 경우의 폴백입니다. | | `BROADCAST_FAILED` | RPC 계층에서 브로드캐스트가 거부되거나 게이트웨이가 릴레이에 실패했습니다. | -| `INVALID_TRANSACTION` | InnerTx 디코딩 또는 구문 분석에 실패했습니다. | +| `INVALID_TRANSACTION` | InnerTx가 디코딩 또는 파싱에 실패했습니다. | | `INVALID_SIGNATURE` | 서명 확인에 실패했습니다. | | `UNSUPPORTED_TX_TYPE` | InnerTx 유형이 레거시, eip2930 또는 eip1559가 아닙니다. | | `WRONG_CHAIN_ID` | InnerTx `chainId`가 누락되었거나 대상 체인과 일치하지 않습니다. | -| `NON_ZERO_GAS_PRICE` | InnerTx에 0이 아닌 가스 가격이 포함되어 있습니다(면제의 경우 0이어야 합니다). | -| `GAS_LIMIT_EXCEEDED` | InnerTx 가스 한도가 `maxGasLimit`을 초과합니다. | -| `DATA_TOO_LARGE` | InnerTx 콜데이터가 `maxDataLength`를 초과합니다. | +| `NON_ZERO_GAS_PRICE` | InnerTx가 0이 아닌 가스 가격을 가지고 있습니다(웨이버의 경우 0이어야 함). | +| `GAS_LIMIT_EXCEEDED` | InnerTx 가스 한도가 `maxGasLimit`을 초과했습니다. | +| `DATA_TOO_LARGE` | InnerTx calldata가 `maxDataLength`를 초과했습니다. | | `TARGET_NOT_ALLOWED` | InnerTx 대상이 `allowedTargets`에 없습니다. | | `GATEWAY_UNAUTHORIZED` | 엔터프라이즈 RPC 게이트웨이가 API 키를 거부했습니다(누락, 유효하지 않거나 만료됨). | -| `QUOTA_EXCEEDED` | 엔터프라이즈 RPC 게이트웨이 가스 할당량이 초과되었습니다. | +| `QUOTA_EXCEEDED` | 엔터프라이즈 RPC 게이트웨이 가스 할당량이 소진되었습니다. | ## 상수 | **상수** | **유형** | **설명** | | :--- | :--- | :--- | -| `DEFAULT_INNER_GAS` | `bigint` | `gas`가 생략될 때의 기본 InnerTx 가스 한도(`150_000n`). | +| `DEFAULT_INNER_GAS` | `bigint` | `gas`가 생략된 경우 기본 InnerTx 가스 한도(`150_000n`)입니다. | | `ENTERPRISE_FLAG` | `bigint` | 레인의 `nonceKey`에 설정된 엔터프라이즈 비트입니다. | -| `ENTERPRISE_MASK` | `bigint` | 레인 ID의 상한: `laneId`는 `[0, ENTERPRISE_MASK - 1]` 범위에 있어야 합니다. | +| `ENTERPRISE_MASK` | `bigint` | 레인 ID의 상한입니다: `laneId`는 `[0, ENTERPRISE_MASK - 1]` 범위 내에 있어야 합니다. | -## 다음으로 권장되는 항목 +## 다음 권장 사항 - [**Stable Enterprise SDK**](/ko/explanation/enterprise-sdk): 레일이 무엇이고 언제 사용해야 하는지. -- [**가스 면제 프로토콜**](/ko/reference/gas-waiver-api): 트랜잭션 형식, 마커 라우팅 및 거버넌스 제어. -- [**보장된 블록 공간**](/ko/explanation/guaranteed-blockspace): Stable이 엔터프라이즈 워크로드에 대해 블록 용량을 예약하는 방법. +- [**가스 웨이버 프로토콜**](/ko/reference/gas-waiver-api): 트랜잭션 형식, 마커 라우팅 및 거버넌스 제어. +- [**보장 블록 공간**](/ko/explanation/guaranteed-blockspace): Stable이 엔터프라이즈 워크로드에 대한 블록 용량을 예약하는 방법. diff --git a/docs/sidebar.json b/docs/sidebar.json index 489c5d1..f610006 100644 --- a/docs/sidebar.json +++ b/docs/sidebar.json @@ -689,7 +689,7 @@ ], "/ko": [ { - "text": "학습", + "text": "학습하기", "collapsed": true, "items": [ { @@ -759,7 +759,7 @@ "link": "/ko/explanation/usdt0-bridging" }, { - "text": "브릿지 보안", + "text": "브리지 보안", "link": "/ko/explanation/bridge-security" }, { @@ -775,7 +775,7 @@ "link": "/ko/explanation/gas-waiver" }, { - "text": "보장된 블록 공간", + "text": "블록 공간 보장", "link": "/ko/explanation/guaranteed-blockspace" }, { @@ -819,7 +819,7 @@ ] }, { - "text": "사용 사례 내러티브", + "text": "사용 사례 설명", "collapsed": true, "items": [ { @@ -831,7 +831,7 @@ "link": "/ko/explanation/use-case-payroll" }, { - "text": "사용 사례: 스폰서", + "text": "사용 사례: 후원", "link": "/ko/explanation/use-case-sponsored" }, { @@ -841,7 +841,7 @@ ] }, { - "text": "토크노믹스", + "text": "토큰 경제학", "link": "/ko/reference/tokenomics" }, { @@ -855,7 +855,7 @@ ] }, { - "text": "구축", + "text": "구축하기", "collapsed": true, "items": [ { @@ -897,7 +897,7 @@ ] }, { - "text": "엔터프라이즈 SDK", + "text": "Enterprise SDK", "collapsed": true, "items": [ { @@ -909,7 +909,7 @@ "link": "/ko/how-to/relay-with-gas-waiver" }, { - "text": "보장된 블록 공간", + "text": "블록 공간 보장", "link": "/ko/how-to/send-guaranteed-transactions" }, { @@ -969,7 +969,7 @@ "link": "/ko/tutorial/send-usdt0" }, { - "text": "수수료 없는 트랜잭션", + "text": "가스 없는 트랜잭션", "link": "/ko/how-to/zero-gas-transactions" }, { @@ -977,7 +977,7 @@ "link": "/ko/how-to/work-with-usdt-gas" }, { - "text": "USDT0 브릿지", + "text": "USDT0 브리지", "link": "/ko/tutorial/bridge-usdt0" } ] @@ -1029,7 +1029,7 @@ "link": "/ko/reference/pay-per-call" }, { - "text": "예정된 사용 사례", + "text": "향후 사용 사례", "link": "/ko/explanation/upcoming-use-cases" } ] @@ -1049,7 +1049,7 @@ "link": "/ko/explanation/contracts-guides" }, { - "text": "첫 번째 계약 배포하기", + "text": "첫 번째 계약 배포", "collapsed": true, "items": [ { @@ -1057,11 +1057,11 @@ "link": "/ko/tutorial/smart-contract" }, { - "text": "계약 확인", + "text": "계약 검증", "link": "/ko/how-to/verify-contract" }, { - "text": "계약 인덱싱", + "text": "계약 색인", "link": "/ko/how-to/index-contract" } ] @@ -1115,11 +1115,11 @@ "link": "/ko/reference/system-transactions-api" }, { - "text": "언바운딩 추적", + "text": "언본딩 추적", "link": "/ko/how-to/track-unbonding" }, { - "text": "검증자 데이터 인덱싱", + "text": "검증자 데이터 색인", "link": "/ko/how-to/index-validator-data" } ] @@ -1133,7 +1133,7 @@ ] }, { - "text": "통합", + "text": "통합하기", "collapsed": true, "items": [ { @@ -1213,7 +1213,7 @@ "collapsed": true, "items": [ { - "text": "브릿지", + "text": "브리지", "link": "/ko/reference/bridges" }, { @@ -1241,7 +1241,7 @@ "link": "/ko/reference/wallets" }, { - "text": "수탁", + "text": "수호", "link": "/ko/reference/custody" }, { @@ -1251,7 +1251,7 @@ ] }, { - "text": "운영 준비", + "text": "프로덕션 준비도", "link": "/ko/how-to/production-readiness" }, { @@ -1271,7 +1271,7 @@ ] }, { - "text": "운영", + "text": "운영하기", "collapsed": true, "items": [ { @@ -1279,7 +1279,7 @@ "link": "/ko/reference/node-operations-overview" }, { - "text": "노드 시스템 요구사항", + "text": "노드 시스템 요구 사항", "link": "/ko/reference/node-system-requirements" }, { @@ -1325,11 +1325,11 @@ "link": "/ko/explanation/ai-agents-guides" }, { - "text": "x402 및 MPP를 통한 지불", + "text": "x402 및 MPP를 통해 지불", "collapsed": true, "items": [ { - "text": "X402", + "text": "x402", "link": "/ko/explanation/x402" }, { @@ -1359,7 +1359,7 @@ "collapsed": true, "items": [ { - "text": "AI로 개발", + "text": "AI 개발", "link": "/ko/how-to/develop-with-ai" }, { @@ -1401,11 +1401,11 @@ "link": "/cn/explanation/core-concepts" }, { - "text": "主要功能", + "text": "主要特点", "link": "/cn/explanation/key-features" }, { - "text": "以太坊对比", + "text": "以太坊比较", "link": "/cn/explanation/ethereum-comparison" }, { @@ -1413,7 +1413,7 @@ "link": "/cn/explanation/ethereum-compatibility" }, { - "text": "终结性", + "text": "最终性", "link": "/cn/explanation/finality" }, { @@ -1447,7 +1447,7 @@ "link": "/cn/explanation/usdt0-bridging" }, { - "text": "桥安全性", + "text": "跨链桥安全性", "link": "/cn/explanation/bridge-security" }, { @@ -1471,7 +1471,7 @@ "link": "/cn/explanation/usdt-transfer-aggregator" }, { - "text": "隐私转账", + "text": "保密转账", "link": "/cn/explanation/confidential-transfer" } ] @@ -1511,19 +1511,19 @@ "collapsed": true, "items": [ { - "text": "用例:支付", + "text": "支付用例", "link": "/cn/explanation/use-case-payments" }, { - "text": "用例:薪资", + "text": "薪资用例", "link": "/cn/explanation/use-case-payroll" }, { - "text": "用例:赞助", + "text": "赞助用例", "link": "/cn/explanation/use-case-sponsored" }, { - "text": "用例:隐私", + "text": "隐私用例", "link": "/cn/explanation/use-case-private" } ] @@ -1551,7 +1551,7 @@ "link": "/cn/explanation/build-overview" }, { - "text": "快速入门", + "text": "快速开始", "link": "/cn/tutorial/quick-start" }, { @@ -1601,7 +1601,7 @@ "link": "/cn/how-to/send-guaranteed-transactions" }, { - "text": "保证中继交易", + "text": "保障中继交易", "link": "/cn/how-to/guaranteed-relayed-transactions" }, { @@ -1683,7 +1683,7 @@ "link": "/cn/how-to/subscribe-and-collect" }, { - "text": "通过发票支付", + "text": "发票支付", "link": "/cn/how-to/pay-with-invoice" } ] @@ -1725,7 +1725,7 @@ ] }, { - "text": "部署合约", + "text": "交付合约", "collapsed": true, "items": [ { @@ -1803,7 +1803,7 @@ "link": "/cn/reference/system-transactions-api" }, { - "text": "跟踪解绑", + "text": "跟踪解除绑定", "link": "/cn/how-to/track-unbonding" }, { @@ -1901,7 +1901,7 @@ "collapsed": true, "items": [ { - "text": "桥", + "text": "跨链桥", "link": "/cn/reference/bridges" }, { @@ -1921,7 +1921,7 @@ "link": "/cn/reference/network-routing" }, { - "text": "出入金", + "text": "法币通道", "link": "/cn/reference/ramps" }, { @@ -2013,7 +2013,7 @@ "link": "/cn/explanation/ai-agents-guides" }, { - "text": "通过 x402 和 MPP 付款", + "text": "通过 x402 和 MPP 支付", "collapsed": true, "items": [ { @@ -2037,7 +2037,7 @@ "link": "/cn/how-to/build-mpp-endpoint" }, { - "text": "使用 MCP 付款", + "text": "使用 MCP 支付", "link": "/cn/how-to/pay-with-mcp" } ] @@ -2047,15 +2047,15 @@ "collapsed": true, "items": [ { - "text": "使用 AI 进行开发", + "text": "与 AI 协同开发", "link": "/cn/how-to/develop-with-ai" }, { - "text": "代理协调器", + "text": "智能协调器", "link": "/cn/reference/agentic-facilitators" }, { - "text": "代理钱包", + "text": "智能钱包", "link": "/cn/reference/agentic-wallets" } ] From 18a6bf11337f8a4266b4add56c83374d945190f7 Mon Sep 17 00:00:00 2001 From: bastienrp Date: Thu, 16 Jul 2026 10:01:55 +0200 Subject: [PATCH 14/20] docs: reflect top-level default signer for the Enterprise SDK SDK main #43 (DR-197) wires one signer through the factory: add the top-level `signer` config field (default for the waiver modules), update the key-resolution order to include it, and note that send/sendBatch now accept a Signer or a viem account. Co-Authored-By: Claude Opus 4.8 --- docs/pages/en/reference/enterprise-sdk.mdx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/pages/en/reference/enterprise-sdk.mdx b/docs/pages/en/reference/enterprise-sdk.mdx index 1415ca3..4f3e893 100644 --- a/docs/pages/en/reference/enterprise-sdk.mdx +++ b/docs/pages/en/reference/enterprise-sdk.mdx @@ -54,15 +54,16 @@ StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver | `rpcEndpoints` | `string[]?` | Chain's built-in RPC | One or more Stable RPC endpoints, tried in order on failure. Override only to point at a private endpoint. | | `enterpriseRpcEndpoints` | `string[]?` | | One or more Enterprise RPC gateway endpoints, tried in order on failure. Required for `guaranteedBlock` and `guaranteedWaiver`. | | `batchSizeLimit` | `number?` | `100` | Maximum transactions per batched RPC call. | +| `signer` | `Signer?` | | Default signer for the waiver modules (`gasWaiver`, `guaranteedWaiver`) when a module has no key of its own. Set it once to drive both from a single custody backend. See [Signing keys and custody](#signing-keys-and-custody). | | `gasWaiver` | `GasWaiverConfig?` | | Enable [relay with gas waiver](#relay-with-gas-waiver). | | `guaranteedBlock` | `GuaranteedBlockConfig?` | | Enable [guaranteed blockspace](#guaranteed-blockspace). | | `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | Enable [guaranteed relay transactions](#guaranteed-relay-transactions). | ### Signing keys and custody -The modules that hold the waiver key (`gasWaiver` and `guaranteedWaiver`) resolve it from a [`SignerSource`](#signersource), in order: `signer` (a custody-grade backend), then `account` (an in-process viem key), then the `STABLE_ENTERPRISE_PRIVATE_KEY` environment variable. `guaranteedBlock` takes a funded `account` directly. +The modules that hold the waiver key (`gasWaiver` and `guaranteedWaiver`) resolve it in order: the module's own `signer`, then its `account` (an in-process viem key), then the top-level [`signer`](#stableenterpriseconfig) on the client config, then the `STABLE_ENTERPRISE_PRIVATE_KEY` environment variable. Set the top-level `signer` once to drive both waiver modules from a single custody backend. `guaranteedBlock` signs with its own funded `account`. -A `Signer` signs a 32-byte digest, so the key never leaves the custody backend. Use `awsKmsSigner` for AWS KMS, `toSigner(account)` to adapt a viem account, or `privateKeySigner(key)` / `envSigner()` for an in-process key. +A `Signer` signs a 32-byte digest, so the key never leaves the custody backend. Use `awsKmsSigner` for AWS KMS, `toSigner(account)` to adapt a viem account, or `privateKeySigner(key)` / `envSigner()` for an in-process key. The per-call sender passed to a module's `send` / `sendBatch` may likewise be a viem account or a `Signer`, so a KMS/HSM key can sign inner transactions without dropping to `relay`. ```bash npm install @aws-sdk/client-kms @@ -372,7 +373,7 @@ const nonceKey = nonceKeyForLane(0n); ### `SignerSource` -The signing-key fields a waiver module (`gasWaiver`, `guaranteedWaiver`) accepts. Resolved in order: `signer`, then `account`, then the `STABLE_ENTERPRISE_PRIVATE_KEY` env var. See [Signing keys and custody](#signing-keys-and-custody). +The signing-key fields a waiver module (`gasWaiver`, `guaranteedWaiver`) accepts. Resolved in order: `signer`, then `account`, then the client's top-level [`signer`](#stableenterpriseconfig), then the `STABLE_ENTERPRISE_PRIVATE_KEY` env var. See [Signing keys and custody](#signing-keys-and-custody). | **Field** | **Type** | **Description** | | :--- | :--- | :--- | From 11941a7a06d86268088797cfaf530b305f4ad4db Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 16 Jul 2026 08:03:46 +0000 Subject: [PATCH 15/20] i18n: auto-translate cn/ko for changed en content --- docs/pages/cn/reference/enterprise-sdk.mdx | 175 ++++++++-------- docs/pages/ko/reference/enterprise-sdk.mdx | 227 +++++++++++---------- docs/sidebar.json | 116 +++++------ 3 files changed, 260 insertions(+), 258 deletions(-) diff --git a/docs/pages/cn/reference/enterprise-sdk.mdx b/docs/pages/cn/reference/enterprise-sdk.mdx index 4434ed9..2d2ecae 100644 --- a/docs/pages/cn/reference/enterprise-sdk.mdx +++ b/docs/pages/cn/reference/enterprise-sdk.mdx @@ -1,21 +1,21 @@ --- source_path: reference/enterprise-sdk.mdx -source_sha: 1415ca3965bbd2c7d362a8e86a728c3a9e6269a7 +source_sha: 4f3e8931e52daf98a9dc5de5921fc734d4284dfb title: "企业级 SDK 参考" -description: "@stablechain/enterprise 的完整参考:createStableEnterprise,燃气费豁免和保证区块空间模块,构建帮助器和错误类。" +description: "@stablechain/enterprise 的完整参考:createStableEnterprise、免燃料费和保证区块空间模块、构建助手以及错误类。" diataxis: "reference" --- # 企业级 SDK 参考 -`@stablechain/enterprise` 的完整细节。这包括客户端 [`createStableEnterprise`](#createstableenterpriseconfig) 及其三个功能([燃气费豁免中继](#relay-with-gas-waiver)、[保证区块空间](#guaranteed-blockspace)和[保证中继交易](#guaranteed-relay-transactions)),低级构建帮助程序以及共享结果和错误类型。有关这些通道的详细信息,请参阅 [Stable 企业级 SDK](/cn/explanation/enterprise-sdk)、[燃气费豁免](/cn/explanation/gas-waiver)和 [保证区块空间](/cn/explanation/guaranteed-blockspace)。 +`@stablechain/enterprise` 的完整界面。这涵盖了客户端从 [`createStableEnterprise`](#createstableenterpriseconfig) 到其三个功能([免燃料费中继](#relay-with-gas-waiver)、[保证区块空间](#guaranteed-blockspace)和[保证中继交易](#guaranteed-relay-transactions))、低级构建助手以及共享的结果和错误类型。有关这些概念的详细信息,请参阅[Stable 企业级 SDK](/cn/explanation/enterprise-sdk)、[免燃料费](/cn/explanation/gas-waiver)和[保证区块空间](/cn/explanation/guaranteed-blockspace)。 :::note -企业级 SDK 目前仅在 Stable 测试网上可用,并且需要申请才能访问。要进行集成,请[联系 Stable](https://discord.gg/stablexyz) 以获取治理注册的豁免密钥和企业级 RPC 网关 API 密钥。 +企业级 SDK 目前仅在 Stable 测试网上提供,并且需要申请才能访问。要进行集成,请[联系 Stable](https://discord.gg/stablexyz) 以获取治理注册的豁免密钥和企业级 RPC 网关 API 密钥。 ::: :::warning -这是一个使用私钥进行签名的服务器端库。切勿在浏览器中运行。将豁免密钥和企业级 RPC 网关 URL 保存在您的后端。 +这是一个需要使用私钥签名的服务器端库。切勿在浏览器中运行它。请将豁免密钥和企业级 RPC 网关 URL 保存在您的后端。 ::: ## 安装 @@ -28,11 +28,11 @@ npm install @stablechain/enterprise viem added 2 packages, audited 3 packages in 2s ``` -`viem >= 2.0.0` 是一个对等依赖项。该软件包重新导出来自 `viem/chains` 的 `stable` 和 `stableTestnet`,因此您无需单独导入它们。 +`viem >= 2.0.0` 是一个对等依赖项。该软件包重新导出了 `viem/chains` 中的 `stable` 和 `stableTestnet`,因此您无需单独导入它们。 ## `createStableEnterprise(config)` -构造一个 `StableEnterpriseClient`。每个模块仅在您配置它时才存在,因此在使用前请使用 `!` 或空检查进行防护。 +构造一个 `StableEnterpriseClient`。每个模块仅在您配置它时才存在,因此在使用前请使用 `!` 或空值检查进行保护。 ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -52,19 +52,20 @@ StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | -| `chain` | `StableChain` | | 目标链。传递 `stable` 或 `stableTestnet`(由包重新导出)。必填项。 | -| `rpcEndpoints` | `string[]?` | 链的内置 RPC | 一个或多个 Stable RPC 端点,在失败时按顺序尝试。仅在指向私有端点时覆盖。 | -| `enterpriseRpcEndpoints` | `string[]?` | | 一个或多个企业级 RPC 网关端点,在失败时按顺序尝试。`guaranteedBlock` 和 `guaranteedWaiver` 必填。 | -| `batchSizeLimit` | `number?` | `100` | 每个批处理 RPC 调用的最大交易数量。 | -| `gasWaiver` | `GasWaiverConfig?` | | 启用[燃气费豁免中继](#relay-with-gas-waiver)。 | +| `chain` | `StableChain` | | 目标链。传入 `stable` 或 `stableTestnet`(由软件包重新导出)。必需。 | +| `rpcEndpoints` | `string[]?` | 链的内置 RPC | 一个或多个 Stable RPC 端点,失败时按顺序尝试。仅在指向私有端点时才覆盖。 | +| `enterpriseRpcEndpoints` | `string[]?` | | 一个或多个企业级 RPC 网关端点,失败时按顺序尝试。`guaranteedBlock` 和 `guaranteedWaiver` 必需。 | +| `batchSizeLimit` | `number?` | `100` | 每个批处理 RPC 调用允许的最大交易数量。 | +| `signer` | `Signer?` | | 豁免模块(`gasWaiver`,`guaranteedWaiver`)的默认签名者,当模块没有自己的密钥时。设置一次以从单个托管后端驱动两者。请参阅[签名密钥和托管](#signing-keys-and-custody)。 | +| `gasWaiver` | `GasWaiverConfig?` | | 启用[免燃料费中继](#relay-with-gas-waiver)。 | | `guaranteedBlock` | `GuaranteedBlockConfig?` | | 启用[保证区块空间](#guaranteed-blockspace)。 | | `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | 启用[保证中继交易](#guaranteed-relay-transactions)。 | ### 签名密钥和托管 -豁免密钥持有模块(`gasWaiver` 和 `guaranteedWaiver`)从 [`SignerSource`](#signersource) 按顺序解析它:`signer`(托管级别的后端),然后是 `account`(进程中的 viem 密钥),然后是 `STABLE_ENTERPRISE_PRIVATE_KEY` 环境变量。`guaranteedBlock` 直接接受已资助的 `account`。 +持有豁免密钥的模块(`gasWaiver` 和 `guaranteedWaiver`)按顺序解析它:模块自己的 `signer`,然后是它的 `account`(一个进程内的 viem 密钥),然后是客户端配置中的顶层 [`signer`](#stableenterpriseconfig),然后是 `STABLE_ENTERPRISE_PRIVATE_KEY` 环境变量。设置一次顶层 `signer` 以从单个托管后端驱动两个豁免模块。`guaranteedBlock` 用它自己的已资助 `account` 签名。 -签名者对 32 字节摘要进行签名,因此密钥从不离开托管后端。AWS KMS 使用 `awsKmsSigner`,viem 账户使用 `toSigner(account)`,进程内密钥使用 `privateKeySigner(key)` / `envSigner()`。 +`Signer` 对 32 字节摘要进行签名,因此密钥从不离开托管后端。AWS KMS 使用 `awsKmsSigner`,viem 账户使用 `toSigner(account)`,或进程内密钥使用 `privateKeySigner(key)` / `envSigner()`。传递给模块 `send` / `sendBatch` 的每次调用发送方同样可以是 viem 账户或 `Signer`,因此 KMS/HSM 密钥可以签署内部交易而无需降级到 `relay`。 ```bash npm install @aws-sdk/client-kms @@ -79,11 +80,11 @@ const signer = await awsKmsSigner({ keyId: process.env.KMS_KEY_ID! }); const enterprise = createStableEnterprise({ chain: stableTestnet, - gasWaiver: { signer }, // 托管级别的豁免密钥,代替 `account` + gasWaiver: { signer }, // 托管级别的豁免密钥,取代 `account` }); ``` -`awsKmsSigner` 在 `@stablechain/enterprise/aws-kms` 子路径中提供,因此 `@aws-sdk/client-kms` 仍然是可选的对等依赖项,不在核心安装中。 +`awsKmsSigner` 在 `@stablechain/enterprise/aws-kms` 子路径中提供,因此 `@aws-sdk/client-kms` 仍然是一个可选的对等依赖项,不在核心安装中。 ### `StableEnterpriseClient` @@ -95,9 +96,9 @@ interface StableEnterpriseClient { } ``` -## 燃气费豁免中继 +## 免燃料费中继 -`gasWaiver` 模块中继免燃气费交易。白名单豁免账户将用户的零燃气费交易 (InnerTx) 封装到 WaiverTx 中并广播。用户不需要 USDT0。每个方法都返回 `H_inner`,即 InnerTx 的哈希,而不是包装器哈希。 +`gasWaiver` 模块中继免燃料费交易。白名单豁免帐户将用户的零燃料费交易 (InnerTx) 封装到 WaiverTx 中并进行广播。用户无需 USDT0。每个方法都返回 `H_inner`,即 InnerTx 哈希,而不是封装器哈希。 在配置中通过 `gasWaiver` 启用它: @@ -121,15 +122,15 @@ const gw = enterprise.gasWaiver!; | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `signer` | `Signer?` | 白名单、治理注册的豁免密钥作为托管签名者 (AWS KMS, HSM)。请参阅[签名密钥和托管](#signing-keys-and-custody)。优先于 `account`。 | -| `account` | `LocalAccount?` | 进程中的 viem 账户作为豁免密钥。当两者都未设置时,回退到 `STABLE_ENTERPRISE_PRIVATE_KEY`。 | +| `signer` | `Signer?` | 作为托管签名者(AWS KMS、HSM)的白名单、治理注册的豁免密钥。优先于 `account`。请参阅[签名密钥和托管](#signing-keys-and-custody)。 | +| `account` | `LocalAccount?` | 作为进程内 viem 账户的豁免密钥。如果两者都未设置,则回退到 `STABLE_ENTERPRISE_PRIVATE_KEY`。 | | `maxGasLimit` | `bigint?` | 继承自 `ValidationLimits`。 | | `maxDataLength` | `number?` | 继承自 `ValidationLimits`。 | | `allowedTargets` | `AllowedTarget[]?` | 继承自 `ValidationLimits`。 | ### `send(account, tx)` -在一个调用中构建、签名和中继一个来自 `account` 的 InnerTx。`gasPrice: 0`、旧类型、`chainId` 和待处理 Nonce 将为您处理。拒绝时抛出 `StableEnterpriseRelayError`。 +在一个调用中构建、签名并中继一个来自 `account` 的 InnerTx。`gasPrice: 0`、遗留类型、`chainId` 和待处理 nonce 都为您处理。拒绝时抛出 `StableEnterpriseRelayError`。 ```ts const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); @@ -139,11 +140,11 @@ const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); { txHash: "0x8f3a...2d41" } ``` -`tx` 参数是 [`WaiverInnerTx`](#waiverinnertx) 加上一个可选的 `nonce`。返回 [`RelayResult`](#relayresult)。 +`tx` 参数是一个 [`WaiverInnerTx`](#waiverinnertx) 加上一个可选的 `nonce`。返回 [`RelayResult`](#relayresult)。 ### `sendBatch(account, txs)` -从一个 `account` 构建、签名和中继多个 InnerTx。Nonce 从账户的待处理 Nonce 自动排序。按顺序为每个输入返回一个结果。 +从一个`account`构建、签名并中继多个InnerTx。Nonces会从账户的待处理nonce自动排序。每个输入按顺序返回一个结果。 ```ts const results = await gw.sendBatch(user, [ @@ -160,7 +161,7 @@ const results = await gw.sendBatch(user, [ ### `relay(signedInnerTxHex)` -中继预签名的零燃气费 InnerTx。在非托管流程中使用此功能,用户在自己的环境中签名并仅将签名后的十六进制交给您,因此豁免操作员永远不会看到用户的密钥。使用 [`buildWaiverInnerTx`](#buildwaiverinnertxsigner-chainid-req) 构建一个。拒绝时抛出。 +中继预签名的零燃料费 InnerTx。这适用于非托管流程,用户在其自己的环境中签名并只向您提供签名的十六进制数据,因此豁免操作员永远不会看到用户的密钥。使用 [`buildWaiverInnerTx`](#buildwaiverinnertxsigner-chainid-req) 构建一个。拒绝时抛出错误。 ```ts import { buildWaiverInnerTx, toSigner } from "@stablechain/enterprise"; @@ -175,7 +176,7 @@ const { txHash } = await gw.relay(signed); ### `relayBatch(signedInnerTxHexes)` -中继一批预签名的 InnerTx。按顺序为每个输入返回一个 [`BatchResultItem`](#batchresultitem)。 +中继一批预签名的 InnerTx。每个输入按顺序返回一个 [`BatchResultItem`](#batchresultitem)。 ```ts const results = await gw.relayBatch([signed0, signed1]); @@ -187,7 +188,7 @@ const results = await gw.relayBatch([signed0, signed1]); ## 保证区块空间 -`guaranteedBlock` 模块通过企业级 RPC 网关中继 GuaranteedTx(类型 `0x3F` CustomTx),以便它们落在预留的企业级通道区块空间中。与燃气费豁免不同,签名者需要支付自己的燃气费,并且必须有资金。每笔交易都带有与企业级通道关联的 2D Nonce,并且广播仅通过网关进行。 +`guaranteedBlock` 模块通过企业级 RPC 网关中继 GuaranteedTx(类型 `0x3F` CustomTx),以便它们落在预留的企业级通道区块空间中。与免燃料费不同,签名者支付自己的燃料费并且需要有资金。每个交易都带有与企业级通道关联的二维 nonce,并且广播仅通过网关进行。 通过 `guaranteedBlock` 和 `enterpriseRpcEndpoints` 启用它: @@ -208,12 +209,12 @@ const gb = enterprise.guaranteedBlock!; | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `account` | `LocalAccount` | 签署每笔 GuaranteedTx 并支付其燃气费的已资助账户。 | -| `laneId` | `bigint` | 企业级通道 ID。必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。无效 ID 将被提前拒绝。 | +| `account` | `LocalAccount` | 签署每个 GuaranteedTx 并支付其燃料费的已注资账户。 | +| `laneId` | `bigint` | 企业级通道 ID。必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。无效 ID 会被立即拒绝。 | ### `send(account, tx)` -构建、签名和中继一个 GuaranteedTx。签名者需要支付燃气费,因此 1559 费用字段是必需的。`chainId`、企业级 `nonceKey` 和 2D Nonce(从网关发现)将为您处理。 +构建、签名并中继一个 GuaranteedTx。1559 燃料费字段是必需的,因为签名者要支付燃料费。`chainId`、企业级 `nonceKey` 和二维 nonce(从网关发现)都为您处理。 ```ts const gasPrice = await publicClient.getGasPrice(); @@ -234,7 +235,7 @@ const { txHash } = await gb.send(signer, { ### `sendBatch(account, txs)` -构建、签名和中继多笔 GuaranteedTx。Nonce 从发现的基数自动排序。失败会导致其后续交易无法进行。 +构建、签名并中继多个 GuaranteedTx。Nonce 会从发现的基础自动排序。失败会影响其后续操作。 ```ts const results = await gb.sendBatch(signer, [ @@ -251,7 +252,7 @@ const results = await gb.sendBatch(signer, [ ### `relay(signedTx)` / `relayBatch(signedTxs)` -中继一个预签名的 GuaranteedTx,或一批预签名的 GuaranteedTx。使用 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req) 构建和签署交易,[`nonceKeyForLane`](#noncekeyforlanelaneid) 用于企业 Nonce 密钥,然后只向操作员提供签名十六进制。 +中继预签名的 GuaranteedTx,或一批 GuaranteedTx。在使用 [`nonceKeyForLane`](#noncekeyforlanelaneid) 作为企业级 Nonce 键时,在其他地方使用 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req) 构建并签署交易,然后只将签署的十六进制数据交给操作员。 ```ts import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; @@ -261,7 +262,7 @@ const signed = await buildGuaranteedTx(toSigner(signer), stableTestnet.id, { gas: 21_000n, gasFeeCap, gasTipCap, - nonce, // 账户当前的 2D 通道 Nonce + nonce, // account's current 2D-lane nonce nonceKey: nonceKeyForLane(0n), }); const { txHash } = await gb.relay(signed); @@ -273,7 +274,7 @@ const { txHash } = await gb.relay(signed); ## 保证中继交易 -`guaranteedWaiver` 模块结合了上述两条通道:通过保证区块空间路由的燃气费豁免交易。内部和外部交易都是 `0x3F` CustomTx,共享一个企业级 `nonceKey`,因此它通过网关广播,就像 `guaranteedBlock` 一样。豁免方支付燃气费,因此用户不需要余额和费用字段,就像 `gasWaiver` 一样。每个方法都返回 `H_inner`。 +`guaranteedWaiver` 模块结合了上述两种机制:通过保证区块空间路由的免燃料费交易。内部和外部交易都是 `0x3F` CustomTx,共享一个企业级 `nonceKey`,因此它像 `guaranteedBlock` 一样通过网关广播。豁免方赞助燃料费,因此用户无需余额和燃料费字段,就像 `gasWaiver` 一样。每个方法都返回 `H_inner`。 通过 `guaranteedWaiver` 和 `enterpriseRpcEndpoints` 启用它: @@ -292,23 +293,23 @@ const gw = enterprise.guaranteedWaiver!; ### `GuaranteedWaiverConfig` -扩展了 [`ValidationLimits`](#validationlimits) 和 [`SignerSource`](#signersource)。它从外部包装器豁免密钥中获取密钥的方式与 `GasWaiverConfig` (先是 `signer`,然后是 `account`,然后是环境变量) 完全相同,并且接受相同的 `maxGasLimit`、`maxDataLength` 和 `allowedTargets` 策略控制。 +扩展了 [`ValidationLimits`](#validationlimits) 和 [`SignerSource`](#signersource)。它外部包装器豁免密钥的来源与 `GasWaiverConfig` 一致(`signer`,然后是 `account`,然后是环境变量),并接受相同的 `maxGasLimit`、`maxDataLength` 和 `allowedTargets` 策略控制。 | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `signer` | `Signer?` | 白名单豁免密钥(签署外部包装器)作为托管签名者。优先于 `account`。请参阅 [签名密钥和托管](#signing-keys-and-custody)。 | -| `account` | `LocalAccount?` | 进程中的 viem 账户作为豁免密钥。当两者都未设置时,回退到 `STABLE_ENTERPRISE_PRIVATE_KEY`。 | +| `signer` | `Signer?` | 作为托管签名者(签署外部包装器)的白名单豁免密钥。优先于 `account`。请参阅[签名密钥和托管](#signing-keys-and-custody)。 | +| `account` | `LocalAccount?` | 作为进程内 viem 账户的豁免密钥。如果两者都未设置,则回退到 `STABLE_ENTERPRISE_PRIVATE_KEY`。 | | `laneId` | `bigint` | 企业级通道 ID。必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。 | ### `send(user, tx)` / `sendBatch(user, txs)` -构建并从 `user` 签署内部 `0x3F` CustomTx,用豁免密钥封装,然后中继。由于燃气费已豁免,因此不需要费用字段。内部 2D Nonce 从网关发现,并且批次从此基数自动排序。 +从 `user` 构建并签署内部 `0x3F` CustomTx,用豁免密钥包装它,然后中继。无需燃料费字段,因为燃料费已豁免。内部 2D nonce 从网关发现,批处理从该基础自动排序。 ```ts -// 单笔 +// single const { txHash } = await gw.send(user, { to: recipient }); -// 批量 +// batch const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); ``` @@ -320,7 +321,7 @@ const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); ### `relay(signedInnerTx)` / `relayBatch(signedInnerTxs)` -对于非托管流,用户使用 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req) 签署内部 `0x3F` CustomTx(费用 `0n`,使用 `nonceKeyForLane(laneId)`),并仅向操作员提供签名十六进制。操作员使用豁免密钥封装并中继。 +对于非托管流,用户使用 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req) 签署内部 `0x3F` CustomTx(费用为 `0n`,使用 `nonceKeyForLane(laneId)`),然后只将签名的十六进制数据交给操作员。操作员使用豁免密钥将其包装并中继。 ```ts import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; @@ -328,12 +329,12 @@ import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enter const signedInner = await buildGuaranteedTx(toSigner(user), stableTestnet.id, { to, gas: 100_000n, - gasFeeCap: 0n, // 豁免 + gasFeeCap: 0n, // waived gasTipCap: 0n, nonce, nonceKey: nonceKeyForLane(0n), }); -const { txHash } = await gw.relay(signedInner); // 豁免方封装 + 广播 → H_inner +const { txHash } = await gw.relay(signedInner); // waiver wraps + broadcasts → H_inner ``` ```text @@ -342,11 +343,11 @@ const { txHash } = await gw.relay(signedInner); // 豁免方封装 + 广播 → ## 构建助手 -用于非托管 `relay` 路径的低级签名者。每个都返回一个已签名的交易作为 `Hex`,不进行 Nonce 获取或费用估算。第一个参数是 [`Signer`](#signing-keys-and-custody):用 `toSigner(account)` 包装一个 viem 账户,或传递一个托管签名者,例如 `awsKmsSigner`。 +用于非托管 `relay` 路径的低级签名者。每个方法都将签名交易作为 `Hex` 返回,没有 nonce 获取或费用估算。第一个参数是 [`Signer`](#signing-keys-and-custody):用 `toSigner(account)` 包装 viem 账户,或传递托管签名者(如 `awsKmsSigner`)。 ### `buildWaiverInnerTx(signer, chainId, req)` -签署一个豁免就绪的 InnerTx,其中包含豁免不变性:`gasPrice: 0`、旧类型和给定的 `chainId`。`req` 是一个 [`WaiverInnerTx`](#waiverinnertx) 加上一个必需的 `nonce`。 +使用预设的豁免条件签署一个豁免就绪的 InnerTx:`gasPrice: 0`、遗留类型和给定的 `chainId`。`req` 是一个 [`WaiverInnerTx`](#waiverinnertx) 加上一个必需的 `nonce`。 ```ts const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to, data, gas: 150_000n, nonce }); @@ -358,11 +359,11 @@ const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to, ### `buildGuaranteedWaiverTx(...)` -将预签名内部交易封装到外部 `0x3F` 豁免 CustomTx 中。由 `guaranteedWaiver.relay` 内部使用;为高级流程导出。 +将预签名内部交易包装到外部 `0x3F` 豁免自定义交易中。内部由 `guaranteedWaiver.relay` 使用;为高级流程导出。 ### `nonceKeyForLane(laneId)` -返回用于 `buildGuaranteedTx` 的通道 ID 的企业 `nonceKey`。 +返回用于通道 ID 的企业级 `nonceKey`,以配合 `buildGuaranteedTx` 使用。 ```ts import { nonceKeyForLane } from "@stablechain/enterprise"; @@ -374,16 +375,16 @@ const nonceKey = nonceKeyForLane(0n); ### `SignerSource` -豁免模块 (`gasWaiver`, `guaranteedWaiver`) 接受的签名密钥字段。按顺序解析:`signer`,然后 `account`,然后是 `STABLE_ENTERPRISE_PRIVATE_KEY` 环境变量。请参阅 [签名密钥和托管](#signing-keys-and-custody)。 +豁免模块(`gasWaiver`,`guaranteedWaiver`)接受的签名密钥字段。按顺序解析:`signer`,然后 `account`,然后客户端的顶层 [`signer`](#stableenterpriseconfig),然后是 `STABLE_ENTERPRISE_PRIVATE_KEY` 环境变量。请参阅[签名密钥和托管](#signing-keys-and-custody)。 | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `signer` | `Signer?` | 托管级别的签名者(AWS KMS、HSM 或 `privateKeySigner`)。优先于 `account`。 | -| `account` | `LocalAccount?` | 进程中的 viem 账户,通过 `toSigner` 转换为 `Signer`。 | +| `signer` | `Signer?` | 托管级别签名者(AWS KMS、HSM 或 `privateKeySigner`)。优先于 `account`。 | +| `account` | `LocalAccount?` | 进程内 viem 账户,通过 `toSigner` 适配为 `Signer`。 | ### `Signer` -一个可插拔的签名器,SDK 通过它签署 32 字节摘要,因此密钥不会离开托管后端。使用 `awsKmsSigner`、`toSigner`、`privateKeySigner` 或 `envSigner` 构建一个。 +一个可插拔的签名器,SDK 通过它对 32 字节哈希进行签名,因此密钥永远不会离开托管后端。使用 `awsKmsSigner`、`toSigner`、`privateKeySigner` 或 `envSigner` 构造一个。 ```ts interface Signer { @@ -395,88 +396,88 @@ interface Signer { | **助手** | **导入** | **描述** | | :--- | :--- | :--- | | `awsKmsSigner({ keyId, client? })` | `@stablechain/enterprise/aws-kms` | 由 AWS KMS `ECC_SECG_P256K1` 密钥支持的签名器。返回 `Promise`。 | -| `toSigner(account)` | `@stablechain/enterprise` | 将 viem `LocalAccount` 转换为 `Signer`。 | -| `privateKeySigner(key)` | `@stablechain/enterprise` | 包装进程中持有的原始私钥的签名器。 | -| `envSigner(varName?)` | `@stablechain/enterprise` | 从 `STABLE_ENTERPRISE_PRIVATE_KEY`(或 `varName`)读取密钥的签名器。 | +| `toSigner(account)` | `@stablechain/enterprise` | 将 viem `LocalAccount` 适配为 `Signer`。 | +| `privateKeySigner(key)` | `@stablechain/enterprise` | 包装进程中原始私钥的签名器。 | +| `envSigner(varName?)` | `@stablechain/enterprise` | 从 `STABLE_ENTERPRISE_PRIVATE_KEY` (或 `varName`) 读取密钥的签名器。 | ### `WaiverInnerTx` -每次调用 InnerTx 中变化的字段。 +每次调用不同的 InnerTx 字段。 | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | -| `to` | `Address` | | 目标地址:用于 ERC-20 转账的代币合约,用于原生代币的接收者。 | -| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | 燃气限制。因为 `gasPrice` 为 0,所以慷慨的限制是免费的。 | +| `to` | `Address` | | 目标地址:ERC-20 代币转账的代币合约,原生代币的接收者。 | +| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | 燃料费限制。由于 `gasPrice` 为 0,因此慷慨的限制是免费的。 | | `data` | `Hex?` | `"0x"` | 调用数据。 | -| `value` | `bigint?` | `0n` | 要发送的原生价值。 | +| `value` | `bigint?` | `0n` | 要发送的原生值。 | ### `GuaranteedTxRequest` | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | | `to` | `Address?` | | 目标地址。 | -| `gas` | `bigint` | | 燃气限制。必需。 | +| `gas` | `bigint` | | 燃料费限制。必需。 | | `gasFeeCap` | `bigint` | | `maxFeePerGas`。必需。 | | `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`。必需。 | | `data` | `Hex?` | `"0x"` | 调用数据。 | -| `value` | `bigint?` | `0n` | 要发送的原生价值。 | +| `value` | `bigint?` | `0n` | 要发送的原生值。 | ### `GuaranteedWaiverTxRequest` -费用字段始终为 0,因此此处省略。 +燃料费字段始终为 0,因此此处省略。 | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | | `to` | `Address` | | 目标地址。 | -| `gas` | `bigint?` | 共享的内部燃气默认值 | 燃气限制。 | +| `gas` | `bigint?` | 共享内部燃料费默认值 | 燃料费限制。 | | `data` | `Hex?` | `"0x"` | 调用数据。 | -| `value` | `bigint?` | `0n` | 要发送的原生价值。燃气费豁免允许价值转移。 | +| `value` | `bigint?` | `0n` | 要发送的原生值。允许豁免值转账。 | ### `ValidationLimits` -由 `gasWaiver` 和 `guaranteedWaiver` 应用于每个 InnerTx 的每合作伙伴策略。 +每个 InnerTx 的合作伙伴策略,由 `gasWaiver` 和 `guaranteedWaiver` 应用。 | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | -| `maxGasLimit` | `bigint?` | `10_000_000n` | InnerTx 的最大燃气限制。超出此限制将因 `GAS_LIMIT_EXCEEDED` 而失败。 | -| `maxDataLength` | `number?` | `131_072` (128 KB) | 调用数据的最大大小(字节)。超出此限制将因 `DATA_TOO_LARGE` 而失败。 | -| `allowedTargets` | `AllowedTarget[]?` | | 豁免可能赞助的合约和方法的白名单。设置后,不在列表中的目标将因 `TARGET_NOT_ALLOWED` 而失败。 | +| `maxGasLimit` | `bigint?` | `10_000_000n` | InnerTx 的最大燃料费限制。超过将导致 `GAS_LIMIT_EXCEEDED` 错误。 | +| `maxDataLength` | `number?` | `131_072` (128 KB) | 调用数据的最大大小(字节)。超过将导致 `DATA_TOO_LARGE` 错误。 | +| `allowedTargets` | `AllowedTarget[]?` | | 豁免可以赞助的合约和方法的白名单。设置后,列表之外的目标将导致 `TARGET_NOT_ALLOWED` 错误。 | ### `AllowedTarget` | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `address` | `Address \| "*"` | InnerTx 可以调用的合约,或者 `"*" `表示匹配任何合约。 | +| `address` | `Address \| "*"` | InnerTx 可以调用的合约,或 `"*"` 以匹配任何合约。 | | `selectors` | `Hex[]?` | 允许的 4 字节方法选择器(例如,ERC-20 `transfer` 的 `"0xa9059cbb"`)。省略或留空以允许 `address` 上的任何方法。 | ### `RelayResult` ```ts interface RelayResult { - txHash: Hash; // 燃气费豁免的 H_inner,独立保证区块的 GuaranteedTx 哈希 + txHash: Hash; // H_inner 用于豁免,GuaranteedTx 哈希用于独立的保证区块 } ``` ### `BatchResultItem` -批处理中每个输入的条目,按输入顺序。批处理不是抛出错误,而是显示每个项目的处理结果。 +批处理中每个输入的条目,按输入顺序排列。批处理不会抛出错误,而是显示每个项目的处理结果。 | **字段** | **类型** | **描述** | | :--- | :--- | :--- | | `index` | `number` | 零基位置,与输入数组匹配。 | -| `success` | `boolean` | 此项目是否已中继。 | +| `success` | `boolean` | 此项目是否中继。 | | `txHash` | `Hash?` | 成功时存在:内部交易哈希。 | | `error` | `{ code: ErrorCode; message: string }?` | 失败时存在。 | ## 错误 -单个交易方法 (`send`, `relay`) 在拒绝时会抛出错误。批量方法则在 [`BatchResultItem.error`](#batchresultitem) 中报告每个项目的失败。所有错误类都扩展自 `StableEnterpriseError`。 +单交易方法 (`send`, `relay`) 在拒绝时抛出错误。批处理方法则在 [`BatchResultItem.error`](#batchresultitem) 中报告每个项目的失败。所有错误类都继承自 `StableEnterpriseError`。 -| **类** | **抛出时机** | **有用字段** | +| **类别** | **抛出条件** | **有用字段** | | :--- | :--- | :--- | -| `StableEnterpriseError` | 所有 SDK 错误的基类。 | `message` | +| `StableEnterpriseError` | 每一个 SDK 错误的基类。 | `message` | | `StableEnterpriseRelayError` | 交易在 RPC 或中继层被拒绝。 | `code` | -| `WaiverValidationError` | InnerTx 在广播前未能通过策略检查(燃气费、数据大小或目标白名单)。 | `code` | +| `WaiverValidationError` | InnerTx 在广播前未能通过策略检查(燃料费、数据大小或目标白名单)。 | `code` | ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -501,29 +502,29 @@ StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not | **代码** | **含义** | | :--- | :--- | -| `UNKNOWN_ERROR` | 没有可用特定代码时的回退。 | -| `BROADCAST_FAILED` | 广播在 RPC 层被拒绝,或者网关未能中继。 | +| `UNKNOWN_ERROR` | 没有特定代码时的回退。 | +| `BROADCAST_FAILED` | 广播在 RPC 层被拒绝,或网关未能中继。 | | `INVALID_TRANSACTION` | InnerTx 解码或解析失败。 | | `INVALID_SIGNATURE` | 签名验证失败。 | | `UNSUPPORTED_TX_TYPE` | InnerTx 类型不是 legacy、eip2930 或 eip1559。 | | `WRONG_CHAIN_ID` | InnerTx `chainId` 缺失或与目标链不匹配。 | -| `NON_ZERO_GAS_PRICE` | InnerTx 带有非零燃气费(豁免必须为零)。 | -| `GAS_LIMIT_EXCEEDED` | InnerTx 燃气限制超过 `maxGasLimit`。 | -| `DATA_TOO_LARGE` | InnerTx 调用数据超过 `maxDataLength`。 | +| `NON_ZERO_GAS_PRICE` | InnerTx 带有非零燃料费价格(对于豁免必须为零)。 | +| `GAS_LIMIT_EXCEEDED` | InnerTx 燃料费限制超出 `maxGasLimit`。 | +| `DATA_TOO_LARGE` | InnerTx 调用数据超出 `maxDataLength`。 | | `TARGET_NOT_ALLOWED` | InnerTx 目标不在 `allowedTargets` 中。 | -| `GATEWAY_UNAUTHORIZED` | 企业级 RPC 网关拒绝了 API 密钥(缺失、无效或过期)。 | -| `QUOTA_EXCEEDED` | 企业级 RPC 网关燃气配额已用尽。 | +| `GATEWAY_UNAUTHORIZED` | 企业级 RPC 网关拒绝了 API 密钥(丢失、无效或已过期)。 | +| `QUOTA_EXCEEDED` | 企业级 RPC 网关燃料费配额已用尽。 | ## 常量 | **常量** | **类型** | **描述** | | :--- | :--- | :--- | -| `DEFAULT_INNER_GAS` | `bigint` | InnerTx 的默认燃气限制 (`150_000n`),当省略 `gas` 时使用。 | -| `ENTERPRISE_FLAG` | `bigint` | 设置在通道 `nonceKey` 上的企业位。 | +| `DEFAULT_INNER_GAS` | `bigint` | 省略 `gas` 时 InnerTx 的默认燃料费限制 (`150_000n`)。 | +| `ENTERPRISE_FLAG` | `bigint` | 在通道的 `nonceKey` 上设置企业位。 | | `ENTERPRISE_MASK` | `bigint` | 通道 ID 的上限:`laneId` 必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。 | -## 接下来的建议 +## 下一步建议 -- [**Stable 企业级 SDK**](/cn/explanation/enterprise-sdk):这些通道是什么以及何时使用它们。 -- [**燃气费豁免协议**](/cn/reference/gas-waiver-api):交易格式、标记路由和治理控制。 -- [**保证区块空间**](/cn/explanation/guaranteed-blockspace):Stable 如何为企业工作负载预留区块容量。 +- [**Stable 企业级 SDK**](/cn/explanation/enterprise-sdk): 什么是这些概念以及何时使用它们。 +- [**免燃料费协议**](/cn/reference/gas-waiver-api): 交易格式、标记路由和治理控制。 +- [**保证区块空间**](/cn/explanation/guaranteed-blockspace): Stable 如何为企业级工作负载预留区块容量。 diff --git a/docs/pages/ko/reference/enterprise-sdk.mdx b/docs/pages/ko/reference/enterprise-sdk.mdx index 026348f..8be2024 100644 --- a/docs/pages/ko/reference/enterprise-sdk.mdx +++ b/docs/pages/ko/reference/enterprise-sdk.mdx @@ -1,21 +1,21 @@ --- source_path: reference/enterprise-sdk.mdx -source_sha: 1415ca3965bbd2c7d362a8e86a728c3a9e6269a7 -title: "엔터프라이즈 SDK 참조" -description: "@stablechain/enterprise에 대한 전체 참조: createStableEnterprise, 가스 웨이버 및 보장 블록 공간 모듈, 빌드 헬퍼 및 오류 클래스." +source_sha: 4f3e8931e52daf98a9dc5de5921fc734d4284dfb +title: "Enterprise SDK 참조" +description: "@stablechain/enterprise에 대한 완벽한 참조: createStableEnterprise, 가스 면제 및 보장된 블록 공간 모듈, 빌드 헬퍼 및 오류 클래스." diataxis: "reference" --- -# 엔터프라이즈 SDK 참조 +# Enterprise SDK 참조 -`@stablechain/enterprise`의 전체 표면입니다. 여기에는 [`createStableEnterprise`](#createstableenterpriseconfig)에서 가져오는 클라이언트, 세 가지 기능([가스 웨이버 대행](#relay-with-gas-waiver), [보장 블록 공간](#guaranteed-blockspace), [보장 릴레이 트랜잭션](#guaranteed-relay-transactions)), 하위 수준 빌드 헬퍼, 공유 결과 및 오류 유형이 포함됩니다. 이러한 레일이 무엇인지는 [Stable Enterprise SDK](/ko/explanation/enterprise-sdk), [가스 웨이버](/ko/explanation/gas-waiver), [보장 블록 공간](/ko/explanation/guaranteed-blockspace)을 참조하세요. +`@stablechain/enterprise`의 전체 표면. 여기에는 [`createStableEnterprise`](#createstableenterpriseconfig)의 클라이언트, 세 가지 기능([가스 면제 릴레이](#relay-with-gas-waiver), [보장된 블록 공간](#guaranteed-blockspace), [보장된 릴레이 트랜잭션](#guaranteed-relay-transactions)), 하위 수준 빌드 헬퍼, 공유 결과 및 오류 유형이 포함됩니다. 이러한 레일 세부 정보에 대해서는 [Stable Enterprise SDK](/ko/explanation/enterprise-sdk), [가스 면제](/ko/explanation/gas-waiver) 및 [보장된 블록 공간](/ko/explanation/guaranteed-blockspace)을 참조하세요. :::note -엔터프라이즈 SDK는 현재 Stable Testnet에서만 사용할 수 있으며, 액세스는 요청 시에만 가능합니다. 통합하려면 Stable에 [문의](https://discord.gg/stablexyz)하여 거버넌스 등록 웨이버 키 및 엔터프라이즈 RPC 게이트웨이 API 키를 받으세요. +Enterprise SDK는 현재 Stable 테스트넷에서만 사용할 수 있으며, 요청 시 액세스할 수 있습니다. 통합하려면 [Stable에 문의](https://discord.gg/stablexyz)하여 거버넌스에 등록된 면제 키와 Enterprise RPC 게이트웨이 API 키를 받으세요. ::: :::warning -이것은 개인 키로 서명하는 서버 측 라이브러리입니다. 브라우저에서 실행하지 마세요. 웨이버 키와 엔터프라이즈 RPC 게이트웨이 URL을 백엔드에 보관하세요. +이것은 개인 키로 서명하는 서버 측 라이브러리입니다. 브라우저에서 절대 실행하지 마십시오. 면제 키와 Enterprise RPC 게이트웨이 URL을 백엔드에 보관하십시오. ::: ## 설치 @@ -28,11 +28,11 @@ npm install @stablechain/enterprise viem added 2 packages, audited 3 packages in 2s ``` -`viem >= 2.0.0`은 피어 의존성입니다. 이 패키지는 `viem/chains`에서 `stable` 및 `stableTestnet`을 다시 내보내므로 별도로 가져올 필요가 없습니다. +`viem >= 2.0.0`은 피어 종속성입니다. 이 패키지는 `viem/chains`에서 `stable` 및 `stableTestnet`을 다시 내보내므로 별도로 가져올 필요가 없습니다. ## `createStableEnterprise(config)` -`StableEnterpriseClient`를 생성합니다. 각 모듈은 구성할 때만 존재하므로 사용하기 전에 `!` 또는 null 검사로 보호하세요. +`StableEnterpriseClient`를 구성합니다. 각 모듈은 구성한 경우에만 존재하므로 사용하기 전에 `!` 또는 null 검사를 사용하여 보호하세요. ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -52,19 +52,20 @@ StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver | **필드** | **유형** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `chain` | `StableChain` | | 대상 체인. `stable` 또는 `stableTestnet` (패키지에서 다시 내보냄)을 전달합니다. 필수입니다. | -| `rpcEndpoints` | `string[]?` | 체인의 내장 RPC | 하나 이상의 Stable RPC 엔드포인트이며, 실패 시 순서대로 시도됩니다. 개인 엔드포인트를 가리키는 경우에만 재정의합니다. | -| `enterpriseRpcEndpoints` | `string[]?` | | 하나 이상의 엔터프라이즈 RPC 게이트웨이 엔드포인트이며, 실패 시 순서대로 시도됩니다. `guaranteedBlock` 및 `guaranteedWaiver`에 필요합니다. | -| `batchSizeLimit` | `number?` | `100` | 일괄 RPC 호출당 최대 트랜잭션 수입니다. | -| `gasWaiver` | `GasWaiverConfig?` | | [가스 웨이버 대행](#relay-with-gas-waiver)을 활성화합니다. | -| `guaranteedBlock` | `GuaranteedBlockConfig?` | | [보장 블록 공간](#guaranteed-blockspace)을 활성화합니다. | -| `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | [보장 릴레이 트랜잭션](#guaranteed-relay-transactions)을 활성화합니다. | +| `chain` | `StableChain` | | 대상 체인. `stable` 또는 `stableTestnet` (패키지에서 다시 내보냄)을 전달합니다. 필수. | +| `rpcEndpoints` | `string[]?` | 체인의 내장 RPC | 실패 시 순서대로 시도되는 하나 이상의 Stable RPC 엔드포인트. 개인 엔드포인트를 가리키는 경우에만 재정의합니다. | +| `enterpriseRpcEndpoints` | `string[]?` | | 실패 시 순서대로 시도되는 하나 이상의 Enterprise RPC 게이트웨이 엔드포인트. `guaranteedBlock` 및 `guaranteedWaiver`에 필요합니다. | +| `batchSizeLimit` | `number?` | `100` | 일괄 RPC 호출당 최대 트랜잭션 수. | +| `signer` | `Signer?` | | 모듈에 자체 키가 없을 때 면제 모듈(`gasWaiver`, `guaranteedWaiver`)에 대한 기본 서명자. 단일 커스터디 백엔드에서 둘 다 구동하려면 한 번 설정합니다. [서명 키 및 커스터디](#signing-keys-and-custody)를 참조하십시오. | +| `gasWaiver` | `GasWaiverConfig?` | | [가스 면제 릴레이](#relay-with-gas-waiver)를 활성화합니다. | +| `guaranteedBlock` | `GuaranteedBlockConfig?` | | [보장된 블록 공간](#guaranteed-blockspace)을 활성화합니다. | +| `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | [보장된 릴레이 트랜잭션](#guaranteed-relay-transactions)을 활성화합니다. | -### 서명 키 및 Custody +### 서명 키 및 커스터디 -웨이버 키(`gasWaiver` 및 `guaranteedWaiver`)를 보유하는 모듈은 [`SignerSource`](#signersource)에서 순서대로 해결됩니다: `signer`(custody 등급 백엔드), 그 다음 `account`(인-프로세스 viem 키), 그 다음 `STABLE_ENTERPRISE_PRIVATE_KEY` 환경 변수. `guaranteedBlock`은 자금이 지원되는 `account`를 직접 사용합니다. +면제 키를 보유하는 모듈(`gasWaiver` 및 `guaranteedWaiver`)은 순서대로 해결합니다: 모듈 자체의 `signer`, 그 다음은 `account` (인-프로세스 viem 키), 그 다음은 클라이언트 구성의 최상위 [`signer`](#stableenterpriseconfig), 그 다음은 `STABLE_ENTERPRISE_PRIVATE_KEY` 환경 변수. 단일 커스터디 백엔드에서 두 면제 모듈을 모두 구동하려면 최상위 `signer`를 한 번 설정하십시오. `guaranteedBlock`은 자체적으로 자금이 지원되는 `account`로 서명합니다. -`Signer`는 32바이트 다이제스트에 서명하므로 키는 custody 백엔드를 벗어나지 않습니다. AWS KMS의 경우 `awsKmsSigner`를 사용하고, viem 계정을 적용하기 위해 `toSigner(account)`를 사용하거나, 인-프로세스 키의 경우 `privateKeySigner(key)` / `envSigner()`를 사용합니다. +`Signer`는 32바이트 다이제스트에 서명하므로 키가 커스터디 백엔드를 떠나지 않습니다. AWS KMS의 경우 `awsKmsSigner`, viem 계정을 조정하는 경우 `toSigner(account)`, 인-프로세스 키의 경우 `privateKeySigner(key)` / `envSigner()`를 사용하십시오. 모듈의 `send` / `sendBatch`에 전달되는 호출별 발신자도 viem 계정 또는 `Signer`일 수 있으므로 KMS/HSM 키는 `relay`로 떨어지지 않고 내부 트랜잭션에 서명할 수 있습니다. ```bash npm install @aws-sdk/client-kms @@ -74,16 +75,16 @@ npm install @aws-sdk/client-kms import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; import { awsKmsSigner } from "@stablechain/enterprise/aws-kms"; -// KMS 키는 ECC_SECG_P256K1 (secp256k1)이어야 합니다. SDK가 주소를 거기서 파생합니다. +// KMS 키는 ECC_SECG_P256K1(secp256k1)이어야 합니다. SDK는 이를 통해 주소를 파생합니다. const signer = await awsKmsSigner({ keyId: process.env.KMS_KEY_ID! }); const enterprise = createStableEnterprise({ chain: stableTestnet, - gasWaiver: { signer }, // `account` 대신 custody 등급 웨이버 키 + gasWaiver: { signer }, // `account` 대신 커스터디 등급 면제 키 }); ``` -`awsKmsSigner`는 `@stablechain/enterprise/aws-kms` 하위 경로에 제공되므로 `@aws-sdk/client-kms`는 핵심 설치에서 제외된 선택적 피어 의존성으로 유지됩니다. +`awsKmsSigner`는 `@stablechain/enterprise/aws-kms` 하위 경로에 제공되어 `@aws-sdk/client-kms`가 코어 설치에서 제외되는 선택적 피어 종속성으로 유지됩니다. ### `StableEnterpriseClient` @@ -95,9 +96,9 @@ interface StableEnterpriseClient { } ``` -## 가스 웨이버 대행 +## 가스 면제 릴레이 -`gasWaiver` 모듈은 가스 면제 트랜잭션을 릴레이합니다. 화이트리스트에 등록된 웨이버 계정은 사용자의 제로 가스 트랜잭션(InnerTx)을 WaiverTx로 묶어 브로드캐스트합니다. 사용자는 USDT0이 필요하지 않습니다. 모든 메서드는 래퍼 해시가 아닌 InnerTx 해시인 `H_inner`를 반환합니다. +`gasWaiver` 모듈은 가스 면제 트랜잭션을 릴레이합니다. 화이트리스트에 등록된 면제 계정은 사용자(InnerTx)의 제로 가스 트랜잭션을 WaiverTx로 래핑하여 브로드캐스트합니다. 사용자는 USDT0가 필요하지 않습니다. 모든 메서드는 래퍼 해시가 아닌 InnerTx 해시인 `H_inner`를 반환합니다. 구성에서 `gasWaiver`를 사용하여 활성화합니다. @@ -121,15 +122,15 @@ const gw = enterprise.gasWaiver!; | **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `signer` | `Signer?` | custody 서명자(AWS KMS, HSM)로서 화이트리스트에 등록된 거버넌스 등록 웨이버 키입니다. [서명 키 및 Custody](#signing-keys-and-custody)를 참조하세요. `account`보다 우선합니다. | -| `account` | `LocalAccount?` | 인-프로세스 viem 계정으로서의 웨이버 키입니다. 둘 다 설정되지 않은 경우 `STABLE_ENTERPRISE_PRIVATE_KEY`로 폴백합니다. | +| `signer` | `Signer?` | 보관 서명자(AWS KMS, HSM)로서 화이트리스트에 등록된 거버넌스 등록 면제 키. [서명 키 및 보관](#signing-keys-and-custody)을 참조하십시오. `account`보다 우선합니다. | +| `account` | `LocalAccount?` | 인-프로세스 viem 계정으로서의 면제 키. 둘 다 설정되지 않은 경우 `STABLE_ENTERPRISE_PRIVATE_KEY`로 대체됩니다. | | `maxGasLimit` | `bigint?` | `ValidationLimits`에서 상속됩니다. | | `maxDataLength` | `number?` | `ValidationLimits`에서 상속됩니다. | | `allowedTargets` | `AllowedTarget[]?` | `ValidationLimits`에서 상속됩니다. | ### `send(account, tx)` -`account`에서 하나의 InnerTx를 한 번의 호출로 빌드, 서명하고 릴레이합니다. `gasPrice: 0`, 레거시 유형, `chainId`, 보류 중인 nonce가 자동으로 처리됩니다. 거부 시 `StableEnterpriseRelayError`가 발생합니다. +`account`에서 하나의 InnerTx를 한 번의 호출로 빌드, 서명 및 릴레이합니다. `gasPrice: 0`, 레거시 유형, `chainId` 및 보류 중인 논스는 자동으로 처리됩니다. 거부 시 `StableEnterpriseRelayError`를 발생시킵니다. ```ts const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); @@ -139,11 +140,11 @@ const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); { txHash: "0x8f3a...2d41" } ``` -`tx` 인수는 선택적 `nonce`가 추가된 [`WaiverInnerTx`](#waiverinnertx)입니다. [`RelayResult`](#relayresult)를 반환합니다. +`tx` 인수는 [`WaiverInnerTx`](#waiverinnertx)와 선택적 `nonce`입니다. [`RelayResult`](#relayresult)를 반환합니다. ### `sendBatch(account, txs)` -하나의 `account`에서 여러 InnerTx를 빌드, 서명하고 릴레이합니다. Nonce는 계정의 보류 중인 nonce에서 자동으로 순서가 지정됩니다. 입력당 하나의 결과를 순서대로 반환합니다. +하나의 `account`에서 여러 InnerTx를 빌드, 서명 및 릴레이합니다. Nonce는 계정의 보류 중인 nonce에서 자동으로 순서가 지정됩니다. 입력당 하나의 결과를 순서대로 반환합니다. ```ts const results = await gw.sendBatch(user, [ @@ -156,11 +157,11 @@ const results = await gw.sendBatch(user, [ [ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: true, txHash: "0x..." } ] ``` -`txs`는 [`WaiverInnerTx`](#waiverinnertx)의 읽기 전용 배열입니다. [`BatchResultItem[]`](#batchresultitem)를 반환합니다. +`txs`는 [`WaiverInnerTx`](#waiverinnertx)의 읽기 전용 배열입니다. [`BatchResultItem[]`](#batchresultitem)을 반환합니다. ### `relay(signedInnerTxHex)` -미리 서명된 제로 가스 InnerTx를 릴레이합니다. 사용자가 자신의 환경에서 서명하고 서명된 헥스만 전달하여 웨이버 운영자가 사용자 키를 볼 수 없는 비보관 흐름에 사용합니다. [`buildWaiverInnerTx`](#buildwaiverinnertxsigner-chainid-req)로 빌드합니다. 거부 시 오류가 발생합니다. +사전 서명된 제로 가스 InnerTx를 릴레이합니다. 사용자가 자신의 환경에서 서명하고 서명된 Hex만 넘겨주는 비수탁 흐름에서 이를 사용하므로 면제 운영자는 사용자의 키를 볼 수 없습니다. [`buildWaiverInnerTx`](#buildwaiverinnertxsigner-chainid-req)를 사용하여 빌드합니다. 거부 시 오류를 발생시킵니다. ```ts import { buildWaiverInnerTx, toSigner } from "@stablechain/enterprise"; @@ -175,7 +176,7 @@ const { txHash } = await gw.relay(signed); ### `relayBatch(signedInnerTxHexes)` -미리 서명된 InnerTx의 배치를 릴레이합니다. 입력당 하나의 [`BatchResultItem`](#batchresultitem)을 순서대로 반환합니다. +사전 서명된 InnerTx 배치를 릴레이합니다. 입력당 하나의 [`BatchResultItem`](#batchresultitem)을 순서대로 반환합니다. ```ts const results = await gw.relayBatch([signed0, signed1]); @@ -185,11 +186,11 @@ 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)를 릴레이하여 예약된 엔터프라이즈 레인 블록 공간에 배치합니다. 가스 웨이버와 달리 서명자는 자체 가스를 지불하며 자금이 지원되어야 합니다. 각 트랜잭션은 엔터프라이즈 레인에 키가 지정된 2D nonce를 가지고 있으며, 브로드캐스트는 게이트웨이를 통해서만 이루어집니다. +`guaranteedBlock` 모듈은 Enterprise RPC 게이트웨이를 통해 GuaranteedTx(유형 `0x3F` CustomTx)를 릴레이하여 예약된 Enterprise-lane 블록 공간에 착륙하도록 합니다. 가스 면제와 달리 서명자는 자체 가스를 지불하며 자금이 있어야 합니다. 각 트랜잭션은 Enterprise 레인에 키가 지정된 2D 논스를 전달하며 브로드캐스팅은 게이트웨이를 통해서만 이루어집니다. -`guaranteedBlock`과 `enterpriseRpcEndpoints`를 사용하여 활성화합니다. +`guaranteedBlock`과 `enterpriseRpcEndpoints`를 사용하여 활성화하세요. ```ts const enterprise = createStableEnterprise({ @@ -208,12 +209,12 @@ const gb = enterprise.guaranteedBlock!; | **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `account` | `LocalAccount` | 각 GuaranteedTx에 서명하고 가스를 지불하는 자금이 지원되는 계정입니다. | -| `laneId` | `bigint` | 엔터프라이즈 레인 ID입니다. `[0, ENTERPRISE_MASK - 1]` 범위 내에 있어야 합니다. 유효하지 않은 ID는 즉시 거부됩니다. | +| `account` | `LocalAccount` | 각 GuaranteedTx에 서명하고 가스를 지불하는 자금이 있는 계정. | +| `laneId` | `bigint` | Enterprise 레인 ID입니다. `[0, ENTERPRISE_MASK - 1]` 범위에 있어야 합니다. 유효하지 않은 ID는 즉시 거부됩니다. | ### `send(account, tx)` -하나의 GuaranteedTx를 빌드, 서명하고 릴레이합니다. 서명자가 가스를 지불하므로 1559 수수료 필드는 필수입니다. `chainId`, 엔터프라이즈 `nonceKey`, 그리고 (게이트웨이에서 발견된) 2D nonce가 자동으로 처리됩니다. +하나의 GuaranteedTx를 빌드, 서명 및 릴레이합니다. 서명자가 가스를 지불하기 때문에 1559 수수료 필드가 필요합니다. `chainId`, Enterprise `nonceKey` 및 2D nonce(게이트웨이에서 검색됨)는 자동으로 처리됩니다. ```ts const gasPrice = await publicClient.getGasPrice(); @@ -230,11 +231,11 @@ const { txHash } = await gb.send(signer, { { txHash: "0xabcd...7890" } ``` -`tx` 인수는 선택적 `nonce`가 추가된 [`GuaranteedTxRequest`](#guaranteedtxrequest)입니다. [`RelayResult`](#relayresult)를 반환합니다. +`tx` 인수는 [`GuaranteedTxRequest`](#guaranteedtxrequest)와 선택적 `nonce`입니다. [`RelayResult`](#relayresult)를 반환합니다. ### `sendBatch(account, txs)` -여러 GuaranteedTx를 빌드, 서명하고 릴레이합니다. Nonce는 발견된 기본값에서 자동으로 순서가 지정됩니다. 실패는 후속 처리됩니다. +여러 GuaranteedTx를 빌드, 서명 및 릴레이합니다. Nonce는 검색된 베이스에서 자동으로 순서가 지정됩니다. 실패는 후속 작업에 영향을 미칩니다. ```ts const results = await gb.sendBatch(signer, [ @@ -247,11 +248,11 @@ const results = await gb.sendBatch(signer, [ [ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: true, txHash: "0x..." } ] ``` -[`BatchResultItem[]`](#batchresultitem)를 반환합니다. +[`BatchResultItem[]`](#batchresultitem)을 반환합니다. ### `relay(signedTx)` / `relayBatch(signedTxs)` -미리 서명된 GuaranteedTx 또는 배치로 릴레이합니다. [`nonceKeyForLane`](#noncekeyforlanelaneid)를 엔터프라이즈 nonce 키로 사용하여 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req)로 다른 곳에서 트랜잭션을 빌드하고 서명한 다음, 운영자에게 서명된 헥스만 전달합니다. +사전 서명된 GuaranteedTx 또는 배치로 릴레이합니다. Enterprise nonce 키에 [`nonceKeyForLane`](#noncekeyforlanelaneid)을 사용하여 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req)로 다른 곳에서 트랜잭션을 빌드하고 서명한 다음 운영자에게 서명된 hex만 전달합니다. ```ts import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; @@ -261,7 +262,7 @@ const signed = await buildGuaranteedTx(toSigner(signer), stableTestnet.id, { gas: 21_000n, gasFeeCap, gasTipCap, - nonce, // 계정의 현재 2D-레인 nonce + nonce, // 계정의 현재 2D-레인 논스 nonceKey: nonceKeyForLane(0n), }); const { txHash } = await gb.relay(signed); @@ -271,11 +272,11 @@ const { txHash } = await gb.relay(signed); { txHash: "0xabcd...7890" } ``` -## 보장 릴레이 트랜잭션 +## 보장된 릴레이 트랜잭션 -`guaranteedWaiver` 모듈은 위 두 가지 레일을 결합합니다. 즉, 보장된 블록 공간을 통해 라우팅되는 가스 면제 트랜잭션입니다. 내부 및 외부 트랜잭션 모두 하나의 엔터프라이즈 `nonceKey`를 공유하는 `0x3F` CustomTx이므로 `guaranteedBlock`처럼 게이트웨이를 통해 브로드캐스트됩니다. 웨이버가 가스를 지원하므로 사용자는 `gasWaiver`처럼 잔액이나 수수료 필드가 필요하지 않습니다. 모든 메서드는 `H_inner`를 반환합니다. +`guaranteedWaiver` 모듈은 위에 있는 두 가지 레일을 결합합니다: 보장된 블록 공간을 통해 라우팅되는 가스 면제 트랜잭션. 내부 및 외부 트랜잭션 모두 하나의 Enterprise `nonceKey`를 공유하는 `0x3F` CustomTx이므로 `guaranteedBlock`과 같이 게이트웨이를 통해 브로드캐스트됩니다. 면제가 가스를 보증하므로 사용자는 `gasWaiver`처럼 잔액이나 수수료 필드가 필요하지 않습니다. 모든 메서드는 `H_inner`를 반환합니다. -`guaranteedWaiver`와 `enterpriseRpcEndpoints`를 사용하여 활성화합니다. +`guaranteedWaiver`와 `enterpriseRpcEndpoints`를 사용하여 활성화하세요. ```ts const enterprise = createStableEnterprise({ @@ -292,23 +293,23 @@ const gw = enterprise.guaranteedWaiver!; ### `GuaranteedWaiverConfig` -[`ValidationLimits`](#validationlimits) 및 [`SignerSource`](#signersource)를 확장합니다. `GasWaiverConfig`와 정확히 동일하게 Outer-wrapper 웨이버 키를 소싱(`signer`, 그 다음 `account`, 그 다음 환경 변수)하고 동일한 `maxGasLimit`, `maxDataLength` 및 `allowedTargets` 정책 제어를 허용합니다. +[`ValidationLimits`](#validationlimits) 및 [`SignerSource`](#signersource)를 확장합니다. `GasWaiverConfig`와 똑같이 외부 래퍼 면제 키를 소싱(`signer`, `account`, 환경 변수)하며 동일한 `maxGasLimit`, `maxDataLength`, `allowedTargets` 정책 제어를 허용합니다. | **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `signer` | `Signer?` | custody 서명자로서 화이트리스트에 등록된 웨이버 키(외부 래퍼에 서명). `account`보다 우선합니다. [서명 키 및 Custody](#signing-keys-and-custody)를 참조하세요. | -| `account` | `LocalAccount?` | 인-프로세스 viem 계정으로서의 웨이버 키입니다. 둘 다 설정되지 않은 경우 `STABLE_ENTERPRISE_PRIVATE_KEY`로 폴백합니다. | -| `laneId` | `bigint` | 엔터프라이즈 레인 ID입니다. `[0, ENTERPRISE_MASK - 1]` 범위 내에 있어야 합니다. | +| `signer` | `Signer?` | (외부 래퍼에 서명하는) 허용된 면제 키를 보관 서명자로 사용합니다. `account`보다 우선합니다. [서명 키 및 보관](#signing-keys-and-custody)을 참조하십시오. | +| `account` | `LocalAccount?` | 인-프로세스 viem 계정으로 사용되는 면제 키입니다. 둘 다 설정되지 않은 경우 `STABLE_ENTERPRISE_PRIVATE_KEY`로 대체됩니다. | +| `laneId` | `bigint` | Enterprise 레인 ID입니다. `[0, ENTERPRISE_MASK - 1]` 범위에 있어야 합니다. | ### `send(user, tx)` / `sendBatch(user, txs)` -`user`에서 내부 `0x3F` CustomTx를 빌드 및 서명하고, 웨이버 키로 래핑하여 릴레이합니다. 가스가 면제되므로 수수료 필드는 필요하지 않습니다. 내부 2D nonce는 게이트웨이에서 발견되며, 배치는 해당 기본값에서 자동으로 순서가 지정됩니다. +`user`에서 내부 `0x3F` CustomTx를 빌드하고 서명한 다음 면제 키로 래핑하고 릴레이합니다. 가스가 면제되므로 수수료 필드가 필요하지 않습니다. 내부 2D 논스는 게이트웨이에서 검색되며 배치는 해당 베이스에서 자동으로 순서가 지정됩니다. ```ts // 단일 const { txHash } = await gw.send(user, { to: recipient }); -// 배치 +// 배치 (batch) const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); ``` @@ -316,11 +317,11 @@ const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); { txHash: "0x8f3a...2d41" } ``` -`tx` 인수는 선택적 `nonce`가 추가된 [`GuaranteedWaiverTxRequest`](#guaranteedwaivertxrequest)입니다. `send`는 [`RelayResult`](#relayresult)를 반환하고, `sendBatch`는 [`BatchResultItem[]`](#batchresultitem)를 반환합니다. +`tx` 인수는 [`GuaranteedWaiverTxRequest`](#guaranteedwaivertxrequest)와 선택적인 `nonce`입니다. `send`는 [`RelayResult`](#relayresult)를 반환하고, `sendBatch`는 [`BatchResultItem[]`](#batchresultitem)를 반환합니다. ### `relay(signedInnerTx)` / `relayBatch(signedInnerTxs)` -비 custody 흐름의 경우, 사용자는 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req) (수수료 `0n`, `nonceKeyForLane(laneId)` 사용)로 내부 `0x3F` CustomTx에 서명하고 운영자에게 서명된 헥스만 전달합니다. 운영자는 웨이버 키로 래핑하고 릴레이합니다. +비수탁 흐름의 경우 사용자는 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req) (수수료 `0n`, `nonceKeyForLane(laneId)` 사용)로 내부 `0x3F` CustomTx에 서명하고 서명된 hex만 운영자에게 전달합니다. 운영자는 면제 키로 이를 래핑하고 릴레이합니다. ```ts import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; @@ -328,12 +329,12 @@ import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enter const signedInner = await buildGuaranteedTx(toSigner(user), stableTestnet.id, { to, gas: 100_000n, - gasFeeCap: 0n, // 면제 + gasFeeCap: 0n, // 면제됨 gasTipCap: 0n, nonce, nonceKey: nonceKeyForLane(0n), }); -const { txHash } = await gw.relay(signedInner); // 웨이버는 래핑 + 브로드캐스트 → H_inner +const { txHash } = await gw.relay(signedInner); // 면제가 래핑 + 브로드캐스트 → H_inner ``` ```text @@ -342,11 +343,11 @@ const { txHash } = await gw.relay(signedInner); // 웨이버는 래핑 + 브로 ## 빌드 헬퍼 -비 custody `relay` 경로를 위한 하위 수준 서명자입니다. 각각 서명된 트랜잭션을 `Hex`로 반환하며, nonce 가져오기 또는 수수료 추정은 없습니다. 첫 번째 인수는 [`Signer`](#signing-keys-and-custody)입니다. `toSigner(account)`로 viem 계정을 래핑하거나 `awsKmsSigner`와 같은 custody 서명자를 전달합니다. +비수탁 `relay` 경로를 위한 하위 수준 서명자. 각각 서명된 트랜잭션을 `Hex`로 반환하며 nonce 가져오기 또는 수수료 추정은 없습니다. 첫 번째 인수는 [`Signer`](#signing-keys-and-custody)입니다. `toSigner(account)`로 viem 계정을 래핑하거나 `awsKmsSigner`와 같은 커스터디 서명자를 전달하세요. ### `buildWaiverInnerTx(signer, chainId, req)` -웨이버 고정값(`gasPrice: 0`, 레거시 유형 및 지정된 `chainId`)이 포함된 웨이버 준비 InnerTx에 서명합니다. `req`는 필수 `nonce`가 추가된 [`WaiverInnerTx`](#waiverinnertx)입니다. +면제 불변성이 포함된 웨이버-레디 InnerTx에 서명합니다. `gasPrice: 0`, 레거시 유형 및 지정된 `chainId`. `req`는 [`WaiverInnerTx`](#waiverinnertx)와 필수 `nonce`입니다. ```ts const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to, data, gas: 150_000n, nonce }); @@ -354,15 +355,15 @@ const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to, ### `buildGuaranteedTx(signer, chainId, req)` -GuaranteedTx(`0x3F` CustomTx)를 빌드하고 서명합니다. `req`는 필수 `nonce` 및 `nonceKey`가 추가된 [`GuaranteedTxRequest`](#guaranteedtxrequest)입니다. +GuaranteedTx(`0x3F` CustomTx)를 빌드하고 서명합니다. `req`는 [`GuaranteedTxRequest`](#guaranteedtxrequest)와 필수 `nonce` 및 `nonceKey`입니다. ### `buildGuaranteedWaiverTx(...)` -미리 서명된 내부 트랜잭션을 외부 `0x3F` 웨이버 CustomTx로 래핑합니다. `guaranteedWaiver.relay`에서 내부적으로 사용됩니다. 고급 흐름을 위해 내보내집니다. +사전 서명된 내부를 외부 `0x3F` 면제 CustomTx로 래핑합니다. `guaranteedWaiver.relay`에서 내부적으로 사용됩니다. 고급 흐름을 위해 내보내집니다. ### `nonceKeyForLane(laneId)` -`buildGuaranteedTx`에서 사용하기 위한 레인 ID의 엔터프라이즈 `nonceKey`를 반환합니다. +`buildGuaranteedTx`에서 사용할 레인 ID에 대한 Enterprise `nonceKey`를 반환합니다. ```ts import { nonceKeyForLane } from "@stablechain/enterprise"; @@ -374,16 +375,16 @@ const nonceKey = nonceKeyForLane(0n); ### `SignerSource` -웨이버 모듈(`gasWaiver`, `guaranteedWaiver`)이 수락하는 서명 키 필드입니다. `signer`, 그 다음 `account`, 그 다음 `STABLE_ENTERPRISE_PRIVATE_KEY` 환경 변수 순으로 해결됩니다. [서명 키 및 Custody](#signing-keys-and-custody)를 참조하세요. +면제 모듈(`gasWaiver`, `guaranteedWaiver`)이 허용하는 서명 키 필드입니다. `signer`, `account`, 클라이언트의 최상위 [`signer`](#stableenterpriseconfig), `STABLE_ENTERPRISE_PRIVATE_KEY` 환경 변수 순으로 해결됩니다. [서명 키 및 커스터디](#signing-keys-and-custody)를 참조하십시오. | **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `signer` | `Signer?` | custody 등급 서명자(AWS KMS, HSM 또는 `privateKeySigner`). `account`보다 우선합니다. | -| `account` | `LocalAccount?` | `toSigner`를 통해 `Signer`로 적용된 인-프로세스 viem 계정입니다. | +| `signer` | `Signer?` | 커스터디 등급 서명자(AWS KMS, HSM 또는 `privateKeySigner`). `account`보다 우선합니다. | +| `account` | `LocalAccount?` | `toSigner`를 통해 `Signer`로 조정된 인-프로세스 viem 계정입니다. | ### `Signer` -SDK가 32바이트 다이제스트를 통해 서명하는 플러그인 가능한 서명자이므로 키는 custody 백엔드를 벗어나지 않습니다. `awsKmsSigner`, `toSigner`, `privateKeySigner` 또는 `envSigner`로 생성합니다. +SDK가 32바이트 다이제스트를 통해 서명하는 플러그형 서명자이므로 키가 커스터디 백엔드를 떠나지 않습니다. `awsKmsSigner`, `toSigner`, `privateKeySigner` 또는 `envSigner`로 하나를 구성합니다. ```ts interface Signer { @@ -392,34 +393,34 @@ interface Signer { } ``` -| **헬퍼** | **가져오기** | **설명** | +| **도우미** | **가져오기** | **설명** | | :--- | :--- | :--- | -| `awsKmsSigner({ keyId, client? })` | `@stablechain/enterprise/aws-kms` | AWS KMS `ECC_SECG_P256K1` 키가 지원하는 서명자입니다. `Promise`를 반환합니다. | -| `toSigner(account)` | `@stablechain/enterprise` | viem `LocalAccount`를 `Signer`에 적용합니다. | +| `awsKmsSigner({ keyId, client? })` | `@stablechain/enterprise/aws-kms` | AWS KMS `ECC_SECG_P256K1` 키로 지원되는 서명자입니다. `Promise`를 반환합니다. | +| `toSigner(account)` | `@stablechain/enterprise` | viem `LocalAccount`를 `Signer`로 조정합니다. | | `privateKeySigner(key)` | `@stablechain/enterprise` | 프로세스에 보관된 원시 개인 키를 래핑하는 서명자입니다. | | `envSigner(varName?)` | `@stablechain/enterprise` | `STABLE_ENTERPRISE_PRIVATE_KEY` (또는 `varName`)에서 키를 읽는 서명자입니다. | ### `WaiverInnerTx` -호출당 변동하는 InnerTx의 필드입니다. +각 호출마다 달라지는 InnerTx 필드. | **필드** | **유형** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `to` | `Address` | | 대상 주소: ERC-20 전송을 위한 토큰 계약, 네이티브 전송을 위한 수신자입니다. | -| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | 가스 한도입니다. `gasPrice`가 0이므로 관대한 한도는 무료입니다. | -| `data` | `Hex?` | `"0x"` | Calldata입니다. | -| `value` | `bigint?` | `0n` | 전송할 네이티브 값입니다. | +| `to` | `Address` | | 대상 주소: ERC-20 전송의 토큰 계약, 네이티브의 수신자. | +| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | 가스 한도. `gasPrice`가 0이므로 관대한 한도는 무료입니다. | +| `data` | `Hex?` | `"0x"` | 콜데이터. | +| `value` | `bigint?` | `0n` | 보낼 네이티브 값. | ### `GuaranteedTxRequest` | **필드** | **유형** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `to` | `Address?` | | 대상 주소입니다. | -| `gas` | `bigint` | | 가스 한도입니다. 필수입니다. | -| `gasFeeCap` | `bigint` | | `maxFeePerGas`입니다. 필수입니다. | -| `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`입니다. 필수입니다. | -| `data` | `Hex?` | `"0x"` | Calldata입니다. | -| `value` | `bigint?` | `0n` | 전송할 네이티브 값입니다. | +| `to` | `Address?` | | 대상 주소. | +| `gas` | `bigint` | | 가스 한도. 필수. | +| `gasFeeCap` | `bigint` | | `maxFeePerGas`. 필수. | +| `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`. 필수. | +| `data` | `Hex?` | `"0x"` | 콜데이터. | +| `value` | `bigint?` | `0n` | 보낼 네이티브 값. | ### `GuaranteedWaiverTxRequest` @@ -427,10 +428,10 @@ interface Signer { | **필드** | **유형** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `to` | `Address` | | 대상 주소입니다. | -| `gas` | `bigint?` | 공유 내부 가스 기본값 | 가스 한도입니다. | -| `data` | `Hex?` | `"0x"` | Calldata입니다. | -| `value` | `bigint?` | `0n` | 전송할 네이티브 값입니다. 웨이버의 경우 값 전송이 허용됩니다. | +| `to` | `Address` | | 대상 주소. | +| `gas` | `bigint?` | 공유 내부 가스 기본값 | 가스 한도. | +| `data` | `Hex?` | `"0x"` | 콜데이터. | +| `value` | `bigint?` | `0n` | 보낼 네이티브 값. 값 전송은 면제에 허용됩니다. | ### `ValidationLimits` @@ -438,16 +439,16 @@ interface Signer { | **필드** | **유형** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `maxGasLimit` | `bigint?` | `10_000_000n` | InnerTx의 최대 가스 한도입니다. 초과하면 `GAS_LIMIT_EXCEEDED`와 함께 실패합니다. | -| `maxDataLength` | `number?` | `131_072` (128KB) | 바이트 단위의 최대 calldata 크기입니다. 초과하면 `DATA_TOO_LARGE`와 함께 실패합니다. | -| `allowedTargets` | `AllowedTarget[]?` | | 웨이버가 후원할 수 있는 허용된 계약 및 메서드의 화이트리스트입니다. 설정된 경우 목록 외부의 대상은 `TARGET_NOT_ALLOWED`와 함께 실패합니다. | +| `maxGasLimit` | `bigint?` | `10_000_000n` | InnerTx에 대한 최대 가스 한도. 이를 초과하면 `GAS_LIMIT_EXCEEDED`로 실패합니다. | +| `maxDataLength` | `number?` | `131_072` (128 KB) | 바이트 단위 최대 콜데이터 크기. 이를 초과하면 `DATA_TOO_LARGE`로 실패합니다. | +| `allowedTargets` | `AllowedTarget[]?` | | 면제를 후원할 수 있는 계약 및 메서드의 허용 목록. 설정된 경우 목록 외의 대상은 `TARGET_NOT_ALLOWED`로 실패합니다. | ### `AllowedTarget` | **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `address` | `Address \| "*"` | InnerTx가 호출할 수 있는 계약 또는 모든 계약과 일치하는 `"*"`입니다. | -| `selectors` | `Hex[]?` | 허용된 4바이트 메서드 선택기 (예: ERC-20 `transfer`의 `"0xa9059cbb"`). `address`의 모든 메서드를 허용하려면 생략하거나 비워 둡니다. | +| `address` | `Address \| "*"` | InnerTx가 호출할 수 있는 계약, 또는 모든 계약과 일치하는 `"*"`입니다. | +| `selectors` | `Hex[]?` | 허용된 4바이트 메서드 셀렉터 (예: ERC-20 `transfer`의 `"0xa9059cbb"`). `address`에서 모든 메서드를 허용하려면 생략하거나 비워 둡니다. | ### `RelayResult` @@ -459,24 +460,24 @@ interface RelayResult { ### `BatchResultItem` -배치의 입력당 하나씩, 입력 순서대로 항목입니다. 단일 결과로 반환되는 경우 발생하는 대신, 일괄 처리된 결과는 각 항목별 결과를 표시합니다. +배치 내 입력당 하나의 항목으로 입력 순서대로 정렬됩니다. 예외를 발생시키는 대신, 배치는 항목별 결과를 표면화합니다. | **필드** | **유형** | **설명** | | :--- | :--- | :--- | | `index` | `number` | 입력 배열과 일치하는 0부터 시작하는 위치입니다. | -| `success` | `boolean` | 이 항목이 릴레이되었는지 여부입니다. | -| `txHash` | `Hash?` | 성공 시 존재: 내부 트랜잭션 해시입니다. | -| `error` | `{ code: ErrorCode; message: string }?` | 실패 시 존재합니다. | +| `success` | `boolean` | 이 항목이 릴레이되었는지 여부. | +| `txHash` | `Hash?` | 성공 시 현재: 내부 트랜잭션 해시. | +| `error` | `{ code: ErrorCode; message: string }?` | 실패 시 현재. | ## 오류 -단일 트랜잭션 메서드(`send`, `relay`)는 거부 시 오류를 발생시킵니다. 일괄 처리 메서드는 대신 [`BatchResultItem.error`](#batchresultitem)에서 항목당 실패를 보고합니다. 모든 오류 클래스는 `StableEnterpriseError`를 확장합니다. +단일 트랜잭션 메서드(`send`, `relay`)는 거부 시 예외를 발생시킵니다. 배치 메서드는 [`BatchResultItem.error`](#batchresultitem)에서 항목별 실패를 보고합니다. 모든 오류 클래스는 `StableEnterpriseError`를 확장합니다. -| **클래스** | **오류 발생 시** | **유용한 필드** | +| **클래스** | **발생 시점** | **유용한 필드** | | :--- | :--- | :--- | -| `StableEnterpriseError` | 모든 SDK 오류의 기본 클래스입니다. | `message` | -| `StableEnterpriseRelayError` | RPC 또는 릴레이 계층에서 트랜잭션이 거부됩니다. | `code` | -| `WaiverValidationError` | InnerTx가 브로드캐스트 전에 정책 검사(가스, 데이터 크기 또는 대상 허용 목록)에 실패합니다. | `code` | +| `StableEnterpriseError` | 모든 SDK 오류의 기본 클래스. | `message` | +| `StableEnterpriseRelayError` | RPC 또는 릴레이 계층에서 트랜잭션이 거부됨. | `code` | +| `WaiverValidationError` | 브로드캐스트 전에 InnerTx가 정책 검사(가스, 데이터 크기 또는 대상 허용 목록)에 실패함. | `code` | ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -497,33 +498,33 @@ StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not ### `ErrorCode` -발생한 오류 또는 `BatchResultItem.error`의 `code`는 다음 중 하나입니다. +던져진 오류 또는 `BatchResultItem.error`의 `code`는 다음 중 하나입니다. | **코드** | **의미** | | :--- | :--- | -| `UNKNOWN_ERROR` | 특정 코드를 사용할 수 없는 경우의 폴백입니다. | -| `BROADCAST_FAILED` | RPC 계층에서 브로드캐스트가 거부되거나 게이트웨이가 릴레이에 실패했습니다. | -| `INVALID_TRANSACTION` | InnerTx가 디코딩 또는 파싱에 실패했습니다. | +| `UNKNOWN_ERROR` | 특정 코드를 사용할 수 없을 때의 대체. | +| `BROADCAST_FAILED` | RPC 계층에서 브로드캐스트가 거부되었거나 게이트웨이가 릴레이에 실패했습니다. | +| `INVALID_TRANSACTION` | InnerTx 디코딩 또는 구문 분석에 실패했습니다. | | `INVALID_SIGNATURE` | 서명 확인에 실패했습니다. | | `UNSUPPORTED_TX_TYPE` | InnerTx 유형이 레거시, eip2930 또는 eip1559가 아닙니다. | -| `WRONG_CHAIN_ID` | InnerTx `chainId`가 누락되었거나 대상 체인과 일치하지 않습니다. | -| `NON_ZERO_GAS_PRICE` | InnerTx가 0이 아닌 가스 가격을 가지고 있습니다(웨이버의 경우 0이어야 함). | -| `GAS_LIMIT_EXCEEDED` | InnerTx 가스 한도가 `maxGasLimit`을 초과했습니다. | -| `DATA_TOO_LARGE` | InnerTx calldata가 `maxDataLength`를 초과했습니다. | +| `WRONG_CHAIN_ID` | InnerTx의 `chainId`가 없거나 대상 체인과 일치하지 않습니다. | +| `NON_ZERO_GAS_PRICE` | InnerTx는 0이 아닌 가스 가격을 가지고 있습니다(면제의 경우 0이어야 함). | +| `GAS_LIMIT_EXCEEDED` | InnerTx 가스 한도가 `maxGasLimit`을 초과합니다. | +| `DATA_TOO_LARGE` | InnerTx 콜데이터가 `maxDataLength`를 초과합니다. | | `TARGET_NOT_ALLOWED` | InnerTx 대상이 `allowedTargets`에 없습니다. | -| `GATEWAY_UNAUTHORIZED` | 엔터프라이즈 RPC 게이트웨이가 API 키를 거부했습니다(누락, 유효하지 않거나 만료됨). | -| `QUOTA_EXCEEDED` | 엔터프라이즈 RPC 게이트웨이 가스 할당량이 소진되었습니다. | +| `GATEWAY_UNAUTHORIZED` | Enterprise RPC 게이트웨이가 API 키를 거부했습니다(누락, 유효하지 않음 또는 만료됨). | +| `QUOTA_EXCEEDED` | Enterprise RPC 게이트웨이 가스 할당량이 소진되었습니다. | ## 상수 | **상수** | **유형** | **설명** | | :--- | :--- | :--- | -| `DEFAULT_INNER_GAS` | `bigint` | `gas`가 생략된 경우 기본 InnerTx 가스 한도(`150_000n`)입니다. | -| `ENTERPRISE_FLAG` | `bigint` | 레인의 `nonceKey`에 설정된 엔터프라이즈 비트입니다. | -| `ENTERPRISE_MASK` | `bigint` | 레인 ID의 상한입니다: `laneId`는 `[0, ENTERPRISE_MASK - 1]` 범위 내에 있어야 합니다. | +| `DEFAULT_INNER_GAS` | `bigint` | `gas`가 생략되었을 때의 기본 InnerTx 가스 제한 (`150_000n`)입니다. | +| `ENTERPRISE_FLAG` | `bigint` | 레인의 `nonceKey`에 설정된 Enterprise 비트입니다. | +| `ENTERPRISE_MASK` | `bigint` | 레인 ID의 상한: `laneId`는 `[0, ENTERPRISE_MASK - 1]` 범위에 있어야 합니다. | ## 다음 권장 사항 -- [**Stable Enterprise SDK**](/ko/explanation/enterprise-sdk): 레일이 무엇이고 언제 사용해야 하는지. -- [**가스 웨이버 프로토콜**](/ko/reference/gas-waiver-api): 트랜잭션 형식, 마커 라우팅 및 거버넌스 제어. -- [**보장 블록 공간**](/ko/explanation/guaranteed-blockspace): Stable이 엔터프라이즈 워크로드에 대한 블록 용량을 예약하는 방법. +- [**Stable Enterprise SDK**](/ko/explanation/enterprise-sdk): 레일이 무엇이며 언제 사용해야 하는지. +- [**가스 면제 프로토콜**](/ko/reference/gas-waiver-api): 트랜잭션 형식, 마커 라우팅 및 거버넌스 제어. +- [**보장된 블록 공간**](/ko/explanation/guaranteed-blockspace): Stable이 엔터프라이즈 워크로드에 대한 블록 용량을 예약하는 방법. diff --git a/docs/sidebar.json b/docs/sidebar.json index f610006..d9bc4b8 100644 --- a/docs/sidebar.json +++ b/docs/sidebar.json @@ -689,7 +689,7 @@ ], "/ko": [ { - "text": "학습하기", + "text": "학습", "collapsed": true, "items": [ { @@ -725,7 +725,7 @@ "link": "/ko/explanation/ethereum-compatibility" }, { - "text": "완결성", + "text": "확정성", "link": "/ko/explanation/finality" }, { @@ -759,7 +759,7 @@ "link": "/ko/explanation/usdt0-bridging" }, { - "text": "브리지 보안", + "text": "브릿지 보안", "link": "/ko/explanation/bridge-security" }, { @@ -775,11 +775,11 @@ "link": "/ko/explanation/gas-waiver" }, { - "text": "블록 공간 보장", + "text": "보장된 블록 공간", "link": "/ko/explanation/guaranteed-blockspace" }, { - "text": "USDT 전송 애그리게이터", + "text": "USDT 전송 Aggregator", "link": "/ko/explanation/usdt-transfer-aggregator" }, { @@ -793,7 +793,7 @@ "collapsed": true, "items": [ { - "text": "핵심 최적화 개요", + "text": "코어 최적화 개요", "link": "/ko/explanation/core-optimization-overview" }, { @@ -823,19 +823,19 @@ "collapsed": true, "items": [ { - "text": "사용 사례: 결제", + "text": "결제 사용 사례", "link": "/ko/explanation/use-case-payments" }, { - "text": "사용 사례: 급여", + "text": "급여 사용 사례", "link": "/ko/explanation/use-case-payroll" }, { - "text": "사용 사례: 후원", + "text": "스폰서 사용 사례", "link": "/ko/explanation/use-case-sponsored" }, { - "text": "사용 사례: 비공개", + "text": "프라이빗 사용 사례", "link": "/ko/explanation/use-case-private" } ] @@ -855,7 +855,7 @@ ] }, { - "text": "구축하기", + "text": "구축", "collapsed": true, "items": [ { @@ -909,7 +909,7 @@ "link": "/ko/how-to/relay-with-gas-waiver" }, { - "text": "블록 공간 보장", + "text": "보장된 블록 공간", "link": "/ko/how-to/send-guaranteed-transactions" }, { @@ -969,7 +969,7 @@ "link": "/ko/tutorial/send-usdt0" }, { - "text": "가스 없는 트랜잭션", + "text": "제로 가스 트랜잭션", "link": "/ko/how-to/zero-gas-transactions" }, { @@ -977,7 +977,7 @@ "link": "/ko/how-to/work-with-usdt-gas" }, { - "text": "USDT0 브리지", + "text": "USDT0 브릿지", "link": "/ko/tutorial/bridge-usdt0" } ] @@ -995,7 +995,7 @@ "link": "/ko/how-to/subscribe-and-collect" }, { - "text": "송장으로 결제", + "text": "인보이스로 결제", "link": "/ko/how-to/pay-with-invoice" } ] @@ -1021,7 +1021,7 @@ "link": "/ko/reference/subscriptions" }, { - "text": "송장", + "text": "인보이스", "link": "/ko/reference/invoices" }, { @@ -1029,7 +1029,7 @@ "link": "/ko/reference/pay-per-call" }, { - "text": "향후 사용 사례", + "text": "예정된 사용 사례", "link": "/ko/explanation/upcoming-use-cases" } ] @@ -1057,11 +1057,11 @@ "link": "/ko/tutorial/smart-contract" }, { - "text": "계약 검증", + "text": "계약 확인", "link": "/ko/how-to/verify-contract" }, { - "text": "계약 색인", + "text": "색인 계약", "link": "/ko/how-to/index-contract" } ] @@ -1091,11 +1091,11 @@ "link": "/ko/reference/bank-module-api" }, { - "text": "배포 모듈", + "text": "분배 모듈", "link": "/ko/explanation/distribution-module" }, { - "text": "배포 모듈 API", + "text": "분배 모듈 API", "link": "/ko/reference/distribution-module-api" }, { @@ -1115,7 +1115,7 @@ "link": "/ko/reference/system-transactions-api" }, { - "text": "언본딩 추적", + "text": "언바운딩 추적", "link": "/ko/how-to/track-unbonding" }, { @@ -1133,7 +1133,7 @@ ] }, { - "text": "통합하기", + "text": "통합", "collapsed": true, "items": [ { @@ -1213,7 +1213,7 @@ "collapsed": true, "items": [ { - "text": "브리지", + "text": "브릿지", "link": "/ko/reference/bridges" }, { @@ -1241,7 +1241,7 @@ "link": "/ko/reference/wallets" }, { - "text": "수호", + "text": "커스터디", "link": "/ko/reference/custody" }, { @@ -1251,7 +1251,7 @@ ] }, { - "text": "프로덕션 준비도", + "text": "프로덕션 준비", "link": "/ko/how-to/production-readiness" }, { @@ -1271,7 +1271,7 @@ ] }, { - "text": "운영하기", + "text": "운영", "collapsed": true, "items": [ { @@ -1279,7 +1279,7 @@ "link": "/ko/reference/node-operations-overview" }, { - "text": "노드 시스템 요구 사항", + "text": "노드 시스템 요구사항", "link": "/ko/reference/node-system-requirements" }, { @@ -1325,7 +1325,7 @@ "link": "/ko/explanation/ai-agents-guides" }, { - "text": "x402 및 MPP를 통해 지불", + "text": "x402 및 MPP를 통해 결제", "collapsed": true, "items": [ { @@ -1341,7 +1341,7 @@ "link": "/ko/explanation/mpp-sessions" }, { - "text": "호출당 지불 구축", + "text": "호출당 결제 구축", "link": "/ko/how-to/build-pay-per-call" }, { @@ -1349,7 +1349,7 @@ "link": "/ko/how-to/build-mpp-endpoint" }, { - "text": "MCP로 지불", + "text": "MCP로 결제", "link": "/ko/how-to/pay-with-mcp" } ] @@ -1359,11 +1359,11 @@ "collapsed": true, "items": [ { - "text": "AI 개발", + "text": "AI를 통한 개발", "link": "/ko/how-to/develop-with-ai" }, { - "text": "에이전트 퍼실리테이터", + "text": "에이전트 촉진자", "link": "/ko/reference/agentic-facilitators" }, { @@ -1401,11 +1401,11 @@ "link": "/cn/explanation/core-concepts" }, { - "text": "主要特点", + "text": "主要功能", "link": "/cn/explanation/key-features" }, { - "text": "以太坊比较", + "text": "以太坊对比", "link": "/cn/explanation/ethereum-comparison" }, { @@ -1413,7 +1413,7 @@ "link": "/cn/explanation/ethereum-compatibility" }, { - "text": "最终性", + "text": "确定性", "link": "/cn/explanation/finality" }, { @@ -1447,7 +1447,7 @@ "link": "/cn/explanation/usdt0-bridging" }, { - "text": "跨链桥安全性", + "text": "跨链安全", "link": "/cn/explanation/bridge-security" }, { @@ -1459,11 +1459,11 @@ "link": "/cn/explanation/usdt0-behavior" }, { - "text": "Gas 减免", + "text": "Gas 豁免", "link": "/cn/explanation/gas-waiver" }, { - "text": "保证区块空间", + "text": "担保块空间", "link": "/cn/explanation/guaranteed-blockspace" }, { @@ -1551,7 +1551,7 @@ "link": "/cn/explanation/build-overview" }, { - "text": "快速开始", + "text": "快速入门", "link": "/cn/tutorial/quick-start" }, { @@ -1585,7 +1585,7 @@ ] }, { - "text": "企业级 SDK", + "text": "企业 SDK", "collapsed": true, "items": [ { @@ -1597,11 +1597,11 @@ "link": "/cn/how-to/relay-with-gas-waiver" }, { - "text": "保证区块空间", + "text": "担保块空间", "link": "/cn/how-to/send-guaranteed-transactions" }, { - "text": "保障中继交易", + "text": "担保中继交易", "link": "/cn/how-to/guaranteed-relayed-transactions" }, { @@ -1611,7 +1611,7 @@ ] }, { - "text": "用户引导", + "text": "用户 onboarding", "collapsed": true, "items": [ { @@ -1683,7 +1683,7 @@ "link": "/cn/how-to/subscribe-and-collect" }, { - "text": "发票支付", + "text": "通过发票支付", "link": "/cn/how-to/pay-with-invoice" } ] @@ -1725,7 +1725,7 @@ ] }, { - "text": "交付合约", + "text": "发布合约", "collapsed": true, "items": [ { @@ -1787,11 +1787,11 @@ "link": "/cn/reference/distribution-module-api" }, { - "text": "质押模块", + "text": "Staking 模块", "link": "/cn/explanation/staking-module" }, { - "text": "质押模块 API", + "text": "Staking 模块 API", "link": "/cn/reference/staking-module-api" }, { @@ -1879,19 +1879,19 @@ ] }, { - "text": "Gas 减免服务", + "text": "Gas 豁免服务", "collapsed": true, "items": [ { - "text": "集成 Gas 减免", + "text": "集成 Gas 豁免", "link": "/cn/how-to/integrate-gas-waiver" }, { - "text": "自托管 Gas 减免", + "text": "自托管 Gas 豁免", "link": "/cn/how-to/self-hosted-gas-waiver" }, { - "text": "Gas 减免 API", + "text": "Gas 豁免 API", "link": "/cn/reference/gas-waiver-api" } ] @@ -1901,7 +1901,7 @@ "collapsed": true, "items": [ { - "text": "跨链桥", + "text": "桥", "link": "/cn/reference/bridges" }, { @@ -1921,7 +1921,7 @@ "link": "/cn/reference/network-routing" }, { - "text": "法币通道", + "text": "出入金", "link": "/cn/reference/ramps" }, { @@ -1951,7 +1951,7 @@ "collapsed": true, "items": [ { - "text": "品牌工具包", + "text": "品牌资料", "link": "/cn/resources/brand-kit" } ] @@ -2047,15 +2047,15 @@ "collapsed": true, "items": [ { - "text": "与 AI 协同开发", + "text": "与 AI 开发", "link": "/cn/how-to/develop-with-ai" }, { - "text": "智能协调器", + "text": "Agentic 促进者", "link": "/cn/reference/agentic-facilitators" }, { - "text": "智能钱包", + "text": "Agentic 钱包", "link": "/cn/reference/agentic-wallets" } ] From 34bf6b8e368989cbf584059c3f178f034014ec95 Mon Sep 17 00:00:00 2001 From: bastienrp Date: Thu, 16 Jul 2026 10:08:24 +0200 Subject: [PATCH 16/20] docs: drop non-null assertions from Enterprise SDK code samples Remove the TypeScript `!` assertions from the code blocks (null-check the module instead), and explain gasFeeCap/gasTipCap as the EIP-1559 maxFeePerGas/maxPriorityFeePerGas in the guaranteed transactions guide. Co-Authored-By: Claude Opus 4.8 --- docs/pages/en/explanation/enterprise-sdk.mdx | 2 +- .../en/how-to/guaranteed-relayed-transactions.mdx | 4 ++-- docs/pages/en/how-to/relay-with-gas-waiver.mdx | 2 +- .../en/how-to/send-guaranteed-transactions.mdx | 6 ++++-- docs/pages/en/reference/enterprise-sdk.mdx | 14 +++++++------- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/docs/pages/en/explanation/enterprise-sdk.mdx b/docs/pages/en/explanation/enterprise-sdk.mdx index c16b058..a632f3b 100644 --- a/docs/pages/en/explanation/enterprise-sdk.mdx +++ b/docs/pages/en/explanation/enterprise-sdk.mdx @@ -17,7 +17,7 @@ const enterprise = createStableEnterprise({ gasWaiver: { account: privateKeyToAccount("0xYOUR_WAIVER_KEY") }, }); -const { txHash } = await enterprise.gasWaiver!.send(user, { to: token, data }); +const { txHash } = await enterprise.gasWaiver.send(user, { to: token, data }); ``` ```text diff --git a/docs/pages/en/how-to/guaranteed-relayed-transactions.mdx b/docs/pages/en/how-to/guaranteed-relayed-transactions.mdx index 770f26c..007be0e 100644 --- a/docs/pages/en/how-to/guaranteed-relayed-transactions.mdx +++ b/docs/pages/en/how-to/guaranteed-relayed-transactions.mdx @@ -29,14 +29,14 @@ import { privateKeyToAccount } from "viem/accounts"; const enterprise = createStableEnterprise({ chain: stableTestnet, - enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // the gateway URL Stable provisions + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL], // the gateway URL Stable provisions guaranteedWaiver: { account: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`), laneId: 0n, // Enterprise lane }, }); -const gw = enterprise.guaranteedWaiver!; +const gw = enterprise.guaranteedWaiver; ``` ```text diff --git a/docs/pages/en/how-to/relay-with-gas-waiver.mdx b/docs/pages/en/how-to/relay-with-gas-waiver.mdx index d27d02a..c1b34aa 100644 --- a/docs/pages/en/how-to/relay-with-gas-waiver.mdx +++ b/docs/pages/en/how-to/relay-with-gas-waiver.mdx @@ -32,7 +32,7 @@ const enterprise = createStableEnterprise({ gasWaiver: { account: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`) }, }); -const gw = enterprise.gasWaiver!; +const gw = enterprise.gasWaiver; ``` ```text diff --git a/docs/pages/en/how-to/send-guaranteed-transactions.mdx b/docs/pages/en/how-to/send-guaranteed-transactions.mdx index c59ac1a..6da305c 100644 --- a/docs/pages/en/how-to/send-guaranteed-transactions.mdx +++ b/docs/pages/en/how-to/send-guaranteed-transactions.mdx @@ -30,14 +30,14 @@ import { privateKeyToAccount } from "viem/accounts"; const enterprise = createStableEnterprise({ chain: stableTestnet, - enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // the gateway URL Stable provisions + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL], // the gateway URL Stable provisions guaranteedBlock: { account: privateKeyToAccount(process.env.SIGNER_PRIVATE_KEY as `0x${string}`), // must be funded laneId: 0n, // Enterprise lane }, }); -const gb = enterprise.guaranteedBlock!; +const gb = enterprise.guaranteedBlock; ``` ```text @@ -67,6 +67,8 @@ console.log("Guaranteed tx:", txHash); Guaranteed tx: 0xabcd...7890 ``` +`gasFeeCap` is the maximum total fee per gas (the EIP-1559 `maxFeePerGas`) and `gasTipCap` is the maximum priority fee per gas (`maxPriorityFeePerGas`). Setting `gasTipCap` to the current gas price and `gasFeeCap` to twice it, as above, is a safe default. + The signer pays gas, so confirm it holds a balance before relaying. A GuaranteedTx from a zero-balance account fails. ## 3. Send a batch diff --git a/docs/pages/en/reference/enterprise-sdk.mdx b/docs/pages/en/reference/enterprise-sdk.mdx index 4f3e893..c89457c 100644 --- a/docs/pages/en/reference/enterprise-sdk.mdx +++ b/docs/pages/en/reference/enterprise-sdk.mdx @@ -30,7 +30,7 @@ added 2 packages, audited 3 packages in 2s ## `createStableEnterprise(config)` -Construct a `StableEnterpriseClient`. Each module is present only when you configure it, so guard with `!` or a null check before use. +Construct a `StableEnterpriseClient`. Each module is present only when you configure it, so null-check it before use. ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -74,7 +74,7 @@ import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; import { awsKmsSigner } from "@stablechain/enterprise/aws-kms"; // the KMS key must be ECC_SECG_P256K1 (secp256k1); the SDK derives the address from it -const signer = await awsKmsSigner({ keyId: process.env.KMS_KEY_ID! }); +const signer = await awsKmsSigner({ keyId: process.env.KMS_KEY_ID }); const enterprise = createStableEnterprise({ chain: stableTestnet, @@ -111,7 +111,7 @@ const enterprise = createStableEnterprise({ }, }); -const gw = enterprise.gasWaiver!; +const gw = enterprise.gasWaiver; ``` ### `GasWaiverConfig` @@ -193,14 +193,14 @@ Enable it with `guaranteedBlock` plus `enterpriseRpcEndpoints`: ```ts const enterprise = createStableEnterprise({ chain: stableTestnet, - enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // the gateway URL Stable provisions + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL], // the gateway URL Stable provisions guaranteedBlock: { account: privateKeyToAccount("0xFUNDED_SIGNER_KEY"), laneId: 0n, }, }); -const gb = enterprise.guaranteedBlock!; +const gb = enterprise.guaranteedBlock; ``` ### `GuaranteedBlockConfig` @@ -279,14 +279,14 @@ Enable it with `guaranteedWaiver` plus `enterpriseRpcEndpoints`: ```ts const enterprise = createStableEnterprise({ chain: stableTestnet, - enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // the gateway URL Stable provisions + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL], // the gateway URL Stable provisions guaranteedWaiver: { account: privateKeyToAccount("0xYOUR_WAIVER_KEY"), laneId: 0n, }, }); -const gw = enterprise.guaranteedWaiver!; +const gw = enterprise.guaranteedWaiver; ``` ### `GuaranteedWaiverConfig` From a551d74a5f4ae326303325417abd805d850369d4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 16 Jul 2026 08:11:35 +0000 Subject: [PATCH 17/20] i18n: auto-translate cn/ko for changed en content --- docs/pages/cn/explanation/enterprise-sdk.mdx | 50 ++-- .../guaranteed-relayed-transactions.mdx | 46 ++-- .../pages/cn/how-to/relay-with-gas-waiver.mdx | 60 ++--- .../how-to/send-guaranteed-transactions.mdx | 50 ++-- docs/pages/cn/reference/enterprise-sdk.mdx | 226 ++++++++--------- docs/pages/ko/explanation/enterprise-sdk.mdx | 44 ++-- .../guaranteed-relayed-transactions.mdx | 52 ++-- .../pages/ko/how-to/relay-with-gas-waiver.mdx | 46 ++-- .../how-to/send-guaranteed-transactions.mdx | 50 ++-- docs/pages/ko/reference/enterprise-sdk.mdx | 236 +++++++++--------- docs/sidebar.json | 136 +++++----- 11 files changed, 500 insertions(+), 496 deletions(-) diff --git a/docs/pages/cn/explanation/enterprise-sdk.mdx b/docs/pages/cn/explanation/enterprise-sdk.mdx index d2e5235..7ab51a8 100644 --- a/docs/pages/cn/explanation/enterprise-sdk.mdx +++ b/docs/pages/cn/explanation/enterprise-sdk.mdx @@ -1,70 +1,70 @@ --- source_path: explanation/enterprise-sdk.mdx -source_sha: c16b058331d58a968753ec4877bb47cd7377fe14 -title: "Stable 企业版 SDK" +source_sha: a632f3be5fbff966d9da230ec302b4ce4e6773f2 +title: "Stable Enterprise SDK" description: "使用类型化的 @stablechain/enterprise SDK 从后端中继免 gas 和保证区块空间的交易。" diataxis: "explanation" --- -# Stable 企业版 SDK +# Stable Enterprise SDK -`@stablechain/enterprise` 是一个用于 Stable 企业版交易通道的服务器端 TypeScript 客户端。它签署并中继两种特权交易:免 gas 交易(您为用户支付 gas)和保证区块空间交易(交易进入预留的企业通道)。您可以在一个客户端上启用其中一种或两种通道。 +`@stablechain/enterprise` 是 Stable 企业交易通道的服务器端 TypeScript 客户端。它会签署并中继两种特权交易:免 gas 交易(由您来支付用户的 gas)和保证区块空间交易(在保留的企业通道中处理)。您可以在一个客户端上启用其中一个或两个通道。 ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; -import { privateKeyToAccount } = "viem/accounts"; +import { privateKeyToAccount } from "viem/accounts"; const enterprise = createStableEnterprise({ chain: stableTestnet, gasWaiver: { account: privateKeyToAccount("0xYOUR_WAIVER_KEY") }, }); -const { txHash } = await enterprise.gasWaiver!.send(user, { to: token, data }); +const { txHash } = await enterprise.gasWaiver.send(user, { to: token, data }); ``` ```text txHash: 0x8f3a...2d41 ``` -调用返回 `H_inner`,即用户交易的哈希值,而不是承载它的包装器交易的哈希值。 +此调用返回 `H_inner`,即用户交易的哈希,而不是承载它的包装器交易的哈希。 ## SDK 的作用 -该 SDK 暴露了三个功能,每个模块一个。每个功能都是可选的且独立配置的,每个功能都带有自己的签名账户,因此您可以使用不同的密钥。 +SDK 暴露了三个功能,每个模块一个。每个功能都是可选的、独立配置的,并且都带有自己的签名账户,以便您可以使用单独的密钥。 -- **免 Gas 中继** (`gasWaiver`):构建、签署和中继免 gas 交易。一个白名单中的免除账户会包装用户的零 gas 交易,这样用户无需持有任何 USDT0 即可进行交易。请参阅[免 Gas](/cn/explanation/gas-waiver)。 -- **保证区块空间** (`guaranteedBlock`):通过企业 RPC 网关中继交易,使其进入预留的企业通道区块空间。与免 gas 不同,签名者支付自己的 gas。请参阅[保证区块空间](/cn/explanation/guaranteed-blockspace)。 -- **保证中继交易** (`guaranteedWaiver`):两者结合。通过保证区块空间路由的免 gas 交易,这样用户无需余额,交易仍会进入企业通道。 +- **免 gas 中继** (`gasWaiver`):构建、签署并中继免 gas 交易。一个白名单中的免 gas 账户会封装用户的零 gas 交易,这样用户就可以在不持有任何 USDT0 的情况下进行交易。请参阅[免 gas](/cn/explanation/gas-waiver)。 +- **保证区块空间** (`guaranteedBlock`):通过企业 RPC 网关中继交易,使其落在保留的企业通道区块空间中。与免 gas 不同,签名者支付自己的 gas。请参阅[保证区块空间](/cn/explanation/guaranteed-blockspace)。 +- **保证中继交易** (`guaranteedWaiver`):两者结合。一种通过保证区块空间路由的免 gas 交易,这样用户就不需要余额,并且交易仍然落在企业通道中。 -每个功能都提供相同的四个方法:`send` 和 `sendBatch` 用于 SDK 签名的托管路径,以及 `relay` 和 `relayBatch` 用于用户在其他地方签名并仅将签名后的十六进制数据交给您的非托管路径。 +每个功能都提供相同的四种方法:`send` 和 `sendBatch` 用于 SDK 签名的托管路径,以及 `relay` 和 `relayBatch` 用于用户在其他地方签名并只向您提供签名十六进制的非托管路径。 -## 访问 +## 访问权限 -企业版 SDK 目前仅在 Stable 测试网可用。 +企业 SDK 目前仅在 Stable Testnet 上可用。 -两个通道都受限。免 gas 需要治理注册的免除密钥,而保证区块空间需要企业 RPC 网关 API 密钥。要集成,请[联系 Stable](https://discord.gg/stablexyz) 获取访问权限。Stable 会为您提供所需的免除密钥和网关端点。 +这两个通道都是受限的。免 gas 需要治理注册的免 gas 密钥,而保证区块空间需要企业 RPC 网关 API 密钥。要进行集成,请[联系 Stable](https://discord.gg/stablexyz) 以获取访问权限。Stable 会为您提供所需的免 gas 密钥和网关端点。 ## 仅限服务器端 :::warning -企业版 SDK 是一个无状态的服务器端库,使用私钥进行签名。切勿在浏览器中运行它。将免责密钥和企业 RPC 网关 URL 保留在您的后端。 +企业 SDK 是一个无状态的服务器端库,使用私钥进行签名。切勿在浏览器中运行它。请将免 gas 密钥和企业 RPC 网关 URL 保留在您的后端。 ::: -豁免密钥是一个白名单中、由治理注册的账户:任何持有该密钥的人都可以在您的策略下资助 gas。企业 RPC 网关 URL 嵌入了您的 API 密钥。将两者都视为秘密。为了将豁免密钥排除在流程之外,请使用 AWS KMS 等托管签名器对其进行备份。请参阅[签名密钥和托管](/cn/reference/enterprise-sdk#signing-keys-and-custody)。 +免 gas 密钥是一个列入白名单的、经过治理注册的账户:任何持有它的人都可以根据您的策略支付 gas。企业 RPC 网关 URL 嵌入了您的 API 密钥。请将两者都视为秘密。为了使免 gas 密钥不被泄露,请使用 AWS KMS 等托管签名服务对其进行备份。请参阅[签名密钥和托管](/cn/reference/enterprise-sdk#signing-keys-and-custody)。 ## 何时使用 -如果您运营后端并希望为用户支付 gas 费用或保证您的交易能够被包含,请使用企业版 SDK。对于日常转账、桥接、兑换和从后端或浏览器获取的金库收益,请使用通用的 [Stable SDK](/cn/explanation/sdk-overview)。 +当您运营后端并希望为用户支付 gas 或为自己的流量保证交易包含时,请使用企业 SDK。对于后端或浏览器中的日常转账、桥接、兑换和金库收益,请改用通用[Stable SDK](/cn/explanation/sdk-overview)。 ## 从这里开始 -- [**免 gas 中继**](/cn/how-to/relay-with-gas-waiver):为用户支付 gas 费用,使其无需持有 USDT0 即可进行交易。 -- [**发送保证交易**](/cn/how-to/send-guaranteed-transactions):将交易放入预留的企业级区块空间。 -- [**保证中继交易**](/cn/how-to/guaranteed-relayed-transactions):结合这两种方式:在企业通道中进行免 gas 交易。 -- [**企业版 SDK 参考**](/cn/reference/enterprise-sdk):每个模块、方法、配置选项和错误类。 +- [**免 gas 中继**](/cn/how-to/relay-with-gas-waiver):为用户支付 gas,这样他们就可以在不持有 USDT0 的情况下进行交易。 +- [**发送保证交易**](/cn/how-to/send-guaranteed-transactions):将交易落在保留的企业通道区块空间中。 +- [**保证中继交易**](/cn/how-to/guaranteed-relayed-transactions):结合这两个通道:企业通道中的免 gas 交易。 +- [**企业 SDK 参考**](/cn/reference/enterprise-sdk):每个模块、方法、配置选项和错误类。 -## 接下来建议 +## 下一步建议 -- [**Gas 豁免协议**](/cn/reference/gas-waiver-api):交易格式、标记路由和治理控制。 +- [**免 gas 协议**](/cn/reference/gas-waiver-api):交易格式、标记路由和治理控制。 - [**Stable SDK**](/cn/explanation/sdk-overview):用于转账、桥接、兑换和收益的通用客户端。 -- [**连接到 Stable**](/cn/reference/connect):测试网的链 ID、RPC 端点和浏览器。 +- [**连接 Stable**](/cn/reference/connect):测试网的链 ID、RPC 端点和浏览器。 diff --git a/docs/pages/cn/how-to/guaranteed-relayed-transactions.mdx b/docs/pages/cn/how-to/guaranteed-relayed-transactions.mdx index db0f74e..efd32f8 100644 --- a/docs/pages/cn/how-to/guaranteed-relayed-transactions.mdx +++ b/docs/pages/cn/how-to/guaranteed-relayed-transactions.mdx @@ -1,29 +1,29 @@ --- source_path: how-to/guaranteed-relayed-transactions.mdx -source_sha: 770f26cb178bfd6e7b678d524f5148a39a3f9946 -title: "有保障的中继交易" -description: "使用 Enterprise SDK 通过有保障的区块空间中继免燃料费交易,这样用户无需余额即可进入企业通道。" +source_sha: 007be0e546cc1251771678ee74523b6a79a2d76d +title: "保证中继交易" +description: "通过 Enterprise SDK 经由保证的区块空间中继免 gas 交易,这样用户无需余额也能进入 Enterprise 通道。" diataxis: "how-to" --- -# 有保障的中继交易 +# 保证中继交易 -将 Enterprise 的功能与 `@stablechain/enterprise` 结合起来。有保障的中继交易是[免燃料费交易](/cn/how-to/relay-with-gas-waiver),它通过[有保障的区块空间](/cn/how-to/send-guaranteed-transactions)进行路由:豁免方支付燃料费,因此用户无需余额和燃料费字段,交易仍能进入预留的企业通道。 +将 Stable 企业级网络与 `@stablechain/enterprise` 结合使用。保证中继交易是[免 gas 交易](/cn/how-to/relay-with-gas-waiver),其通过[保证的区块空间](/cn/how-to/send-guaranteed-transactions)进行路由:免除交易费的功能支付 gas 费,因此用户无需余额和费用字段,交易仍会进入预留的 Enterprise 通道。 -`guaranteedWaiver` 模块处理双方。用户签署内部 `0x3F` CustomTx,白名单中的豁免账户将其包装在共享相同企业 `nonceKey` 的外部 `0x3F` CustomTx 中,并通过企业 RPC 网关进行广播。每个方法都返回用户的交易哈希 `H_inner`。 +`guaranteedWaiver` 模块同时处理这两个方面。用户签署内部的 `0x3F` CustomTx,白名单中的免除交易费账户将其包装在一个共享相同 Enterprise `nonceKey` 的外部 `0x3F` CustomTx 中,并通过 Enterprise RPC 网关广播。每个方法都返回 `H_inner`,即用户的交易哈希。 -## 先决条件 +## 前提条件 - Node.js 20 或更高版本,并安装 `@stablechain/enterprise` 和 `viem`。请参阅 [Enterprise SDK 参考](/cn/reference/enterprise-sdk#install)。 -- 一个在管理中注册的豁免密钥和一个企业 RPC 网关 API 密钥。Enterprise SDK 目前仅支持测试网,并且需要请求才能访问:[联系 Stable](https://discord.gg/stablexyz) 获取两者。 +- 一个在治理层注册的免除交易费密钥和一个 Enterprise RPC 网关 API 密钥。Enterprise SDK 目前仅支持测试网,并且需要申请访问权限:[联系 Stable](https://discord.gg/stablexyz) 以获取这两项。 :::warning -这是一个服务器端库。请将豁免密钥和企业 RPC 网关 URL 保留在您的后端:网关 URL 嵌入了您的 API 密钥。 +这是一个服务器端库。请将免除交易费密钥和 Enterprise RPC 网关 URL 保留在您的后端:网关 URL 嵌入了您的 API 密钥。 ::: -## 1. 使用有保障的豁免模块创建客户端 +## 1. 使用保证免除交易费模块创建客户端 -将 `guaranteedWaiver` 和 `enterpriseRpcEndpoints` 传递给 `createStableEnterprise`。该模块接收白名单中的豁免密钥(用于签署外部包装器)以及企业通道。它还接受与 `gasWaiver` 相同的 `allowedTargets`、`maxGasLimit` 和 `maxDataLength` 策略限制。 +将 `guaranteedWaiver` 和 `enterpriseRpcEndpoints` 传递给 `createStableEnterprise`。该模块接收白名单中的免除交易费密钥 (用于签署外部包装器) 和 Enterprise 通道。它还接受与 `gasWaiver` 相同的 `allowedTargets`、`maxGasLimit` 和 `maxDataLength` 策略限制。 ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -31,14 +31,14 @@ import { privateKeyToAccount } from "viem/accounts"; const enterprise = createStableEnterprise({ chain: stableTestnet, - enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // the gateway URL Stable provisions + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL], // the gateway URL Stable provisions guaranteedWaiver: { account: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`), laneId: 0n, // Enterprise lane }, }); -const gw = enterprise.guaranteedWaiver!; +const gw = enterprise.guaranteedWaiver; ``` ```text @@ -46,12 +46,12 @@ StableEnterpriseClient { gasWaiver: undefined, guaranteedBlock: undefined, guara ``` :::tip -要将豁免密钥保存在托管后端中,请传递 `signer` 而不是 `account`。`@stablechain/enterprise/aws-kms` 中的 `awsKmsSigner` 支持 AWS KMS。请参阅[签署密钥和托管](/cn/reference/enterprise-sdk#signing-keys-and-custody)。 +要将免除交易费密钥保留在托管后端中,请传递 `signer` 而不是 `account`。`@stablechain/enterprise/aws-kms` 中的 `awsKmsSigner` 支持 AWS KMS。请参阅[签名密钥和托管](/cn/reference/enterprise-sdk#signing-keys-and-custody)。 ::: ## 2. 中继单个交易 -使用用户的账户和变化的字段调用 `send`。燃料费被豁免,因此用户无需余额和燃料费字段。内部的 `0x3F` CustomTx、其企业 `nonceKey` 和 2D nonce(从网关发现)都会为您处理。 +使用用户账户和变化的字段调用 `send`。由于免除了 gas 费,用户不需要余额和费用字段。内部的 `0x3F` CustomTx、其 Enterprise `nonceKey` 和 2D nonce (从网关发现) 都会为您处理。 ```ts const user = privateKeyToAccount(process.env.USER_PRIVATE_KEY as `0x${string}`); @@ -64,11 +64,11 @@ console.log("H_inner:", txHash); H_inner: 0x8f3a...2d41 ``` -`gas` 默认为共享的内部燃料费默认值;仅在需要覆盖时才传递它。允许价值转移,因此您也可以传递 `value`。 +`gas` 默认为共享的内部 gas 默认值;仅在覆盖时传递。允许价值转移,因此您也可以传递 `value`。 -## 3. 中继批处理 +## 3. 中继批次交易 -调用 `sendBatch` 中继来自一个用户的多个交易。内部 nonce 从发现的基础自动排序,您会按输入顺序获得每个输入一个结果。一个失败会使其后续的交易中止。 +调用 `sendBatch` 中继来自一个用户的多笔交易。内部 nonce 会从发现的基本 nonce 自动排序,并且您会按照输入顺序获得每个输入的单个结果。失败会导致其后续交易无法进行。 ```ts const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); @@ -85,7 +85,7 @@ for (const r of results) { ## 4. 中继预签名交易 -对于非托管流程,用户在其自己的环境中签署内部 `0x3F` CustomTx,并仅将已签署的十六进制字符串交给您。使用 `buildGuaranteedTx` 构建它,其中企业 nonce 密钥使用 `nonceKeyForLane`,燃料费设置为零(燃料费被豁免)。您的后端使用豁免密钥包装它,并使用 `relay` 进行中继。 +对于非托管流程,用户在其自己的环境中签署内部 `0x3F` CustomTx,并只向您提供签名的十六进制数据。使用 `buildGuaranteedTx` 构建它,其中 Enterprise nonce 密钥使用 `nonceKeyForLane`,费用为零 (gas 已免除)。您的后端会使用免除交易费密钥对其进行封装,并使用 `relay` 进行中继。 ```ts import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; @@ -113,7 +113,7 @@ H_inner: 0x8f3a...2d41 ## 处理拒绝 -`send` 和 `relay` 在拒绝时会抛出 `StableEnterpriseRelayError`。由于此流程通过网关路由,因此网关代码(如 `GATEWAY_UNAUTHORIZED` 和 `QUOTA_EXCEEDED`)以及豁免策略代码(如 `TARGET_NOT_ALLOWED`)都适用。 +`send` 和 `relay` 在拒绝时会抛出 `StableEnterpriseRelayError`。由于此流程通过网关路由,因此网关代码 (如 `GATEWAY_UNAUTHORIZED` 和 `QUOTA_EXCEEDED`) 以及免除交易费策略代码 (如 `TARGET_NOT_ALLOWED`) 都适用。 ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -132,10 +132,10 @@ try { StableEnterpriseRelayError: relay failed [GATEWAY_UNAUTHORIZED]: invalid api key ``` -有关所有拒绝原因,请参阅完整的 [`ErrorCode`](/cn/reference/enterprise-sdk#errorcode) 表。 +请参阅完整的 [`ErrorCode`](/cn/reference/enterprise-sdk#errorcode) 表,了解所有拒绝原因。 ## 接下来去哪里 -- [**中继免燃料费交易**](/cn/how-to/relay-with-gas-waiver):为用户提供燃料费,但不使用有保障的通道。 -- [**发送有保障的交易**](/cn/how-to/send-guaranteed-transactions):单独使用有保障的区块空间,由签名者支付燃料费。 +- [**使用免 gas 功能中继**](/cn/how-to/relay-with-gas-waiver):为用户支付 gas 费,无需保证通道。 +- [**发送保证交易**](/cn/how-to/send-guaranteed-transactions):单独使用保证区块空间,由签署者支付 gas 费。 - [**Enterprise SDK 参考**](/cn/reference/enterprise-sdk#guaranteed-relay-transactions):所有方法、配置选项和错误类的完整说明。 diff --git a/docs/pages/cn/how-to/relay-with-gas-waiver.mdx b/docs/pages/cn/how-to/relay-with-gas-waiver.mdx index d249e64..a68208c 100644 --- a/docs/pages/cn/how-to/relay-with-gas-waiver.mdx +++ b/docs/pages/cn/how-to/relay-with-gas-waiver.mdx @@ -1,29 +1,29 @@ --- source_path: how-to/relay-with-gas-waiver.mdx -source_sha: d27d02a1e7956429991b4af81f097719e3eabd34 -title: "使用 Gas Waiver 进行中继" -description: "通过 Enterprise SDK 赞助用户的 gas:中继零 gas 交易,批量中继,强制执行策略限制,以及中继预签名交易。" +source_sha: c1b34aab292d8e9623b59810cd6b668468e834ce +title: "使用 Gas 代付中继交易" +description: "使用 Enterprise SDK 赞助用户的 gas:中继零 gas 交易、批量中继、强制执行策略限制以及中继预签名交易。" diataxis: "how-to" --- -# 使用 Gas Waiver 进行中继 +# 使用 Gas 代付中继交易 -使用 `@stablechain/enterprise` 赞助用户的 gas。列入白名单的 waiver 账户会封装用户的零 gas 交易(内部交易),并将其广播,这样用户无需持有任何 USDT0 即可进行交易。`gasWaiver` 模块在一个调用中构建、签名和中继,因此您每个操作只需调用一个方法。 +使用 `@stablechain/enterprise` 赞助用户的 gas 费用。白名单代付账户会包装用户的零 gas 交易 (InnerTx) 并广播它,因此用户无需持有任何 USDT0 即可进行交易。`gasWaiver` 模块在一个调用中构建、签名和中继,因此您每个操作只需调用一个方法。 -每个方法都返回 `H_inner`,即用户交易的哈希值,而不是承载它的封装器。 +每个方法都返回 `H_inner`,即用户交易的哈希,而不是承载它的包装器。 ## 先决条件 - Node.js 20 或更高版本,并安装了 `@stablechain/enterprise` 和 `viem`。请参阅 [Enterprise SDK 参考](/cn/reference/enterprise-sdk#install)。 -- 治理注册的 waiver 密钥。Enterprise SDK 目前仅适用于测试网,并且访问受限:请[联系 Stable](https://discord.gg/stablexyz) 以获取白名单 waiver 密钥。 +- 治理注册的代付密钥。Enterprise SDK 目前仅限测试网,并且访问受限:[联系 Stable](https://discord.gg/stablexyz) 获取白名单代付密钥。 :::warning -这是一个服务器端库,它使用私钥进行签名。切勿在浏览器中运行它。将 waiver 密钥保存在您的后端。 +这是一个使用私钥进行签名的服务器端库。切勿在浏览器中运行它。将代付密钥保存在您的后端。 ::: -## 1. 使用 gas waiver 模块创建客户端 +## 1. 使用 gas 代付模块创建客户端 -将 `gasWaiver: { account }` 传递给 `createStableEnterprise`,其中 `account` 是您列入白名单的 waiver 密钥。只有在配置后,模块才会在客户端上出现。 +将 `gasWaiver: { account }` 传递给 `createStableEnterprise`,其中 `account` 是您的白名单代付密钥。仅在您配置后,模块才会在客户端上出现。 ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -34,7 +34,7 @@ const enterprise = createStableEnterprise({ gasWaiver: { account: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`) }, }); -const gw = enterprise.gasWaiver!; +const gw = enterprise.gasWaiver; ``` ```text @@ -44,12 +44,12 @@ StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver `rpcEndpoints` 选项是可选的。如果未设置,客户端将使用链的内置 RPC。 :::tip -要将 waiver 密钥保存在托管后端中,请传递 `signer` 而不是 `account`。`@stablechain/enterprise/aws-kms` 中的 `awsKmsSigner` 使用 AWS KMS 作为后端。请参阅[签名密钥和托管](/cn/reference/enterprise-sdk#signing-keys-and-custody)。 +要将代付密钥保存在托管后端中,请传递 `signer` 而不是 `account`。`@stablechain/enterprise/aws-kms` 中的 `awsKmsSigner` 支持 AWS KMS。请参阅[签名密钥和托管](/cn/reference/enterprise-sdk#signing-keys-and-custody)。 ::: ## 2. 中继单个交易 -使用用户账户和可变字段调用 `send`。`gasPrice: 0`、遗留类型、`chainId` 和待处理 nonce 都已为您处理,因此您只需传递 `to`,以及可选的 `data`、`value` 和 `gas`。 +使用用户帐户和变化的字段调用 `send`。`gasPrice: 0`、旧版类型、`chainId` 和待处理 Nonce 都已为您处理,因此您只需传递 `to`,以及可选的 `data`、`value` 和 `gas`。 ```ts const user = privateKeyToAccount(process.env.USER_PRIVATE_KEY as `0x${string}`); @@ -62,11 +62,11 @@ console.log("H_inner:", txHash); H_inner: 0x8f3a...2d41 ``` -用户不需要 USDT0:waiver 账户会赞助 gas。`gas` 默认为 `150_000n` (`DEFAULT_INNER_GAS`),足以覆盖代币转账或批准。对于更繁重的调用,请传递显式的 `gas`。 +用户不需要 USDT0:代付账户会赞助 gas。`gas` 默认为 `150_000n` (`DEFAULT_INNER_GAS`),足以覆盖代币转账或批准。对于更复杂的调用,请传递显式的 `gas`。 ## 3. 批量中继 -调用 `sendBatch` 可以中继来自一个账户的多个交易。Nonce 会自动从账户的待处理 nonce 序列化,并且您会根据输入顺序获得每个输入一个结果。 +调用 `sendBatch` 从一个账户中继多笔交易。Nonce 会根据账户的待处理 Nonce 自动排序,并且您会按输入顺序获得每个输入的结果。 ```ts const results = await gw.sendBatch(user, [ @@ -84,11 +84,11 @@ for (const r of results) { [1] ✔ 0x2b7c...9e04 ``` -批量处理会在 `result.error` 中报告每个项目的失败,而不是抛出异常,因此一个坏交易不会导致其他交易失败。 +批量处理报告每个项目的失败 `result.error` 而不是抛出异常,因此一个糟糕的交易不会影响其余交易。 -## 4. 执行每合作伙伴策略限制 +## 4. 执行每个合作伙伴的策略限制 -通过向配置添加策略限制来限制 waiver 密钥可以赞助的内容。违反限制的内部交易将在广播前被拒绝。 +通过向配置添加策略限制来限制代付密钥可以赞助的内容。违反限制的 InnerTx 在广播前将被拒绝。 ```ts const enterprise = createStableEnterprise({ @@ -98,22 +98,22 @@ const enterprise = createStableEnterprise({ maxGasLimit: 500_000n, maxDataLength: 4_096, allowedTargets: [ - { address: token, selectors: ["0xa9059cbb"] }, // 仅限 ERC-20 转账 + { address: token, selectors: ["0xa9059cbb"] }, // ERC-20 transfer only ], }, }); ``` -目标合约不在 `allowedTargets` 中的交易将失败并显示 `TARGET_NOT_ALLOWED`;超过 `maxGasLimit` 的交易将失败并显示 `GAS_LIMIT_EXCEEDED`。使用 `"*"` 作为 `address` 允许任何合约,并省略 `selectors` 允许任何方法。 +针对 `allowedTargets` 之外的合约的交易将失败并显示 `TARGET_NOT_ALLOWED`;超过 `maxGasLimit` 的交易将失败并显示 `GAS_LIMIT_EXCEEDED`。使用 `"*"` 作为 `address` 允许任何合约,并省略 `selectors` 允许任何方法。 ## 5. 中继预签名交易 -对于非托管流程,用户在其自己的环境中签署内部交易并仅向您提供签名十六进制,因此您永远不会看到他们的密钥。使用 `buildWaiverInnerTx` 构建它,然后使用 `relay` 中继。 +对于非托管流程,用户在其自己的环境中签署 InnerTx 并仅将签名十六进制传递给您,因此您永远不会看到他们的密钥。使用 `buildWaiverInnerTx` 构建它,然后使用 `relay` 中继它。 ```ts import { buildWaiverInnerTx, toSigner } from "@stablechain/enterprise"; -// 在用户侧 — buildWaiverInnerTx 通过 Signer 签名;toSigner 适配 viem 账户 +// 在用户端 — buildWaiverInnerTx 通过 Signer 签名;toSigner 适配 viem 账户 const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to: token, data, gas: 150_000n, nonce }); // 在您的后端 @@ -125,11 +125,11 @@ console.log("H_inner:", txHash); H_inner: 0x8f3a...2d41 ``` -对于多个预签名交易,请使用 `relayBatch`,它会像 `sendBatch` 一样为每个输入返回一个结果。 +对于多个预签名交易,请使用 `relayBatch`,它像 `sendBatch` 一样为每个输入返回一个结果。 ## 处理拒绝 -`send` 和 `relay` 在拒绝时会抛出 `StableEnterpriseRelayError`,并带有一个您可以分支的 `code`。 +`send` 和 `relay` 在拒绝时会抛出 `StableEnterpriseRelayError`,并带有您可以分支的 `code`。 ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -138,7 +138,7 @@ try { await gw.send(user, { to: token, data }); } catch (err) { if (err instanceof StableEnterpriseRelayError && err.code === "TARGET_NOT_ALLOWED") { - // 内部交易目标不在配置的允许列表中 + // InnerTx 目标不在配置的白名单中 } throw err; } @@ -148,10 +148,10 @@ try { StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not allowed ``` -有关所有拒绝原因,请参阅完整的 [`ErrorCode`](/cn/reference/enterprise-sdk#errorcode) 表格。 +请参阅完整的 [`ErrorCode`](/cn/reference/enterprise-sdk#errorcode) 表格以了解所有拒绝原因。 -## 后续步骤 +## 下一步 -- [**发送保证交易**](/cn/how-to/send-guaranteed-transactions):将交易提交到保留的企业通道区块空间,并将其与 gas waiver 结合使用。 -- [**Enterprise SDK 参考**](/cn/reference/enterprise-sdk#relay-with-gas-waiver):所有方法、配置选项和错误类的完整说明。 -- [**Gas waiver**](/cn/explanation/gas-waiver):零 gas 交易如何在协议层面工作。 +- [**发送保证交易**](/cn/how-to/send-guaranteed-transactions):在保留的 Enterprise 通道区块空间中进行交易,并将其与 gas 代付结合使用。 +- [**Enterprise SDK 参考**](/cn/reference/enterprise-sdk#relay-with-gas-waiver):每个方法、配置选项和错误类的完整说明。 +- [**Gas 代付**](/cn/explanation/gas-waiver):协议级别的零 gas 交易工作原理。 diff --git a/docs/pages/cn/how-to/send-guaranteed-transactions.mdx b/docs/pages/cn/how-to/send-guaranteed-transactions.mdx index 8fd0a1f..805ce1d 100644 --- a/docs/pages/cn/how-to/send-guaranteed-transactions.mdx +++ b/docs/pages/cn/how-to/send-guaranteed-transactions.mdx @@ -1,30 +1,30 @@ --- source_path: how-to/send-guaranteed-transactions.mdx -source_sha: c59ac1a053751e961d75071fa7799dbd9dc4b847 -title: "发送有保障的交易" -description: "使用 Enterprise SDK 在预留的企业通道区块空间中进行交易,并将有保障的区块空间与 Gas 豁免结合,以实现免 Gas 中继交易。" +source_sha: 6da305c74e7ddb43f31a4ed11e7f4d5313f0cabe +title: "发送担保交易" +description: "使用 Enterprise SDK 在预留的 Enterprise-lane 区块空间中执行交易,并将担保区块空间与免燃气费结合起来,实现无燃气转发。" diataxis: "how-to" --- -# 发送有保障的交易 +# 发送担保交易 -使用 `@stablechain/enterprise` 通过预留的企业通道区块空间路由交易。`guaranteedBlock` 模块通过 Enterprise RPC 网关中继 GuaranteedTx(一种类型为 `0x3F` 的 CustomTx),使其进入为企业工作负载预留的容量中。与 Gas 豁免不同,签名者支付自己的 Gas,因此必须为其提供资金。 +使用 `@stablechain/enterprise` 通过预留的 Enterprise-lane 区块空间路由交易。`guaranteedBlock` 模块通过 Enterprise RPC 网关转发 GuaranteedTx (一种 `0x3F` 类型的 CustomTx),使其进入为企业工作负载预留的容量中。与免燃气费不同,签名者需要支付自己的燃气费,因此必须有足够的资金。 -您可以将其与 Gas 豁免结合,以获得[有保障的中继交易](/cn/how-to/guaranteed-relayed-transactions):即获得 Gas 豁免但仍进入企业通道的交易。 +您可以将其与免燃气费结合使用,以获得[担保转发交易](/cn/how-to/guaranteed-relayed-transactions):免燃气费交易仍能进入企业通道。 ## 先决条件 -- Node.js 20 或更高版本,以及已安装的 `@stablechain/enterprise` 和 `viem`。请参阅 [Enterprise SDK 参考](/cn/reference/enterprise-sdk#install)。 -- Enterprise RPC 网关 API 密钥。Enterprise SDK 目前仅限于测试网,并且访问受限:请[联系 Stable](https://discord.gg/stablexyz) 以获取网关端点。 -- 一个有资金的签名者,因为 GuaranteedTx 会支付自己的 Gas。 +- Node.js 20 或更高版本,并安装 `@stablechain/enterprise` 和 `viem`。请参阅 [Enterprise SDK 参考](/cn/reference/enterprise-sdk#install)。 +- Enterprise RPC 网关 API 密钥。Enterprise SDK 目前仅支持测试网,并且访问受限:[联系 Stable](https://discord.gg/stablexyz) 获取网关端点。 +- 一个有资金的签名者,因为 GuaranteedTx 需要支付自己的燃气费。 :::warning 这是一个服务器端库。将 Enterprise RPC 网关 URL 保留在您的后端:它嵌入了您的 API 密钥。 ::: -## 1. 使用有保障的区块空间模块创建客户端 +## 1. 使用担保区块空间模块创建客户端 -将 `guaranteedBlock` 和 `enterpriseRpcEndpoints` 传递给 `createStableEnterprise`。网关是唯一接受 `0x3F` GuaranteedTx 的端点,并且它包含您的 API 密钥。无效的 `laneId` 会被立即拒绝。 +将 `guaranteedBlock` 和 `enterpriseRpcEndpoints` 传递给 `createStableEnterprise`。网关是唯一接受 `0x3F` GuaranteedTxs 的端点,并且它包含您的 API 密钥。无效的 `laneId` 会被提前拒绝。 ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -32,14 +32,14 @@ import { privateKeyToAccount } from "viem/accounts"; const enterprise = createStableEnterprise({ chain: stableTestnet, - enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // the gateway URL Stable provisions + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL], // the gateway URL Stable provisions guaranteedBlock: { account: privateKeyToAccount(process.env.SIGNER_PRIVATE_KEY as `0x${string}`), // must be funded laneId: 0n, // Enterprise lane }, }); -const gb = enterprise.guaranteedBlock!; +const gb = enterprise.guaranteedBlock; ``` ```text @@ -48,7 +48,7 @@ StableEnterpriseClient { gasWaiver: undefined, guaranteedBlock, guaranteedWaiver ## 2. 发送单笔交易 -使用签名者和可变字段调用 `send`。由于签名者支付 Gas,因此 1559 费用字段是必需的。`chainId`、Enterprise `nonceKey` 和 2D nonce(从网关发现)都会为您处理。 +使用签名者和可变字段调用 `send`。1559 费用字段是必需的,因为签名者需要支付燃气费。`chainId`、Enterprise `nonceKey` 和 2D nonce(从网关中发现)已为您处理。 ```ts import { createPublicClient, http } from "viem"; @@ -69,11 +69,13 @@ console.log("Guaranteed tx:", txHash); Guaranteed tx: 0xabcd...7890 ``` -签名者支付 Gas,因此在进行中继之前请确认其持有余额。来自零余额账户的 GuaranteedTx 会失败。 +`gasFeeCap` 是每单位燃气的最大总费用(EIP-1559 `maxFeePerGas`),`gasTipCap` 是每单位燃气的最大优先费用(`maxPriorityFeePerGas`)。如上所示,将 `gasTipCap` 设置为当前燃气价格并将 `gasFeeCap` 设置为其两倍是一个安全的默认值。 -## 3. 批量发送 +签名者支付燃气费,因此请在转发前确认其持有余额。来自零余额账户的 GuaranteedTx 会失败。 -调用 `sendBatch` 发送多笔交易。Nonce 会从发现的基数自动排序,并且您会按输入顺序获得每个输入的一个结果。失败会中止其后续操作。 +## 3. 发送批处理 + +调用 `sendBatch` 发送多笔交易。Nonce 会从发现的基础自动排序,并且您会按输入顺序获得每个输入的一个结果。失败会使其后续交易受阻。 ```ts const results = await gb.sendBatch(signer, [ @@ -93,7 +95,7 @@ for (const r of results) { ## 4. 发送预签名交易 -对于非托管流程,使用 `buildGuaranteedTx` 在其他地方构建并签署 GuaranteedTx,然后只将签名后的十六进制字符串交给操作员。Enterprise nonce 密钥来自 `nonceKeyForLane`。 +对于非托管流程,使用 `buildGuaranteedTx` 在其他地方构建并签署 GuaranteedTx,然后只将签署的十六进制数据交给操作员。Enterprise nonce 密钥来自 `nonceKeyForLane`。 ```ts import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; @@ -117,13 +119,13 @@ Guaranteed tx: 0xabcd...7890 对于多笔预签名交易,请使用 `relayBatch`。 -## 与 Gas 豁免结合 +## 与免燃气费结合 -为了豁免用户的 Gas 并仍然进入企业通道,请将这两个通道与 `guaranteedWaiver` 模块结合使用。用户无需余额和费用字段,并且交易通过同一网关路由。请参阅[有保障的中继交易](/cn/how-to/guaranteed-relayed-transactions)。 +要免除用户的燃气费并仍进入 Enterprise 通道,请使用 `guaranteedWaiver` 模块组合两个轨道。用户无需余额和费用字段,并且交易通过相同的网关进行路由。请参阅[担保转发交易](/cn/how-to/guaranteed-relayed-transactions)。 ## 处理拒绝 -`send` 和 `relay` 在拒绝时会抛出 `StableEnterpriseRelayError`。网关特定的代码包括 `GATEWAY_UNAUTHORIZED`(API 密钥缺失或无效)和 `QUOTA_EXCEEDED`(网关 Gas 配额已用尽)。 +`send` 和 `relay` 在拒绝时会抛出 `StableEnterpriseRelayError`。网关特定的错误代码包括 `GATEWAY_UNAUTHORIZED`(API 密钥缺失或无效)和 `QUOTA_EXCEEDED`(网关燃气配额已用尽)。 ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -144,6 +146,6 @@ StableEnterpriseRelayError: relay failed [GATEWAY_UNAUTHORIZED]: invalid api key ## 下一步 -- [**有保障的中继交易**](/cn/how-to/guaranteed-relayed-transactions):一次调用即可豁免用户的 Gas 并进入企业通道。 -- [**使用 Gas 豁免进行中继**](/cn/how-to/relay-with-gas-waiver):赞助用户的 Gas,让他们无需持有 USDT0 即可进行交易。 -- [**Enterprise SDK 参考**](/cn/reference/enterprise-sdk#guaranteed-blockspace):方法、配置选项和错误类的完整列表。 +- [**担保转发交易**](/cn/how-to/guaranteed-relayed-transactions):一次调用即可免除用户的燃气费并进入 Enterprise 通道。 +- [**免燃气费转发**](/cn/how-to/relay-with-gas-waiver):为用户的燃气费提供赞助,以便他们在不持有 USDT0 的情况下进行交易。 +- [**Enterprise SDK 参考**](/cn/reference/enterprise-sdk#guaranteed-blockspace):所有方法、配置选项和错误类的完整说明。 diff --git a/docs/pages/cn/reference/enterprise-sdk.mdx b/docs/pages/cn/reference/enterprise-sdk.mdx index 2d2ecae..3c4f10d 100644 --- a/docs/pages/cn/reference/enterprise-sdk.mdx +++ b/docs/pages/cn/reference/enterprise-sdk.mdx @@ -1,21 +1,21 @@ --- source_path: reference/enterprise-sdk.mdx -source_sha: 4f3e8931e52daf98a9dc5de5921fc734d4284dfb -title: "企业级 SDK 参考" -description: "@stablechain/enterprise 的完整参考:createStableEnterprise、免燃料费和保证区块空间模块、构建助手以及错误类。" +source_sha: c89457ca29556b5a94b9cb4562bd9d210d38701d +title: "企业级SDK参考" +description: "完整的@stablechain/enterprise参考:包括createStableEnterprise、免Gas模块和保证区块空间模块、构建助手以及错误类。" diataxis: "reference" --- -# 企业级 SDK 参考 +# 企业级SDK参考 -`@stablechain/enterprise` 的完整界面。这涵盖了客户端从 [`createStableEnterprise`](#createstableenterpriseconfig) 到其三个功能([免燃料费中继](#relay-with-gas-waiver)、[保证区块空间](#guaranteed-blockspace)和[保证中继交易](#guaranteed-relay-transactions))、低级构建助手以及共享的结果和错误类型。有关这些概念的详细信息,请参阅[Stable 企业级 SDK](/cn/explanation/enterprise-sdk)、[免燃料费](/cn/explanation/gas-waiver)和[保证区块空间](/cn/explanation/guaranteed-blockspace)。 +`@stablechain/enterprise` 的完整表面。这涵盖了客户端从 [`createStableEnterprise`](#createstableenterpriseconfig) 开始,其三个功能([免Gas中继](#relay-with-gas-waiver)、[保证区块空间](#guaranteed-blockspace)和[保证中继交易](#guaranteed-relay-transactions)),低级别的构建助手,以及共享的结果和错误类型。有关这些轨道的含义,请参阅 [Stable企业级SDK](/cn/explanation/enterprise-sdk)、[免Gas](/cn/explanation/gas-waiver) 和 [保证区块空间](/cn/explanation/guaranteed-blockspace)。 :::note -企业级 SDK 目前仅在 Stable 测试网上提供,并且需要申请才能访问。要进行集成,请[联系 Stable](https://discord.gg/stablexyz) 以获取治理注册的豁免密钥和企业级 RPC 网关 API 密钥。 +企业级SDK目前仅在Stable测试网上可用,并且需要申请访问。要进行集成,请[联系Stable](https://discord.gg/stablexyz)以获取经治理注册的豁免密钥和企业级RPC网关API密钥。 ::: :::warning -这是一个需要使用私钥签名的服务器端库。切勿在浏览器中运行它。请将豁免密钥和企业级 RPC 网关 URL 保存在您的后端。 +这是一个使用私钥进行签名的服务器端库。切勿在浏览器中运行。保留豁免密钥和企业级RPC网关URL在您的后端。 ::: ## 安装 @@ -32,7 +32,7 @@ added 2 packages, audited 3 packages in 2s ## `createStableEnterprise(config)` -构造一个 `StableEnterpriseClient`。每个模块仅在您配置它时才存在,因此在使用前请使用 `!` 或空值检查进行保护。 +构造一个 `StableEnterpriseClient`。每个模块仅在您配置后才存在,因此在使用前请进行空值检查。 ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -52,20 +52,20 @@ StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | -| `chain` | `StableChain` | | 目标链。传入 `stable` 或 `stableTestnet`(由软件包重新导出)。必需。 | -| `rpcEndpoints` | `string[]?` | 链的内置 RPC | 一个或多个 Stable RPC 端点,失败时按顺序尝试。仅在指向私有端点时才覆盖。 | -| `enterpriseRpcEndpoints` | `string[]?` | | 一个或多个企业级 RPC 网关端点,失败时按顺序尝试。`guaranteedBlock` 和 `guaranteedWaiver` 必需。 | -| `batchSizeLimit` | `number?` | `100` | 每个批处理 RPC 调用允许的最大交易数量。 | -| `signer` | `Signer?` | | 豁免模块(`gasWaiver`,`guaranteedWaiver`)的默认签名者,当模块没有自己的密钥时。设置一次以从单个托管后端驱动两者。请参阅[签名密钥和托管](#signing-keys-and-custody)。 | -| `gasWaiver` | `GasWaiverConfig?` | | 启用[免燃料费中继](#relay-with-gas-waiver)。 | -| `guaranteedBlock` | `GuaranteedBlockConfig?` | | 启用[保证区块空间](#guaranteed-blockspace)。 | -| `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | 启用[保证中继交易](#guaranteed-relay-transactions)。 | +| `chain` | `StableChain` | | 目标链。传入 `stable` 或 `stableTestnet`(由软件包重新导出)。必填项。 | +| `rpcEndpoints` | `string[]?` | 链的内置RPC | 一个或多个Stable RPC端点,在失败时按顺序尝试。仅在指向私有端点时覆盖。 | +| `enterpriseRpcEndpoints` | `string[]?` | | 一个或多个企业级RPC网关端点,在失败时按顺序尝试。`guaranteedBlock` 和 `guaranteedWaiver` 需要。 | +| `batchSizeLimit` | `number?` | `100` | 每个批量RPC调用的最大事务数。 | +| `signer` | `Signer?` | | 免Gas模块 (`gasWaiver`、`guaranteedWaiver`) 的默认签名器,当模块没有自己的密钥时。设置一次即可通过一个托管后端驱动两者。请参阅 [签名密钥和托管](#signing-keys-and-custody)。 | +| `gasWaiver` | `GasWaiverConfig?` | | 启用 [免Gas中继](#relay-with-gas-waiver)。 | +| `guaranteedBlock` | `GuaranteedBlockConfig?` | | 启用 [保证区块空间](#guaranteed-blockspace)。 | +| `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | 启用 [保证中继交易](#guaranteed-relay-transactions)。 | ### 签名密钥和托管 -持有豁免密钥的模块(`gasWaiver` 和 `guaranteedWaiver`)按顺序解析它:模块自己的 `signer`,然后是它的 `account`(一个进程内的 viem 密钥),然后是客户端配置中的顶层 [`signer`](#stableenterpriseconfig),然后是 `STABLE_ENTERPRISE_PRIVATE_KEY` 环境变量。设置一次顶层 `signer` 以从单个托管后端驱动两个豁免模块。`guaranteedBlock` 用它自己的已资助 `account` 签名。 +持有免Gas密钥的模块(`gasWaiver` 和 `guaranteedWaiver`)按顺序解析:模块自己的 `signer`,然后是其 `account`(一个进程内viem密钥),然后是客户端配置的顶级 [`signer`](#stableenterpriseconfig),最后是 `STABLE_ENTERPRISE_PRIVATE_KEY` 环境变量。设置一次顶级 `signer` 可以通过一个托管后端驱动这两个免Gas模块。`guaranteedBlock` 使用其自身已资助的 `account` 进行签名。 -`Signer` 对 32 字节摘要进行签名,因此密钥从不离开托管后端。AWS KMS 使用 `awsKmsSigner`,viem 账户使用 `toSigner(account)`,或进程内密钥使用 `privateKeySigner(key)` / `envSigner()`。传递给模块 `send` / `sendBatch` 的每次调用发送方同样可以是 viem 账户或 `Signer`,因此 KMS/HSM 密钥可以签署内部交易而无需降级到 `relay`。 +`Signer` 对 32 字节的摘要进行签名,因此密钥永远不会离开托管后端。对于AWS KMS,请使用 `awsKmsSigner`,使用 `toSigner(account)` 来适应viem账户,或使用 `privateKeySigner(key)` / `envSigner()` 来使用进程内密钥。传递给模块 `send` / `sendBatch` 的每调用发送方也可以是viem账户或 `Signer`,因此KMS/HSM密钥可以签署内部交易而无需降级到 `relay`。 ```bash npm install @aws-sdk/client-kms @@ -75,16 +75,16 @@ npm install @aws-sdk/client-kms import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; import { awsKmsSigner } from "@stablechain/enterprise/aws-kms"; -// KMS 密钥必须是 ECC_SECG_P256K1 (secp256k1);SDK 从中派生地址 -const signer = await awsKmsSigner({ keyId: process.env.KMS_KEY_ID! }); +// KMS密钥必须是ECC_SECG_P256K1 (secp256k1);SDK从中派生地址 +const signer = await awsKmsSigner({ keyId: process.env.KMS_KEY_ID }); const enterprise = createStableEnterprise({ chain: stableTestnet, - gasWaiver: { signer }, // 托管级别的豁免密钥,取代 `account` + gasWaiver: { signer }, // 托管级免Gas密钥,替代`account` }); ``` -`awsKmsSigner` 在 `@stablechain/enterprise/aws-kms` 子路径中提供,因此 `@aws-sdk/client-kms` 仍然是一个可选的对等依赖项,不在核心安装中。 +`awsKmsSigner` 发布在 `@stablechain/enterprise/aws-kms` 子路径中,因此 `@aws-sdk/client-kms` 仍是一个可选的对等依赖项,不属于核心安装。 ### `StableEnterpriseClient` @@ -96,9 +96,9 @@ interface StableEnterpriseClient { } ``` -## 免燃料费中继 +## 免Gas中继 -`gasWaiver` 模块中继免燃料费交易。白名单豁免帐户将用户的零燃料费交易 (InnerTx) 封装到 WaiverTx 中并进行广播。用户无需 USDT0。每个方法都返回 `H_inner`,即 InnerTx 哈希,而不是封装器哈希。 +`gasWaiver` 模块中继免Gas交易。一个白名单的免Gas账户将用户的零Gas交易(InnerTx)封装成一个WaiverTx并广播。用户不需要USDT0。每个方法都返回 `H_inner`,即InnerTx哈希,而不是封装哈希。 在配置中通过 `gasWaiver` 启用它: @@ -113,17 +113,17 @@ const enterprise = createStableEnterprise({ }, }); -const gw = enterprise.gasWaiver!; +const gw = enterprise.gasWaiver; ``` ### `GasWaiverConfig` -扩展了 [`ValidationLimits`](#validationlimits) 和 [`SignerSource`](#signersource)。 +扩展 [`ValidationLimits`](#validationlimits) 和 [`SignerSource`](#signersource)。 | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `signer` | `Signer?` | 作为托管签名者(AWS KMS、HSM)的白名单、治理注册的豁免密钥。优先于 `account`。请参阅[签名密钥和托管](#signing-keys-and-custody)。 | -| `account` | `LocalAccount?` | 作为进程内 viem 账户的豁免密钥。如果两者都未设置,则回退到 `STABLE_ENTERPRISE_PRIVATE_KEY`。 | +| `signer` | `Signer?` | 作为托管签名器(AWS KMS、HSM)的白名单、治理注册免Gas密钥。请参阅 [签名密钥和托管](#signing-keys-and-custody)。优先于 `account`。 | +| `account` | `LocalAccount?` | 作为进程内viem账户的免Gas密钥。当两者都未设置时,回退到 `STABLE_ENTERPRISE_PRIVATE_KEY`。 | | `maxGasLimit` | `bigint?` | 继承自 `ValidationLimits`。 | | `maxDataLength` | `number?` | 继承自 `ValidationLimits`。 | | `allowedTargets` | `AllowedTarget[]?` | 继承自 `ValidationLimits`。 | @@ -144,7 +144,7 @@ const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); ### `sendBatch(account, txs)` -从一个`account`构建、签名并中继多个InnerTx。Nonces会从账户的待处理nonce自动排序。每个输入按顺序返回一个结果。 +从一个 `account` 构建、签名并中继多个 InnerTx。Nonce 会从账户的待处理 nonce 自动排序。按顺序返回每个输入的单个结果。 ```ts const results = await gw.sendBatch(user, [ @@ -157,11 +157,11 @@ const results = await gw.sendBatch(user, [ [ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: true, txHash: "0x..." } ] ``` -`txs` 是一个 [`WaiverInnerTx`](#waiverinnertx) 的只读数组。返回 [`BatchResultItem[]`](#batchresultitem)。 +`txs` 是一个只读的 [`WaiverInnerTx`](#waiverinnertx) 数组。返回 [`BatchResultItem[]`](#batchresultitem)。 ### `relay(signedInnerTxHex)` -中继预签名的零燃料费 InnerTx。这适用于非托管流程,用户在其自己的环境中签名并只向您提供签名的十六进制数据,因此豁免操作员永远不会看到用户的密钥。使用 [`buildWaiverInnerTx`](#buildwaiverinnertxsigner-chainid-req) 构建一个。拒绝时抛出错误。 +中继一个预签名的零Gas InnerTx。当用户在自己的环境中签名并仅将签名后的十六进制字符串交给您时,请使用此方法进行非托管流程,以便免Gas操作员永远不会看到用户的密钥。使用 [`buildWaiverInnerTx`](#buildwaiverinnertxsigner-chainid-req) 构建一个。拒绝时抛出错误。 ```ts import { buildWaiverInnerTx, toSigner } from "@stablechain/enterprise"; @@ -176,7 +176,7 @@ const { txHash } = await gw.relay(signed); ### `relayBatch(signedInnerTxHexes)` -中继一批预签名的 InnerTx。每个输入按顺序返回一个 [`BatchResultItem`](#batchresultitem)。 +中继一批预签名的 InnerTx。按顺序为每个输入返回一个 [`BatchResultItem`](#batchresultitem)。 ```ts const results = await gw.relayBatch([signed0, signed1]); @@ -188,33 +188,33 @@ const results = await gw.relayBatch([signed0, signed1]); ## 保证区块空间 -`guaranteedBlock` 模块通过企业级 RPC 网关中继 GuaranteedTx(类型 `0x3F` CustomTx),以便它们落在预留的企业级通道区块空间中。与免燃料费不同,签名者支付自己的燃料费并且需要有资金。每个交易都带有与企业级通道关联的二维 nonce,并且广播仅通过网关进行。 +`guaranteedBlock` 模块通过企业 RPC 网关中继 GuaranteedTx(类型为 `0x3F` CustomTx),以便它们落在预留的企业通道区块空间中。与免Gas不同,签名者支付自己的Gas,并且必须有资金。每笔交易都带有与企业通道关联的二维nonce,并且广播仅通过网关进行。 通过 `guaranteedBlock` 和 `enterpriseRpcEndpoints` 启用它: ```ts const enterprise = createStableEnterprise({ chain: stableTestnet, - enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable 提供的网关 URL + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL], // Stable提供的网关URL guaranteedBlock: { account: privateKeyToAccount("0xFUNDED_SIGNER_KEY"), laneId: 0n, }, }); -const gb = enterprise.guaranteedBlock!; +const gb = enterprise.guaranteedBlock; ``` ### `GuaranteedBlockConfig` | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `account` | `LocalAccount` | 签署每个 GuaranteedTx 并支付其燃料费的已注资账户。 | -| `laneId` | `bigint` | 企业级通道 ID。必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。无效 ID 会被立即拒绝。 | +| `account` | `LocalAccount` | 对每个GuaranteedTx进行签名并支付其Gas的已资助账户。 | +| `laneId` | `bigint` | 企业通道ID。必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。无效ID会提前被拒绝。 | ### `send(account, tx)` -构建、签名并中继一个 GuaranteedTx。1559 燃料费字段是必需的,因为签名者要支付燃料费。`chainId`、企业级 `nonceKey` 和二维 nonce(从网关发现)都为您处理。 +构建、签名并中继一个GuaranteedTx。1559费用字段是必需的,因为签名者支付Gas。`chainId`、企业级 `nonceKey` 和二维nonce(从网关发现)都会自动为您处理。 ```ts const gasPrice = await publicClient.getGasPrice(); @@ -235,7 +235,7 @@ const { txHash } = await gb.send(signer, { ### `sendBatch(account, txs)` -构建、签名并中继多个 GuaranteedTx。Nonce 会从发现的基础自动排序。失败会影响其后续操作。 +构建、签名并中继多个 GuaranteedTx。Nonces 会从发现的基础自动排序。失败会影响其后续操作。 ```ts const results = await gb.sendBatch(signer, [ @@ -252,7 +252,7 @@ const results = await gb.sendBatch(signer, [ ### `relay(signedTx)` / `relayBatch(signedTxs)` -中继预签名的 GuaranteedTx,或一批 GuaranteedTx。在使用 [`nonceKeyForLane`](#noncekeyforlanelaneid) 作为企业级 Nonce 键时,在其他地方使用 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req) 构建并签署交易,然后只将签署的十六进制数据交给操作员。 +中继一个预签名的GuaranteedTx,或一批GuaranteedTx。使用 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req) 并利用 [`nonceKeyForLane`](#noncekeyforlanelaneid) 作为企业级nonceKey,在其他地方构建并签署交易,然后仅将签名的十六进制数据交给操作员。 ```ts import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; @@ -262,7 +262,7 @@ const signed = await buildGuaranteedTx(toSigner(signer), stableTestnet.id, { gas: 21_000n, gasFeeCap, gasTipCap, - nonce, // account's current 2D-lane nonce + nonce, // 账户当前的2D通道nonce nonceKey: nonceKeyForLane(0n), }); const { txHash } = await gb.relay(signed); @@ -274,42 +274,42 @@ const { txHash } = await gb.relay(signed); ## 保证中继交易 -`guaranteedWaiver` 模块结合了上述两种机制:通过保证区块空间路由的免燃料费交易。内部和外部交易都是 `0x3F` CustomTx,共享一个企业级 `nonceKey`,因此它像 `guaranteedBlock` 一样通过网关广播。豁免方赞助燃料费,因此用户无需余额和燃料费字段,就像 `gasWaiver` 一样。每个方法都返回 `H_inner`。 +`guaranteedWaiver` 模块结合了上述两个功能:一个免Gas交易通过保证区块空间路由。内部和外部交易都是 `0x3F` CustomTx,共享一个企业级 `nonceKey`,因此它通过网关广播,就像 `guaranteedBlock` 一样。免Gas模块支付Gas,所以用户不需要余额,也没有费用字段,就像 `gasWaiver` 一样。每个方法都返回 `H_inner`。 通过 `guaranteedWaiver` 和 `enterpriseRpcEndpoints` 启用它: ```ts const enterprise = createStableEnterprise({ chain: stableTestnet, - enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable 提供的网关 URL + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL], // Stable提供的网关URL guaranteedWaiver: { account: privateKeyToAccount("0xYOUR_WAIVER_KEY"), laneId: 0n, }, }); -const gw = enterprise.guaranteedWaiver!; +const gw = enterprise.guaranteedWaiver; ``` ### `GuaranteedWaiverConfig` -扩展了 [`ValidationLimits`](#validationlimits) 和 [`SignerSource`](#signersource)。它外部包装器豁免密钥的来源与 `GasWaiverConfig` 一致(`signer`,然后是 `account`,然后是环境变量),并接受相同的 `maxGasLimit`、`maxDataLength` 和 `allowedTargets` 策略控制。 +扩展 [`ValidationLimits`](#validationlimits) 和 [`SignerSource`](#signersource)。它从 `GasWaiverConfig` (`signer`,然后是 `account`,然后是环境变量)中获取外部封装的免Gas密钥,并接受相同的 `maxGasLimit`、`maxDataLength` 和 `allowedTargets` 策略控制。 | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `signer` | `Signer?` | 作为托管签名者(签署外部包装器)的白名单豁免密钥。优先于 `account`。请参阅[签名密钥和托管](#signing-keys-and-custody)。 | -| `account` | `LocalAccount?` | 作为进程内 viem 账户的豁免密钥。如果两者都未设置,则回退到 `STABLE_ENTERPRISE_PRIVATE_KEY`。 | -| `laneId` | `bigint` | 企业级通道 ID。必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。 | +| `signer` | `Signer?` | 作为托管签名器的白名单免Gas密钥(用于签名外部封装)。优先于 `account`。请参阅 [签名密钥和托管](#signing-keys-and-custody)。 | +| `account` | `LocalAccount?` | 作为进程内viem账户的免Gas密钥。当两者都未设置时,回退到 `STABLE_ENTERPRISE_PRIVATE_KEY`。 | +| `laneId` | `bigint` | 企业通道ID。必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。 | ### `send(user, tx)` / `sendBatch(user, txs)` -从 `user` 构建并签署内部 `0x3F` CustomTx,用豁免密钥包装它,然后中继。无需燃料费字段,因为燃料费已豁免。内部 2D nonce 从网关发现,批处理从该基础自动排序。 +从 `user` 构建并签署内部 `0x3F` CustomTx,用免Gas密钥封装它,然后中继。由于Gas已免除,无需费用字段。内部二维 nonce 从网关发现,批次将从此基础开始自动排序。 ```ts -// single +// 单个 const { txHash } = await gw.send(user, { to: recipient }); -// batch +// 批次 const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); ``` @@ -321,7 +321,7 @@ const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); ### `relay(signedInnerTx)` / `relayBatch(signedInnerTxs)` -对于非托管流,用户使用 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req) 签署内部 `0x3F` CustomTx(费用为 `0n`,使用 `nonceKeyForLane(laneId)`),然后只将签名的十六进制数据交给操作员。操作员使用豁免密钥将其包装并中继。 +对于非托管流程,用户使用 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req)(费用 `0n`,使用 `nonceKeyForLane(laneId)`)签署内部 `0x3F` CustomTx,然后只将签名的十六进制数据交给操作员。操作员使用免Gas密钥将其封装并中继。 ```ts import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; @@ -329,12 +329,12 @@ import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enter const signedInner = await buildGuaranteedTx(toSigner(user), stableTestnet.id, { to, gas: 100_000n, - gasFeeCap: 0n, // waived + gasFeeCap: 0n, // 免除 gasTipCap: 0n, nonce, nonceKey: nonceKeyForLane(0n), }); -const { txHash } = await gw.relay(signedInner); // waiver wraps + broadcasts → H_inner +const { txHash } = await gw.relay(signedInner); // 免Gas模块封装+广播 → H_inner ``` ```text @@ -343,11 +343,11 @@ const { txHash } = await gw.relay(signedInner); // waiver wraps + broadcasts → ## 构建助手 -用于非托管 `relay` 路径的低级签名者。每个方法都将签名交易作为 `Hex` 返回,没有 nonce 获取或费用估算。第一个参数是 [`Signer`](#signing-keys-and-custody):用 `toSigner(account)` 包装 viem 账户,或传递托管签名者(如 `awsKmsSigner`)。 +用于非托管 `relay` 路径的低级签名器。每个签名器都将签名的交易作为 `Hex` 返回,不包含 nonce 获取或费用估算。第一个参数是 [`Signer`](#signing-keys-and-custody):使用 `toSigner(account)` 封装一个 viem 账户,或者传入一个托管签名器,例如 `awsKmsSigner`。 ### `buildWaiverInnerTx(signer, chainId, req)` -使用预设的豁免条件签署一个豁免就绪的 InnerTx:`gasPrice: 0`、遗留类型和给定的 `chainId`。`req` 是一个 [`WaiverInnerTx`](#waiverinnertx) 加上一个必需的 `nonce`。 +使用预设的豁免条件签名一个可豁免的 InnerTx:`gasPrice: 0`、遗留类型和给定的 `chainId`。`req` 是一个 [`WaiverInnerTx`](#waiverinnertx) 和一个必需的 `nonce`。 ```ts const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to, data, gas: 150_000n, nonce }); @@ -359,11 +359,11 @@ const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to, ### `buildGuaranteedWaiverTx(...)` -将预签名内部交易包装到外部 `0x3F` 豁免自定义交易中。内部由 `guaranteedWaiver.relay` 使用;为高级流程导出。 +将预签名的内部交易封装到外部的 `0x3F` 免Gas自定义交易中。内部由 `guaranteedWaiver.relay` 使用;为高级流程导出。 ### `nonceKeyForLane(laneId)` -返回用于通道 ID 的企业级 `nonceKey`,以配合 `buildGuaranteedTx` 使用。 +返回用于 `buildGuaranteedTx` 的通道ID的企业级 `nonceKey`。 ```ts import { nonceKeyForLane } from "@stablechain/enterprise"; @@ -375,16 +375,16 @@ const nonceKey = nonceKeyForLane(0n); ### `SignerSource` -豁免模块(`gasWaiver`,`guaranteedWaiver`)接受的签名密钥字段。按顺序解析:`signer`,然后 `account`,然后客户端的顶层 [`signer`](#stableenterpriseconfig),然后是 `STABLE_ENTERPRISE_PRIVATE_KEY` 环境变量。请参阅[签名密钥和托管](#signing-keys-and-custody)。 +免Gas模块 (`gasWaiver`, `guaranteedWaiver`) 接受的签名密钥字段。按顺序解析:`signer`,然后是 `account`,然后是客户端的顶级 [`signer`](#stableenterpriseconfig),然后是 `STABLE_ENTERPRISE_PRIVATE_KEY` 环境变量。请参阅 [签名密钥和托管](#signing-keys-and-custody)。 | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `signer` | `Signer?` | 托管级别签名者(AWS KMS、HSM 或 `privateKeySigner`)。优先于 `account`。 | -| `account` | `LocalAccount?` | 进程内 viem 账户,通过 `toSigner` 适配为 `Signer`。 | +| `signer` | `Signer?` | 托管级签名器(AWS KMS、HSM 或 `privateKeySigner`)。优先于 `account`。 | +| `account` | `LocalAccount?` | 进程内viem账户,通过 `toSigner` 转换为 `Signer`。 | ### `Signer` -一个可插拔的签名器,SDK 通过它对 32 字节哈希进行签名,因此密钥永远不会离开托管后端。使用 `awsKmsSigner`、`toSigner`、`privateKeySigner` 或 `envSigner` 构造一个。 +一个可插拔的签名器,SDK通过它签署一个32字节的摘要,因此密钥永远不会离开托管后端。使用 `awsKmsSigner`、`toSigner`、`privateKeySigner` 或 `envSigner` 构造一个。 ```ts interface Signer { @@ -395,89 +395,89 @@ interface Signer { | **助手** | **导入** | **描述** | | :--- | :--- | :--- | -| `awsKmsSigner({ keyId, client? })` | `@stablechain/enterprise/aws-kms` | 由 AWS KMS `ECC_SECG_P256K1` 密钥支持的签名器。返回 `Promise`。 | -| `toSigner(account)` | `@stablechain/enterprise` | 将 viem `LocalAccount` 适配为 `Signer`。 | -| `privateKeySigner(key)` | `@stablechain/enterprise` | 包装进程中原始私钥的签名器。 | -| `envSigner(varName?)` | `@stablechain/enterprise` | 从 `STABLE_ENTERPRISE_PRIVATE_KEY` (或 `varName`) 读取密钥的签名器。 | +| `awsKmsSigner({ keyId, client? })` | `@stablechain/enterprise/aws-kms` | 由AWS KMS `ECC_SECG_P256K1` 密钥支持的签名器。返回 `Promise`。 | +| `toSigner(account)` | `@stablechain/enterprise` | 将viem `LocalAccount` 适配为 `Signer`。 | +| `privateKeySigner(key)` | `@stablechain/enterprise` | 封装了进程中持有的原始私钥的签名器。 | +| `envSigner(varName?)` | `@stablechain/enterprise` | 从 `STABLE_ENTERPRISE_PRIVATE_KEY`(或 `varName`)读取密钥的签名器。 | ### `WaiverInnerTx` -每次调用不同的 InnerTx 字段。 +InnerTx中每个调用都不同的字段。 | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | -| `to` | `Address` | | 目标地址:ERC-20 代币转账的代币合约,原生代币的接收者。 | -| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | 燃料费限制。由于 `gasPrice` 为 0,因此慷慨的限制是免费的。 | +| `to` | `Address` | | 目标地址:ERC-20转账的代币合约,原生代币的接收方。 | +| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | Gas限制。因为 `gasPrice` 是0,所以慷慨的限制是免费的。 | | `data` | `Hex?` | `"0x"` | 调用数据。 | -| `value` | `bigint?` | `0n` | 要发送的原生值。 | +| `value` | `bigint?` | `0n` | 发送的原生币数量。 | ### `GuaranteedTxRequest` | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | -| `to` | `Address?` | | 目标地址。 | -| `gas` | `bigint` | | 燃料费限制。必需。 | -| `gasFeeCap` | `bigint` | | `maxFeePerGas`。必需。 | -| `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`。必需。 | +| `to` | `Address?` | | 目标地址。 | +| `gas` | `bigint` | | Gas限制。必填项。 | +| `gasFeeCap` | `bigint` | | `maxFeePerGas`。必填项。 | +| `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`。必填项。 | | `data` | `Hex?` | `"0x"` | 调用数据。 | -| `value` | `bigint?` | `0n` | 要发送的原生值。 | +| `value` | `bigint?` | `0n` | 发送的原生币数量。 | ### `GuaranteedWaiverTxRequest` -燃料费字段始终为 0,因此此处省略。 +费用字段始终为0,因此此处省略。 | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | -| `to` | `Address` | | 目标地址。 | -| `gas` | `bigint?` | 共享内部燃料费默认值 | 燃料费限制。 | +| `to` | `Address` | | 目标地址。 | +| `gas` | `bigint?` | 共享的内部gas默认值 | Gas限制。 | | `data` | `Hex?` | `"0x"` | 调用数据。 | -| `value` | `bigint?` | `0n` | 要发送的原生值。允许豁免值转账。 | +| `value` | `bigint?` | `0n` | 发送的原生币数量。允许豁免价值转账。 | ### `ValidationLimits` -每个 InnerTx 的合作伙伴策略,由 `gasWaiver` 和 `guaranteedWaiver` 应用。 +应用于 `gasWaiver` 和 `guaranteedWaiver` 的每个 InnerTx 的合作伙伴策略。 | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | -| `maxGasLimit` | `bigint?` | `10_000_000n` | InnerTx 的最大燃料费限制。超过将导致 `GAS_LIMIT_EXCEEDED` 错误。 | -| `maxDataLength` | `number?` | `131_072` (128 KB) | 调用数据的最大大小(字节)。超过将导致 `DATA_TOO_LARGE` 错误。 | -| `allowedTargets` | `AllowedTarget[]?` | | 豁免可以赞助的合约和方法的白名单。设置后,列表之外的目标将导致 `TARGET_NOT_ALLOWED` 错误。 | +| `maxGasLimit` | `bigint?` | `10_000_000n` | InnerTx的最大Gas限制。超过此限制将导致 `GAS_LIMIT_EXCEEDED` 错误。 | +| `maxDataLength` | `number?` | `131_072` (128 KB) | 调用数据的最大字节大小。超过此限制将导致 `DATA_TOO_LARGE` 错误。 | +| `allowedTargets` | `AllowedTarget[]?` | | 免Gas模块可能赞助的合约和方法的白名单。设置后,列表之外的目标将导致 `TARGET_NOT_ALLOWED` 错误。 | ### `AllowedTarget` | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `address` | `Address \| "*"` | InnerTx 可以调用的合约,或 `"*"` 以匹配任何合约。 | -| `selectors` | `Hex[]?` | 允许的 4 字节方法选择器(例如,ERC-20 `transfer` 的 `"0xa9059cbb"`)。省略或留空以允许 `address` 上的任何方法。 | +| `address` | `Address \| "*"` | InnerTx可能调用的合约,或 `"*"` 以匹配任何合约。 | +| `selectors` | `Hex[]?` | 允许的4字节方法选择器(例如ERC-20 `transfer` 的 `"0xa9059cbb"`)。省略或留空以允许 `address` 上的任何方法。 | ### `RelayResult` ```ts interface RelayResult { - txHash: Hash; // H_inner 用于豁免,GuaranteedTx 哈希用于独立的保证区块 + txHash: Hash; // 免Gas是H_inner,独立保证区块是GuaranteedTx哈希 } ``` ### `BatchResultItem` -批处理中每个输入的条目,按输入顺序排列。批处理不会抛出错误,而是显示每个项目的处理结果。 +批处理中每个输入的一个条目,按输入顺序排列。批处理不会抛出错误,而是显示每个项目的处理结果。 | **字段** | **类型** | **描述** | | :--- | :--- | :--- | | `index` | `number` | 零基位置,与输入数组匹配。 | -| `success` | `boolean` | 此项目是否中继。 | +| `success` | `boolean` | 此项目是否已中继。 | | `txHash` | `Hash?` | 成功时存在:内部交易哈希。 | | `error` | `{ code: ErrorCode; message: string }?` | 失败时存在。 | ## 错误 -单交易方法 (`send`, `relay`) 在拒绝时抛出错误。批处理方法则在 [`BatchResultItem.error`](#batchresultitem) 中报告每个项目的失败。所有错误类都继承自 `StableEnterpriseError`。 +单个事务方法(`send`、`relay`)在拒绝时抛出异常。批量方法则在 [`BatchResultItem.error`](#batchresultitem) 中报告每项失败。所有错误类都继承自 `StableEnterpriseError`。 -| **类别** | **抛出条件** | **有用字段** | +| **类** | **抛出条件** | **有用字段** | | :--- | :--- | :--- | -| `StableEnterpriseError` | 每一个 SDK 错误的基类。 | `message` | -| `StableEnterpriseRelayError` | 交易在 RPC 或中继层被拒绝。 | `code` | -| `WaiverValidationError` | InnerTx 在广播前未能通过策略检查(燃料费、数据大小或目标白名单)。 | `code` | +| `StableEnterpriseError` | 所有SDK错误的基础类。 | `message` | +| `StableEnterpriseRelayError` | 交易在RPC或中继层被拒绝。 | `code` | +| `WaiverValidationError` | InnerTx在广播前未能通过策略检查(Gas、数据大小或目标白名单)。 | `code` | ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -486,7 +486,7 @@ try { await gw.send(user, { to: token, data }); } catch (err) { if (err instanceof StableEnterpriseRelayError && err.code === "TARGET_NOT_ALLOWED") { - // InnerTx 目标不在配置的白名单中 + // InnerTx目标不在配置的白名单中 } throw err; } @@ -498,33 +498,33 @@ StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not ### `ErrorCode` -抛出的错误或 `BatchResultItem.error` 上的 `code` 是以下之一: +抛出错误或 `BatchResultItem.error` 上的 `code` 是以下之一: | **代码** | **含义** | | :--- | :--- | -| `UNKNOWN_ERROR` | 没有特定代码时的回退。 | -| `BROADCAST_FAILED` | 广播在 RPC 层被拒绝,或网关未能中继。 | -| `INVALID_TRANSACTION` | InnerTx 解码或解析失败。 | +| `UNKNOWN_ERROR` | 当没有特定代码时的回退。 | +| `BROADCAST_FAILED` | 广播在RPC层被拒绝,或网关中继失败。 | +| `INVALID_TRANSACTION` | InnerTx解码或解析失败。 | | `INVALID_SIGNATURE` | 签名验证失败。 | -| `UNSUPPORTED_TX_TYPE` | InnerTx 类型不是 legacy、eip2930 或 eip1559。 | +| `UNSUPPORTED_TX_TYPE` | InnerTx类型不是遗留、eip2930或eip1559。 | | `WRONG_CHAIN_ID` | InnerTx `chainId` 缺失或与目标链不匹配。 | -| `NON_ZERO_GAS_PRICE` | InnerTx 带有非零燃料费价格(对于豁免必须为零)。 | -| `GAS_LIMIT_EXCEEDED` | InnerTx 燃料费限制超出 `maxGasLimit`。 | -| `DATA_TOO_LARGE` | InnerTx 调用数据超出 `maxDataLength`。 | -| `TARGET_NOT_ALLOWED` | InnerTx 目标不在 `allowedTargets` 中。 | -| `GATEWAY_UNAUTHORIZED` | 企业级 RPC 网关拒绝了 API 密钥(丢失、无效或已过期)。 | -| `QUOTA_EXCEEDED` | 企业级 RPC 网关燃料费配额已用尽。 | +| `NON_ZERO_GAS_PRICE` | InnerTx带有非零Gas价格(豁免必须为零)。 | +| `GAS_LIMIT_EXCEEDED` | InnerTx Gas限制超过 `maxGasLimit`。 | +| `DATA_TOO_LARGE` | InnerTx调用数据超过 `maxDataLength`。 | +| `TARGET_NOT_ALLOWED` | InnerTx目标不在 `allowedTargets` 中。 | +| `GATEWAY_UNAUTHORIZED` | 企业RPC网关拒绝了API密钥(缺失、无效或过期)。 | +| `QUOTA_EXCEEDED` | 企业RPC网关Gas配额已用尽。 | -## 常量 +## 常数 -| **常量** | **类型** | **描述** | +| **常数** | **类型** | **描述** | | :--- | :--- | :--- | -| `DEFAULT_INNER_GAS` | `bigint` | 省略 `gas` 时 InnerTx 的默认燃料费限制 (`150_000n`)。 | -| `ENTERPRISE_FLAG` | `bigint` | 在通道的 `nonceKey` 上设置企业位。 | -| `ENTERPRISE_MASK` | `bigint` | 通道 ID 的上限:`laneId` 必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。 | +| `DEFAULT_INNER_GAS` | `bigint` | 当 `gas` 省略时,InnerTx的默认Gas限制 (`150_000n`)。 | +| `ENTERPRISE_FLAG` | `bigint` | 设置在通道 `nonceKey` 上的企业位。 | +| `ENTERPRISE_MASK` | `bigint` | 通道ID的上限:`laneId` 必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。 | ## 下一步建议 -- [**Stable 企业级 SDK**](/cn/explanation/enterprise-sdk): 什么是这些概念以及何时使用它们。 -- [**免燃料费协议**](/cn/reference/gas-waiver-api): 交易格式、标记路由和治理控制。 -- [**保证区块空间**](/cn/explanation/guaranteed-blockspace): Stable 如何为企业级工作负载预留区块容量。 +- [**Stable企业级SDK**](/cn/explanation/enterprise-sdk):了解这些轨道的含义以及何时使用它们。 +- [**免Gas协议**](/cn/reference/gas-waiver-api):交易格式、标记路由和治理控制。 +- [**保证区块空间**](/cn/explanation/guaranteed-blockspace):Stable如何为企业级工作负载预留区块容量。 diff --git a/docs/pages/ko/explanation/enterprise-sdk.mdx b/docs/pages/ko/explanation/enterprise-sdk.mdx index 9b4dab6..495808d 100644 --- a/docs/pages/ko/explanation/enterprise-sdk.mdx +++ b/docs/pages/ko/explanation/enterprise-sdk.mdx @@ -1,14 +1,14 @@ --- source_path: explanation/enterprise-sdk.mdx -source_sha: c16b058331d58a968753ec4877bb47cd7377fe14 +source_sha: a632f3be5fbff966d9da230ec302b4ce4e6773f2 title: "Stable Enterprise SDK" -description: "유형화된 @stablechain/enterprise SDK를 사용하여 백엔드에서 가스 면제 및 블록 공간 보장 트랜잭션을 릴레이하세요." +description: "유형화된 @stablechain/enterprise SDK를 사용하여 백엔드에서 가스 면제 및 블록 공간 보장 트랜잭션을 릴레이합니다." diataxis: "explanation" --- # Stable Enterprise SDK -`@stablechain/enterprise`는 Stable의 엔터프라이즈 트랜잭션 레일을 위한 서버 측 타입스크립트 클라이언트입니다. 이는 두 가지 종류의 특권 트랜잭션, 즉 사용자의 가스를 후원하는 가스 면제 트랜잭션과 예약된 엔터프라이즈 레인에 도달하는 블록 공간 보장 트랜잭션을 서명하고 릴레이합니다. 하나의 클라이언트에서 두 레일 중 하나 또는 둘 다를 활성화할 수 있습니다. +`@stablechain/enterprise`는 Stable의 엔터프라이즈 트랜잭션 레일을 위한 서버 측 TypeScript 클라이언트입니다. 사용자의 가스를 후원하는 가스 면제 트랜잭션과 예약된 엔터프라이즈 레인에 포함되는 블록 공간 보장 트랜잭션의 두 가지 종류의 특권 트랜잭션을 서명하고 릴레이합니다. 하나의 클라이언트에서 두 레일 중 하나 또는 둘 다를 활성화할 수 있습니다. ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -19,52 +19,52 @@ const enterprise = createStableEnterprise({ gasWaiver: { account: privateKeyToAccount("0xYOUR_WAIVER_KEY") }, }); -const { txHash } = await enterprise.gasWaiver!.send(user, { to: token, data }); +const { txHash } = await enterprise.gasWaiver.send(user, { to: token, data }); ``` ```text txHash: 0x8f3a...2d41 ``` -이 호출은 사용자 트랜잭션의 해시(`H_inner`)를 반환하며, 이를 전달한 래퍼 트랜잭션이 아닙니다. +호출은 사용자의 트랜잭션 해시인 `H_inner`를 반환하며, 이를 전달한 래퍼 트랜잭션은 반환하지 않습니다. ## SDK의 기능 -SDK는 모듈당 세 가지 기능을 제공합니다. 각 기능은 선택 사항이며 독립적으로 구성되며, 자체 서명 계정을 포함하므로 별도의 키를 사용할 수 있습니다. +SDK는 모듈당 하나의 기능을 노출합니다. 각 기능은 선택 사항이며 독립적으로 구성되며, 각각 고유한 서명 계정을 가지고 있으므로 별도의 키를 사용할 수 있습니다. -- **가스 면제와 함께 릴레이** (`gasWaiver`): 가스 면제 트랜잭션을 빌드, 서명 및 릴레이합니다. 화이트리스트에 등록된 면제 계정이 사용자의 제로 가스 트랜잭션을 래핑하므로 사용자는 USDT0을 보유하지 않고 거래할 수 있습니다. [가스 면제](/ko/explanation/gas-waiver)를 참조하세요. -- **블록 공간 보장** (`guaranteedBlock`): 엔터프라이즈 RPC 게이트웨이를 통해 트랜잭션을 릴레이하므로 예약된 엔터프라이즈 레인 블록 공간에 도달합니다. 가스 면제와 달리 서명자는 자체 가스를 지불합니다. [블록 공간 보장](/ko/explanation/guaranteed-blockspace)을 참조하세요. -- **보장된 릴레이 트랜잭션** (`guaranteedWaiver`): 두 기능을 모두 결합합니다. 엔터프라이즈 레인을 통해 라우팅되는 가스 면제 트랜잭션이므로 사용자는 잔액이 필요 없으며 트랜잭션은 엔터프라이즈 레인에 도달합니다. +- **가스 면제 릴레이** (`gasWaiver`): 가스 면제 트랜잭션을 구축하고 서명하며 릴레이합니다. 화이트리스트에 등록된 면제 계정이 사용자의 제로 가스 트랜잭션을 래핑하여 사용자가 USDT0를 보유하지 않고도 트랜잭션을 할 수 있도록 합니다. [가스 면제](/ko/explanation/gas-waiver)를 참조하십시오. +- **블록 공간 보장** (`guaranteedBlock`): 엔터프라이즈 RPC 게이트웨이를 통해 트랜잭션을 릴레이하여 예약된 엔터프라이즈 레인 블록 공간에 포함되도록 합니다. 가스 면제와 달리 서명자는 자체 가스를 지불합니다. [블록 공간 보장](/ko/explanation/guaranteed-blockspace)을 참조하십시오. +- **보장된 릴레이 트랜잭션** (`guaranteedWaiver`): 두 가지를 모두 결합합니다. 블록 공간 보장을 통해 라우팅된 가스 면제 트랜잭션이므로 사용자는 잔고가 필요 없으며 트랜잭션은 여전히 엔터프라이즈 레인에 포함됩니다. -모든 기능은 동일한 네 가지 메서드를 제공합니다. SDK가 서명하는 관리 경로의 경우 `send` 및 `sendBatch`를, 사용자가 다른 곳에서 서명하고 서명된 헥스만 전달하는 비관리 경로의 경우 `relay` 및 `relayBatch`를 제공합니다. +모든 기능은 동일한 네 가지 메서드를 제공합니다. SDK가 서명하는 관리 경로의 `send` 및 `sendBatch`, 그리고 사용자가 다른 곳에서 서명하고 서명된 헥스만 전달하는 비관리 경로의 `relay` 및 `relayBatch`입니다. -## 접근 +## 액세스 -엔터프라이즈 SDK는 현재 Stable Testnet에서만 사용할 수 있습니다. +엔터프라이즈 SDK는 현재 Stable 테스트넷에서만 사용할 수 있습니다. -두 레일 모두 게이트로 보호됩니다. 가스 면제는 거버넌스 등록 면제 키를 요구하고, 보장된 블록 공간은 엔터프라이즈 RPC 게이트웨이 API 키를 요구합니다. 통합하려면, 접근 권한을 얻기 위해 [Stable에 문의](https://discord.gg/stablexyz)하세요. Stable은 필요한 면제 키와 게이트웨이 엔드포인트를 제공합니다. +두 레일 모두 게이트로 보호됩니다. 가스 면제에는 거버넌스에 등록된 면제 키가 필요하며, 블록 공간 보장에는 엔터프라이즈 RPC 게이트웨이 API 키가 필요합니다. 통합하려면 [Stable에 문의](https://discord.gg/stablexyz)하여 액세스 권한을 얻으십시오. Stable은 필요한 면제 키와 게이트웨이 엔드포인트를 제공합니다. ## 서버 측 전용 :::warning -엔터프라이즈 SDK는 개인 키로 서명하는 상태 비저장 서버 측 라이브러리입니다. 브라우저에서 실행하지 마세요. 면제 키와 엔터프라이즈 RPC 게이트웨이 URL을 백엔드에 보관하세요. +엔터프라이즈 SDK는 개인 키로 서명하는 상태 비저장 서버 측 라이브러리입니다. 브라우저에서 실행하지 마십시오. 면제 키와 엔터프라이즈 RPC 게이트웨이 URL을 백엔드에 보관하십시오. ::: -면제 키는 화이트리스트에 등록된 거버넌스 등록 계정입니다. 이를 보유한 누구든지 정책에 따라 가스를 후원할 수 있습니다. 기업 RPC 게이트웨이 URL에는 API 키가 포함되어 있습니다. 둘 다 비밀로 취급해야 합니다. 면제 키를 프로세스 외부에 보관하려면 AWS KMS와 같은 보관 서명자로 백업하십시오. [서명 키 및 보관](/ko/reference/enterprise-sdk#signing-keys-and-custody)를 참조하십시오. +면제 키는 화이트리스트에 등록된 거버넌스 등록 계정입니다. 이를 소유한 누구든지 귀하의 정책에 따라 가스를 후원할 수 있습니다. 엔터프라이즈 RPC 게이트웨이 URL에는 API 키가 포함되어 있습니다. 둘 다 비밀로 취급하십시오. 면제 키를 프로세스 외부에서 유지하려면 AWS KMS와 같은 보관 서명자로 백업하십시오. [서명 키 및 보관](/ko/reference/enterprise-sdk#signing-keys-and-custody)을 참조하십시오. -## 언제 사용해야 하는가 +## 언제 사용해야 할까요? -백엔드를 운영하며 사용자의 가스를 후원하거나 자체 트래픽에 대한 포함을 보장하려는 경우 엔터프라이즈 SDK를 사용하십시오. 백엔드 또는 브라우저에서 일상적인 전송, 브리지, 스왑 및 볼트 수익을 위해서는 일반적인 목적의 [Stable SDK](/ko/explanation/sdk-overview)를 대신 사용하십시오. +백엔드를 운영하고 사용자의 가스를 후원하거나 자체 트래픽에 대한 포함을 보장하려는 경우 엔터프라이즈 SDK를 사용하십시오. 백엔드 또는 브라우저에서 일상적인 송금, 브리지, 스왑 및 볼트 수익을 위해서는 범용 [Stable SDK](/ko/explanation/sdk-overview)를 대신 사용하십시오. -## 여기서 시작 +## 여기서 시작하세요 -- [**가스 면제와 함께 릴레이**](/ko/how-to/relay-with-gas-waiver): 사용자가 USDT0를 보유하지 않고 거래할 수 있도록 가스를 후원합니다. -- [**보장된 트랜잭션 전송**](/ko/how-to/send-guaranteed-transactions): 예약된 엔터프라이즈 레인 블록 공간에 트랜잭션을 실현합니다. +- [**가스 면제 릴레이**](/ko/how-to/relay-with-gas-waiver): 사용자가 USDT0를 보유하지 않고도 트랙잭션을 할 수 있도록 가스를 후원합니다. +- [**보장된 트랜잭션 보내기**](/ko/how-to/send-guaranteed-transactions): 예약된 엔터프라이즈 레인 블록 공간에 트랜잭션을 포함시킵니다. - [**보장된 릴레이 트랜잭션**](/ko/how-to/guaranteed-relayed-transactions): 두 레일을 모두 결합합니다: 엔터프라이즈 레인의 가스 면제 트랜잭션. - [**엔터프라이즈 SDK 참조**](/ko/reference/enterprise-sdk): 모든 모듈, 메서드, 구성 옵션 및 오류 클래스. ## 다음 권장 사항 - [**가스 면제 프로토콜**](/ko/reference/gas-waiver-api): 트랜잭션 형식, 마커 라우팅 및 거버넌스 제어. -- [**Stable SDK**](/ko/explanation/sdk-overview): 전송, 브리징, 스왑 및 수익을 위한 범용 클라이언트. -- [**Stable에 연결**](/ko/reference/connect): 테스트넷용 체인 ID, RPC 엔드포인트 및 탐색기. +- [**Stable SDK**](/ko/explanation/sdk-overview): 송금, 브리징, 스왑 및 수익을 위한 범용 클라이언트. +- [**Stable에 연결**](/ko/reference/connect): 테스트넷의 체인 ID, RPC 엔드포인트 및 익스플로러. diff --git a/docs/pages/ko/how-to/guaranteed-relayed-transactions.mdx b/docs/pages/ko/how-to/guaranteed-relayed-transactions.mdx index 5fe7918..70eba20 100644 --- a/docs/pages/ko/how-to/guaranteed-relayed-transactions.mdx +++ b/docs/pages/ko/how-to/guaranteed-relayed-transactions.mdx @@ -1,29 +1,29 @@ --- source_path: how-to/guaranteed-relayed-transactions.mdx -source_sha: 770f26cb178bfd6e7b678d524f5148a39a3f9946 -title: "보장된 릴레이 트랜잭션" -description: "Enterprise SDK를 통해 보장된 블록 공간으로 가스가 면제된 트랜잭션을 릴레이하여 사용자는 잔액이 없어도 Enterprise 라인에 접속할 수 있습니다." +source_sha: 007be0e546cc1251771678ee74523b6a79a2d76d +title: "보장된 중계 트랜잭션" +description: "Enterprise SDK를 사용하여 보장된 블록 공간을 통해 가스 면제 트랜잭션을 중계하여 사용자가 잔액 없이도 Enterprise 레인에 진입할 수 있도록 합니다." diataxis: "how-to" --- -# 보장된 릴레이 트랜잭션 +# 보장된 중계 트랜잭션 -`@stablechain/enterprise`와 함께 두 가지 Enterprise 레일을 결합하세요. 보장된 릴레이 트랜잭션은 [가스가 면제된 트랜잭션](/ko/how-to/relay-with-gas-waiver)을 [보장된 블록 공간](/ko/how-to/send-guaranteed-transactions)을 통해 라우팅하는 것입니다. 즉, 면제는 가스를 후원하므로 사용자는 잔액이나 수수료 필드가 필요 없으며, 트랜잭션은 예약된 Enterprise 레인에 도착합니다. +`@stablechain/enterprise`를 사용하여 두 가지 Enterprise 레일을 모두 결합합니다. 보장된 중계 트랜잭션은 [가스 면제 트랜잭션](/ko/how-to/relay-with-gas-waiver)을 [보장된 블록 공간](/ko/how-to/send-guaranteed-transactions)을 통해 라우팅하는 것입니다. 즉, 면제가 가스를 지원하므로 사용자는 잔액이나 수수료 필드가 필요 없으며 트랜잭션은 예약된 Enterprise 레인에 진입합니다. -`guaranteedWaiver` 모듈은 양쪽을 모두 처리합니다. 사용자는 내부 `0x3F` CustomTx에 서명하고, 화이트리스트에 있는 면제 계정은 동일한 Enterprise `nonceKey`를 공유하는 외부 `0x3F` CustomTx로 래핑한 다음, Enterprise RPC 게이트웨이를 통해 브로드캐스트합니다. 모든 메소드는 사용자 트랜잭션 해시인 `H_inner`를 반환합니다. +`guaranteedWaiver` 모듈은 양측을 모두 처리합니다. 사용자는 내부 `0x3F` CustomTx에 서명하고, 화이트리스트에 등록된 면제 계정은 동일한 Enterprise `nonceKey`를 공유하는 외부 `0x3F` CustomTx로 래핑하고, Enterprise RPC 게이트웨이를 통해 브로드캐스트합니다. 모든 메소드는 사용자의 트랜잭션 해시인 `H_inner`를 반환합니다. ## 전제 조건 -- Node.js 20 이상, `@stablechain/enterprise` 및 `viem` 설치. [Enterprise SDK 참조](/ko/reference/enterprise-sdk#install)를 참조하세요. -- 거버넌스에 등록된 면제 키와 Enterprise RPC 게이트웨이 API 키. 현재 Enterprise SDK는 테스트넷 전용이며 요청 시 액세스할 수 있습니다. 둘 다 [Stable에 문의](https://discord.gg/stablexyz)하여 얻으세요. +- Node.js 20 이상, 그리고 `@stablechain/enterprise` 및 `viem` 설치. [Enterprise SDK 참조](/ko/reference/enterprise-sdk#install)를 참조하세요. +- 거버넌스에 등록된 면제 키와 Enterprise RPC 게이트웨이 API 키. Enterprise SDK는 현재 테스트넷 전용이며 요청 시 액세스가 가능합니다. 둘 다 얻으려면 [Stable에 문의](https://discord.gg/stablexyz)하세요. :::warning -이것은 서버 측 라이브러리입니다. 면제 키와 Enterprise RPC 게이트웨이 URL을 백엔드에 보관하세요. 게이트웨이 URL에는 API 키가 포함되어 있습니다. +이것은 서버 측 라이브러리입니다. 면제 키와 Enterprise RPC 게이트웨이 URL을 백엔드에 보관하세요. 게이트웨이 URL에 API 키가 포함되어 있습니다. ::: ## 1. 보장된 면제 모듈로 클라이언트 생성 -`guaranteedWaiver` 및 `enterpriseRpcEndpoints`를 `createStableEnterprise`에 전달합니다. 이 모듈은 화이트리스트에 있는 면제 키(외부 래퍼에 서명)와 Enterprise 레인을 가져옵니다. 또한 `gasWaiver`와 동일한 `allowedTargets`, `maxGasLimit`, `maxDataLength` 정책 제한도 허용합니다. +`guaranteedWaiver`와 `enterpriseRpcEndpoints`를 `createStableEnterprise`에 전달합니다. 이 모듈은 화이트리스트에 등록된 면제 키(외부 래퍼에 서명)와 Enterprise 레인을 사용합니다. 또한 `gasWaiver`와 동일한 `allowedTargets`, `maxGasLimit`, `maxDataLength` 정책 제한을 허용합니다. ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -31,14 +31,14 @@ import { privateKeyToAccount } from "viem/accounts"; const enterprise = createStableEnterprise({ chain: stableTestnet, - enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable이 제공하는 게이트웨이 URL + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL], // Stable에서 제공하는 게이트웨이 URL guaranteedWaiver: { account: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`), laneId: 0n, // Enterprise 레인 }, }); -const gw = enterprise.guaranteedWaiver!; +const gw = enterprise.guaranteedWaiver; ``` ```text @@ -46,12 +46,12 @@ StableEnterpriseClient { gasWaiver: undefined, guaranteedBlock: undefined, guara ``` :::tip -면제 키를 보관 백엔드에 보관하려면 `account` 대신 `signer`를 전달합니다. `@stablechain/enterprise/aws-kms`의 `awsKmsSigner`는 AWS KMS로 이를 지원합니다. [서명 키 및 보관](/ko/reference/enterprise-sdk#signing-keys-and-custody)을 참조하세요. +면제 키를 보관 백엔드에 유지하려면 `account` 대신 `signer`를 전달하세요. `@stablechain/enterprise/aws-kms`의 `awsKmsSigner`는 AWS KMS로 이를 지원합니다. [서명 키 및 보관](/ko/reference/enterprise-sdk#signing-keys-and-custody)을 참조하세요. ::: -## 2. 단일 트랜잭션 릴레이 +## 2. 단일 트랜잭션 중계 -사용자 계정과 변하는 필드를 사용하여 `send`를 호출합니다. 가스가 면제되므로 사용자에게는 잔액이나 수수료 필드가 필요 없습니다. 내부 `0x3F` CustomTx, 해당 Enterprise `nonceKey`, 그리고 게이트웨이에서 발견된 2D 논스는 자동으로 처리됩니다. +사용자의 계정과 변경되는 필드를 사용하여 `send`를 호출합니다. 가스는 면제되므로 사용자는 잔액이나 수수료 필드가 필요 없습니다. 내부 `0x3F` CustomTx, 해당 Enterprise `nonceKey`, 그리고 (게이트웨이에서 발견된) 2D nonce는 자동으로 처리됩니다. ```ts const user = privateKeyToAccount(process.env.USER_PRIVATE_KEY as `0x${string}`); @@ -64,11 +64,11 @@ console.log("H_inner:", txHash); H_inner: 0x8f3a...2d41 ``` -`gas`는 공유된 내부 가스 기본값으로 설정됩니다. 재정의하려면 전달합니다. 값 전송이 허용되므로 `value`를 전달할 수도 있습니다. +`gas`는 공유된 내부 가스 기본값으로 설정됩니다. 재정의하려면 필요할 때만 전달하세요. 값 전송이 허용되므로 `value`도 전달할 수 있습니다. -## 3. 배치 릴레이 +## 3. 배치 중계 -한 사용자로부터 여러 트랜잭션을 릴레이하려면 `sendBatch`를 호출합니다. 내부 논스는 발견된 기본값에서 자동으로 시퀀싱되며, 입력 순서대로 입력당 하나의 결과를 얻습니다. 실패는 후속 트랜잭션을 중단시킵니다. +단일 사용자로부터 여러 트랜잭션을 중계하려면 `sendBatch`를 호출합니다. 내부 nonce는 발견된 기준에서 자동으로 순차적으로 생성되며, 입력 순서대로 입력당 하나의 결과를 얻습니다. 실패는 후속 항목을 중단시킵니다. ```ts const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); @@ -83,25 +83,25 @@ for (const r of results) { [1] ✔ 0x2b7c...9e04 ``` -## 4. 사전 서명된 트랜잭션 릴레이 +## 4. 사전 서명된 트랜잭션 중계 -비보관 플로우의 경우, 사용자는 자신의 환경에서 내부 `0x3F` CustomTx에 서명하고 서명된 헥스만 전달합니다. `nonceKeyForLane`을 Enterprise 논스 키로 사용하고 수수료를 0으로 설정하여 (가스가 면제됨) `buildGuaranteedTx`로 빌드합니다. 백엔드는 이를 면제 키로 래핑하고 `relay`로 릴레이합니다. +비수탁형 흐름의 경우, 사용자는 자신의 환경에서 내부 `0x3F` CustomTx에 서명하고 서명된 헥스만 전달합니다. Enterprise nonce 키에는 `nonceKeyForLane`을 사용하고 수수료는 0으로(가스 면제) 설정하여 `buildGuaranteedTx`로 빌드합니다. 백엔드는 이를 면제 키로 래핑하고 `relay`로 중계합니다. ```ts import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; -// 사용자 측 — buildGuaranteedTx는 Signer를 통해 서명합니다. toSigner는 viem 계정을 조정합니다. +// 사용자의 측면 - buildGuaranteedTx는 Signer를 통해 서명합니다. toSigner는 viem 계정을 조정합니다. const signedInner = await buildGuaranteedTx(toSigner(user), stableTestnet.id, { to: recipient, gas: 100_000n, - gasFeeCap: 0n, // 면제됨 + gasFeeCap: 0n, // 면제 gasTipCap: 0n, - nonce, // 사용자의 현재 2D-레인 논스 + nonce, // 사용자의 현재 2D-레인 nonce nonceKey: nonceKeyForLane(0n), // Enterprise 레인 0 }); // 백엔드에서 -const { txHash } = await gw.relay(signedInner); // 면제 래핑 + 브로드캐스트 → H_inner +const { txHash } = await gw.relay(signedInner); // waiver는 래핑 + 브로드캐스트 → H_inner console.log("H_inner:", txHash); ``` @@ -113,7 +113,7 @@ H_inner: 0x8f3a...2d41 ## 거부 처리 -`send` 및 `relay`는 거부 시 `StableEnterpriseRelayError`를 발생시킵니다. 이 플로우는 게이트웨이를 통해 라우팅되므로 `GATEWAY_UNAUTHORIZED` 및 `QUOTA_EXCEEDED`와 같은 게이트웨이 코드가 `TARGET_NOT_ALLOWED`와 같은 면제 정책 코드와 함께 적용됩니다. +`send` 및 `relay`는 거부 시 `StableEnterpriseRelayError`를 throw합니다. 이 흐름은 게이트웨이를 통해 라우팅되므로 `GATEWAY_UNAUTHORIZED` 및 `QUOTA_EXCEEDED`와 같은 게이트웨이 코드는 `TARGET_NOT_ALLOWED`와 같은 면제 정책 코드와 함께 적용됩니다. ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -136,6 +136,6 @@ StableEnterpriseRelayError: relay failed [GATEWAY_UNAUTHORIZED]: invalid api key ## 다음 단계 -- [**가스 면제로 릴레이**](/ko/how-to/relay-with-gas-waiver): 보장된 레인 없이 사용자의 가스를 후원합니다. +- [**가스 면제로 중계**](/ko/how-to/relay-with-gas-waiver): 보장된 레인 없이 사용자의 가스를 지원합니다. - [**보장된 트랜잭션 전송**](/ko/how-to/send-guaranteed-transactions): 서명자가 가스를 지불하는 경우, 보장된 블록 공간을 단독으로 사용합니다. - [**Enterprise SDK 참조**](/ko/reference/enterprise-sdk#guaranteed-relay-transactions): 모든 메소드, 구성 옵션 및 오류 클래스에 대한 전체 설명입니다. diff --git a/docs/pages/ko/how-to/relay-with-gas-waiver.mdx b/docs/pages/ko/how-to/relay-with-gas-waiver.mdx index e94fd33..8ecef5c 100644 --- a/docs/pages/ko/how-to/relay-with-gas-waiver.mdx +++ b/docs/pages/ko/how-to/relay-with-gas-waiver.mdx @@ -1,6 +1,6 @@ --- source_path: how-to/relay-with-gas-waiver.mdx -source_sha: d27d02a1e7956429991b4af81f097719e3eabd34 +source_sha: c1b34aab292d8e9623b59810cd6b668468e834ce title: "가스 면제 릴레이" description: "Enterprise SDK로 사용자의 가스를 후원하세요: 제로 가스 트랜잭션을 릴레이하고, 릴레이를 일괄 처리하고, 정책 제한을 적용하고, 사전 서명된 트랜잭션을 릴레이합니다." diataxis: "how-to" @@ -8,14 +8,14 @@ diataxis: "how-to" # 가스 면제 릴레이 -`@stablechain/enterprise`를 사용하여 사용자의 가스를 후원하세요. 화이트리스트에 등록된 면제 계정은 사용자의 제로 가스 트랜잭션(InnerTx)을 래핑하고 브로드캐스트하여 사용자가 USDT0를 보유하지 않고도 트랜잭션할 수 있도록 합니다. `gasWaiver` 모듈은 한 번의 호출로 빌드, 서명 및 릴레이를 수행하므로 작업당 하나의 메서드를 호출합니다. +`@stablechain/enterprise`로 사용자의 가스를 후원하세요. 화이트리스트에 등록된 면제 계정은 사용자의 제로 가스 트랜잭션(InnerTx)을 래핑하여 브로드캐스트하므로, 사용자는 USDT0를 보유하지 않고도 트랜잭션을 수행할 수 있습니다. `gasWaiver` 모듈은 한 번의 호출로 빌드, 서명 및 릴레이를 수행하므로, 각 작업당 하나의 메서드를 호출합니다. -모든 메서드는 트랜잭션을 전달한 래퍼가 아닌, 사용자 트랜잭션의 해시인 `H_inner`를 반환합니다. +모든 메서드는 트랜잭션을 담고 있는 래퍼가 아닌, 사용자 트랜잭션의 해시인 `H_inner`를 반환합니다. ## 전제 조건 -- Node.js 20 이상, 그리고 `@stablechain/enterprise`와 `viem` 설치. [Enterprise SDK 참조](/ko/reference/enterprise-sdk#install)를 참조하세요. -- 거버넌스에 등록된 면제 키. Enterprise SDK는 현재 테스트넷 전용이며 접근이 제한됩니다: 화이트리스트에 등록된 면제 키를 받으려면 [Stable에 문의](https://discord.gg/stablexyz)하세요. +- Node.js 20 이상, 그리고 `@stablechain/enterprise`와 `viem`이 설치되어 있어야 합니다. [Enterprise SDK 참조](/ko/reference/enterprise-sdk#install)를 참조하세요. +- 거버넌스에 등록된 면제 키. Enterprise SDK는 현재 테스트넷 전용이며 접근이 제한되어 있습니다: 화이트리스트에 등록된 면제 키를 받으려면 [Stable에 문의](https://discord.gg/stablexyz)하세요. :::warning 이것은 개인 키로 서명하는 서버 측 라이브러리입니다. 브라우저에서 실행하지 마십시오. 면제 키는 백엔드에 보관하십시오. @@ -23,7 +23,7 @@ diataxis: "how-to" ## 1. 가스 면제 모듈로 클라이언트 생성 -`createStableEnterprise`에 `gasWaiver: { account }`를 전달합니다. 여기서 `account`는 화이트리스트에 등록된 면제 키입니다. 모듈은 구성할 때만 클라이언트에 존재합니다. +`gasWaiver: { account }`를 `createStableEnterprise`에 전달합니다. 여기서 `account`는 화이트리스트에 등록된 면제 키입니다. 모듈은 클라이언트에 구성해야만 존재합니다. ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -34,7 +34,7 @@ const enterprise = createStableEnterprise({ gasWaiver: { account: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`) }, }); -const gw = enterprise.gasWaiver!; +const gw = enterprise.gasWaiver; ``` ```text @@ -44,12 +44,12 @@ StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver `rpcEndpoints` 옵션은 선택 사항입니다. 설정하지 않으면 클라이언트는 체인의 내장 RPC를 사용합니다. :::tip -면제 키를 보관 백엔드에 보관하려면 `account` 대신 `signer`를 전달하세요. `@stablechain/enterprise/aws-kms`의 `awsKmsSigner`는 AWS KMS로 이를 지원합니다. [서명 키 및 보관](/ko/reference/enterprise-sdk#signing-keys-and-custody)을 참조하십시오. +면제 키를 보관 백엔드에 보관하려면 `account` 대신 `signer`를 전달하세요. `@stablechain/enterprise/aws-kms`의 `awsKmsSigner`는 AWS KMS로 이를 지원합니다. [서명 키 및 보관](/ko/reference/enterprise-sdk#signing-keys-and-custody)을 참조하세요. ::: ## 2. 단일 트랜잭션 릴레이 -사용자 계정과 변경되는 필드를 사용하여 `send`를 호출합니다. `gasPrice: 0`, 레거시 유형, `chainId`, 보류 중인 nonce는 자동으로 처리되므로, `to`, 그리고 선택적으로 `data`, `value`, `gas`만 전달하면 됩니다. +사용자 계정 및 변경되는 필드와 함께 `send`를 호출합니다. `gasPrice: 0`, 레거시 유형, `chainId`, 보류 중인 논스가 자동으로 처리되므로, `to`만 전달하고 선택적으로 `data`, `value`, `gas`를 전달하면 됩니다. ```ts const user = privateKeyToAccount(process.env.USER_PRIVATE_KEY as `0x${string}`); @@ -62,11 +62,11 @@ console.log("H_inner:", txHash); H_inner: 0x8f3a...2d41 ``` -사용자는 USDT0가 필요하지 않습니다. 면제 계정이 가스를 후원합니다. `gas`는 기본적으로 `150_000n`(`DEFAULT_INNER_GAS`)이며, 이는 토큰 전송 또는 승인을 포함합니다. 더 무거운 호출에는 명시적인 `gas`를 전달하십시오. +사용자는 USDT0가 필요하지 않습니다: 면제 계정이 가스를 후원합니다. `gas`는 토큰 전송 또는 승인을 포함하는 `150_000n` (`DEFAULT_INNER_GAS`)으로 기본 설정됩니다. 더 많은 가스가 필요한 호출의 경우 명시적인 `gas`를 전달하세요. ## 3. 배치 릴레이 -하나의 계정에서 여러 트랜잭션을 릴레이하려면 `sendBatch`를 호출합니다. Nonce는 계정의 보류 중인 nonce에서 자동으로 시퀀싱되며, 입력 순서대로 입력당 하나의 결과를 얻습니다. +단일 계정에서 여러 트랜잭션을 릴레이하려면 `sendBatch`를 호출합니다. 논스는 계정의 보류 중인 논스에서 자동으로 순서가 지정되며, 입력 순서대로 각 입력당 하나의 결과를 얻습니다. ```ts const results = await gw.sendBatch(user, [ @@ -84,11 +84,11 @@ for (const r of results) { [1] ✔ 0x2b7c...9e04 ``` -배치는 실패를 스로우하는 대신 `result.error`의 항목별로 보고하므로, 하나의 잘못된 트랜잭션이 나머지 트랜잭션을 망치지 않습니다. +배치는 실패를 throw하는 대신 `result.error`에 항목별로 보고하므로, 하나의 잘못된 트랜잭션으로 인해 나머지가 모두 실패하지 않습니다. ## 4. 파트너별 정책 제한 적용 -설정에 정책 제한을 추가하여 면제 키가 후원할 수 있는 것을 제한합니다. 제한을 위반하는 InnerTx는 브로드캐스트 전에 거부됩니다. +설정에 정책 제한을 추가하여 면제 키가 후원할 수 있는 대상을 제한합니다. 제한을 위반하는 InnerTx는 방송 전에 거부됩니다. ```ts const enterprise = createStableEnterprise({ @@ -98,22 +98,22 @@ const enterprise = createStableEnterprise({ maxGasLimit: 500_000n, maxDataLength: 4_096, allowedTargets: [ - { address: token, selectors: ["0xa9059cbb"] }, // ERC-20 전송만 + { address: token, selectors: ["0xa9059cbb"] }, // ERC-20 전송만 허용 ], }, }); ``` -`allowedTargets` 외부의 컨트랙트로의 트랜잭션은 `TARGET_NOT_ALLOWED`와 함께 실패하고, `maxGasLimit`을 초과하는 트랜잭션은 `GAS_LIMIT_EXCEEDED`와 함께 실패합니다. 어떤 컨트랙트든 허용하려면 `address`로 `"*"를 사용하고, 어떤 메서드든 허용하려면 `selectors`를 생략합니다. +`allowedTargets` 외부에 있는 계약으로의 트랜잭션은 `TARGET_NOT_ALLOWED` 오류와 함께 실패하며, `maxGasLimit`을 초과하는 트랜잭션은 `GAS_LIMIT_EXCEEDED` 오류와 함께 실패합니다. `address`로 `"*"`를 사용하여 모든 계약을 허용하고, `selectors`를 생략하여 모든 메서드를 허용할 수 있습니다. ## 5. 사전 서명된 트랜잭션 릴레이 -비수탁 흐름의 경우, 사용자는 자신의 환경에서 InnerTx에 서명하고 서명된 16진수만 제공하므로 사용자의 키를 볼 수 없습니다. `buildWaiverInnerTx`로 빌드한 다음 `relay`로 릴레이합니다. +비수탁형 흐름의 경우, 사용자는 자신의 환경에서 InnerTx를 서명하고 서명된 헥스만 전달하므로, 사용자의 키를 볼 필요가 없습니다. `buildWaiverInnerTx`로 빌드한 다음, `relay`로 릴레이합니다. ```ts import { buildWaiverInnerTx, toSigner } from "@stablechain/enterprise"; -// 사용자 측에서 — buildWaiverInnerTx는 Signer를 통해 서명합니다. toSigner는 viem 계정을 조정합니다. +// 사용자 측에서 — buildWaiverInnerTx는 Signer를 통해 서명하며; toSigner는 viem 계정을 적용합니다. const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to: token, data, gas: 150_000n, nonce }); // 백엔드에서 @@ -125,11 +125,11 @@ console.log("H_inner:", txHash); H_inner: 0x8f3a...2d41 ``` -여러 개의 사전 서명된 트랜잭션의 경우, `sendBatch`와 같이 입력당 하나의 결과를 반환하는 `relayBatch`를 사용합니다. +여러 개의 사전 서명된 트랜잭션의 경우, `relayBatch`를 사용하세요. 이는 `sendBatch`와 같이 입력당 하나의 결과를 반환합니다. ## 거부 처리 -`send` 및 `relay`는 거부 시 `StableEnterpriseRelayError`를 던지며, 분기할 수 있는 `code`를 포함합니다. +`send` 및 `relay`는 거부 시 `StableEnterpriseRelayError`를 throw하며, 분기할 수 있는 `code`를 포함합니다. ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -145,13 +145,13 @@ try { ``` ```text -StableEnterpriseRelayError: 릴레이 실패 [TARGET_NOT_ALLOWED]: 대상 0x... 허용되지 않음 +StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not allowed ``` -모든 거부 이유에 대한 전체 [`ErrorCode`](/ko/reference/enterprise-sdk#errorcode) 테이블을 참조하십시오. +모든 거부 이유에 대한 전체 [`ErrorCode`](/ko/reference/enterprise-sdk#errorcode) 테이블을 참조하세요. ## 다음 단계 -- [**보장된 트랜잭션 보내기**](/ko/how-to/send-guaranteed-transactions): 예약된 Enterprise-lane 블록스페이스에 트랜잭션을 전송하고 가스 면제와 결합합니다. -- [**Enterprise SDK 참조**](/ko/reference/enterprise-sdk#relay-with-gas-waiver): 모든 메서드, 구성 옵션 및 오류 클래스 전체. +- [**보장된 트랜잭션 전송**](/ko/how-to/send-guaranteed-transactions): 예약된 엔터프라이즈 레인 블록 공간에 트랜잭션을 전송하고, 이를 가스 면제와 결합합니다. +- [**Enterprise SDK 참조**](/ko/reference/enterprise-sdk#relay-with-gas-waiver): 모든 메서드, 구성 옵션 및 오류 클래스의 전체 목록입니다. - [**가스 면제**](/ko/explanation/gas-waiver): 프로토콜 수준에서 제로 가스 트랜잭션이 작동하는 방식. diff --git a/docs/pages/ko/how-to/send-guaranteed-transactions.mdx b/docs/pages/ko/how-to/send-guaranteed-transactions.mdx index 61e7c3c..4ae6f08 100644 --- a/docs/pages/ko/how-to/send-guaranteed-transactions.mdx +++ b/docs/pages/ko/how-to/send-guaranteed-transactions.mdx @@ -1,30 +1,30 @@ --- source_path: how-to/send-guaranteed-transactions.mdx -source_sha: c59ac1a053751e961d75071fa7799dbd9dc4b847 +source_sha: 6da305c74e7ddb43f31a4ed11e7f4d5313f0cabe title: "보장된 트랜잭션 전송" -description: "Enterprise SDK를 사용하여 예약된 Enterprise-레인 블록 공간에 트랜잭션을 배치하고, 보장된 블록 공간과 가스 면제를 결합하여 가스 없이 전송합니다." +description: "Enterprise SDK를 사용하여 예약된 Enterprise 레인 블록스페이스에 트랜잭션을 전송하고, 보장된 블록스페이스와 가스 면제를 결합하여 가스 없이 트랜잭션을 릴레이합니다." diataxis: "how-to" --- # 보장된 트랜잭션 전송 -`@stablechain/enterprise`를 사용하여 예약된 엔터프라이즈 레인 블록 공간을 통해 트랜잭션을 라우팅합니다. `guaranteedBlock` 모듈은 엔터프라이즈 RPC 게이트웨이를 통해 GuaranteedTx(유형 `0x3F` CustomTx)를 중계하여 엔터프라이즈 워크로드용으로 예약된 용량에 트랜잭션을 배치합니다. 가스 면제와 달리 서명자는 자체 가스를 지불하므로 자금이 충분해야 합니다. +`@stablechain/enterprise`를 사용하여 예약된 Enterprise 레인 블록스페이스를 통해 트랜잭션을 라우팅하세요. `guaranteedBlock` 모듈은 GuaranteedTx (0x3F 유형 CustomTx)를 Enterprise RPC 게이트웨이를 통해 릴레이하여 기업 워크로드용으로 예약된 용량에 들어가게 합니다. 가스 면제와 달리 서명자는 자체 가스를 지불해야 하므로 자금이 필요합니다. -이를 가스 면제와 결합하여 [보장된 릴레이 트랜잭션](/ko/how-to/guaranteed-relayed-transactions)을 얻을 수 있습니다. 이는 엔터프라이즈 레인에 배치되는 가스 면제 트랜잭션입니다. +이를 가스 면제와 결합하여 [보장된 릴레이 트랜잭션](/ko/how-to/guaranteed-relayed-transactions)을 얻을 수 있습니다. 이는 Enterprise 레인에 들어가는 가스 면제 트랜잭션입니다. ## 전제 조건 -- Node.js 20 이상, 그리고 `@stablechain/enterprise` 및 `viem`이 설치되어 있어야 합니다. [Enterprise SDK 참조](/ko/reference/enterprise-sdk#install)를 참조하십시오. -- Enterprise RPC 게이트웨이 API 키. Enterprise SDK는 현재 테스트넷 전용이며, 접근이 제한됩니다. 게이트웨이 엔드포인트를 얻으려면 [Stable에 문의](https://discord.gg/stablexyz)하십시오. -- GuaranteedTx가 자체 가스를 지불하므로 자금이 충분한 서명자가 필요합니다. +- Node.js 20 이상, 그리고 `@stablechain/enterprise` 및 `viem`이 설치되어 있어야 합니다. [Enterprise SDK 참조](/ko/reference/enterprise-sdk#install)를 확인하세요. +- Enterprise RPC 게이트웨이 API 키. Enterprise SDK는 현재 테스트넷 전용이며 접근이 제한되어 있습니다. 게이트웨이 엔드포인트를 얻으려면 [Stable에 문의하세요](https://discord.gg/stablexyz). +- GuaranteedTx는 자체 가스를 지불하므로 자금이 충분한 서명자가 필요합니다. :::warning -이것은 서버 측 라이브러리입니다. Enterprise RPC 게이트웨이 URL을 백엔드에 보관하십시오. 여기에는 API 키가 포함되어 있습니다. +이것은 서버 측 라이브러리입니다. Enterprise RPC 게이트웨이 URL을 백엔드에 유지하세요. API 키가 포함되어 있습니다. ::: -## 1. 보장된 블록 공간 모듈로 클라이언트 생성 +## 1. guaranteed blockspace 모듈로 클라이언트 생성 -`guaranteedBlock` 및 `enterpriseRpcEndpoints`를 `createStableEnterprise`에 전달합니다. 게이트웨이는 `0x3F` GuaranteedTxs를 허용하는 유일한 엔드포인트이며, API 키를 보유합니다. 잘못된 `laneId`는 즉시 거부됩니다. +`guaranteedBlock` 및 `enterpriseRpcEndpoints`를 `createStableEnterprise`에 전달합니다. 게이트웨이는 `0x3F` GuaranteedTx를 허용하는 유일한 엔드포인트이며, API 키를 보유합니다. 유효하지 않은 `laneId`는 즉시 거부됩니다. ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -32,14 +32,14 @@ import { privateKeyToAccount } from "viem/accounts"; const enterprise = createStableEnterprise({ chain: stableTestnet, - enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable이 제공하는 게이트웨이 URL + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL], // Stable이 제공하는 게이트웨이 URL guaranteedBlock: { account: privateKeyToAccount(process.env.SIGNER_PRIVATE_KEY as `0x${string}`), // 자금이 충분해야 함 laneId: 0n, // Enterprise 레인 }, }); -const gb = enterprise.guaranteedBlock!; +const gb = enterprise.guaranteedBlock; ``` ```text @@ -69,11 +69,13 @@ console.log("Guaranteed tx:", txHash); Guaranteed tx: 0xabcd...7890 ``` -서명자가 가스를 지불하므로 릴레이하기 전에 잔액이 충분한지 확인하십시오. 잔액이 0인 계정에서 보장된 트랜잭션은 실패합니다. +`gasFeeCap`은 가스당 최대 총 수수료(EIP-1559 `maxFeePerGas`)이며, `gasTipCap`은 가스당 최대 우선순위 수수료(`maxPriorityFeePerGas`)입니다. 위와 같이 `gasTipCap`을 현재 가스 가격으로 설정하고 `gasFeeCap`을 그 두 배로 설정하는 것이 안전한 기본값입니다. -## 3. 배치 전송 +서명자가 가스를 지불하므로 릴레이하기 전에 잔액이 있는지 확인하십시오. 잔액이 없는 계정에서 GuaranteedTx를 보내면 실패합니다. -여러 트랜잭션을 보내려면 `sendBatch`를 호출합니다. 논스는 발견된 베이스에서 자동으로 순서가 지정되며, 입력 순서대로 입력당 하나의 결과를 얻습니다. 실패하면 후속 작업이 중단됩니다. +## 3. 일괄 전송 + +여러 트랜잭션을 보내려면 `sendBatch`를 호출합니다. 논스는 발견된 기본값에서 자동으로 순서가 지정되며, 입력 순서대로 입력당 하나의 결과가 나옵니다. 하나의 실패는 후속 트랜잭션에 영향을 미칩니다. ```ts const results = await gb.sendBatch(signer, [ @@ -93,7 +95,7 @@ for (const r of results) { ## 4. 사전 서명된 트랜잭션 전송 -비수탁 흐름의 경우 `buildGuaranteedTx`를 사용하여 다른 곳에서 GuaranteedTx를 빌드하고 서명한 다음, 서명된 헥스만 운영자에게 전달합니다. Enterprise 논스 키는 `nonceKeyForLane`에서 가져옵니다. +비수탁형 흐름의 경우 `buildGuaranteedTx`를 사용하여 다른 곳에서 GuaranteedTx를 빌드하고 서명한 다음, 운영자에게 서명된 hex만 전달합니다. Enterprise 논스 키는 `nonceKeyForLane`에서 가져옵니다. ```ts import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; @@ -103,7 +105,7 @@ const signed = await buildGuaranteedTx(toSigner(signer), stableTestnet.id, { gas: 21_000n, gasFeeCap, gasTipCap, - nonce, // 계정의 현재 2D 레인 논스 + nonce, // 계정의 현재 2D-레인 논스 nonceKey: nonceKeyForLane(0n), // Enterprise 레인 0 }); @@ -115,15 +117,15 @@ console.log("Guaranteed tx:", txHash); Guaranteed tx: 0xabcd...7890 ``` -사전 서명된 여러 트랜잭션의 경우 `relayBatch`를 사용하십시오. +사전 서명된 여러 트랜잭션의 경우 `relayBatch`를 사용합니다. ## 가스 면제와 결합 -사용자의 가스를 면제하고 Enterprise 레인에 배치하려면 `guaranteedWaiver` 모듈로 두 레일을 구성합니다. 사용자는 잔액이나 수수료 필드가 필요 없으며, 트랜잭션은 동일한 게이트웨이를 통해 라우팅됩니다. [보장된 릴레이 트랜잭션](/ko/how-to/guaranteed-relayed-transactions)을 참조하십시오. +사용자의 가스를 면제하고 여전히 Enterprise 레인에 들어가려면 `guaranteedWaiver` 모듈로 두 레일을 구성합니다. 사용자는 잔액이나 수수료 필드가 필요 없으며 트랜잭션은 동일한 게이트웨이를 통해 라우팅됩니다. [보장된 릴레이 트랜잭션](/ko/how-to/guaranteed-relayed-transactions)을 참조하세요. ## 거부 처리 -`send` 및 `relay`는 거부 시 `StableEnterpriseRelayError`를 발생시킵니다. 게이트웨이 특정 코드는 `GATEWAY_UNAUTHORIZED`(누락되거나 잘못된 API 키) 및 `QUOTA_EXCEEDED`(게이트웨이 가스 할당량 소진)를 포함합니다. +`send` 및 `relay`는 거부 시 `StableEnterpriseRelayError`를 발생시킵니다. 게이트웨이별 코드에는 `GATEWAY_UNAUTHORIZED`(누락되거나 유효하지 않은 API 키) 및 `QUOTA_EXCEEDED`(게이트웨이 가스 할당량 소진)가 있습니다. ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -132,7 +134,7 @@ try { await gb.send(signer, { to: recipient, gas: 21_000n, gasFeeCap, gasTipCap }); } catch (err) { if (err instanceof StableEnterpriseRelayError && err.code === "GATEWAY_UNAUTHORIZED") { - // Enterprise RPC 게이트웨이가 API 키를 거부했습니다 + // Enterprise RPC 게이트웨이가 API 키를 거부했습니다. } throw err; } @@ -142,8 +144,8 @@ try { StableEnterpriseRelayError: relay failed [GATEWAY_UNAUTHORIZED]: invalid api key ``` -## 다음으로 이동할 곳 +## 다음 단계 -- [**보장된 릴레이 트랜잭션**](/ko/how-to/guaranteed-relayed-transactions): 사용자의 가스를 면제하고 한 번의 호출로 Enterprise 레인에 배치합니다. -- [**가스 면제로 릴레이**](/ko/how-to/relay-with-gas-waiver): 사용자가 USDT0를 보유하지 않고도 트랜잭션을 할 수 있도록 가스를 후원합니다. +- [**보장된 릴레이 트랜잭션**](/ko/how-to/guaranteed-relayed-transactions): 한 번의 호출로 사용자의 가스를 면제하고 Enterprise 레인에 진입합니다. +- [**가스 면제로 릴레이**](/ko/how-to/relay-with-gas-waiver): 사용자의 가스를 후원하여 USDT0 없이 트랜잭션을 처리하게 합니다. - [**Enterprise SDK 참조**](/ko/reference/enterprise-sdk#guaranteed-blockspace): 모든 메서드, 구성 옵션 및 오류 클래스에 대한 전체 설명입니다. diff --git a/docs/pages/ko/reference/enterprise-sdk.mdx b/docs/pages/ko/reference/enterprise-sdk.mdx index 8be2024..9ee89d1 100644 --- a/docs/pages/ko/reference/enterprise-sdk.mdx +++ b/docs/pages/ko/reference/enterprise-sdk.mdx @@ -1,21 +1,21 @@ --- source_path: reference/enterprise-sdk.mdx -source_sha: 4f3e8931e52daf98a9dc5de5921fc734d4284dfb -title: "Enterprise SDK 참조" -description: "@stablechain/enterprise에 대한 완벽한 참조: createStableEnterprise, 가스 면제 및 보장된 블록 공간 모듈, 빌드 헬퍼 및 오류 클래스." +source_sha: c89457ca29556b5a94b9cb4562bd9d210d38701d +title: "엔터프라이즈 SDK 레퍼런스" +description: "@stablechain/enterprise에 대한 완벽한 레퍼런스: createStableEnterprise, 가스 면제 및 보장된 블록스페이스 모듈, 빌드 헬퍼, 오류 클래스." diataxis: "reference" --- -# Enterprise SDK 참조 +# 엔터프라이즈 SDK 레퍼런스 -`@stablechain/enterprise`의 전체 표면. 여기에는 [`createStableEnterprise`](#createstableenterpriseconfig)의 클라이언트, 세 가지 기능([가스 면제 릴레이](#relay-with-gas-waiver), [보장된 블록 공간](#guaranteed-blockspace), [보장된 릴레이 트랜잭션](#guaranteed-relay-transactions)), 하위 수준 빌드 헬퍼, 공유 결과 및 오류 유형이 포함됩니다. 이러한 레일 세부 정보에 대해서는 [Stable Enterprise SDK](/ko/explanation/enterprise-sdk), [가스 면제](/ko/explanation/gas-waiver) 및 [보장된 블록 공간](/ko/explanation/guaranteed-blockspace)을 참조하세요. +`@stablechain/enterprise`의 전체 표면입니다. 여기에는 [`createStableEnterprise`](#createstableenterpriseconfig)를 통한 클라이언트, 세 가지 기능([가스 면제 릴레이](#relay-with-gas-waiver), [보장된 블록스페이스](#guaranteed-blockspace), [보장된 릴레이 트랜잭션](#guaranteed-relay-transactions)), 저수준 빌드 헬퍼, 공유 결과 및 오류 유형이 포함됩니다. 이러한 레일이 무엇인지는 [Stable Enterprise SDK](/ko/explanation/enterprise-sdk), [Gas waiver](/ko/explanation/gas-waiver), [Guaranteed blockspace](/ko/explanation/guaranteed-blockspace)를 참조하세요. :::note -Enterprise SDK는 현재 Stable 테스트넷에서만 사용할 수 있으며, 요청 시 액세스할 수 있습니다. 통합하려면 [Stable에 문의](https://discord.gg/stablexyz)하여 거버넌스에 등록된 면제 키와 Enterprise RPC 게이트웨이 API 키를 받으세요. +엔터프라이즈 SDK는 현재 Stable Testnet에서만 사용할 수 있으며, 액세스는 요청 시 제공됩니다. 통합하려면 [Stable에 문의](https://discord.gg/stablexyz)하여 거버넌스에 등록된 면제 키와 엔터프라이즈 RPC 게이트웨이 API 키를 받으세요. ::: :::warning -이것은 개인 키로 서명하는 서버 측 라이브러리입니다. 브라우저에서 절대 실행하지 마십시오. 면제 키와 Enterprise RPC 게이트웨이 URL을 백엔드에 보관하십시오. +이것은 개인 키로 서명하는 서버 측 라이브러리입니다. 브라우저에서 실행하지 마세요. 면제 키와 엔터프라이즈 RPC 게이트웨이 URL을 백엔드에 보관하세요. ::: ## 설치 @@ -28,11 +28,11 @@ npm install @stablechain/enterprise viem added 2 packages, audited 3 packages in 2s ``` -`viem >= 2.0.0`은 피어 종속성입니다. 이 패키지는 `viem/chains`에서 `stable` 및 `stableTestnet`을 다시 내보내므로 별도로 가져올 필요가 없습니다. +`viem >= 2.0.0`은 피어 종속성입니다. 패키지는 `viem/chains`에서 `stable` 및 `stableTestnet`을 재Export하므로 별도로 Import할 필요가 없습니다. ## `createStableEnterprise(config)` -`StableEnterpriseClient`를 구성합니다. 각 모듈은 구성한 경우에만 존재하므로 사용하기 전에 `!` 또는 null 검사를 사용하여 보호하세요. +`StableEnterpriseClient`를 생성합니다. 각 모듈은 구성한 경우에만 존재하므로 사용 전에 null 검사를 수행합니다. ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -50,22 +50,22 @@ StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver ### `StableEnterpriseConfig` -| **필드** | **유형** | **기본값** | **설명** | +| **필드** | **타입** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `chain` | `StableChain` | | 대상 체인. `stable` 또는 `stableTestnet` (패키지에서 다시 내보냄)을 전달합니다. 필수. | -| `rpcEndpoints` | `string[]?` | 체인의 내장 RPC | 실패 시 순서대로 시도되는 하나 이상의 Stable RPC 엔드포인트. 개인 엔드포인트를 가리키는 경우에만 재정의합니다. | -| `enterpriseRpcEndpoints` | `string[]?` | | 실패 시 순서대로 시도되는 하나 이상의 Enterprise RPC 게이트웨이 엔드포인트. `guaranteedBlock` 및 `guaranteedWaiver`에 필요합니다. | -| `batchSizeLimit` | `number?` | `100` | 일괄 RPC 호출당 최대 트랜잭션 수. | -| `signer` | `Signer?` | | 모듈에 자체 키가 없을 때 면제 모듈(`gasWaiver`, `guaranteedWaiver`)에 대한 기본 서명자. 단일 커스터디 백엔드에서 둘 다 구동하려면 한 번 설정합니다. [서명 키 및 커스터디](#signing-keys-and-custody)를 참조하십시오. | -| `gasWaiver` | `GasWaiverConfig?` | | [가스 면제 릴레이](#relay-with-gas-waiver)를 활성화합니다. | -| `guaranteedBlock` | `GuaranteedBlockConfig?` | | [보장된 블록 공간](#guaranteed-blockspace)을 활성화합니다. | -| `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | [보장된 릴레이 트랜잭션](#guaranteed-relay-transactions)을 활성화합니다. | +| `chain` | `StableChain` | | 대상 체인입니다. `stable` 또는 `stableTestnet`을 전달합니다(패키지에서 재export됨). 필수. | +| `rpcEndpoints` | `string[]?` | 체인의 내장 RPC | 실패 시 순서대로 시도하는 하나 이상의 Stable RPC 엔드포인트입니다. 개인 엔드포인트를 가리키려면 재정의만 수행합니다. | +| `enterpriseRpcEndpoints` | `string[]?` | | 실패 시 순서대로 시도하는 하나 이상의 엔터프라이즈 RPC 게이트웨이 엔드포인트입니다. `guaranteedBlock` 및 `guaranteedWaiver`에 필요합니다. | +| `batchSizeLimit` | `number?` | `100` | 일괄 RPC 호출당 최대 트랜잭션 수입니다. | +| `signer` | `Signer?` | | 모듈 자체 키가 없을 때 면제 모듈(`gasWaiver`, `guaranteedWaiver`)에 대한 기본 서명자입니다. 단일 커스터디 백엔드에서 두 모듈을 모두 구동하기 위해 한 번 설정합니다. [서명 키 및 커스터디](#signing-keys-and-custody)를 참조하세요. | +| `gasWaiver` | `GasWaiverConfig?` | | [가스 면제 릴레이](#relay-with-gas-waiver)를 활성화합니다. | +| `guaranteedBlock` | `GuaranteedBlockConfig?` | | [보장된 블록스페이스](#guaranteed-blockspace)를 활성화합니다. | +| `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | [보장된 릴레이 트랜잭션](#guaranteed-relay-transactions)을 활성화합니다. | ### 서명 키 및 커스터디 -면제 키를 보유하는 모듈(`gasWaiver` 및 `guaranteedWaiver`)은 순서대로 해결합니다: 모듈 자체의 `signer`, 그 다음은 `account` (인-프로세스 viem 키), 그 다음은 클라이언트 구성의 최상위 [`signer`](#stableenterpriseconfig), 그 다음은 `STABLE_ENTERPRISE_PRIVATE_KEY` 환경 변수. 단일 커스터디 백엔드에서 두 면제 모듈을 모두 구동하려면 최상위 `signer`를 한 번 설정하십시오. `guaranteedBlock`은 자체적으로 자금이 지원되는 `account`로 서명합니다. +면제 키(`gasWaiver` 및 `guaranteedWaiver`)를 보유하는 모듈은 모듈 자체의 `signer`, 그리고 `account` (인 프로세스 viem 키), 그리고 클라이언트 구성의 최상위 [`signer`](#stableenterpriseconfig), 그리고 `STABLE_ENTERPRISE_PRIVATE_KEY` 환경 변수 순으로 키를 해결합니다. 단일 커스터디 백엔드에서 두 면제 모듈을 모두 구동하기 위해 최상위 `signer`를 한 번 설정합니다. `guaranteedBlock`은 자체 자금 조달된 `account`로 서명합니다. -`Signer`는 32바이트 다이제스트에 서명하므로 키가 커스터디 백엔드를 떠나지 않습니다. AWS KMS의 경우 `awsKmsSigner`, viem 계정을 조정하는 경우 `toSigner(account)`, 인-프로세스 키의 경우 `privateKeySigner(key)` / `envSigner()`를 사용하십시오. 모듈의 `send` / `sendBatch`에 전달되는 호출별 발신자도 viem 계정 또는 `Signer`일 수 있으므로 KMS/HSM 키는 `relay`로 떨어지지 않고 내부 트랜잭션에 서명할 수 있습니다. +`Signer`는 32바이트 다이제스트에 서명하므로 키는 커스터디 백엔드를 떠나지 않습니다. AWS KMS의 경우 `awsKmsSigner`를 사용하고, viem 계정을 조정하려면 `toSigner(account)`를 사용하거나, 인 프로세스 키의 경우 `privateKeySigner(key)` / `envSigner()`를 사용합니다. 모듈의 `send` / `sendBatch`에 전달되는 호출당 발신자도 viem 계정 또는 `Signer`일 수 있으므로 KMS/HSM 키는 `relay`로 떨어지지 않고 내부 트랜잭션에 서명할 수 있습니다. ```bash npm install @aws-sdk/client-kms @@ -75,8 +75,8 @@ npm install @aws-sdk/client-kms import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; import { awsKmsSigner } from "@stablechain/enterprise/aws-kms"; -// KMS 키는 ECC_SECG_P256K1(secp256k1)이어야 합니다. SDK는 이를 통해 주소를 파생합니다. -const signer = await awsKmsSigner({ keyId: process.env.KMS_KEY_ID! }); +// KMS 키는 ECC_SECG_P256K1(secp256k1)이어야 합니다. SDK는 이를 기반으로 주소를 파생합니다. +const signer = await awsKmsSigner({ keyId: process.env.KMS_KEY_ID }); const enterprise = createStableEnterprise({ chain: stableTestnet, @@ -84,7 +84,7 @@ const enterprise = createStableEnterprise({ }); ``` -`awsKmsSigner`는 `@stablechain/enterprise/aws-kms` 하위 경로에 제공되어 `@aws-sdk/client-kms`가 코어 설치에서 제외되는 선택적 피어 종속성으로 유지됩니다. +`awsKmsSigner`는 `@stablechain/enterprise/aws-kms` 하위 경로에 포함되어 `@aws-sdk/client-kms`가 코어 설치에서 제외된 선택적 피어 종속성으로 유지됩니다. ### `StableEnterpriseClient` @@ -98,7 +98,7 @@ interface StableEnterpriseClient { ## 가스 면제 릴레이 -`gasWaiver` 모듈은 가스 면제 트랜잭션을 릴레이합니다. 화이트리스트에 등록된 면제 계정은 사용자(InnerTx)의 제로 가스 트랜잭션을 WaiverTx로 래핑하여 브로드캐스트합니다. 사용자는 USDT0가 필요하지 않습니다. 모든 메서드는 래퍼 해시가 아닌 InnerTx 해시인 `H_inner`를 반환합니다. +`gasWaiver` 모듈은 가스 면제 트랜잭션을 릴레이합니다. 화이트리스트에 있는 면제 계정은 사용자의 제로 가스 트랜잭션(InnerTx)을 WaiverTx로 래핑하여 브로드캐스트합니다. 사용자는 USDT0가 필요 없습니다. 모든 메서드는 래퍼 해시가 아닌 InnerTx 해시인 `H_inner`를 반환합니다. 구성에서 `gasWaiver`를 사용하여 활성화합니다. @@ -113,24 +113,24 @@ const enterprise = createStableEnterprise({ }, }); -const gw = enterprise.gasWaiver!; +const gw = enterprise.gasWaiver; ``` ### `GasWaiverConfig` [`ValidationLimits`](#validationlimits) 및 [`SignerSource`](#signersource)를 확장합니다. -| **필드** | **유형** | **설명** | +| **필드** | **타입** | **설명** | | :--- | :--- | :--- | -| `signer` | `Signer?` | 보관 서명자(AWS KMS, HSM)로서 화이트리스트에 등록된 거버넌스 등록 면제 키. [서명 키 및 보관](#signing-keys-and-custody)을 참조하십시오. `account`보다 우선합니다. | -| `account` | `LocalAccount?` | 인-프로세스 viem 계정으로서의 면제 키. 둘 다 설정되지 않은 경우 `STABLE_ENTERPRISE_PRIVATE_KEY`로 대체됩니다. | +| `signer` | `Signer?` | 거버넌스에 등록된 화이트리스트 면제 키(커스터디 서명자: AWS KMS, HSM). [서명 키 및 커스터디](#signing-keys-and-custody)를 참조하세요. `account`보다 우선합니다. | +| `account` | `LocalAccount?` | 인 프로세스 viem 계정으로 사용되는 면제 키입니다. 둘 다 설정되지 않은 경우 `STABLE_ENTERPRISE_PRIVATE_KEY`로 대체됩니다. | | `maxGasLimit` | `bigint?` | `ValidationLimits`에서 상속됩니다. | | `maxDataLength` | `number?` | `ValidationLimits`에서 상속됩니다. | | `allowedTargets` | `AllowedTarget[]?` | `ValidationLimits`에서 상속됩니다. | ### `send(account, tx)` -`account`에서 하나의 InnerTx를 한 번의 호출로 빌드, 서명 및 릴레이합니다. `gasPrice: 0`, 레거시 유형, `chainId` 및 보류 중인 논스는 자동으로 처리됩니다. 거부 시 `StableEnterpriseRelayError`를 발생시킵니다. +`account`에서 하나의 InnerTx를 한 번의 호출로 빌드, 서명 및 릴레이합니다. `gasPrice: 0`, 레거시 유형, `chainId`, 보류 중인 nonce는 자동으로 처리됩니다. 거부 시 `StableEnterpriseRelayError`를 발생시킵니다. ```ts const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); @@ -140,11 +140,11 @@ const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); { txHash: "0x8f3a...2d41" } ``` -`tx` 인수는 [`WaiverInnerTx`](#waiverinnertx)와 선택적 `nonce`입니다. [`RelayResult`](#relayresult)를 반환합니다. +`tx` 인수는 선택적 `nonce`가 추가된 [`WaiverInnerTx`](#waiverinnertx)입니다. [`RelayResult`](#relayresult)를 반환합니다. ### `sendBatch(account, txs)` -하나의 `account`에서 여러 InnerTx를 빌드, 서명 및 릴레이합니다. Nonce는 계정의 보류 중인 nonce에서 자동으로 순서가 지정됩니다. 입력당 하나의 결과를 순서대로 반환합니다. +하나의 `account`에서 여러 InnerTx를 빌드, 서명 및 릴레이합니다. Nonce는 계정의 보류 중인 nonce에서 자동으로 시퀀싱됩니다. 입력당 하나의 결과를 순서대로 반환합니다. ```ts const results = await gw.sendBatch(user, [ @@ -161,7 +161,7 @@ const results = await gw.sendBatch(user, [ ### `relay(signedInnerTxHex)` -사전 서명된 제로 가스 InnerTx를 릴레이합니다. 사용자가 자신의 환경에서 서명하고 서명된 Hex만 넘겨주는 비수탁 흐름에서 이를 사용하므로 면제 운영자는 사용자의 키를 볼 수 없습니다. [`buildWaiverInnerTx`](#buildwaiverinnertxsigner-chainid-req)를 사용하여 빌드합니다. 거부 시 오류를 발생시킵니다. +사전 서명된 제로 가스 InnerTx를 릴레이합니다. 사용자가 자신의 환경에서 서명하고 서명된 헥스만 전달하는 비관리형 흐름에 사용하므로 면제 운영자는 사용자의 키를 볼 수 없습니다. [`buildWaiverInnerTx`](#buildwaiverinnertxsigner-chainid-req)를 사용하여 빌드합니다. 거부 시 오류가 발생합니다. ```ts import { buildWaiverInnerTx, toSigner } from "@stablechain/enterprise"; @@ -176,7 +176,7 @@ const { txHash } = await gw.relay(signed); ### `relayBatch(signedInnerTxHexes)` -사전 서명된 InnerTx 배치를 릴레이합니다. 입력당 하나의 [`BatchResultItem`](#batchresultitem)을 순서대로 반환합니다. +사전 서명된 InnerTx의 배치를 릴레이합니다. 입력당 하나의 [`BatchResultItem`](#batchresultitem)을 순서대로 반환합니다. ```ts const results = await gw.relayBatch([signed0, signed1]); @@ -186,35 +186,35 @@ const results = await gw.relayBatch([signed0, signed1]); [ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: false, error: { code: "TARGET_NOT_ALLOWED", message: "..." } } ] ``` -## 보장된 블록 공간 +## 보장된 블록스페이스 -`guaranteedBlock` 모듈은 Enterprise RPC 게이트웨이를 통해 GuaranteedTx(유형 `0x3F` CustomTx)를 릴레이하여 예약된 Enterprise-lane 블록 공간에 착륙하도록 합니다. 가스 면제와 달리 서명자는 자체 가스를 지불하며 자금이 있어야 합니다. 각 트랜잭션은 Enterprise 레인에 키가 지정된 2D 논스를 전달하며 브로드캐스팅은 게이트웨이를 통해서만 이루어집니다. +`guaranteedBlock` 모듈은 엔터프라이즈 RPC 게이트웨이를 통해 GuaranteedTx(유형 `0x3F` CustomTx)를 릴레이하여 예약된 엔터프라이즈 레인 블록스페이스에 착륙시킵니다. 가스 면제와 달리 서명자는 자체 가스를 지불하며 자금이 있어야 합니다. 각 트랜잭션은 엔터프라이즈 레인에 키가 지정된 2D nonce를 가지며, 브로드캐스팅은 게이트웨이를 통해서만 이루어집니다. -`guaranteedBlock`과 `enterpriseRpcEndpoints`를 사용하여 활성화하세요. +`guaranteedBlock`과 `enterpriseRpcEndpoints`를 사용하여 활성화합니다. ```ts const enterprise = createStableEnterprise({ chain: stableTestnet, - enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable이 제공하는 게이트웨이 URL + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL], // Stable에서 제공하는 게이트웨이 URL guaranteedBlock: { account: privateKeyToAccount("0xFUNDED_SIGNER_KEY"), laneId: 0n, }, }); -const gb = enterprise.guaranteedBlock!; +const gb = enterprise.guaranteedBlock; ``` ### `GuaranteedBlockConfig` -| **필드** | **유형** | **설명** | +| **필드** | **타입** | **설명** | | :--- | :--- | :--- | -| `account` | `LocalAccount` | 각 GuaranteedTx에 서명하고 가스를 지불하는 자금이 있는 계정. | -| `laneId` | `bigint` | Enterprise 레인 ID입니다. `[0, ENTERPRISE_MASK - 1]` 범위에 있어야 합니다. 유효하지 않은 ID는 즉시 거부됩니다. | +| `account` | `LocalAccount` | 각 GuaranteedTx에 서명하고 가스를 지불하는 자금 조달된 계정입니다. | +| `laneId` | `bigint` | 엔터프라이즈 레인 ID입니다. `[0, ENTERPRISE_MASK - 1]` 범위에 있어야 합니다. 유효하지 않은 ID는 즉시 거부됩니다. | ### `send(account, tx)` -하나의 GuaranteedTx를 빌드, 서명 및 릴레이합니다. 서명자가 가스를 지불하기 때문에 1559 수수료 필드가 필요합니다. `chainId`, Enterprise `nonceKey` 및 2D nonce(게이트웨이에서 검색됨)는 자동으로 처리됩니다. +하나의 GuaranteedTx를 빌드, 서명 및 릴레이합니다. 서명자가 가스를 지불하므로 1559 수수료 필드가 필요합니다. `chainId`, 엔터프라이즈 `nonceKey`, 그리고 2D nonce(게이트웨이에서 검색됨)는 자동으로 처리됩니다. ```ts const gasPrice = await publicClient.getGasPrice(); @@ -231,11 +231,11 @@ const { txHash } = await gb.send(signer, { { txHash: "0xabcd...7890" } ``` -`tx` 인수는 [`GuaranteedTxRequest`](#guaranteedtxrequest)와 선택적 `nonce`입니다. [`RelayResult`](#relayresult)를 반환합니다. +`tx` 인수는 선택적 `nonce`가 추가된 [`GuaranteedTxRequest`](#guaranteedtxrequest)입니다. [`RelayResult`](#relayresult)를 반환합니다. ### `sendBatch(account, txs)` -여러 GuaranteedTx를 빌드, 서명 및 릴레이합니다. Nonce는 검색된 베이스에서 자동으로 순서가 지정됩니다. 실패는 후속 작업에 영향을 미칩니다. +여러 GuaranteedTx를 빌드, 서명 및 릴레이합니다. Nonce는 검색된 베이스에서 자동으로 시퀀싱됩니다. 실패하면 후속 항목이 중단됩니다. ```ts const results = await gb.sendBatch(signer, [ @@ -252,7 +252,7 @@ const results = await gb.sendBatch(signer, [ ### `relay(signedTx)` / `relayBatch(signedTxs)` -사전 서명된 GuaranteedTx 또는 배치로 릴레이합니다. Enterprise nonce 키에 [`nonceKeyForLane`](#noncekeyforlanelaneid)을 사용하여 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req)로 다른 곳에서 트랜잭션을 빌드하고 서명한 다음 운영자에게 서명된 hex만 전달합니다. +사전 서명된 GuaranteedTx 또는 해당 배치 중 하나를 릴레이합니다. [`nonceKeyForLane`](#noncekeyforlanelaneid)을 엔터프라이즈 nonce 키로 사용하여 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req)로 트랜잭션을 다른 곳에서 빌드하고 서명한 다음, 운영자에게 서명된 헥스만 전달합니다. ```ts import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; @@ -262,7 +262,7 @@ const signed = await buildGuaranteedTx(toSigner(signer), stableTestnet.id, { gas: 21_000n, gasFeeCap, gasTipCap, - nonce, // 계정의 현재 2D-레인 논스 + nonce, // 계정의 현재 2D 레인 nonce nonceKey: nonceKeyForLane(0n), }); const { txHash } = await gb.relay(signed); @@ -274,42 +274,42 @@ const { txHash } = await gb.relay(signed); ## 보장된 릴레이 트랜잭션 -`guaranteedWaiver` 모듈은 위에 있는 두 가지 레일을 결합합니다: 보장된 블록 공간을 통해 라우팅되는 가스 면제 트랜잭션. 내부 및 외부 트랜잭션 모두 하나의 Enterprise `nonceKey`를 공유하는 `0x3F` CustomTx이므로 `guaranteedBlock`과 같이 게이트웨이를 통해 브로드캐스트됩니다. 면제가 가스를 보증하므로 사용자는 `gasWaiver`처럼 잔액이나 수수료 필드가 필요하지 않습니다. 모든 메서드는 `H_inner`를 반환합니다. +`guaranteedWaiver` 모듈은 위 두 가지 레일을 결합합니다. 즉, 보장된 블록스페이스를 통해 라우팅되는 가스 면제 트랜잭션입니다. 내부 및 외부 트랜잭션 모두 하나의 엔터프라이즈 `nonceKey`를 공유하는 `0x3F` CustomTx이므로 `guaranteedBlock`처럼 게이트웨이를 통해 브로드캐스트됩니다. 면제는 가스를 후원하므로 사용자는 `gasWaiver`처럼 잔액이나 수수료 필드가 필요 없습니다. 모든 메서드는 `H_inner`를 반환합니다. -`guaranteedWaiver`와 `enterpriseRpcEndpoints`를 사용하여 활성화하세요. +`guaranteedWaiver`와 `enterpriseRpcEndpoints`를 사용하여 활성화합니다. ```ts const enterprise = createStableEnterprise({ chain: stableTestnet, - enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL!], // Stable이 제공하는 게이트웨이 URL + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL], // Stable에서 제공하는 게이트웨이 URL guaranteedWaiver: { account: privateKeyToAccount("0xYOUR_WAIVER_KEY"), laneId: 0n, }, }); -const gw = enterprise.guaranteedWaiver!; +const gw = enterprise.guaranteedWaiver; ``` ### `GuaranteedWaiverConfig` -[`ValidationLimits`](#validationlimits) 및 [`SignerSource`](#signersource)를 확장합니다. `GasWaiverConfig`와 똑같이 외부 래퍼 면제 키를 소싱(`signer`, `account`, 환경 변수)하며 동일한 `maxGasLimit`, `maxDataLength`, `allowedTargets` 정책 제어를 허용합니다. +[`ValidationLimits`](#validationlimits) 및 [`SignerSource`](#signersource)를 확장합니다. `GasWaiverConfig`와 똑같이 외부 래퍼 면제 키를 소싱(`signer`, `account`, 환경 변수 순)하고 동일한 `maxGasLimit`, `maxDataLength`, `allowedTargets` 정책 제어를 허용합니다. -| **필드** | **유형** | **설명** | +| **필드** | **타입** | **설명** | | :--- | :--- | :--- | -| `signer` | `Signer?` | (외부 래퍼에 서명하는) 허용된 면제 키를 보관 서명자로 사용합니다. `account`보다 우선합니다. [서명 키 및 보관](#signing-keys-and-custody)을 참조하십시오. | -| `account` | `LocalAccount?` | 인-프로세스 viem 계정으로 사용되는 면제 키입니다. 둘 다 설정되지 않은 경우 `STABLE_ENTERPRISE_PRIVATE_KEY`로 대체됩니다. | -| `laneId` | `bigint` | Enterprise 레인 ID입니다. `[0, ENTERPRISE_MASK - 1]` 범위에 있어야 합니다. | +| `signer` | `Signer?` | 커스터디 서명자로 사용되는 화이트리스트 면제 키(외부 래퍼에 서명). `account`보다 우선합니다. [서명 키 및 커스터디](#signing-keys-and-custody)를 참조하세요. | +| `account` | `LocalAccount?` | 인 프로세스 viem 계정으로 사용되는 면제 키입니다. 둘 다 설정되지 않은 경우 `STABLE_ENTERPRISE_PRIVATE_KEY`로 대체됩니다. | +| `laneId` | `bigint` | 엔터프라이즈 레인 ID입니다. `[0, ENTERPRISE_MASK - 1]` 범위에 있어야 합니다. | ### `send(user, tx)` / `sendBatch(user, txs)` -`user`에서 내부 `0x3F` CustomTx를 빌드하고 서명한 다음 면제 키로 래핑하고 릴레이합니다. 가스가 면제되므로 수수료 필드가 필요하지 않습니다. 내부 2D 논스는 게이트웨이에서 검색되며 배치는 해당 베이스에서 자동으로 순서가 지정됩니다. +`user`로부터 내부 `0x3F` CustomTx를 빌드하고 서명한 다음, 면제 키로 래핑하여 릴레이합니다. 가스가 면제되므로 수수료 필드는 필요 없습니다. 내부 2D nonce는 게이트웨이에서 검색되며, 배치는 해당 베이스에서 자동으로 시퀀싱됩니다. ```ts // 단일 const { txHash } = await gw.send(user, { to: recipient }); -// 배치 (batch) +// 배치 const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); ``` @@ -317,11 +317,11 @@ const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); { txHash: "0x8f3a...2d41" } ``` -`tx` 인수는 [`GuaranteedWaiverTxRequest`](#guaranteedwaivertxrequest)와 선택적인 `nonce`입니다. `send`는 [`RelayResult`](#relayresult)를 반환하고, `sendBatch`는 [`BatchResultItem[]`](#batchresultitem)를 반환합니다. +`tx` 인수는 선택적 `nonce`가 추가된 [`GuaranteedWaiverTxRequest`](#guaranteedwaivertxrequest)입니다. `send`는 [`RelayResult`](#relayresult)를 반환하고, `sendBatch`는 [`BatchResultItem[]`](#batchresultitem)을 반환합니다. ### `relay(signedInnerTx)` / `relayBatch(signedInnerTxs)` -비수탁 흐름의 경우 사용자는 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req) (수수료 `0n`, `nonceKeyForLane(laneId)` 사용)로 내부 `0x3F` CustomTx에 서명하고 서명된 hex만 운영자에게 전달합니다. 운영자는 면제 키로 이를 래핑하고 릴레이합니다. +비관리형 흐름의 경우, 사용자는 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req)(수수료 `0n`, `nonceKeyForLane(laneId)` 사용)로 내부 `0x3F` CustomTx에 서명하고, 운영자에게 서명된 헥스만 전달합니다. 운영자는 면제 키로 래핑하여 릴레이합니다. ```ts import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; @@ -334,7 +334,7 @@ const signedInner = await buildGuaranteedTx(toSigner(user), stableTestnet.id, { nonce, nonceKey: nonceKeyForLane(0n), }); -const { txHash } = await gw.relay(signedInner); // 면제가 래핑 + 브로드캐스트 → H_inner +const { txHash } = await gw.relay(signedInner); // 면제 래퍼 + 브로드캐스트 → H_inner ``` ```text @@ -343,11 +343,11 @@ const { txHash } = await gw.relay(signedInner); // 면제가 래핑 + 브로드 ## 빌드 헬퍼 -비수탁 `relay` 경로를 위한 하위 수준 서명자. 각각 서명된 트랜잭션을 `Hex`로 반환하며 nonce 가져오기 또는 수수료 추정은 없습니다. 첫 번째 인수는 [`Signer`](#signing-keys-and-custody)입니다. `toSigner(account)`로 viem 계정을 래핑하거나 `awsKmsSigner`와 같은 커스터디 서명자를 전달하세요. +비관리형 `relay` 경로를 위한 저수준 서명자입니다. 각각은 논스 가져오기나 수수료 추정 없이 서명된 트랜잭션을 `Hex`로 반환합니다. 첫 번째 인수는 [`Signer`](#signing-keys-and-custody)입니다. `toSigner(account)`로 viem 계정을 래핑하거나 `awsKmsSigner`와 같은 커스터디 서명자를 전달하세요. ### `buildWaiverInnerTx(signer, chainId, req)` -면제 불변성이 포함된 웨이버-레디 InnerTx에 서명합니다. `gasPrice: 0`, 레거시 유형 및 지정된 `chainId`. `req`는 [`WaiverInnerTx`](#waiverinnertx)와 필수 `nonce`입니다. +`gasPrice: 0`, 레거시 유형, 지정된 `chainId`와 같이 면제 불변값이 내장된 면제 준비 InnerTx에 서명합니다. `req`는 필수 `nonce`가 추가된 [`WaiverInnerTx`](#waiverinnertx)입니다. ```ts const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to, data, gas: 150_000n, nonce }); @@ -355,15 +355,15 @@ const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to, ### `buildGuaranteedTx(signer, chainId, req)` -GuaranteedTx(`0x3F` CustomTx)를 빌드하고 서명합니다. `req`는 [`GuaranteedTxRequest`](#guaranteedtxrequest)와 필수 `nonce` 및 `nonceKey`입니다. +GuaranteedTx(`0x3F` CustomTx)를 빌드하고 서명합니다. `req`는 필수 `nonce` 및 `nonceKey`가 추가된 [`GuaranteedTxRequest`](#guaranteedtxrequest)입니다. ### `buildGuaranteedWaiverTx(...)` -사전 서명된 내부를 외부 `0x3F` 면제 CustomTx로 래핑합니다. `guaranteedWaiver.relay`에서 내부적으로 사용됩니다. 고급 흐름을 위해 내보내집니다. +사전 서명된 내부 트랜잭션을 외부 `0x3F` 면제 CustomTx로 래핑합니다. `guaranteedWaiver.relay`에서 내부적으로 사용되며, 고급 흐름을 위해 Export됩니다. ### `nonceKeyForLane(laneId)` -`buildGuaranteedTx`에서 사용할 레인 ID에 대한 Enterprise `nonceKey`를 반환합니다. +`buildGuaranteedTx`에서 사용하기 위해 레인 ID에 대한 엔터프라이즈 `nonceKey`를 반환합니다. ```ts import { nonceKeyForLane } from "@stablechain/enterprise"; @@ -371,20 +371,20 @@ import { nonceKeyForLane } from "@stablechain/enterprise"; const nonceKey = nonceKeyForLane(0n); ``` -## 유형 +## 타입 ### `SignerSource` -면제 모듈(`gasWaiver`, `guaranteedWaiver`)이 허용하는 서명 키 필드입니다. `signer`, `account`, 클라이언트의 최상위 [`signer`](#stableenterpriseconfig), `STABLE_ENTERPRISE_PRIVATE_KEY` 환경 변수 순으로 해결됩니다. [서명 키 및 커스터디](#signing-keys-and-custody)를 참조하십시오. +면제 모듈(`gasWaiver`, `guaranteedWaiver`)이 허용하는 서명 키 필드입니다. `signer`, `account`, 클라이언트의 최상위 [`signer`](#stableenterpriseconfig), `STABLE_ENTERPRISE_PRIVATE_KEY` 환경 변수 순으로 해결됩니다. [서명 키 및 커스터디](#signing-keys-and-custody)를 참조하세요. -| **필드** | **유형** | **설명** | +| **필드** | **타입** | **설명** | | :--- | :--- | :--- | | `signer` | `Signer?` | 커스터디 등급 서명자(AWS KMS, HSM 또는 `privateKeySigner`). `account`보다 우선합니다. | -| `account` | `LocalAccount?` | `toSigner`를 통해 `Signer`로 조정된 인-프로세스 viem 계정입니다. | +| `account` | `LocalAccount?` | `toSigner`를 통해 `Signer`로 조정된 인 프로세스 viem 계정입니다. | ### `Signer` -SDK가 32바이트 다이제스트를 통해 서명하는 플러그형 서명자이므로 키가 커스터디 백엔드를 떠나지 않습니다. `awsKmsSigner`, `toSigner`, `privateKeySigner` 또는 `envSigner`로 하나를 구성합니다. +SDK가 32바이트 다이제스트에 서명하는 플러그형 서명자이므로 키는 커스터디 백엔드를 떠나지 않습니다. `awsKmsSigner`, `toSigner`, `privateKeySigner` 또는 `envSigner`를 사용하여 구성합니다. ```ts interface Signer { @@ -393,91 +393,91 @@ interface Signer { } ``` -| **도우미** | **가져오기** | **설명** | +| **헬퍼** | **임포트** | **설명** | | :--- | :--- | :--- | -| `awsKmsSigner({ keyId, client? })` | `@stablechain/enterprise/aws-kms` | AWS KMS `ECC_SECG_P256K1` 키로 지원되는 서명자입니다. `Promise`를 반환합니다. | +| `awsKmsSigner({ keyId, client? })` | `@stablechain/enterprise/aws-kms` | AWS KMS `ECC_SECG_P256K1` 키가 지원하는 서명자입니다. `Promise`를 반환합니다. | | `toSigner(account)` | `@stablechain/enterprise` | viem `LocalAccount`를 `Signer`로 조정합니다. | -| `privateKeySigner(key)` | `@stablechain/enterprise` | 프로세스에 보관된 원시 개인 키를 래핑하는 서명자입니다. | +| `privateKeySigner(key)` | `@stablechain/enterprise` | 인 프로세스로 보관된 원시 개인 키를 래핑하는 서명자입니다. | | `envSigner(varName?)` | `@stablechain/enterprise` | `STABLE_ENTERPRISE_PRIVATE_KEY` (또는 `varName`)에서 키를 읽는 서명자입니다. | ### `WaiverInnerTx` -각 호출마다 달라지는 InnerTx 필드. +호출당 변하는 InnerTx의 필드입니다. -| **필드** | **유형** | **기본값** | **설명** | +| **필드** | **타입** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `to` | `Address` | | 대상 주소: ERC-20 전송의 토큰 계약, 네이티브의 수신자. | -| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | 가스 한도. `gasPrice`가 0이므로 관대한 한도는 무료입니다. | -| `data` | `Hex?` | `"0x"` | 콜데이터. | -| `value` | `bigint?` | `0n` | 보낼 네이티브 값. | +| `to` | `Address` | | 대상 주소: ERC-20 전송의 경우 토큰 컨트랙트, 기본값의 경우 수신자입니다. | +| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | 가스 한도입니다. `gasPrice`가 0이므로 관대한 한도는 무료입니다. | +| `data` | `Hex?` | `"0x"` | 콜데이터입니다. | +| `value` | `bigint?` | `0n` | 전송할 기본값입니다. | ### `GuaranteedTxRequest` -| **필드** | **유형** | **기본값** | **설명** | +| **필드** | **타입** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `to` | `Address?` | | 대상 주소. | -| `gas` | `bigint` | | 가스 한도. 필수. | -| `gasFeeCap` | `bigint` | | `maxFeePerGas`. 필수. | -| `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`. 필수. | -| `data` | `Hex?` | `"0x"` | 콜데이터. | -| `value` | `bigint?` | `0n` | 보낼 네이티브 값. | +| `to` | `Address?` | | 대상 주소입니다. | +| `gas` | `bigint` | | 가스 한도입니다. 필수. | +| `gasFeeCap` | `bigint` | | `maxFeePerGas`입니다. 필수. | +| `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`입니다. 필수. | +| `data` | `Hex?` | `"0x"` | 콜데이터입니다. | +| `value` | `bigint?` | `0n` | 전송할 기본값입니다. | ### `GuaranteedWaiverTxRequest` 수수료 필드는 항상 0이므로 여기서는 생략됩니다. -| **필드** | **유형** | **기본값** | **설명** | +| **필드** | **타입** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `to` | `Address` | | 대상 주소. | -| `gas` | `bigint?` | 공유 내부 가스 기본값 | 가스 한도. | -| `data` | `Hex?` | `"0x"` | 콜데이터. | -| `value` | `bigint?` | `0n` | 보낼 네이티브 값. 값 전송은 면제에 허용됩니다. | +| `to` | `Address` | | 대상 주소입니다. | +| `gas` | `bigint?` | 공유 내부 가스 기본값 | 가스 한도입니다. | +| `data` | `Hex?` | `"0x"` | 콜데이터입니다. | +| `value` | `bigint?` | `0n` | 전송할 기본값입니다. 면제의 경우 값 전송이 허용됩니다. | ### `ValidationLimits` `gasWaiver` 및 `guaranteedWaiver`에 의해 각 InnerTx에 적용되는 파트너별 정책입니다. -| **필드** | **유형** | **기본값** | **설명** | +| **필드** | **타입** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `maxGasLimit` | `bigint?` | `10_000_000n` | InnerTx에 대한 최대 가스 한도. 이를 초과하면 `GAS_LIMIT_EXCEEDED`로 실패합니다. | -| `maxDataLength` | `number?` | `131_072` (128 KB) | 바이트 단위 최대 콜데이터 크기. 이를 초과하면 `DATA_TOO_LARGE`로 실패합니다. | -| `allowedTargets` | `AllowedTarget[]?` | | 면제를 후원할 수 있는 계약 및 메서드의 허용 목록. 설정된 경우 목록 외의 대상은 `TARGET_NOT_ALLOWED`로 실패합니다. | +| `maxGasLimit` | `bigint?` | `10_000_000n` | InnerTx의 최대 가스 한도입니다. 초과하면 `GAS_LIMIT_EXCEEDED`와 함께 실패합니다. | +| `maxDataLength` | `number?` | `131_072` (128 KB) | 최대 콜데이터 크기(바이트)입니다. 초과하면 `DATA_TOO_LARGE`와 함께 실패합니다. | +| `allowedTargets` | `AllowedTarget[]?` | | 면제가 후원할 수 있는 컨트랙트 및 메서드의 허용 목록입니다. 설정된 경우 목록에 없는 대상은 `TARGET_NOT_ALLOWED`와 함께 실패합니다. | ### `AllowedTarget` -| **필드** | **유형** | **설명** | +| **필드** | **타입** | **설명** | | :--- | :--- | :--- | -| `address` | `Address \| "*"` | InnerTx가 호출할 수 있는 계약, 또는 모든 계약과 일치하는 `"*"`입니다. | -| `selectors` | `Hex[]?` | 허용된 4바이트 메서드 셀렉터 (예: ERC-20 `transfer`의 `"0xa9059cbb"`). `address`에서 모든 메서드를 허용하려면 생략하거나 비워 둡니다. | +| `address` | `Address \| "*"` | InnerTx가 호출할 수 있는 컨트랙트 또는 모든 컨트랙트에 일치하는 `"*"`입니다. | +| `selectors` | `Hex[]?` | 허용된 4바이트 메서드 셀렉터(예: ERC-20 `transfer`의 경우 `"0xa9059cbb"`). `address`에서 모든 메서드를 허용하려면 생략하거나 비워 둡니다. | ### `RelayResult` ```ts interface RelayResult { - txHash: Hash; // 웨이버의 경우 H_inner, 독립형 보장 블록의 경우 GuaranteedTx 해시 + txHash: Hash; // 면제의 경우 H_inner, 독립형 보장 블록의 경우 GuaranteedTx 해시 } ``` ### `BatchResultItem` -배치 내 입력당 하나의 항목으로 입력 순서대로 정렬됩니다. 예외를 발생시키는 대신, 배치는 항목별 결과를 표면화합니다. +배치에서 입력당 하나의 항목이 입력 순서대로 반환됩니다. 예외를 던지는 대신, 배치는 항목별 결과를 나타냅니다. -| **필드** | **유형** | **설명** | +| **필드** | **타입** | **설명** | | :--- | :--- | :--- | | `index` | `number` | 입력 배열과 일치하는 0부터 시작하는 위치입니다. | -| `success` | `boolean` | 이 항목이 릴레이되었는지 여부. | -| `txHash` | `Hash?` | 성공 시 현재: 내부 트랜잭션 해시. | -| `error` | `{ code: ErrorCode; message: string }?` | 실패 시 현재. | +| `success` | `boolean` | 이 항목이 릴레이되었는지 여부입니다. | +| `txHash` | `Hash?` | 성공 시 존재: 내부 트랜잭션 해시입니다. | +| `error` | `{ code: ErrorCode; message: string }?` | 실패 시 존재합니다. | ## 오류 -단일 트랜잭션 메서드(`send`, `relay`)는 거부 시 예외를 발생시킵니다. 배치 메서드는 [`BatchResultItem.error`](#batchresultitem)에서 항목별 실패를 보고합니다. 모든 오류 클래스는 `StableEnterpriseError`를 확장합니다. +단일 트랜잭션 메서드(`send`, `relay`)는 거부 시 예외를 발생시킵니다. 일괄 메서드는 [`BatchResultItem.error`](#batchresultitem)에 항목별 실패를 보고합니다. 모든 오류 클래스는 `StableEnterpriseError`를 확장합니다. | **클래스** | **발생 시점** | **유용한 필드** | | :--- | :--- | :--- | -| `StableEnterpriseError` | 모든 SDK 오류의 기본 클래스. | `message` | -| `StableEnterpriseRelayError` | RPC 또는 릴레이 계층에서 트랜잭션이 거부됨. | `code` | -| `WaiverValidationError` | 브로드캐스트 전에 InnerTx가 정책 검사(가스, 데이터 크기 또는 대상 허용 목록)에 실패함. | `code` | +| `StableEnterpriseError` | 모든 SDK 오류의 기본 클래스입니다. | `message` | +| `StableEnterpriseRelayError` | 트랜잭션이 RPC 또는 릴레이 계층에서 거부됩니다. | `code` | +| `WaiverValidationError` | InnerTx가 브로드캐스트 전에 정책 검사(가스, 데이터 크기 또는 대상 허용 목록)에 실패합니다. | `code` | ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -498,33 +498,33 @@ StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not ### `ErrorCode` -던져진 오류 또는 `BatchResultItem.error`의 `code`는 다음 중 하나입니다. +발생된 오류 또는 `BatchResultItem.error`의 `code`는 다음 중 하나입니다. | **코드** | **의미** | | :--- | :--- | -| `UNKNOWN_ERROR` | 특정 코드를 사용할 수 없을 때의 대체. | +| `UNKNOWN_ERROR` | 특정 코드를 사용할 수 없는 경우의 대체값입니다. | | `BROADCAST_FAILED` | RPC 계층에서 브로드캐스트가 거부되었거나 게이트웨이가 릴레이에 실패했습니다. | -| `INVALID_TRANSACTION` | InnerTx 디코딩 또는 구문 분석에 실패했습니다. | +| `INVALID_TRANSACTION` | InnerTx를 디코딩하거나 구문 분석하는 데 실패했습니다. | | `INVALID_SIGNATURE` | 서명 확인에 실패했습니다. | | `UNSUPPORTED_TX_TYPE` | InnerTx 유형이 레거시, eip2930 또는 eip1559가 아닙니다. | -| `WRONG_CHAIN_ID` | InnerTx의 `chainId`가 없거나 대상 체인과 일치하지 않습니다. | +| `WRONG_CHAIN_ID` | InnerTx `chainId`가 없거나 대상 체인과 일치하지 않습니다. | | `NON_ZERO_GAS_PRICE` | InnerTx는 0이 아닌 가스 가격을 가지고 있습니다(면제의 경우 0이어야 함). | | `GAS_LIMIT_EXCEEDED` | InnerTx 가스 한도가 `maxGasLimit`을 초과합니다. | | `DATA_TOO_LARGE` | InnerTx 콜데이터가 `maxDataLength`를 초과합니다. | | `TARGET_NOT_ALLOWED` | InnerTx 대상이 `allowedTargets`에 없습니다. | -| `GATEWAY_UNAUTHORIZED` | Enterprise RPC 게이트웨이가 API 키를 거부했습니다(누락, 유효하지 않음 또는 만료됨). | -| `QUOTA_EXCEEDED` | Enterprise RPC 게이트웨이 가스 할당량이 소진되었습니다. | +| `GATEWAY_UNAUTHORIZED` | 엔터프라이즈 RPC 게이트웨이가 API 키를 거부했습니다(누락, 유효하지 않음 또는 만료됨). | +| `QUOTA_EXCEEDED` | 엔터프라이즈 RPC 게이트웨이 가스 할당량이 소진되었습니다. | ## 상수 -| **상수** | **유형** | **설명** | +| **상수** | **타입** | **설명** | | :--- | :--- | :--- | -| `DEFAULT_INNER_GAS` | `bigint` | `gas`가 생략되었을 때의 기본 InnerTx 가스 제한 (`150_000n`)입니다. | -| `ENTERPRISE_FLAG` | `bigint` | 레인의 `nonceKey`에 설정된 Enterprise 비트입니다. | +| `DEFAULT_INNER_GAS` | `bigint` | `gas`가 생략된 경우 기본 InnerTx 가스 한도(`150_000n`). | +| `ENTERPRISE_FLAG` | `bigint` | 레인의 `nonceKey`에 설정된 엔터프라이즈 비트입니다. | | `ENTERPRISE_MASK` | `bigint` | 레인 ID의 상한: `laneId`는 `[0, ENTERPRISE_MASK - 1]` 범위에 있어야 합니다. | ## 다음 권장 사항 - [**Stable Enterprise SDK**](/ko/explanation/enterprise-sdk): 레일이 무엇이며 언제 사용해야 하는지. - [**가스 면제 프로토콜**](/ko/reference/gas-waiver-api): 트랜잭션 형식, 마커 라우팅 및 거버넌스 제어. -- [**보장된 블록 공간**](/ko/explanation/guaranteed-blockspace): Stable이 엔터프라이즈 워크로드에 대한 블록 용량을 예약하는 방법. +- [**보장된 블록스페이스**](/ko/explanation/guaranteed-blockspace): Stable이 엔터프라이즈 워크로드에 대한 블록 용량을 예약하는 방법. diff --git a/docs/sidebar.json b/docs/sidebar.json index d9bc4b8..6160aec 100644 --- a/docs/sidebar.json +++ b/docs/sidebar.json @@ -689,7 +689,7 @@ ], "/ko": [ { - "text": "학습", + "text": "학습하기", "collapsed": true, "items": [ { @@ -725,15 +725,15 @@ "link": "/ko/explanation/ethereum-compatibility" }, { - "text": "확정성", + "text": "완결성", "link": "/ko/explanation/finality" }, { - "text": "가스 가격", + "text": "가스 가격 책정", "link": "/ko/explanation/gas-pricing" }, { - "text": "가스 가격 API", + "text": "가스 가격 책정 API", "link": "/ko/reference/gas-pricing-api" }, { @@ -779,7 +779,7 @@ "link": "/ko/explanation/guaranteed-blockspace" }, { - "text": "USDT 전송 Aggregator", + "text": "USDT 전송 애그리게이터", "link": "/ko/explanation/usdt-transfer-aggregator" }, { @@ -793,7 +793,7 @@ "collapsed": true, "items": [ { - "text": "코어 최적화 개요", + "text": "핵심 최적화 개요", "link": "/ko/explanation/core-optimization-overview" }, { @@ -813,13 +813,13 @@ "link": "/ko/explanation/high-performance-rpc" }, { - "text": "아우토반", + "text": "Autobahn", "link": "/ko/explanation/autobahn" } ] }, { - "text": "사용 사례 설명", + "text": "사용 사례 내러티브", "collapsed": true, "items": [ { @@ -841,7 +841,7 @@ ] }, { - "text": "토큰 경제학", + "text": "토크노믹스", "link": "/ko/reference/tokenomics" }, { @@ -855,7 +855,7 @@ ] }, { - "text": "구축", + "text": "구축하기", "collapsed": true, "items": [ { @@ -897,7 +897,7 @@ ] }, { - "text": "Enterprise SDK", + "text": "기업 SDK", "collapsed": true, "items": [ { @@ -931,7 +931,7 @@ "link": "/ko/explanation/accounts-overview" }, { - "text": "계정 색인", + "text": "계정 인덱스", "link": "/ko/explanation/accounts-guides" }, { @@ -957,7 +957,7 @@ "link": "/ko/explanation/payments-overview" }, { - "text": "결제 색인", + "text": "결제 인덱스", "link": "/ko/explanation/payments-guides" }, { @@ -991,7 +991,7 @@ "link": "/ko/how-to/build-p2p-payments" }, { - "text": "구독 및 수집", + "text": "구독 및 수금", "link": "/ko/how-to/subscribe-and-collect" }, { @@ -1029,7 +1029,7 @@ "link": "/ko/reference/pay-per-call" }, { - "text": "예정된 사용 사례", + "text": "향후 사용 사례", "link": "/ko/explanation/upcoming-use-cases" } ] @@ -1037,31 +1037,31 @@ ] }, { - "text": "계약 배포", + "text": "컨트랙트 배포", "collapsed": true, "items": [ { - "text": "계약 개요", + "text": "컨트랙트 개요", "link": "/ko/explanation/contracts-overview" }, { - "text": "계약 색인", + "text": "컨트랙트 인덱스", "link": "/ko/explanation/contracts-guides" }, { - "text": "첫 번째 계약 배포", + "text": "첫 번째 컨트랙트 배포", "collapsed": true, "items": [ { - "text": "스마트 계약", + "text": "스마트 컨트랙트", "link": "/ko/tutorial/smart-contract" }, { - "text": "계약 확인", + "text": "컨트랙트 확인", "link": "/ko/how-to/verify-contract" }, { - "text": "색인 계약", + "text": "컨트랙트 색인", "link": "/ko/how-to/index-contract" } ] @@ -1083,19 +1083,19 @@ "link": "/ko/reference/system-modules-api-overview" }, { - "text": "은행 모듈", + "text": "뱅크 모듈", "link": "/ko/explanation/bank-module" }, { - "text": "은행 모듈 API", + "text": "뱅크 모듈 API", "link": "/ko/reference/bank-module-api" }, { - "text": "분배 모듈", + "text": "배포 모듈", "link": "/ko/explanation/distribution-module" }, { - "text": "분배 모듈 API", + "text": "배포 모듈 API", "link": "/ko/reference/distribution-module-api" }, { @@ -1119,7 +1119,7 @@ "link": "/ko/how-to/track-unbonding" }, { - "text": "검증자 데이터 색인", + "text": "검증인 데이터 색인", "link": "/ko/how-to/index-validator-data" } ] @@ -1133,7 +1133,7 @@ ] }, { - "text": "통합", + "text": "통합하기", "collapsed": true, "items": [ { @@ -1241,7 +1241,7 @@ "link": "/ko/reference/wallets" }, { - "text": "커스터디", + "text": "수호", "link": "/ko/reference/custody" }, { @@ -1271,7 +1271,7 @@ ] }, { - "text": "운영", + "text": "운영하기", "collapsed": true, "items": [ { @@ -1295,7 +1295,7 @@ "link": "/ko/how-to/use-node-snapshots" }, { - "text": "검증자 실행", + "text": "검증인 실행", "link": "/ko/how-to/run-validator" }, { @@ -1321,15 +1321,15 @@ "link": "/ko/explanation/agent-settlement" }, { - "text": "AI 에이전트 색인", + "text": "AI 에이전트 인덱스", "link": "/ko/explanation/ai-agents-guides" }, { - "text": "x402 및 MPP를 통해 결제", + "text": "x402 및 MPP를 통한 지불", "collapsed": true, "items": [ { - "text": "x402", + "text": "X402", "link": "/ko/explanation/x402" }, { @@ -1341,7 +1341,7 @@ "link": "/ko/explanation/mpp-sessions" }, { - "text": "호출당 결제 구축", + "text": "호출당 지불 구축", "link": "/ko/how-to/build-pay-per-call" }, { @@ -1349,7 +1349,7 @@ "link": "/ko/how-to/build-mpp-endpoint" }, { - "text": "MCP로 결제", + "text": "MCP로 지불", "link": "/ko/how-to/pay-with-mcp" } ] @@ -1363,11 +1363,11 @@ "link": "/ko/how-to/develop-with-ai" }, { - "text": "에이전트 촉진자", + "text": "에이전트식 조력자", "link": "/ko/reference/agentic-facilitators" }, { - "text": "에이전트 지갑", + "text": "에이전트식 지갑", "link": "/ko/reference/agentic-wallets" } ] @@ -1413,7 +1413,7 @@ "link": "/cn/explanation/ethereum-compatibility" }, { - "text": "确定性", + "text": "最终性", "link": "/cn/explanation/finality" }, { @@ -1439,15 +1439,15 @@ "link": "/cn/explanation/usdt-features-overview" }, { - "text": "资金流", + "text": "资金流转", "link": "/cn/explanation/flow-of-funds" }, { - "text": "USDT0 跨链", + "text": "USDT0 桥接", "link": "/cn/explanation/usdt0-bridging" }, { - "text": "跨链安全", + "text": "桥接安全", "link": "/cn/explanation/bridge-security" }, { @@ -1463,15 +1463,15 @@ "link": "/cn/explanation/gas-waiver" }, { - "text": "担保块空间", + "text": "保证区块空间", "link": "/cn/explanation/guaranteed-blockspace" }, { - "text": "USDT 转账聚合器", + "text": "USDT 传输聚合器", "link": "/cn/explanation/usdt-transfer-aggregator" }, { - "text": "保密转账", + "text": "保密传输", "link": "/cn/explanation/confidential-transfer" } ] @@ -1493,7 +1493,7 @@ "link": "/cn/explanation/execution" }, { - "text": "Stable DB", + "text": "Stable 数据库", "link": "/cn/explanation/stable-db" }, { @@ -1511,19 +1511,19 @@ "collapsed": true, "items": [ { - "text": "支付用例", + "text": "用例:支付", "link": "/cn/explanation/use-case-payments" }, { - "text": "薪资用例", + "text": "用例:工资", "link": "/cn/explanation/use-case-payroll" }, { - "text": "赞助用例", + "text": "用例:赞助", "link": "/cn/explanation/use-case-sponsored" }, { - "text": "隐私用例", + "text": "用例:私有", "link": "/cn/explanation/use-case-private" } ] @@ -1551,7 +1551,7 @@ "link": "/cn/explanation/build-overview" }, { - "text": "快速入门", + "text": "快速开始", "link": "/cn/tutorial/quick-start" }, { @@ -1571,7 +1571,7 @@ "link": "/cn/reference/sdk" }, { - "text": "赚取收益", + "text": "获取收益", "link": "/cn/how-to/earn-yield" }, { @@ -1597,11 +1597,11 @@ "link": "/cn/how-to/relay-with-gas-waiver" }, { - "text": "担保块空间", + "text": "保证区块空间", "link": "/cn/how-to/send-guaranteed-transactions" }, { - "text": "担保中继交易", + "text": "保证中继交易", "link": "/cn/how-to/guaranteed-relayed-transactions" }, { @@ -1637,7 +1637,7 @@ ] }, { - "text": "接受付款", + "text": "接收付款", "collapsed": true, "items": [ { @@ -1649,7 +1649,7 @@ "link": "/cn/explanation/payments-guides" }, { - "text": "转移 USDT0", + "text": "移动 USDT0", "collapsed": true, "items": [ { @@ -1725,7 +1725,7 @@ ] }, { - "text": "发布合约", + "text": "部署合约", "collapsed": true, "items": [ { @@ -1787,11 +1787,11 @@ "link": "/cn/reference/distribution-module-api" }, { - "text": "Staking 模块", + "text": "质押模块", "link": "/cn/explanation/staking-module" }, { - "text": "Staking 模块 API", + "text": "质押模块 API", "link": "/cn/reference/staking-module-api" }, { @@ -1807,7 +1807,7 @@ "link": "/cn/how-to/track-unbonding" }, { - "text": "索引验证者数据", + "text": "索引验证器数据", "link": "/cn/how-to/index-validator-data" } ] @@ -1905,7 +1905,7 @@ "link": "/cn/reference/bridges" }, { - "text": "DEX", + "text": "去中心化交易所 (DEX)", "link": "/cn/reference/dexes" }, { @@ -1921,7 +1921,7 @@ "link": "/cn/reference/network-routing" }, { - "text": "出入金", + "text": "坡道", "link": "/cn/reference/ramps" }, { @@ -1951,7 +1951,7 @@ "collapsed": true, "items": [ { - "text": "品牌资料", + "text": "品牌工具包", "link": "/cn/resources/brand-kit" } ] @@ -1983,7 +1983,7 @@ "link": "/cn/how-to/use-node-snapshots" }, { - "text": "运行验证者", + "text": "运行验证器", "link": "/cn/how-to/run-validator" }, { @@ -2017,7 +2017,7 @@ "collapsed": true, "items": [ { - "text": "X402", + "text": "x402", "link": "/cn/explanation/x402" }, { @@ -2047,15 +2047,15 @@ "collapsed": true, "items": [ { - "text": "与 AI 开发", + "text": "使用 AI 开发", "link": "/cn/how-to/develop-with-ai" }, { - "text": "Agentic 促进者", + "text": "代理协调器", "link": "/cn/reference/agentic-facilitators" }, { - "text": "Agentic 钱包", + "text": "代理钱包", "link": "/cn/reference/agentic-wallets" } ] From e431fcf814e31a6124963341a8c22092e9bfa276 Mon Sep 17 00:00:00 2001 From: bastienrp Date: Fri, 17 Jul 2026 08:42:54 +0200 Subject: [PATCH 18/20] docs: align KMS example env var with the SDK example (AWS_KMS_KEY_ID) Co-Authored-By: Claude Opus 4.8 --- docs/pages/en/reference/enterprise-sdk.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/en/reference/enterprise-sdk.mdx b/docs/pages/en/reference/enterprise-sdk.mdx index c89457c..d0bc44d 100644 --- a/docs/pages/en/reference/enterprise-sdk.mdx +++ b/docs/pages/en/reference/enterprise-sdk.mdx @@ -74,7 +74,7 @@ import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; import { awsKmsSigner } from "@stablechain/enterprise/aws-kms"; // the KMS key must be ECC_SECG_P256K1 (secp256k1); the SDK derives the address from it -const signer = await awsKmsSigner({ keyId: process.env.KMS_KEY_ID }); +const signer = await awsKmsSigner({ keyId: process.env.AWS_KMS_KEY_ID }); const enterprise = createStableEnterprise({ chain: stableTestnet, From 080f255af65baaaecc6169ad44df5bce1d495b8f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 17 Jul 2026 06:44:46 +0000 Subject: [PATCH 19/20] i18n: auto-translate cn/ko for changed en content --- docs/pages/cn/reference/enterprise-sdk.mdx | 204 +++++++++--------- docs/pages/ko/reference/enterprise-sdk.mdx | 232 ++++++++++----------- docs/sidebar.json | 152 +++++++------- 3 files changed, 294 insertions(+), 294 deletions(-) diff --git a/docs/pages/cn/reference/enterprise-sdk.mdx b/docs/pages/cn/reference/enterprise-sdk.mdx index 3c4f10d..b860a60 100644 --- a/docs/pages/cn/reference/enterprise-sdk.mdx +++ b/docs/pages/cn/reference/enterprise-sdk.mdx @@ -1,21 +1,21 @@ --- source_path: reference/enterprise-sdk.mdx -source_sha: c89457ca29556b5a94b9cb4562bd9d210d38701d +source_sha: d0bc44dc34b19b1a7f7cadeda2ceaa68d296220a title: "企业级SDK参考" -description: "完整的@stablechain/enterprise参考:包括createStableEnterprise、免Gas模块和保证区块空间模块、构建助手以及错误类。" +description: "@stablechain/enterprise 的完整参考:createStableEnterprise、免Gas模块和保证区块空间模块、构建助手以及错误类。" diataxis: "reference" --- # 企业级SDK参考 -`@stablechain/enterprise` 的完整表面。这涵盖了客户端从 [`createStableEnterprise`](#createstableenterpriseconfig) 开始,其三个功能([免Gas中继](#relay-with-gas-waiver)、[保证区块空间](#guaranteed-blockspace)和[保证中继交易](#guaranteed-relay-transactions)),低级别的构建助手,以及共享的结果和错误类型。有关这些轨道的含义,请参阅 [Stable企业级SDK](/cn/explanation/enterprise-sdk)、[免Gas](/cn/explanation/gas-waiver) 和 [保证区块空间](/cn/explanation/guaranteed-blockspace)。 +`@stablechain/enterprise` 的完整表面。这涵盖了从 [`createStableEnterprise`](#createstableenterpriseconfig) 客户端开始,其三个功能([免Gas中继](#relay-with-gas-waiver)、[保证区块空间](#guaranteed-blockspace) 和 [保证中继交易](#guaranteed-relay-transactions)),低级别的构建助手,以及共享结果和错误类型。有关这些原理,请参阅[Stable企业级SDK](/cn/explanation/enterprise-sdk)、[免Gas](/cn/explanation/gas-waiver) 和 [保证区块空间](/cn/explanation/guaranteed-blockspace)。 :::note -企业级SDK目前仅在Stable测试网上可用,并且需要申请访问。要进行集成,请[联系Stable](https://discord.gg/stablexyz)以获取经治理注册的豁免密钥和企业级RPC网关API密钥。 +企业级SDK目前仅在Stable测试网上可用,并且需要申请才能访问。要进行集成,请[联系Stable](https://discord.gg/stablexyz)以获取政fu注册的豁免密钥和企业级RPC网关API密钥。 ::: :::warning -这是一个使用私钥进行签名的服务器端库。切勿在浏览器中运行。保留豁免密钥和企业级RPC网关URL在您的后端。 +这是一个使用私钥进行签名的服务器端库。切勿在浏览器中运行。请将豁免密钥和企业级RPC网关URL保留在您的后端。 ::: ## 安装 @@ -28,11 +28,11 @@ npm install @stablechain/enterprise viem added 2 packages, audited 3 packages in 2s ``` -`viem >= 2.0.0` 是一个对等依赖项。该软件包重新导出了 `viem/chains` 中的 `stable` 和 `stableTestnet`,因此您无需单独导入它们。 +`viem >= 2.0.0` 是一个对等依赖项。此包重新导出了 `viem/chains` 中的 `stable` 和 `stableTestnet`,因此您无需单独导入它们。 ## `createStableEnterprise(config)` -构造一个 `StableEnterpriseClient`。每个模块仅在您配置后才存在,因此在使用前请进行空值检查。 +构造一个 `StableEnterpriseClient`。每个模块仅在您配置它时才存在,因此在使用前请进行空值检查。 ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -52,20 +52,20 @@ StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | -| `chain` | `StableChain` | | 目标链。传入 `stable` 或 `stableTestnet`(由软件包重新导出)。必填项。 | -| `rpcEndpoints` | `string[]?` | 链的内置RPC | 一个或多个Stable RPC端点,在失败时按顺序尝试。仅在指向私有端点时覆盖。 | -| `enterpriseRpcEndpoints` | `string[]?` | | 一个或多个企业级RPC网关端点,在失败时按顺序尝试。`guaranteedBlock` 和 `guaranteedWaiver` 需要。 | -| `batchSizeLimit` | `number?` | `100` | 每个批量RPC调用的最大事务数。 | -| `signer` | `Signer?` | | 免Gas模块 (`gasWaiver`、`guaranteedWaiver`) 的默认签名器,当模块没有自己的密钥时。设置一次即可通过一个托管后端驱动两者。请参阅 [签名密钥和托管](#signing-keys-and-custody)。 | -| `gasWaiver` | `GasWaiverConfig?` | | 启用 [免Gas中继](#relay-with-gas-waiver)。 | -| `guaranteedBlock` | `GuaranteedBlockConfig?` | | 启用 [保证区块空间](#guaranteed-blockspace)。 | -| `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | 启用 [保证中继交易](#guaranteed-relay-transactions)。 | +| `chain` | `StableChain` | | 目标链。传递 `stable` 或 `stableTestnet`(由包重新导出)。必填。 | +| `rpcEndpoints` | `string[]?` | 链的内置RPC | 一个或多个Stable RPC端点,在失败时按顺序尝试。仅在指向私有端点时才覆盖。 | +| `enterpriseRpcEndpoints` | `string[]?` | | 一个或多个企业级RPC网关端点,在失败时按顺序尝试。`guaranteedBlock` 和 `guaranteedWaiver` 必填。 | +| `batchSizeLimit` | `number?` | `100` | 每个批处理RPC调用的最大交易数量。 | +| `signer` | `Signer?` | | 当模块没有自己的密钥时,免Gas模块(`gasWaiver`,`guaranteedWaiver`)的默认签名者。设置一次以通过单个托管后端驱动两者。请参阅[签名密钥和托管](#signing-keys-and-custody)。 | +| `gasWaiver` | `GasWaiverConfig?` | | 启用[免Gas中继](#relay-with-gas-waiver)。 | +| `guaranteedBlock` | `GuaranteedBlockConfig?` | | 启用[保证区块空间](#guaranteed-blockspace)。 | +| `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | 启用[保证中继交易](#guaranteed-relay-transactions)。 | ### 签名密钥和托管 -持有免Gas密钥的模块(`gasWaiver` 和 `guaranteedWaiver`)按顺序解析:模块自己的 `signer`,然后是其 `account`(一个进程内viem密钥),然后是客户端配置的顶级 [`signer`](#stableenterpriseconfig),最后是 `STABLE_ENTERPRISE_PRIVATE_KEY` 环境变量。设置一次顶级 `signer` 可以通过一个托管后端驱动这两个免Gas模块。`guaranteedBlock` 使用其自身已资助的 `account` 进行签名。 +持有豁免密钥的模块(`gasWaiver` 和 `guaranteedWaiver`)按顺序解析它:模块自己的 `signer`,然后是它的 `account`(一个进程内的viem密钥),然后是客户端配置中的顶层 [`signer`](#stableenterpriseconfig),然后是 `STABLE_ENTERPRISE_PRIVATE_KEY` 环境变量。设置顶层 `signer` 一次,即可通过单个托管后端驱动两个豁免模块。`guaranteedBlock` 使用其自身资助的 `account` 进行签名。 -`Signer` 对 32 字节的摘要进行签名,因此密钥永远不会离开托管后端。对于AWS KMS,请使用 `awsKmsSigner`,使用 `toSigner(account)` 来适应viem账户,或使用 `privateKeySigner(key)` / `envSigner()` 来使用进程内密钥。传递给模块 `send` / `sendBatch` 的每调用发送方也可以是viem账户或 `Signer`,因此KMS/HSM密钥可以签署内部交易而无需降级到 `relay`。 +`Signer` 对 32 字节的摘要进行签名,因此密钥从不离开托管后端。对于AWS KMS,请使用 `awsKmsSigner`;要适配viem账户,请使用 `toSigner(account)`;对于进程内密钥,请使用 `privateKeySigner(key)` / `envSigner()`。传递给模块 `send` / `sendBatch` 的每次调用发送者也可以是viem账户或 `Signer`,因此KMS/HSM密钥可以签署内部交易而无需降级到 `relay`。 ```bash npm install @aws-sdk/client-kms @@ -75,16 +75,16 @@ npm install @aws-sdk/client-kms import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; import { awsKmsSigner } from "@stablechain/enterprise/aws-kms"; -// KMS密钥必须是ECC_SECG_P256K1 (secp256k1);SDK从中派生地址 -const signer = await awsKmsSigner({ keyId: process.env.KMS_KEY_ID }); +// KMS密钥必须是ECC_SECG_P256K1 (secp256k1);SDK会从它派生地址 +const signer = await awsKmsSigner({ keyId: process.env.AWS_KMS_KEY_ID }); const enterprise = createStableEnterprise({ chain: stableTestnet, - gasWaiver: { signer }, // 托管级免Gas密钥,替代`account` + gasWaiver: { signer }, // 代替 `account` 的托管级免Gas密钥 }); ``` -`awsKmsSigner` 发布在 `@stablechain/enterprise/aws-kms` 子路径中,因此 `@aws-sdk/client-kms` 仍是一个可选的对等依赖项,不属于核心安装。 +`awsKmsSigner` 在 `@stablechain/enterprise/aws-kms` 子路径中提供,因此 `@aws-sdk/client-kms` 仍然是一个可选的对等依赖项,不属于核心安装。 ### `StableEnterpriseClient` @@ -98,7 +98,7 @@ interface StableEnterpriseClient { ## 免Gas中继 -`gasWaiver` 模块中继免Gas交易。一个白名单的免Gas账户将用户的零Gas交易(InnerTx)封装成一个WaiverTx并广播。用户不需要USDT0。每个方法都返回 `H_inner`,即InnerTx哈希,而不是封装哈希。 +`gasWaiver` 模块中继免Gas交易。一个白名单豁免账户将用户的零Gas交易(InnerTx)包装成WaiverTx并进行广播。用户不需要USDT0。每个方法都返回 `H_inner`,即InnerTx哈希,而不是包装器哈希。 在配置中通过 `gasWaiver` 启用它: @@ -122,15 +122,15 @@ const gw = enterprise.gasWaiver; | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `signer` | `Signer?` | 作为托管签名器(AWS KMS、HSM)的白名单、治理注册免Gas密钥。请参阅 [签名密钥和托管](#signing-keys-and-custody)。优先于 `account`。 | -| `account` | `LocalAccount?` | 作为进程内viem账户的免Gas密钥。当两者都未设置时,回退到 `STABLE_ENTERPRISE_PRIVATE_KEY`。 | +| `signer` | `Signer?` | 作为托管签名者(AWS KMS, HSM)的白名单、政fu注册豁免密钥。请参阅[签名密钥和托管](#signing-keys-and-custody)。优先于 `account`。 | +| `account` | `LocalAccount?` | 作为进程内viem账户的豁免密钥。当两者都未设置时,回退到 `STABLE_ENTERPRISE_PRIVATE_KEY`。 | | `maxGasLimit` | `bigint?` | 继承自 `ValidationLimits`。 | | `maxDataLength` | `number?` | 继承自 `ValidationLimits`。 | | `allowedTargets` | `AllowedTarget[]?` | 继承自 `ValidationLimits`。 | ### `send(account, tx)` -在一个调用中构建、签名并中继一个来自 `account` 的 InnerTx。`gasPrice: 0`、遗留类型、`chainId` 和待处理 nonce 都为您处理。拒绝时抛出 `StableEnterpriseRelayError`。 +构建、签名并中继一个`account`的InnerTx,一步到位。`gasPrice: 0`、遗留类型、`chainId`和待处理的nonce都为您处理。拒绝时抛出`StableEnterpriseRelayError`。 ```ts const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); @@ -140,11 +140,11 @@ const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); { txHash: "0x8f3a...2d41" } ``` -`tx` 参数是一个 [`WaiverInnerTx`](#waiverinnertx) 加上一个可选的 `nonce`。返回 [`RelayResult`](#relayresult)。 +`tx` 参数是 [`WaiverInnerTx`](#waiverinnertx) 加上一个可选的 `nonce`。返回 [`RelayResult`](#relayresult)。 ### `sendBatch(account, txs)` -从一个 `account` 构建、签名并中继多个 InnerTx。Nonce 会从账户的待处理 nonce 自动排序。按顺序返回每个输入的单个结果。 +从一个`account`构建、签名并中继多个InnerTx。nonce从账户的待处理nonce开始自动排序。返回每个输入的结g果,按顺序。 ```ts const results = await gw.sendBatch(user, [ @@ -157,11 +157,11 @@ const results = await gw.sendBatch(user, [ [ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: true, txHash: "0x..." } ] ``` -`txs` 是一个只读的 [`WaiverInnerTx`](#waiverinnertx) 数组。返回 [`BatchResultItem[]`](#batchresultitem)。 +`txs` 是一个[`WaiverInnerTx`](#waiverinnertx)的只读数组。返回[`BatchResultItem[]`](#batchresultitem)。 ### `relay(signedInnerTxHex)` -中继一个预签名的零Gas InnerTx。当用户在自己的环境中签名并仅将签名后的十六进制字符串交给您时,请使用此方法进行非托管流程,以便免Gas操作员永远不会看到用户的密钥。使用 [`buildWaiverInnerTx`](#buildwaiverinnertxsigner-chainid-req) 构建一个。拒绝时抛出错误。 +中继一个预签名的零Gas InnerTx。这用于非托管流程,其中用户在自己的环境中签名并只向您提供签名的十六进制数据,以便豁免操作员从不看到用户的密钥。使用 [`buildWaiverInnerTx`](#buildwaiverinnertxsigner-chainid-req) 构建一个。拒绝时抛出。 ```ts import { buildWaiverInnerTx, toSigner } from "@stablechain/enterprise"; @@ -176,7 +176,7 @@ const { txHash } = await gw.relay(signed); ### `relayBatch(signedInnerTxHexes)` -中继一批预签名的 InnerTx。按顺序为每个输入返回一个 [`BatchResultItem`](#batchresultitem)。 +中继一批预签名的 InnerTx。为每个输入按顺序返回一个 [`BatchResultItem`](#batchresultitem)。 ```ts const results = await gw.relayBatch([signed0, signed1]); @@ -188,14 +188,14 @@ const results = await gw.relayBatch([signed0, signed1]); ## 保证区块空间 -`guaranteedBlock` 模块通过企业 RPC 网关中继 GuaranteedTx(类型为 `0x3F` CustomTx),以便它们落在预留的企业通道区块空间中。与免Gas不同,签名者支付自己的Gas,并且必须有资金。每笔交易都带有与企业通道关联的二维nonce,并且广播仅通过网关进行。 +`guaranteedBlock` 模块通过企业级 RPC 网关中继 GuaranteedTx(类型为 `0x3F` CustomTx),以便它们落在预留的企业专用区块空间中。与免Gas不同,签名者需要支付自己的Gas并必须有资金。每笔交易都带有与企业通道相关联的二维 Nonce,并且只能通过网关进行广播。 通过 `guaranteedBlock` 和 `enterpriseRpcEndpoints` 启用它: ```ts const enterprise = createStableEnterprise({ chain: stableTestnet, - enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL], // Stable提供的网关URL + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL], // Stable 提供的网关 URL guaranteedBlock: { account: privateKeyToAccount("0xFUNDED_SIGNER_KEY"), laneId: 0n, @@ -209,12 +209,12 @@ const gb = enterprise.guaranteedBlock; | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `account` | `LocalAccount` | 对每个GuaranteedTx进行签名并支付其Gas的已资助账户。 | -| `laneId` | `bigint` | 企业通道ID。必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。无效ID会提前被拒绝。 | +| `account` | `LocalAccount` | 签署每笔 GuaranteedTx 并支付其 Gas 的有资金账户。 | +| `laneId` | `bigint` | 企业通道ID。必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。无效的ID将立即被拒绝。 | ### `send(account, tx)` -构建、签名并中继一个GuaranteedTx。1559费用字段是必需的,因为签名者支付Gas。`chainId`、企业级 `nonceKey` 和二维nonce(从网关发现)都会自动为您处理。 +构建、签名并中继一个 GuaranteedTx。因为签名者要支付 Gas,所以需要 1559 费用字段。`chainId`、企业 `nonceKey` 和二维 Nonce(从网关发现)都会为您处理。 ```ts const gasPrice = await publicClient.getGasPrice(); @@ -231,11 +231,11 @@ const { txHash } = await gb.send(signer, { { txHash: "0xabcd...7890" } ``` -`tx` 参数是一个 [`GuaranteedTxRequest`](#guaranteedtxrequest) 加上一个可选的 `nonce`。返回 [`RelayResult`](#relayresult)。 +`tx` 参数是 [`GuaranteedTxRequest`](#guaranteedtxrequest) 加上一个可选的 `nonce`。返回 [`RelayResult`](#relayresult)。 ### `sendBatch(account, txs)` -构建、签名并中继多个 GuaranteedTx。Nonces 会从发现的基础自动排序。失败会影响其后续操作。 +构建、签名并中继若干 GuaranteedTx。随机数从发现的基本值自动排序。失败会影响其后续结果。 ```ts const results = await gb.sendBatch(signer, [ @@ -252,7 +252,7 @@ const results = await gb.sendBatch(signer, [ ### `relay(signedTx)` / `relayBatch(signedTxs)` -中继一个预签名的GuaranteedTx,或一批GuaranteedTx。使用 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req) 并利用 [`nonceKeyForLane`](#noncekeyforlanelaneid) 作为企业级nonceKey,在其他地方构建并签署交易,然后仅将签名的十六进制数据交给操作员。 +中继一个预签名的 GuaranteedTx,或批量中继。使用 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req) 和 [`nonceKeyForLane`](#noncekeyforlanelaneid) 对企业级 Nonce 密钥在其他地方构建和签名交易,然后只将签名的十六进制数据交给操作员。 ```ts import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; @@ -262,7 +262,7 @@ const signed = await buildGuaranteedTx(toSigner(signer), stableTestnet.id, { gas: 21_000n, gasFeeCap, gasTipCap, - nonce, // 账户当前的2D通道nonce + nonce, // 账户当前的 2D-通道 nonce nonceKey: nonceKeyForLane(0n), }); const { txHash } = await gb.relay(signed); @@ -274,14 +274,14 @@ const { txHash } = await gb.relay(signed); ## 保证中继交易 -`guaranteedWaiver` 模块结合了上述两个功能:一个免Gas交易通过保证区块空间路由。内部和外部交易都是 `0x3F` CustomTx,共享一个企业级 `nonceKey`,因此它通过网关广播,就像 `guaranteedBlock` 一样。免Gas模块支付Gas,所以用户不需要余额,也没有费用字段,就像 `gasWaiver` 一样。每个方法都返回 `H_inner`。 +`guaranteedWaiver` 模块结合了上述两种机制:通过保证区块空间路由的免Gas交易。内部和外部交易都是 `0x3F` 定制交易,共享一个企业 `nonceKey`,因此它像 `guaranteedBlock` 一样通过网关广播。免Gas方赞助 Gas,因此用户不需要余额和费用字段,就像 `gasWaiver` 一样。每个方法都返回 `H_inner`。 通过 `guaranteedWaiver` 和 `enterpriseRpcEndpoints` 启用它: ```ts const enterprise = createStableEnterprise({ chain: stableTestnet, - enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL], // Stable提供的网关URL + enterpriseRpcEndpoints: [process.env.ENTERPRISE_RPC_URL], // Stable 提供的网关 URL guaranteedWaiver: { account: privateKeyToAccount("0xYOUR_WAIVER_KEY"), laneId: 0n, @@ -293,17 +293,17 @@ const gw = enterprise.guaranteedWaiver; ### `GuaranteedWaiverConfig` -扩展 [`ValidationLimits`](#validationlimits) 和 [`SignerSource`](#signersource)。它从 `GasWaiverConfig` (`signer`,然后是 `account`,然后是环境变量)中获取外部封装的免Gas密钥,并接受相同的 `maxGasLimit`、`maxDataLength` 和 `allowedTargets` 策略控制。 +扩展 [`ValidationLimits`](#validationlimits) 和 [`SignerSource`](#signersource)。它外部包装豁免密钥的方式与 `GasWaiverConfig` 完全相同(`signer`,然后是 `account`,然后是环境变量),并接受相同的 `maxGasLimit`、`maxDataLength` 和 `allowedTargets` 策略控制。 | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `signer` | `Signer?` | 作为托管签名器的白名单免Gas密钥(用于签名外部封装)。优先于 `account`。请参阅 [签名密钥和托管](#signing-keys-and-custody)。 | -| `account` | `LocalAccount?` | 作为进程内viem账户的免Gas密钥。当两者都未设置时,回退到 `STABLE_ENTERPRISE_PRIVATE_KEY`。 | +| `signer` | `Signer?` | 作为托管签名者(签署外部包装器)的白名单豁免密钥。优先于 `account`。请参阅[签名密钥和托管](#signing-keys-and-custody)。 | +| `account` | `LocalAccount?` | 作为进程内viem账户的豁免密钥。当两者都未设置时,回退到 `STABLE_ENTERPRISE_PRIVATE_KEY`。 | | `laneId` | `bigint` | 企业通道ID。必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。 | ### `send(user, tx)` / `sendBatch(user, txs)` -从 `user` 构建并签署内部 `0x3F` CustomTx,用免Gas密钥封装它,然后中继。由于Gas已免除,无需费用字段。内部二维 nonce 从网关发现,批次将从此基础开始自动排序。 +从`user`构建并签署内部`0x3F` CustomTx,用免Gas密钥包装,然后中继。由于Gas已免除,无需费用字段。内部2D nonce从网关发现,批次将从该基础自动排序。 ```ts // 单个 @@ -321,7 +321,7 @@ const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); ### `relay(signedInnerTx)` / `relayBatch(signedInnerTxs)` -对于非托管流程,用户使用 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req)(费用 `0n`,使用 `nonceKeyForLane(laneId)`)签署内部 `0x3F` CustomTx,然后只将签名的十六进制数据交给操作员。操作员使用免Gas密钥将其封装并中继。 +对于非托管流程,用户使用 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req) 签署内部 `0x3F` CustomTx(费用为 `0n`,使用 `nonceKeyForLane(laneId)`),并只将签名的十六进制数据交给操作员。操作员用豁免密钥包装并中继。 ```ts import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; @@ -329,25 +329,25 @@ import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enter const signedInner = await buildGuaranteedTx(toSigner(user), stableTestnet.id, { to, gas: 100_000n, - gasFeeCap: 0n, // 免除 + gasFeeCap: 0n, // 已豁免 gasTipCap: 0n, nonce, nonceKey: nonceKeyForLane(0n), }); -const { txHash } = await gw.relay(signedInner); // 免Gas模块封装+广播 → H_inner +const { txHash } = await gw.relay(signedInner); // 豁免包装 + 广播 → H_inner ``` ```text { txHash: "0x8f3a...2d41" } ``` -## 构建助手 +## 构建辅助函数 -用于非托管 `relay` 路径的低级签名器。每个签名器都将签名的交易作为 `Hex` 返回,不包含 nonce 获取或费用估算。第一个参数是 [`Signer`](#signing-keys-and-custody):使用 `toSigner(account)` 封装一个 viem 账户,或者传入一个托管签名器,例如 `awsKmsSigner`。 +用于非托管 `relay` 路径的低级签名者。每个签名者都以 `Hex` 形式返回一个已签名交易,不进行 nonce 获取或费用估算。第一个参数是一个 [`Signer`](#signing-keys-and-custody):用 `toSigner(account)` 包装一个 viem 账户,或者传递一个托管签名者(例如 `awsKmsSigner`)。 ### `buildWaiverInnerTx(signer, chainId, req)` -使用预设的豁免条件签名一个可豁免的 InnerTx:`gasPrice: 0`、遗留类型和给定的 `chainId`。`req` 是一个 [`WaiverInnerTx`](#waiverinnertx) 和一个必需的 `nonce`。 +使用预设的免Gas规则签名豁免版内部交易:`gasPrice: 0`、旧版类型和给定的 `chainId`。`req` 是 [`WaiverInnerTx`](#waiverinnertx) 加上一个必需的 `nonce`。 ```ts const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to, data, gas: 150_000n, nonce }); @@ -355,15 +355,15 @@ const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to, ### `buildGuaranteedTx(signer, chainId, req)` -构建并签署一个 GuaranteedTx (`0x3F` CustomTx)。`req` 是一个 [`GuaranteedTxRequest`](#guaranteedtxrequest) 加上一个必需的 `nonce` 和 `nonceKey`。 +构建并签名一个 GuaranteedTx (`0x3F` CustomTx)。`req` 是一个 [`GuaranteedTxRequest`](#guaranteedtxrequest) 加上一个必需的 `nonce` 和 `nonceKey`。 ### `buildGuaranteedWaiverTx(...)` -将预签名的内部交易封装到外部的 `0x3F` 免Gas自定义交易中。内部由 `guaranteedWaiver.relay` 使用;为高级流程导出。 +将预签名的内部交易包装到外部 `0x3F` 免Gas自定义交易中。供 `guaranteedWaiver.relay` 内部使用;为高级流程导出。 ### `nonceKeyForLane(laneId)` -返回用于 `buildGuaranteedTx` 的通道ID的企业级 `nonceKey`。 +返回 `laneId` 对应的企业 `nonceKey`,供 `buildGuaranteedTx` 使用。 ```ts import { nonceKeyForLane } from "@stablechain/enterprise"; @@ -375,16 +375,16 @@ const nonceKey = nonceKeyForLane(0n); ### `SignerSource` -免Gas模块 (`gasWaiver`, `guaranteedWaiver`) 接受的签名密钥字段。按顺序解析:`signer`,然后是 `account`,然后是客户端的顶级 [`signer`](#stableenterpriseconfig),然后是 `STABLE_ENTERPRISE_PRIVATE_KEY` 环境变量。请参阅 [签名密钥和托管](#signing-keys-and-custody)。 +免Gas模块(`gasWaiver`、`guaranteedWaiver`)接受的签名密钥字段。按顺序解析:`signer`,然后是 `account`,然后是客户端的顶级 [`signer`](#stableenterpriseconfig),然后是 `STABLE_ENTERPRISE_PRIVATE_KEY` 环境变量。请参阅[签名密钥和 custod](#signing-keys-and-custody)。 | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `signer` | `Signer?` | 托管级签名器(AWS KMS、HSM 或 `privateKeySigner`)。优先于 `account`。 | -| `account` | `LocalAccount?` | 进程内viem账户,通过 `toSigner` 转换为 `Signer`。 | +| `signer` | `Signer?` | 托管级签名者(AWS KMS、HSM 或 `privateKeySigner`)。优先于 `account`。 | +| `account` | `LocalAccount?` | 进程内viem账户,通过 `toSigner` 适配为 `Signer`。 | ### `Signer` -一个可插拔的签名器,SDK通过它签署一个32字节的摘要,因此密钥永远不会离开托管后端。使用 `awsKmsSigner`、`toSigner`、`privateKeySigner` 或 `envSigner` 构造一个。 +一个可插拔的签名器,SDK 通过它对 32 字节的摘要进行签名,因此密钥永远不会离开托管后端。可以使用 `awsKmsSigner`、`toSigner`、`privateKeySigner` 或 `envSigner` 来构造一个签名器。 ```ts interface Signer { @@ -393,74 +393,74 @@ interface Signer { } ``` -| **助手** | **导入** | **描述** | +| **辅助函数** | **导入** | **描述** | | :--- | :--- | :--- | -| `awsKmsSigner({ keyId, client? })` | `@stablechain/enterprise/aws-kms` | 由AWS KMS `ECC_SECG_P256K1` 密钥支持的签名器。返回 `Promise`。 | -| `toSigner(account)` | `@stablechain/enterprise` | 将viem `LocalAccount` 适配为 `Signer`。 | -| `privateKeySigner(key)` | `@stablechain/enterprise` | 封装了进程中持有的原始私钥的签名器。 | -| `envSigner(varName?)` | `@stablechain/enterprise` | 从 `STABLE_ENTERPRISE_PRIVATE_KEY`(或 `varName`)读取密钥的签名器。 | +| `awsKmsSigner({ keyId, client? })` | `@stablechain/enterprise/aws-kms` | 由 AWS KMS `ECC_SECG_P256K1` 密钥支持的签名者。返回 `Promise`。 | +| `toSigner(account)` | `@stablechain/enterprise` | 将 viem `LocalAccount` 适配为 `Signer`。 | +| `privateKeySigner(key)` | `@stablechain/enterprise` | 包装进程中持有的原始私钥的签名者。 | +| `envSigner(varName?)` | `@stablechain/enterprise` | 从 `STABLE_ENTERPRISE_PRIVATE_KEY`(或 `varName`)读取密钥的签名者。 | ### `WaiverInnerTx` -InnerTx中每个调用都不同的字段。 +每次调用都会变化的 InnerTx 字段。 | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | -| `to` | `Address` | | 目标地址:ERC-20转账的代币合约,原生代币的接收方。 | -| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | Gas限制。因为 `gasPrice` 是0,所以慷慨的限制是免费的。 | +| `to` | `Address` | | 目标地址:用于ERC-20转账的代币合约,用于原生代币的接收方。 | +| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | Gas限制。由于 `gasPrice` 为 0,高限制也是免费的。 | | `data` | `Hex?` | `"0x"` | 调用数据。 | -| `value` | `bigint?` | `0n` | 发送的原生币数量。 | +| `value` | `bigint?` | `0n` | 发送的原生价值。 | ### `GuaranteedTxRequest` | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | | `to` | `Address?` | | 目标地址。 | -| `gas` | `bigint` | | Gas限制。必填项。 | -| `gasFeeCap` | `bigint` | | `maxFeePerGas`。必填项。 | -| `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`。必填项。 | +| `gas` | `bigint` | | Gas限制。必填。 | +| `gasFeeCap` | `bigint` | | `maxFeePerGas`。必填。 | +| `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`。必填。 | | `data` | `Hex?` | `"0x"` | 调用数据。 | -| `value` | `bigint?` | `0n` | 发送的原生币数量。 | +| `value` | `bigint?` | `0n` | 发送的原生价值。 | ### `GuaranteedWaiverTxRequest` -费用字段始终为0,因此此处省略。 +费用字段始终为 0,因此此处省略。 | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | | `to` | `Address` | | 目标地址。 | -| `gas` | `bigint?` | 共享的内部gas默认值 | Gas限制。 | +| `gas` | `bigint?` | 共享内部Gas默认值 | Gas限制。 | | `data` | `Hex?` | `"0x"` | 调用数据。 | -| `value` | `bigint?` | `0n` | 发送的原生币数量。允许豁免价值转账。 | +| `value` | `bigint?` | `0n` | 发送的原生价值。免Gas允许价值转移。 | ### `ValidationLimits` -应用于 `gasWaiver` 和 `guaranteedWaiver` 的每个 InnerTx 的合作伙伴策略。 +`gasWaiver` 和 `guaranteedWaiver` 对每个 InnerTx 应用的按合作伙伴策略。 | **字段** | **类型** | **默认值** | **描述** | | :--- | :--- | :--- | :--- | -| `maxGasLimit` | `bigint?` | `10_000_000n` | InnerTx的最大Gas限制。超过此限制将导致 `GAS_LIMIT_EXCEEDED` 错误。 | -| `maxDataLength` | `number?` | `131_072` (128 KB) | 调用数据的最大字节大小。超过此限制将导致 `DATA_TOO_LARGE` 错误。 | -| `allowedTargets` | `AllowedTarget[]?` | | 免Gas模块可能赞助的合约和方法的白名单。设置后,列表之外的目标将导致 `TARGET_NOT_ALLOWED` 错误。 | +| `maxGasLimit` | `bigint?` | `10_000_000n` | InnerTx 的最大 Gas 限制。超过此值将导致 `GAS_LIMIT_EXCEEDED` 错误。 | +| `maxDataLength` | `number?` | `131_072` (128 KB) | 调用数据的最大大小(字节)。超过此值将导致 `DATA_TOO_LARGE` 错误。 | +| `allowedTargets` | `AllowedTarget[]?` | | 免Gas方可能赞助的合约和方法的白名单。设置后,不在列表中的目标将导致 `TARGET_NOT_ALLOWED` 错误。 | ### `AllowedTarget` | **字段** | **类型** | **描述** | | :--- | :--- | :--- | -| `address` | `Address \| "*"` | InnerTx可能调用的合约,或 `"*"` 以匹配任何合约。 | -| `selectors` | `Hex[]?` | 允许的4字节方法选择器(例如ERC-20 `transfer` 的 `"0xa9059cbb"`)。省略或留空以允许 `address` 上的任何方法。 | +| `address` | `Address \| "*"` | InnerTx 可以调用的合约,或 `"*"` 表示匹配任何合约。 | +| `selectors` | `Hex[]?` | 允许的 4 字节方法选择器(例如,ERC-20 `transfer` 的 `"0xa9059cbb"`)。省略或留空以允许 `address` 上的任何方法。 | ### `RelayResult` ```ts interface RelayResult { - txHash: Hash; // 免Gas是H_inner,独立保证区块是GuaranteedTx哈希 + txHash: Hash; // 免Gas是 H_inner,独立保证区块是 GuaranteedTx hash } ``` ### `BatchResultItem` -批处理中每个输入的一个条目,按输入顺序排列。批处理不会抛出错误,而是显示每个项目的处理结果。 +批次中每个输入一个条目,按输入顺序排列。批次会报告每个项目的结g果,而不是抛出异常。 | **字段** | **类型** | **描述** | | :--- | :--- | :--- | @@ -471,13 +471,13 @@ interface RelayResult { ## 错误 -单个事务方法(`send`、`relay`)在拒绝时抛出异常。批量方法则在 [`BatchResultItem.error`](#batchresultitem) 中报告每项失败。所有错误类都继承自 `StableEnterpriseError`。 +单个交易方法 (`send`, `relay`) 在拒绝时抛出异常。批量方法在 [`BatchResultItem.error`](#batchresultitem) 中报告每个项目的失败。所有错误类都扩展自 `StableEnterpriseError`。 | **类** | **抛出条件** | **有用字段** | | :--- | :--- | :--- | | `StableEnterpriseError` | 所有SDK错误的基础类。 | `message` | | `StableEnterpriseRelayError` | 交易在RPC或中继层被拒绝。 | `code` | -| `WaiverValidationError` | InnerTx在广播前未能通过策略检查(Gas、数据大小或目标白名单)。 | `code` | +| `WaiverValidationError` | InnerTx在广播前未能通过策略检查(gas、数据大小或目标白名单)。 | `code` | ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -486,7 +486,7 @@ try { await gw.send(user, { to: token, data }); } catch (err) { if (err instanceof StableEnterpriseRelayError && err.code === "TARGET_NOT_ALLOWED") { - // InnerTx目标不在配置的白名单中 + // InnerTx 目标不在配置的白名单中 } throw err; } @@ -498,33 +498,33 @@ StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not ### `ErrorCode` -抛出错误或 `BatchResultItem.error` 上的 `code` 是以下之一: +抛出错误或 `BatchResultItem.error` 上的 `code` 之一是: | **代码** | **含义** | | :--- | :--- | -| `UNKNOWN_ERROR` | 当没有特定代码时的回退。 | -| `BROADCAST_FAILED` | 广播在RPC层被拒绝,或网关中继失败。 | +| `UNKNOWN_ERROR` | 没有特定代码时的备用代码。 | +| `BROADCAST_FAILED` | 在RPC层广播被拒绝,或网关中继失败。 | | `INVALID_TRANSACTION` | InnerTx解码或解析失败。 | | `INVALID_SIGNATURE` | 签名验证失败。 | -| `UNSUPPORTED_TX_TYPE` | InnerTx类型不是遗留、eip2930或eip1559。 | +| `UNSUPPORTED_TX_TYPE` | InnerTx类型不是legacy、eip2930或eip1559。 | | `WRONG_CHAIN_ID` | InnerTx `chainId` 缺失或与目标链不匹配。 | -| `NON_ZERO_GAS_PRICE` | InnerTx带有非零Gas价格(豁免必须为零)。 | -| `GAS_LIMIT_EXCEEDED` | InnerTx Gas限制超过 `maxGasLimit`。 | -| `DATA_TOO_LARGE` | InnerTx调用数据超过 `maxDataLength`。 | -| `TARGET_NOT_ALLOWED` | InnerTx目标不在 `allowedTargets` 中。 | -| `GATEWAY_UNAUTHORIZED` | 企业RPC网关拒绝了API密钥(缺失、无效或过期)。 | -| `QUOTA_EXCEEDED` | 企业RPC网关Gas配额已用尽。 | +| `NON_ZERO_GAS_PRICE` | InnerTx带有非零gas price(免Gas时必须为零)。 | +| `GAS_LIMIT_EXCEEDED` | InnerTx 的 Gas 限制超过 `maxGasLimit`。 | +| `DATA_TOO_LARGE` | InnerTx 调用数据超过 `maxDataLength`。 | +| `TARGET_NOT_ALLOWED` | InnerTx 目标不在 `allowedTargets` 中。 | +| `GATEWAY_UNAUTHORIZED` | 企业级RPC网关拒绝了API密钥(缺失、无效或过期)。 | +| `QUOTA_EXCEEDED` | 企业级RPC网关Gas配额已用尽。 | -## 常数 +## 常量 | **常数** | **类型** | **描述** | | :--- | :--- | :--- | -| `DEFAULT_INNER_GAS` | `bigint` | 当 `gas` 省略时,InnerTx的默认Gas限制 (`150_000n`)。 | +| `DEFAULT_INNER_GAS` | `bigint` | 当省略 `gas` 时,默认的 InnerTx Gas 限制 (`150_000n`)。 | | `ENTERPRISE_FLAG` | `bigint` | 设置在通道 `nonceKey` 上的企业位。 | -| `ENTERPRISE_MASK` | `bigint` | 通道ID的上限:`laneId` 必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。 | +| `ENTERPRISE_MASK` | `bigint` | 通道 ID 的上限:`laneId` 必须在 `[0, ENTERPRISE_MASK - 1]` 范围内。 | -## 下一步建议 +## 接下来推荐 -- [**Stable企业级SDK**](/cn/explanation/enterprise-sdk):了解这些轨道的含义以及何时使用它们。 -- [**免Gas协议**](/cn/reference/gas-waiver-api):交易格式、标记路由和治理控制。 -- [**保证区块空间**](/cn/explanation/guaranteed-blockspace):Stable如何为企业级工作负载预留区块容量。 +- [**Stable 企业级 SDK**](/cn/explanation/enterprise-sdk):详细了解这些机制及其使用场景。 +- [**免Gas协议**](/cn/reference/gas-waiver-api):交易格式、标记路由和政fu控制。 +- [**保证区块空间**](/cn/explanation/guaranteed-blockspace):Stable 如何为企业工作负载预留区块容量。 diff --git a/docs/pages/ko/reference/enterprise-sdk.mdx b/docs/pages/ko/reference/enterprise-sdk.mdx index 9ee89d1..c0be8c3 100644 --- a/docs/pages/ko/reference/enterprise-sdk.mdx +++ b/docs/pages/ko/reference/enterprise-sdk.mdx @@ -1,21 +1,21 @@ --- source_path: reference/enterprise-sdk.mdx -source_sha: c89457ca29556b5a94b9cb4562bd9d210d38701d +source_sha: d0bc44dc34b19b1a7f7cadeda2ceaa68d296220a title: "엔터프라이즈 SDK 레퍼런스" -description: "@stablechain/enterprise에 대한 완벽한 레퍼런스: createStableEnterprise, 가스 면제 및 보장된 블록스페이스 모듈, 빌드 헬퍼, 오류 클래스." +description: "@stablechain/enterprise에 대한 완벽한 레퍼런스: createStableEnterprise, 가스 면제 및 보장된 블록스페이스 모듈, 빌드 헬퍼, 그리고 오류 클래스." diataxis: "reference" --- # 엔터프라이즈 SDK 레퍼런스 -`@stablechain/enterprise`의 전체 표면입니다. 여기에는 [`createStableEnterprise`](#createstableenterpriseconfig)를 통한 클라이언트, 세 가지 기능([가스 면제 릴레이](#relay-with-gas-waiver), [보장된 블록스페이스](#guaranteed-blockspace), [보장된 릴레이 트랜잭션](#guaranteed-relay-transactions)), 저수준 빌드 헬퍼, 공유 결과 및 오류 유형이 포함됩니다. 이러한 레일이 무엇인지는 [Stable Enterprise SDK](/ko/explanation/enterprise-sdk), [Gas waiver](/ko/explanation/gas-waiver), [Guaranteed blockspace](/ko/explanation/guaranteed-blockspace)를 참조하세요. +`@stablechain/enterprise`의 완전한 표면입니다. 여기에는 [`createStableEnterprise`](#createstableenterpriseconfig)로부터의 클라이언트, 세 가지 기능([가스 면제 릴레이](#relay-with-gas-waiver), [보장된 블록스페이스](#guaranteed-blockspace), [보장된 릴레이 트랜잭션](#guaranteed-relay-transactions)), 하위 수준 빌드 헬퍼, 그리고 공유 결과 및 오류 유형이 포함됩니다. 이러한 레일이 무엇인지는 [Stable 엔터프라이즈 SDK](/ko/explanation/enterprise-sdk), [가스 면제](/ko/explanation/gas-waiver), 그리고 [보장된 블록스페이스](/ko/explanation/guaranteed-blockspace)를 참조하십시오. :::note -엔터프라이즈 SDK는 현재 Stable Testnet에서만 사용할 수 있으며, 액세스는 요청 시 제공됩니다. 통합하려면 [Stable에 문의](https://discord.gg/stablexyz)하여 거버넌스에 등록된 면제 키와 엔터프라이즈 RPC 게이트웨이 API 키를 받으세요. +엔터프라이즈 SDK는 현재 Stable 테스트넷에서만 사용할 수 있으며, 액세스는 요청 시에 제공됩니다. 통합하려면 [Stable에 문의](https://discord.gg/stablexyz)하여 거버넌스에 등록된 면제 키와 엔터프라이즈 RPC 게이트웨이 API 키를 받으세요. ::: :::warning -이것은 개인 키로 서명하는 서버 측 라이브러리입니다. 브라우저에서 실행하지 마세요. 면제 키와 엔터프라이즈 RPC 게이트웨이 URL을 백엔드에 보관하세요. +이것은 개인 키로 서명하는 서버 측 라이브러리입니다. 브라우저에서 절대 실행하지 마세요. 면제 키와 엔터프라이즈 RPC 게이트웨이 URL은 백엔드에 보관하십시오. ::: ## 설치 @@ -28,11 +28,11 @@ npm install @stablechain/enterprise viem added 2 packages, audited 3 packages in 2s ``` -`viem >= 2.0.0`은 피어 종속성입니다. 패키지는 `viem/chains`에서 `stable` 및 `stableTestnet`을 재Export하므로 별도로 Import할 필요가 없습니다. +`viem >= 2.0.0`은 피어 종속성입니다. 이 패키지는 `viem/chains`에서 `stable` 및 `stableTestnet`을 다시 내보내므로 별도로 가져올 필요가 없습니다. ## `createStableEnterprise(config)` -`StableEnterpriseClient`를 생성합니다. 각 모듈은 구성한 경우에만 존재하므로 사용 전에 null 검사를 수행합니다. +`StableEnterpriseClient`를 생성합니다. 각 모듈은 구성할 때만 존재하므로 사용하기 전에 널 체크를 하세요. ```ts import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; @@ -50,22 +50,22 @@ StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver ### `StableEnterpriseConfig` -| **필드** | **타입** | **기본값** | **설명** | +| **필드** | **유형** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `chain` | `StableChain` | | 대상 체인입니다. `stable` 또는 `stableTestnet`을 전달합니다(패키지에서 재export됨). 필수. | -| `rpcEndpoints` | `string[]?` | 체인의 내장 RPC | 실패 시 순서대로 시도하는 하나 이상의 Stable RPC 엔드포인트입니다. 개인 엔드포인트를 가리키려면 재정의만 수행합니다. | -| `enterpriseRpcEndpoints` | `string[]?` | | 실패 시 순서대로 시도하는 하나 이상의 엔터프라이즈 RPC 게이트웨이 엔드포인트입니다. `guaranteedBlock` 및 `guaranteedWaiver`에 필요합니다. | -| `batchSizeLimit` | `number?` | `100` | 일괄 RPC 호출당 최대 트랜잭션 수입니다. | -| `signer` | `Signer?` | | 모듈 자체 키가 없을 때 면제 모듈(`gasWaiver`, `guaranteedWaiver`)에 대한 기본 서명자입니다. 단일 커스터디 백엔드에서 두 모듈을 모두 구동하기 위해 한 번 설정합니다. [서명 키 및 커스터디](#signing-keys-and-custody)를 참조하세요. | +| `chain` | `StableChain` | | 대상 체인. `stable` 또는 `stableTestnet`을 전달합니다(패키지에서 다시 내보냄). 필수. | +| `rpcEndpoints` | `string[]?` | 체인의 내장 RPC | 하나 이상의 Stable RPC 엔드포인트이며, 실패 시 순서대로 시도됩니다. 개인 엔드포인트를 가리키도록만 오버라이드합니다. | +| `enterpriseRpcEndpoints` | `string[]?` | | 하나 이상의 엔터프라이즈 RPC 게이트웨이 엔드포인트이며, 실패 시 순서대로 시도됩니다. `guaranteedBlock` 및 `guaranteedWaiver`에 필요합니다. | +| `batchSizeLimit` | `number?` | `100` | 배치된 RPC 호출당 최대 트랜잭션 수. | +| `signer` | `Signer?` | | 모듈 자체에 키가 없을 때 면제 모듈(`gasWaiver`, `guaranteedWaiver`)의 기본 서명자입니다. 단일 커스터디 백엔드에서 둘 다 구동하려면 한 번 설정합니다. [서명 키 및 커스터디](#signing-keys-and-custody)를 참조하십시오. | | `gasWaiver` | `GasWaiverConfig?` | | [가스 면제 릴레이](#relay-with-gas-waiver)를 활성화합니다. | | `guaranteedBlock` | `GuaranteedBlockConfig?` | | [보장된 블록스페이스](#guaranteed-blockspace)를 활성화합니다. | | `guaranteedWaiver` | `GuaranteedWaiverConfig?` | | [보장된 릴레이 트랜잭션](#guaranteed-relay-transactions)을 활성화합니다. | ### 서명 키 및 커스터디 -면제 키(`gasWaiver` 및 `guaranteedWaiver`)를 보유하는 모듈은 모듈 자체의 `signer`, 그리고 `account` (인 프로세스 viem 키), 그리고 클라이언트 구성의 최상위 [`signer`](#stableenterpriseconfig), 그리고 `STABLE_ENTERPRISE_PRIVATE_KEY` 환경 변수 순으로 키를 해결합니다. 단일 커스터디 백엔드에서 두 면제 모듈을 모두 구동하기 위해 최상위 `signer`를 한 번 설정합니다. `guaranteedBlock`은 자체 자금 조달된 `account`로 서명합니다. +면제 키를 보유하는 모듈(`gasWaiver` 및 `guaranteedWaiver`)은 순서대로 이를 해결합니다: 모듈 자체의 `signer`, 그 다음 해당 `account`(인 프로세스 viem 키), 그 다음 클라이언트 구성의 최상위 [`signer`](#stableenterpriseconfig), 그 다음 `STABLE_ENTERPRISE_PRIVATE_KEY` 환경 변수. 단일 커스터디 백엔드에서 두 면제 모듈을 모두 구동하려면 최상위 `signer`를 한 번 설정합니다. `guaranteedBlock`은 자체 자금 조달된 `account`로 서명합니다. -`Signer`는 32바이트 다이제스트에 서명하므로 키는 커스터디 백엔드를 떠나지 않습니다. AWS KMS의 경우 `awsKmsSigner`를 사용하고, viem 계정을 조정하려면 `toSigner(account)`를 사용하거나, 인 프로세스 키의 경우 `privateKeySigner(key)` / `envSigner()`를 사용합니다. 모듈의 `send` / `sendBatch`에 전달되는 호출당 발신자도 viem 계정 또는 `Signer`일 수 있으므로 KMS/HSM 키는 `relay`로 떨어지지 않고 내부 트랜잭션에 서명할 수 있습니다. +`Signer`는 32바이트 다이제스트에 서명하므로, 키는 커스터디 백엔드를 떠나지 않습니다. AWS KMS의 경우 `awsKmsSigner`를 사용하고, viem 계정을 적용하기 위해 `toSigner(account)`를 사용하거나, 인 프로세스 키의 경우 `privateKeySigner(key)` / `envSigner()`를 사용합니다. 모듈의 `send` / `sendBatch`에 전달되는 호출당 발신자도 viem 계정 또는 `Signer`일 수 있으므로, KMS/HSM 키는 `relay`로 떨어뜨리지 않고 내부 트랜잭션에 서명할 수 있습니다. ```bash npm install @aws-sdk/client-kms @@ -75,16 +75,16 @@ npm install @aws-sdk/client-kms import { createStableEnterprise, stableTestnet } from "@stablechain/enterprise"; import { awsKmsSigner } from "@stablechain/enterprise/aws-kms"; -// KMS 키는 ECC_SECG_P256K1(secp256k1)이어야 합니다. SDK는 이를 기반으로 주소를 파생합니다. -const signer = await awsKmsSigner({ keyId: process.env.KMS_KEY_ID }); +// KMS 키는 ECC_SECG_P256K1(secp256k1)이어야 합니다. SDK는 그로부터 주소를 파생합니다. +const signer = await awsKmsSigner({ keyId: process.env.AWS_KMS_KEY_ID }); const enterprise = createStableEnterprise({ chain: stableTestnet, - gasWaiver: { signer }, // `account` 대신 커스터디 등급 면제 키 + gasWaiver: { signer }, // 'account' 대신 커스터디 등급의 면제 키 }); ``` -`awsKmsSigner`는 `@stablechain/enterprise/aws-kms` 하위 경로에 포함되어 `@aws-sdk/client-kms`가 코어 설치에서 제외된 선택적 피어 종속성으로 유지됩니다. +`awsKmsSigner`는 `@stablechain/enterprise/aws-kms` 하위 경로에서 제공되므로 `@aws-sdk/client-kms`는 코어 설치에서 제외되는 선택적 피어 종속성으로 유지됩니다. ### `StableEnterpriseClient` @@ -98,9 +98,9 @@ interface StableEnterpriseClient { ## 가스 면제 릴레이 -`gasWaiver` 모듈은 가스 면제 트랜잭션을 릴레이합니다. 화이트리스트에 있는 면제 계정은 사용자의 제로 가스 트랜잭션(InnerTx)을 WaiverTx로 래핑하여 브로드캐스트합니다. 사용자는 USDT0가 필요 없습니다. 모든 메서드는 래퍼 해시가 아닌 InnerTx 해시인 `H_inner`를 반환합니다. +`gasWaiver` 모듈은 가스 면제 트랜잭션을 릴레이합니다. 화이트리스트된 면제 계정은 사용자의 제로 가스 트랜잭션(InnerTx)을 WaiverTx로 래핑하고 이를 브로드캐스트합니다. 사용자는 USDT0가 필요하지 않습니다. 모든 메서드는 래퍼 해시가 아닌 InnerTx 해시인 `H_inner`를 반환합니다. -구성에서 `gasWaiver`를 사용하여 활성화합니다. +구성에서 `gasWaiver`로 활성화합니다. ```ts const enterprise = createStableEnterprise({ @@ -120,17 +120,17 @@ const gw = enterprise.gasWaiver; [`ValidationLimits`](#validationlimits) 및 [`SignerSource`](#signersource)를 확장합니다. -| **필드** | **타입** | **설명** | +| **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `signer` | `Signer?` | 거버넌스에 등록된 화이트리스트 면제 키(커스터디 서명자: AWS KMS, HSM). [서명 키 및 커스터디](#signing-keys-and-custody)를 참조하세요. `account`보다 우선합니다. | -| `account` | `LocalAccount?` | 인 프로세스 viem 계정으로 사용되는 면제 키입니다. 둘 다 설정되지 않은 경우 `STABLE_ENTERPRISE_PRIVATE_KEY`로 대체됩니다. | -| `maxGasLimit` | `bigint?` | `ValidationLimits`에서 상속됩니다. | -| `maxDataLength` | `number?` | `ValidationLimits`에서 상속됩니다. | -| `allowedTargets` | `AllowedTarget[]?` | `ValidationLimits`에서 상속됩니다. | +| `signer` | `Signer?` | 커스터디 서명자(AWS KMS, HSM)로 화이트리스트에 등록된 거버넌스 등록 면제 키. [서명 키 및 커스터디](#signing-keys-and-custody)를 참조하십시오. `account`보다 우선합니다. | +| `account` | `LocalAccount?` | 인 프로세스 viem 계정으로서의 면제 키. 둘 다 설정되지 않은 경우 `STABLE_ENTERPRISE_PRIVATE_KEY`로 폴백됩니다. | +| `maxGasLimit` | `bigint?` | `ValidationLimits`에서 상속됨. | +| `maxDataLength` | `number?` | `ValidationLimits`에서 상속됨. | +| `allowedTargets` | `AllowedTarget[]?` | `ValidationLimits`에서 상속됨. | ### `send(account, tx)` -`account`에서 하나의 InnerTx를 한 번의 호출로 빌드, 서명 및 릴레이합니다. `gasPrice: 0`, 레거시 유형, `chainId`, 보류 중인 nonce는 자동으로 처리됩니다. 거부 시 `StableEnterpriseRelayError`를 발생시킵니다. +`account`로부터 하나의 InnerTx를 한 번의 호출로 빌드, 서명 및 릴레이합니다. `gasPrice: 0`, 레거시 유형, `chainId`, 그리고 보류 중인 nonce는 자동으로 처리됩니다. 거부 시 `StableEnterpriseRelayError`를 throw 합니다. ```ts const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); @@ -140,11 +140,11 @@ const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n }); { txHash: "0x8f3a...2d41" } ``` -`tx` 인수는 선택적 `nonce`가 추가된 [`WaiverInnerTx`](#waiverinnertx)입니다. [`RelayResult`](#relayresult)를 반환합니다. +`tx` 인수는 [`WaiverInnerTx`](#waiverinnertx)와 선택적 `nonce`입니다. [`RelayResult`](#relayresult)를 반환합니다. ### `sendBatch(account, txs)` -하나의 `account`에서 여러 InnerTx를 빌드, 서명 및 릴레이합니다. Nonce는 계정의 보류 중인 nonce에서 자동으로 시퀀싱됩니다. 입력당 하나의 결과를 순서대로 반환합니다. +하나의 `account`에서 여러 InnerTx를 빌드, 서명 및 릴레이합니다. nonce는 계정의 보류 중인 nonce를 기준으로 자동 시퀀싱됩니다. 입력 순서대로 각 입력에 대한 결과를 하나씩 반환합니다. ```ts const results = await gw.sendBatch(user, [ @@ -157,11 +157,11 @@ const results = await gw.sendBatch(user, [ [ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: true, txHash: "0x..." } ] ``` -`txs`는 [`WaiverInnerTx`](#waiverinnertx)의 읽기 전용 배열입니다. [`BatchResultItem[]`](#batchresultitem)을 반환합니다. +`txs`는 [`WaiverInnerTx`](#waiverinnertx)의 읽기 전용 배열입니다. [`BatchResultItem[]`](#batchresultitem)를 반환합니다. ### `relay(signedInnerTxHex)` -사전 서명된 제로 가스 InnerTx를 릴레이합니다. 사용자가 자신의 환경에서 서명하고 서명된 헥스만 전달하는 비관리형 흐름에 사용하므로 면제 운영자는 사용자의 키를 볼 수 없습니다. [`buildWaiverInnerTx`](#buildwaiverinnertxsigner-chainid-req)를 사용하여 빌드합니다. 거부 시 오류가 발생합니다. +미리 서명된 제로 가스 InnerTx를 릴레이합니다. 사용자가 자신의 환경에서 서명하고 서명된 헥스만 전달하는 비관리형 흐름에 사용하므로, 면제 운영자는 사용자의 키를 보지 않습니다. [`buildWaiverInnerTx`](#buildwaiverinnertxsigner-chainid-req)로 빌드합니다. 거부 시 예외를 발생시킵니다. ```ts import { buildWaiverInnerTx, toSigner } from "@stablechain/enterprise"; @@ -176,7 +176,7 @@ const { txHash } = await gw.relay(signed); ### `relayBatch(signedInnerTxHexes)` -사전 서명된 InnerTx의 배치를 릴레이합니다. 입력당 하나의 [`BatchResultItem`](#batchresultitem)을 순서대로 반환합니다. +미리 서명된 InnerTx의 배치를 릴레이합니다. 입력 순서대로 각 입력에 대한 [`BatchResultItem`](#batchresultitem)을 하나씩 반환합니다. ```ts const results = await gw.relayBatch([signed0, signed1]); @@ -188,9 +188,9 @@ const results = await gw.relayBatch([signed0, signed1]); ## 보장된 블록스페이스 -`guaranteedBlock` 모듈은 엔터프라이즈 RPC 게이트웨이를 통해 GuaranteedTx(유형 `0x3F` CustomTx)를 릴레이하여 예약된 엔터프라이즈 레인 블록스페이스에 착륙시킵니다. 가스 면제와 달리 서명자는 자체 가스를 지불하며 자금이 있어야 합니다. 각 트랜잭션은 엔터프라이즈 레인에 키가 지정된 2D nonce를 가지며, 브로드캐스팅은 게이트웨이를 통해서만 이루어집니다. +`guaranteedBlock` 모듈은 엔터프라이즈 RPC 게이트웨이를 통해 GuaranteedTx(유형 `0x3F` CustomTx)를 릴레이하여 예약된 엔터프라이즈 레인 블록스페이스에 도달하도록 합니다. 가스 면제와 달리, 서명자는 자신의 가스를 지불하며 자금이 있어야 합니다. 각 트랜잭션은 엔터프라이즈 레인에 키가 지정된 2D 논스를 포함하며, 브로드캐스팅은 게이트웨이를 통해서만 이루어집니다. -`guaranteedBlock`과 `enterpriseRpcEndpoints`를 사용하여 활성화합니다. +`guaranteedBlock`과 `enterpriseRpcEndpoints`로 활성화합니다. ```ts const enterprise = createStableEnterprise({ @@ -207,14 +207,14 @@ const gb = enterprise.guaranteedBlock; ### `GuaranteedBlockConfig` -| **필드** | **타입** | **설명** | +| **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `account` | `LocalAccount` | 각 GuaranteedTx에 서명하고 가스를 지불하는 자금 조달된 계정입니다. | -| `laneId` | `bigint` | 엔터프라이즈 레인 ID입니다. `[0, ENTERPRISE_MASK - 1]` 범위에 있어야 합니다. 유효하지 않은 ID는 즉시 거부됩니다. | +| `account` | `LocalAccount` | 각 GuaranteedTx에 서명하고 가스를 지불하는 자금이 있는 계정. | +| `laneId` | `bigint` | 엔터프라이즈 레인 ID. `[0, ENTERPRISE_MASK - 1]` 범위 내에 있어야 합니다. 유효하지 않은 ID는 즉시 거부됩니다. | ### `send(account, tx)` -하나의 GuaranteedTx를 빌드, 서명 및 릴레이합니다. 서명자가 가스를 지불하므로 1559 수수료 필드가 필요합니다. `chainId`, 엔터프라이즈 `nonceKey`, 그리고 2D nonce(게이트웨이에서 검색됨)는 자동으로 처리됩니다. +하나의 GuaranteedTx를 빌드, 서명 및 릴레이합니다. 서명자가 가스를 지불하므로 1559 수수료 필드가 필요합니다. `chainId`, 엔터프라이즈 `nonceKey`, 그리고 게이트웨이에서 검색된 2D nonce는 자동으로 처리됩니다. ```ts const gasPrice = await publicClient.getGasPrice(); @@ -231,11 +231,11 @@ const { txHash } = await gb.send(signer, { { txHash: "0xabcd...7890" } ``` -`tx` 인수는 선택적 `nonce`가 추가된 [`GuaranteedTxRequest`](#guaranteedtxrequest)입니다. [`RelayResult`](#relayresult)를 반환합니다. +`tx` 인수는 [`GuaranteedTxRequest`](#guaranteedtxrequest)에 선택적 `nonce`가 추가된 것입니다. [`RelayResult`](#relayresult)를 반환합니다. ### `sendBatch(account, txs)` -여러 GuaranteedTx를 빌드, 서명 및 릴레이합니다. Nonce는 검색된 베이스에서 자동으로 시퀀싱됩니다. 실패하면 후속 항목이 중단됩니다. +여러 GuaranteedTx를 빌드, 서명 및 릴레이합니다. 논스는 검색된 기본값에서 자동으로 시퀀싱됩니다. 실패는 후속 작업에 영향을 미칩니다. ```ts const results = await gb.sendBatch(signer, [ @@ -248,11 +248,11 @@ const results = await gb.sendBatch(signer, [ [ { index: 0, success: true, txHash: "0x..." }, { index: 1, success: true, txHash: "0x..." } ] ``` -[`BatchResultItem[]`](#batchresultitem)을 반환합니다. +[`BatchResultItem[]`](#batchresultitem)를 반환합니다. ### `relay(signedTx)` / `relayBatch(signedTxs)` -사전 서명된 GuaranteedTx 또는 해당 배치 중 하나를 릴레이합니다. [`nonceKeyForLane`](#noncekeyforlanelaneid)을 엔터프라이즈 nonce 키로 사용하여 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req)로 트랜잭션을 다른 곳에서 빌드하고 서명한 다음, 운영자에게 서명된 헥스만 전달합니다. +미리 서명된 GuaranteedTx 또는 배치로 릴레이합니다. 엔터프라이즈 nonce 키에는 [`nonceKeyForLane`](#noncekeyforlanelaneid)을 사용하여 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req)로 트랜잭션을 다른 곳에서 빌드하고 서명한 다음, 서명된 헥스만 운영자에게 전달합니다. ```ts import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; @@ -274,9 +274,9 @@ const { txHash } = await gb.relay(signed); ## 보장된 릴레이 트랜잭션 -`guaranteedWaiver` 모듈은 위 두 가지 레일을 결합합니다. 즉, 보장된 블록스페이스를 통해 라우팅되는 가스 면제 트랜잭션입니다. 내부 및 외부 트랜잭션 모두 하나의 엔터프라이즈 `nonceKey`를 공유하는 `0x3F` CustomTx이므로 `guaranteedBlock`처럼 게이트웨이를 통해 브로드캐스트됩니다. 면제는 가스를 후원하므로 사용자는 `gasWaiver`처럼 잔액이나 수수료 필드가 필요 없습니다. 모든 메서드는 `H_inner`를 반환합니다. +`guaranteedWaiver` 모듈은 위 두 가지 레일을 결합합니다: 보장된 블록스페이스를 통해 라우팅되는 가스 면제 트랜잭션. 내부 및 외부 트랜잭션 모두 하나의 엔터프라이즈 `nonceKey`를 공유하는 `0x3F` CustomTx이므로, `guaranteedBlock`처럼 게이트웨이를 통해 브로드캐스트됩니다. 면제는 가스를 지원하므로, `gasWaiver`처럼 사용자는 잔액이나 수수료 필드가 필요하지 않습니다. 모든 메서드는 `H_inner`를 반환합니다. -`guaranteedWaiver`와 `enterpriseRpcEndpoints`를 사용하여 활성화합니다. +`guaranteedWaiver`와 `enterpriseRpcEndpoints`로 활성화합니다. ```ts const enterprise = createStableEnterprise({ @@ -293,17 +293,17 @@ const gw = enterprise.guaranteedWaiver; ### `GuaranteedWaiverConfig` -[`ValidationLimits`](#validationlimits) 및 [`SignerSource`](#signersource)를 확장합니다. `GasWaiverConfig`와 똑같이 외부 래퍼 면제 키를 소싱(`signer`, `account`, 환경 변수 순)하고 동일한 `maxGasLimit`, `maxDataLength`, `allowedTargets` 정책 제어를 허용합니다. +[`ValidationLimits`](#validationlimits) 및 [`SignerSource`](#signersource)를 확장합니다. 이는 `GasWaiverConfig`와 동일하게 외부 래퍼 면제 키를 소싱하며(`signer`, 그 다음 `account`, 그 다음 env 변수), 동일한 `maxGasLimit`, `maxDataLength`, `allowedTargets` 정책 컨트롤을 허용합니다. -| **필드** | **타입** | **설명** | +| **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `signer` | `Signer?` | 커스터디 서명자로 사용되는 화이트리스트 면제 키(외부 래퍼에 서명). `account`보다 우선합니다. [서명 키 및 커스터디](#signing-keys-and-custody)를 참조하세요. | -| `account` | `LocalAccount?` | 인 프로세스 viem 계정으로 사용되는 면제 키입니다. 둘 다 설정되지 않은 경우 `STABLE_ENTERPRISE_PRIVATE_KEY`로 대체됩니다. | -| `laneId` | `bigint` | 엔터프라이즈 레인 ID입니다. `[0, ENTERPRISE_MASK - 1]` 범위에 있어야 합니다. | +| `signer` | `Signer?` | 커스터디 서명자로서의 화이트리스트된 면제 키(외부 래퍼에 서명). `account`보다 우선합니다. [서명 키 및 커스터디](#signing-keys-and-custody)를 참조하십시오. | +| `account` | `LocalAccount?` | 인 프로세스 viem 계정으로서의 면제 키. 둘 다 설정되지 않은 경우 `STABLE_ENTERPRISE_PRIVATE_KEY`로 폴백됩니다. | +| `laneId` | `bigint` | 엔터프라이즈 레인 ID. `[0, ENTERPRISE_MASK - 1]` 범위 내에 있어야 합니다. | ### `send(user, tx)` / `sendBatch(user, txs)` -`user`로부터 내부 `0x3F` CustomTx를 빌드하고 서명한 다음, 면제 키로 래핑하여 릴레이합니다. 가스가 면제되므로 수수료 필드는 필요 없습니다. 내부 2D nonce는 게이트웨이에서 검색되며, 배치는 해당 베이스에서 자동으로 시퀀싱됩니다. +`user`로부터 내부 `0x3F` CustomTx를 빌드하고 서명한 다음, 면제 키로 래핑하고 릴레이합니다. 가스가 면제되므로 수수료 필드는 필요하지 않습니다. 내부 2D 논스는 게이트웨이에서 검색되며, 배치는 해당 베이스에서 자동으로 시퀀싱됩니다. ```ts // 단일 @@ -317,11 +317,11 @@ const results = await gw.sendBatch(user, [{ to: a }, { to: b }]); { txHash: "0x8f3a...2d41" } ``` -`tx` 인수는 선택적 `nonce`가 추가된 [`GuaranteedWaiverTxRequest`](#guaranteedwaivertxrequest)입니다. `send`는 [`RelayResult`](#relayresult)를 반환하고, `sendBatch`는 [`BatchResultItem[]`](#batchresultitem)을 반환합니다. +`tx` 인수는 [`GuaranteedWaiverTxRequest`](#guaranteedwaivertxrequest)에 선택적 `nonce`가 추가된 것입니다. `send`는 [`RelayResult`](#relayresult)를 반환하고, `sendBatch`는 [`BatchResultItem[]`](#batchresultitem)를 반환합니다. ### `relay(signedInnerTx)` / `relayBatch(signedInnerTxs)` -비관리형 흐름의 경우, 사용자는 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req)(수수료 `0n`, `nonceKeyForLane(laneId)` 사용)로 내부 `0x3F` CustomTx에 서명하고, 운영자에게 서명된 헥스만 전달합니다. 운영자는 면제 키로 래핑하여 릴레이합니다. +비관리형 흐름의 경우, 사용자는 [`buildGuaranteedTx`](#buildguaranteedtxsigner-chainid-req)를 사용하여 내부 `0x3F` CustomTx에 서명하고(수수료 `0n`, `nonceKeyForLane(laneId)` 사용), 서명된 헥스만 운영자에게 전달합니다. 운영자는 이를 면제 키로 래핑하고 릴레이합니다. ```ts import { buildGuaranteedTx, nonceKeyForLane, toSigner } from "@stablechain/enterprise"; @@ -334,7 +334,7 @@ const signedInner = await buildGuaranteedTx(toSigner(user), stableTestnet.id, { nonce, nonceKey: nonceKeyForLane(0n), }); -const { txHash } = await gw.relay(signedInner); // 면제 래퍼 + 브로드캐스트 → H_inner +const { txHash } = await gw.relay(signedInner); // 면제 래핑 + 브로드캐스트 → H_inner ``` ```text @@ -343,11 +343,11 @@ const { txHash } = await gw.relay(signedInner); // 면제 래퍼 + 브로드캐 ## 빌드 헬퍼 -비관리형 `relay` 경로를 위한 저수준 서명자입니다. 각각은 논스 가져오기나 수수료 추정 없이 서명된 트랜잭션을 `Hex`로 반환합니다. 첫 번째 인수는 [`Signer`](#signing-keys-and-custody)입니다. `toSigner(account)`로 viem 계정을 래핑하거나 `awsKmsSigner`와 같은 커스터디 서명자를 전달하세요. +비관리형 `relay` 경로를 위한 하위 수준 서명자입니다. 각 서명자는 서명된 트랜잭션을 `Hex`로 반환하며, 논스 가져오기 또는 수수료 추정은 없습니다. 첫 번째 인수는 [`Signer`](#signing-keys-and-custody)입니다: `toSigner(account)`로 viem 계정을 래핑하거나 `awsKmsSigner`와 같은 커스터디 서명자를 전달합니다. ### `buildWaiverInnerTx(signer, chainId, req)` -`gasPrice: 0`, 레거시 유형, 지정된 `chainId`와 같이 면제 불변값이 내장된 면제 준비 InnerTx에 서명합니다. `req`는 필수 `nonce`가 추가된 [`WaiverInnerTx`](#waiverinnertx)입니다. +면제 준비된 InnerTx에 서명합니다. 면제 불변값이 내장되어 있습니다: `gasPrice: 0`, 레거시 유형, 그리고 주어진 `chainId`. `req`는 필수 `nonce`가 포함된 [`WaiverInnerTx`](#waiverinnertx)입니다. ```ts const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to, data, gas: 150_000n, nonce }); @@ -355,11 +355,11 @@ const signed = await buildWaiverInnerTx(toSigner(user), stableTestnet.id, { to, ### `buildGuaranteedTx(signer, chainId, req)` -GuaranteedTx(`0x3F` CustomTx)를 빌드하고 서명합니다. `req`는 필수 `nonce` 및 `nonceKey`가 추가된 [`GuaranteedTxRequest`](#guaranteedtxrequest)입니다. +GuaranteedTx(`0x3F` CustomTx)를 빌드하고 서명합니다. `req`는 필수 `nonce` 및 `nonceKey`가 포함된 [`GuaranteedTxRequest`](#guaranteedtxrequest)입니다. ### `buildGuaranteedWaiverTx(...)` -사전 서명된 내부 트랜잭션을 외부 `0x3F` 면제 CustomTx로 래핑합니다. `guaranteedWaiver.relay`에서 내부적으로 사용되며, 고급 흐름을 위해 Export됩니다. +미리 서명된 내부 트랜잭션을 외부 `0x3F` 면제 CustomTx로 래핑합니다. `guaranteedWaiver.relay`에서 내부적으로 사용됩니다. 고급 흐름을 위해 내보내집니다. ### `nonceKeyForLane(laneId)` @@ -375,16 +375,16 @@ const nonceKey = nonceKeyForLane(0n); ### `SignerSource` -면제 모듈(`gasWaiver`, `guaranteedWaiver`)이 허용하는 서명 키 필드입니다. `signer`, `account`, 클라이언트의 최상위 [`signer`](#stableenterpriseconfig), `STABLE_ENTERPRISE_PRIVATE_KEY` 환경 변수 순으로 해결됩니다. [서명 키 및 커스터디](#signing-keys-and-custody)를 참조하세요. +면제 모듈(`gasWaiver`, `guaranteedWaiver`)이 허용하는 서명 키 필드입니다. 순서대로 해결됩니다: `signer`, 그 다음 `account`, 그 다음 클라이언트의 최상위 [`signer`](#stableenterpriseconfig), 그 다음 `STABLE_ENTERPRISE_PRIVATE_KEY` 환경 변수. [서명 키 및 커스터디](#signing-keys-and-custody)를 참조하십시오. -| **필드** | **타입** | **설명** | +| **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `signer` | `Signer?` | 커스터디 등급 서명자(AWS KMS, HSM 또는 `privateKeySigner`). `account`보다 우선합니다. | -| `account` | `LocalAccount?` | `toSigner`를 통해 `Signer`로 조정된 인 프로세스 viem 계정입니다. | +| `signer` | `Signer?` | 커스터디 등급의 서명자 (AWS KMS, HSM 또는 `privateKeySigner`). `account`보다 우선합니다. | +| `account` | `LocalAccount?` | `toSigner`를 통해 `Signer`로 변환된 인 프로세스 viem 계정. | ### `Signer` -SDK가 32바이트 다이제스트에 서명하는 플러그형 서명자이므로 키는 커스터디 백엔드를 떠나지 않습니다. `awsKmsSigner`, `toSigner`, `privateKeySigner` 또는 `envSigner`를 사용하여 구성합니다. +SDK가 32바이트 다이제스트에 서명하는 플러그형 서명자이므로, 키는 커스터디 백엔드를 떠나지 않습니다. `awsKmsSigner`, `toSigner`, `privateKeySigner` 또는 `envSigner`로 하나를 구성합니다. ```ts interface Signer { @@ -393,62 +393,62 @@ interface Signer { } ``` -| **헬퍼** | **임포트** | **설명** | +| **헬퍼** | **가져오기** | **설명** | | :--- | :--- | :--- | -| `awsKmsSigner({ keyId, client? })` | `@stablechain/enterprise/aws-kms` | AWS KMS `ECC_SECG_P256K1` 키가 지원하는 서명자입니다. `Promise`를 반환합니다. | -| `toSigner(account)` | `@stablechain/enterprise` | viem `LocalAccount`를 `Signer`로 조정합니다. | -| `privateKeySigner(key)` | `@stablechain/enterprise` | 인 프로세스로 보관된 원시 개인 키를 래핑하는 서명자입니다. | -| `envSigner(varName?)` | `@stablechain/enterprise` | `STABLE_ENTERPRISE_PRIVATE_KEY` (또는 `varName`)에서 키를 읽는 서명자입니다. | +| `awsKmsSigner({ keyId, client? })` | `@stablechain/enterprise/aws-kms` | AWS KMS `ECC_SECG_P256K1` 키로 지원되는 서명자. `Promise`를 반환합니다. | +| `toSigner(account)` | `@stablechain/enterprise` | `LocalAccount` viem 계정을 `Signer`로 적용합니다. | +| `privateKeySigner(key)` | `@stablechain/enterprise` | 프로세스 내에서 유지되는 원시 개인 키를 래핑하는 서명자입니다. | +| `envSigner(varName?)` | `@stablechain/enterprise` | `STABLE_ENTERPRISE_PRIVATE_KEY`(또는 `varName`)에서 키를 읽는 서명자입니다. | ### `WaiverInnerTx` -호출당 변하는 InnerTx의 필드입니다. +호출마다 달라지는 InnerTx의 필드입니다. -| **필드** | **타입** | **기본값** | **설명** | +| **필드** | **유형** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `to` | `Address` | | 대상 주소: ERC-20 전송의 경우 토큰 컨트랙트, 기본값의 경우 수신자입니다. | -| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | 가스 한도입니다. `gasPrice`가 0이므로 관대한 한도는 무료입니다. | -| `data` | `Hex?` | `"0x"` | 콜데이터입니다. | -| `value` | `bigint?` | `0n` | 전송할 기본값입니다. | +| `to` | `Address` | | 대상 주소: ERC-20 전송을 위한 토큰 계약, 네이티브 전송을 위한 수신자. | +| `gas` | `bigint?` | `DEFAULT_INNER_GAS` (`150_000n`) | 가스 한도. `gasPrice`가 0이므로, 넉넉한 한도는 무료입니다. | +| `data` | `Hex?` | `"0x"` | Calldata. | +| `value` | `bigint?` | `0n` | 보낼 네이티브 값. | ### `GuaranteedTxRequest` -| **필드** | **타입** | **기본값** | **설명** | +| **필드** | **유형** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `to` | `Address?` | | 대상 주소입니다. | -| `gas` | `bigint` | | 가스 한도입니다. 필수. | -| `gasFeeCap` | `bigint` | | `maxFeePerGas`입니다. 필수. | -| `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`입니다. 필수. | -| `data` | `Hex?` | `"0x"` | 콜데이터입니다. | -| `value` | `bigint?` | `0n` | 전송할 기본값입니다. | +| `to` | `Address?` | | 대상 주소. | +| `gas` | `bigint` | | 가스 한도. 필수. | +| `gasFeeCap` | `bigint` | | `maxFeePerGas`. 필수. | +| `gasTipCap` | `bigint` | | `maxPriorityFeePerGas`. 필수. | +| `data` | `Hex?` | `"0x"` | Calldata. | +| `value` | `bigint?` | `0n` | 보낼 네이티브 값. | ### `GuaranteedWaiverTxRequest` 수수료 필드는 항상 0이므로 여기서는 생략됩니다. -| **필드** | **타입** | **기본값** | **설명** | +| **필드** | **유형** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `to` | `Address` | | 대상 주소입니다. | -| `gas` | `bigint?` | 공유 내부 가스 기본값 | 가스 한도입니다. | -| `data` | `Hex?` | `"0x"` | 콜데이터입니다. | -| `value` | `bigint?` | `0n` | 전송할 기본값입니다. 면제의 경우 값 전송이 허용됩니다. | +| `to` | `Address` | | 대상 주소. | +| `gas` | `bigint?` | 공유 내부 가스 기본값 | 가스 한도. | +| `data` | `Hex?` | `"0x"` | Calldata. | +| `value` | `bigint?` | `0n` | 보낼 네이티브 값. 면제를 위해 값 전송이 허용됩니다. | ### `ValidationLimits` `gasWaiver` 및 `guaranteedWaiver`에 의해 각 InnerTx에 적용되는 파트너별 정책입니다. -| **필드** | **타입** | **기본값** | **설명** | +| **필드** | **유형** | **기본값** | **설명** | | :--- | :--- | :--- | :--- | -| `maxGasLimit` | `bigint?` | `10_000_000n` | InnerTx의 최대 가스 한도입니다. 초과하면 `GAS_LIMIT_EXCEEDED`와 함께 실패합니다. | -| `maxDataLength` | `number?` | `131_072` (128 KB) | 최대 콜데이터 크기(바이트)입니다. 초과하면 `DATA_TOO_LARGE`와 함께 실패합니다. | -| `allowedTargets` | `AllowedTarget[]?` | | 면제가 후원할 수 있는 컨트랙트 및 메서드의 허용 목록입니다. 설정된 경우 목록에 없는 대상은 `TARGET_NOT_ALLOWED`와 함께 실패합니다. | +| `maxGasLimit` | `bigint?` | `10_000_000n` | InnerTx의 최대 가스 한도. 이를 초과하면 `GAS_LIMIT_EXCEEDED`로 실패합니다. | +| `maxDataLength` | `number?` | `131_072` (128 KB) | 바이트 단위의 최대 calldata 크기. 이를 초과하면 `DATA_TOO_LARGE`로 실패합니다. | +| `allowedTargets` | `AllowedTarget[]?` | | 면제를 후원할 수 있는 계약 및 메서드의 허용 목록. 설정된 경우, 목록에 없는 대상은 `TARGET_NOT_ALLOWED`로 실패합니다. | ### `AllowedTarget` -| **필드** | **타입** | **설명** | +| **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `address` | `Address \| "*"` | InnerTx가 호출할 수 있는 컨트랙트 또는 모든 컨트랙트에 일치하는 `"*"`입니다. | -| `selectors` | `Hex[]?` | 허용된 4바이트 메서드 셀렉터(예: ERC-20 `transfer`의 경우 `"0xa9059cbb"`). `address`에서 모든 메서드를 허용하려면 생략하거나 비워 둡니다. | +| `address` | `Address \| "*"` | InnerTx가 호출할 수 있는 계약, 또는 모든 계약과 일치하는 `"*"`입니다. | +| `selectors` | `Hex[]?` | 허용된 4바이트 메서드 선택자(예: ERC-20 `transfer`의 `"0xa9059cbb"`). `address`에서 모든 메서드를 허용하려면 생략하거나 비워 둡니다. | ### `RelayResult` @@ -460,24 +460,24 @@ interface RelayResult { ### `BatchResultItem` -배치에서 입력당 하나의 항목이 입력 순서대로 반환됩니다. 예외를 던지는 대신, 배치는 항목별 결과를 나타냅니다. +배치에서 입력당 하나씩, 입력 순서대로 항목. 예외를 던지는 대신, 배치는 항목별 결과를 [`BatchResultItem.error`](#batchresultitem)로 표시합니다. -| **필드** | **타입** | **설명** | +| **필드** | **유형** | **설명** | | :--- | :--- | :--- | -| `index` | `number` | 입력 배열과 일치하는 0부터 시작하는 위치입니다. | -| `success` | `boolean` | 이 항목이 릴레이되었는지 여부입니다. | -| `txHash` | `Hash?` | 성공 시 존재: 내부 트랜잭션 해시입니다. | -| `error` | `{ code: ErrorCode; message: string }?` | 실패 시 존재합니다. | +| `index` | `number` | 입력 배열과 일치하는 0부터 시작하는 위치. | +| `success` | `boolean` | 이 항목이 릴레이되었는지 여부. | +| `txHash` | `Hash?` | 성공 시 존재: 내부 트랜잭션 해시. | +| `error` | `{ code: ErrorCode; message: string }?` | 실패 시 존재. | ## 오류 -단일 트랜잭션 메서드(`send`, `relay`)는 거부 시 예외를 발생시킵니다. 일괄 메서드는 [`BatchResultItem.error`](#batchresultitem)에 항목별 실패를 보고합니다. 모든 오류 클래스는 `StableEnterpriseError`를 확장합니다. +단일 트랜잭션 메서드(`send`, `relay`)는 거부 시 예외를 발생시킵니다. 배치 메서드는 대신 [`BatchResultItem.error`](#batchresultitem)에서 항목별 실패를 보고합니다. 모든 오류 클래스는 `StableEnterpriseError`를 확장합니다. | **클래스** | **발생 시점** | **유용한 필드** | | :--- | :--- | :--- | -| `StableEnterpriseError` | 모든 SDK 오류의 기본 클래스입니다. | `message` | -| `StableEnterpriseRelayError` | 트랜잭션이 RPC 또는 릴레이 계층에서 거부됩니다. | `code` | -| `WaiverValidationError` | InnerTx가 브로드캐스트 전에 정책 검사(가스, 데이터 크기 또는 대상 허용 목록)에 실패합니다. | `code` | +| `StableEnterpriseError` | 모든 SDK 오류의 기본 클래스. | `message` | +| `StableEnterpriseRelayError` | RPC 또는 릴레이 레이어에서 트랜잭션이 거부될 때. | `code` | +| `WaiverValidationError` | InnerTx가 브로드캐스트 전에 정책 검사(가스, 데이터 크기 또는 대상 허용 목록)에 실패하는 경우. | `code` | ```ts import { StableEnterpriseRelayError } from "@stablechain/enterprise"; @@ -486,7 +486,7 @@ try { await gw.send(user, { to: token, data }); } catch (err) { if (err instanceof StableEnterpriseRelayError && err.code === "TARGET_NOT_ALLOWED") { - // InnerTx 대상이 구성된 허용 목록 외부에 있습니다. + // InnerTx 대상이 구성된 허용 목록 외부에 있습니다 } throw err; } @@ -498,33 +498,33 @@ StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not ### `ErrorCode` -발생된 오류 또는 `BatchResultItem.error`의 `code`는 다음 중 하나입니다. +던진 오류 또는 `BatchResultItem.error`의 `code`는 다음 중 하나입니다. | **코드** | **의미** | | :--- | :--- | -| `UNKNOWN_ERROR` | 특정 코드를 사용할 수 없는 경우의 대체값입니다. | -| `BROADCAST_FAILED` | RPC 계층에서 브로드캐스트가 거부되었거나 게이트웨이가 릴레이에 실패했습니다. | -| `INVALID_TRANSACTION` | InnerTx를 디코딩하거나 구문 분석하는 데 실패했습니다. | +| `UNKNOWN_ERROR` | 특정 코드를 사용할 수 없을 때의 폴백. | +| `BROADCAST_FAILED` | RPC 계층에서 브로드캐스트가 거부되거나 게이트웨이가 릴레이에 실패했습니다. | +| `INVALID_TRANSACTION` | InnerTx가 디코딩 또는 파싱에 실패했습니다. | | `INVALID_SIGNATURE` | 서명 확인에 실패했습니다. | | `UNSUPPORTED_TX_TYPE` | InnerTx 유형이 레거시, eip2930 또는 eip1559가 아닙니다. | | `WRONG_CHAIN_ID` | InnerTx `chainId`가 없거나 대상 체인과 일치하지 않습니다. | -| `NON_ZERO_GAS_PRICE` | InnerTx는 0이 아닌 가스 가격을 가지고 있습니다(면제의 경우 0이어야 함). | +| `NON_ZERO_GAS_PRICE` | InnerTx는 0이 아닌 가스 가격을 가집니다(면제의 경우 0이어야 함). | | `GAS_LIMIT_EXCEEDED` | InnerTx 가스 한도가 `maxGasLimit`을 초과합니다. | -| `DATA_TOO_LARGE` | InnerTx 콜데이터가 `maxDataLength`를 초과합니다. | +| `DATA_TOO_LARGE` | InnerTx calldata가 `maxDataLength`를 초과합니다. | | `TARGET_NOT_ALLOWED` | InnerTx 대상이 `allowedTargets`에 없습니다. | -| `GATEWAY_UNAUTHORIZED` | 엔터프라이즈 RPC 게이트웨이가 API 키를 거부했습니다(누락, 유효하지 않음 또는 만료됨). | +| `GATEWAY_UNAUTHORIZED` | 엔터프라이즈 RPC 게이트웨이가 API 키를 거부했습니다(누락, 유효하지 않거나 만료됨). | | `QUOTA_EXCEEDED` | 엔터프라이즈 RPC 게이트웨이 가스 할당량이 소진되었습니다. | ## 상수 -| **상수** | **타입** | **설명** | +| **상수** | **유형** | **설명** | | :--- | :--- | :--- | -| `DEFAULT_INNER_GAS` | `bigint` | `gas`가 생략된 경우 기본 InnerTx 가스 한도(`150_000n`). | -| `ENTERPRISE_FLAG` | `bigint` | 레인의 `nonceKey`에 설정된 엔터프라이즈 비트입니다. | -| `ENTERPRISE_MASK` | `bigint` | 레인 ID의 상한: `laneId`는 `[0, ENTERPRISE_MASK - 1]` 범위에 있어야 합니다. | +| `DEFAULT_INNER_GAS` | `bigint` | `gas`가 생략될 때의 기본 InnerTx 가스 한도(`150_000n`). | +| `ENTERPRISE_FLAG` | `bigint` | 레인의 `nonceKey`에 설정된 엔터프라이즈 비트. | +| `ENTERPRISE_MASK` | `bigint` | 레인 ID의 상한: `laneId`는 `[0, ENTERPRISE_MASK - 1]` 범위 내에 있어야 합니다. | ## 다음 권장 사항 -- [**Stable Enterprise SDK**](/ko/explanation/enterprise-sdk): 레일이 무엇이며 언제 사용해야 하는지. +- [**Stable 엔터프라이즈 SDK**](/ko/explanation/enterprise-sdk): 레일이 무엇이며 언제 사용해야 하는지. - [**가스 면제 프로토콜**](/ko/reference/gas-waiver-api): 트랜잭션 형식, 마커 라우팅 및 거버넌스 제어. - [**보장된 블록스페이스**](/ko/explanation/guaranteed-blockspace): Stable이 엔터프라이즈 워크로드에 대한 블록 용량을 예약하는 방법. diff --git a/docs/sidebar.json b/docs/sidebar.json index 6160aec..0c042e4 100644 --- a/docs/sidebar.json +++ b/docs/sidebar.json @@ -689,7 +689,7 @@ ], "/ko": [ { - "text": "학습하기", + "text": "학습", "collapsed": true, "items": [ { @@ -729,11 +729,11 @@ "link": "/ko/explanation/finality" }, { - "text": "가스 가격 책정", + "text": "가스 가격", "link": "/ko/explanation/gas-pricing" }, { - "text": "가스 가격 책정 API", + "text": "가스 가격 API", "link": "/ko/reference/gas-pricing-api" }, { @@ -779,7 +779,7 @@ "link": "/ko/explanation/guaranteed-blockspace" }, { - "text": "USDT 전송 애그리게이터", + "text": "USDT 전송 Aggregator", "link": "/ko/explanation/usdt-transfer-aggregator" }, { @@ -813,13 +813,13 @@ "link": "/ko/explanation/high-performance-rpc" }, { - "text": "Autobahn", + "text": "아우토반", "link": "/ko/explanation/autobahn" } ] }, { - "text": "사용 사례 내러티브", + "text": "사용 사례 설명", "collapsed": true, "items": [ { @@ -831,7 +831,7 @@ "link": "/ko/explanation/use-case-payroll" }, { - "text": "스폰서 사용 사례", + "text": "후원 사용 사례", "link": "/ko/explanation/use-case-sponsored" }, { @@ -841,7 +841,7 @@ ] }, { - "text": "토크노믹스", + "text": "토큰 경제학", "link": "/ko/reference/tokenomics" }, { @@ -855,7 +855,7 @@ ] }, { - "text": "구축하기", + "text": "구축", "collapsed": true, "items": [ { @@ -887,17 +887,17 @@ "link": "/ko/how-to/earn-yield" }, { - "text": "viem 통합", + "text": "Viem 통합", "link": "/ko/how-to/sdk-with-viem" }, { - "text": "wagmi 통합", + "text": "Wagmi 통합", "link": "/ko/how-to/sdk-with-wagmi" } ] }, { - "text": "기업 SDK", + "text": "Enterprise SDK", "collapsed": true, "items": [ { @@ -957,7 +957,7 @@ "link": "/ko/explanation/payments-overview" }, { - "text": "결제 인덱스", + "text": "결제 색인", "link": "/ko/explanation/payments-guides" }, { @@ -983,7 +983,7 @@ ] }, { - "text": "사용자에게 청구", + "text": "사용자에게 요금 부과", "collapsed": true, "items": [ { @@ -991,7 +991,7 @@ "link": "/ko/how-to/build-p2p-payments" }, { - "text": "구독 및 수금", + "text": "구독 및 수집", "link": "/ko/how-to/subscribe-and-collect" }, { @@ -1029,7 +1029,7 @@ "link": "/ko/reference/pay-per-call" }, { - "text": "향후 사용 사례", + "text": "예정된 사용 사례", "link": "/ko/explanation/upcoming-use-cases" } ] @@ -1037,31 +1037,31 @@ ] }, { - "text": "컨트랙트 배포", + "text": "계약 배포", "collapsed": true, "items": [ { - "text": "컨트랙트 개요", + "text": "계약 개요", "link": "/ko/explanation/contracts-overview" }, { - "text": "컨트랙트 인덱스", + "text": "계약 색인", "link": "/ko/explanation/contracts-guides" }, { - "text": "첫 번째 컨트랙트 배포", + "text": "첫 번째 계약 배포", "collapsed": true, "items": [ { - "text": "스마트 컨트랙트", + "text": "스마트 계약", "link": "/ko/tutorial/smart-contract" }, { - "text": "컨트랙트 확인", + "text": "계약 검증", "link": "/ko/how-to/verify-contract" }, { - "text": "컨트랙트 색인", + "text": "계약 색인", "link": "/ko/how-to/index-contract" } ] @@ -1083,19 +1083,19 @@ "link": "/ko/reference/system-modules-api-overview" }, { - "text": "뱅크 모듈", + "text": "은행 모듈", "link": "/ko/explanation/bank-module" }, { - "text": "뱅크 모듈 API", + "text": "은행 모듈 API", "link": "/ko/reference/bank-module-api" }, { - "text": "배포 모듈", + "text": "분배 모듈", "link": "/ko/explanation/distribution-module" }, { - "text": "배포 모듈 API", + "text": "분배 모듈 API", "link": "/ko/reference/distribution-module-api" }, { @@ -1115,7 +1115,7 @@ "link": "/ko/reference/system-transactions-api" }, { - "text": "언바운딩 추적", + "text": "언본딩 추적", "link": "/ko/how-to/track-unbonding" }, { @@ -1133,7 +1133,7 @@ ] }, { - "text": "통합하기", + "text": "통합", "collapsed": true, "items": [ { @@ -1225,7 +1225,7 @@ "link": "/ko/reference/oracles" }, { - "text": "RPC 제공업체", + "text": "RPC 제공자", "link": "/ko/reference/rpc-providers" }, { @@ -1233,7 +1233,7 @@ "link": "/ko/reference/network-routing" }, { - "text": "램프", + "text": "경사로", "link": "/ko/reference/ramps" }, { @@ -1241,7 +1241,7 @@ "link": "/ko/reference/wallets" }, { - "text": "수호", + "text": "수탁", "link": "/ko/reference/custody" }, { @@ -1251,7 +1251,7 @@ ] }, { - "text": "프로덕션 준비", + "text": "생산 준비", "link": "/ko/how-to/production-readiness" }, { @@ -1271,7 +1271,7 @@ ] }, { - "text": "운영하기", + "text": "운영", "collapsed": true, "items": [ { @@ -1279,7 +1279,7 @@ "link": "/ko/reference/node-operations-overview" }, { - "text": "노드 시스템 요구사항", + "text": "노드 시스템 요구 사항", "link": "/ko/reference/node-system-requirements" }, { @@ -1295,7 +1295,7 @@ "link": "/ko/how-to/use-node-snapshots" }, { - "text": "검증인 실행", + "text": "검증자 실행", "link": "/ko/how-to/run-validator" }, { @@ -1321,15 +1321,15 @@ "link": "/ko/explanation/agent-settlement" }, { - "text": "AI 에이전트 인덱스", + "text": "AI 에이전트 색인", "link": "/ko/explanation/ai-agents-guides" }, { - "text": "x402 및 MPP를 통한 지불", + "text": "x402 및 MPP를 통한 결제", "collapsed": true, "items": [ { - "text": "X402", + "text": "x402", "link": "/ko/explanation/x402" }, { @@ -1349,7 +1349,7 @@ "link": "/ko/how-to/build-mpp-endpoint" }, { - "text": "MCP로 지불", + "text": "MCP로 결제", "link": "/ko/how-to/pay-with-mcp" } ] @@ -1359,15 +1359,15 @@ "collapsed": true, "items": [ { - "text": "AI를 통한 개발", + "text": "AI로 개발", "link": "/ko/how-to/develop-with-ai" }, { - "text": "에이전트식 조력자", + "text": "에이전트 촉진자", "link": "/ko/reference/agentic-facilitators" }, { - "text": "에이전트식 지갑", + "text": "에이전틱 지갑", "link": "/ko/reference/agentic-wallets" } ] @@ -1401,7 +1401,7 @@ "link": "/cn/explanation/core-concepts" }, { - "text": "主要功能", + "text": "主要特点", "link": "/cn/explanation/key-features" }, { @@ -1439,19 +1439,19 @@ "link": "/cn/explanation/usdt-features-overview" }, { - "text": "资金流转", + "text": "资金流", "link": "/cn/explanation/flow-of-funds" }, { - "text": "USDT0 桥接", + "text": "USDT0 跨链", "link": "/cn/explanation/usdt0-bridging" }, { - "text": "桥接安全", + "text": "跨链桥安全性", "link": "/cn/explanation/bridge-security" }, { - "text": "USDT 作为 Gas 代币", + "text": "USDT0 作为 Gas 代币", "link": "/cn/explanation/usdt-as-gas-token" }, { @@ -1459,7 +1459,7 @@ "link": "/cn/explanation/usdt0-behavior" }, { - "text": "Gas 豁免", + "text": "Gas 减免", "link": "/cn/explanation/gas-waiver" }, { @@ -1467,11 +1467,11 @@ "link": "/cn/explanation/guaranteed-blockspace" }, { - "text": "USDT 传输聚合器", + "text": "USDT0 转账聚合器", "link": "/cn/explanation/usdt-transfer-aggregator" }, { - "text": "保密传输", + "text": "保密转账", "link": "/cn/explanation/confidential-transfer" } ] @@ -1511,19 +1511,19 @@ "collapsed": true, "items": [ { - "text": "用例:支付", + "text": "支付用例", "link": "/cn/explanation/use-case-payments" }, { - "text": "用例:工资", + "text": "薪资用例", "link": "/cn/explanation/use-case-payroll" }, { - "text": "用例:赞助", + "text": "赞助用例", "link": "/cn/explanation/use-case-sponsored" }, { - "text": "用例:私有", + "text": "隐私用例", "link": "/cn/explanation/use-case-private" } ] @@ -1571,21 +1571,21 @@ "link": "/cn/reference/sdk" }, { - "text": "获取收益", + "text": "赚取收益", "link": "/cn/how-to/earn-yield" }, { - "text": "viem 集成", + "text": "Viem 集成", "link": "/cn/how-to/sdk-with-viem" }, { - "text": "wagmi 集成", + "text": "Wagmi 集成", "link": "/cn/how-to/sdk-with-wagmi" } ] }, { - "text": "企业 SDK", + "text": "企业级 SDK", "collapsed": true, "items": [ { @@ -1611,7 +1611,7 @@ ] }, { - "text": "用户 onboarding", + "text": "用户引导", "collapsed": true, "items": [ { @@ -1637,7 +1637,7 @@ ] }, { - "text": "接收付款", + "text": "接受付款", "collapsed": true, "items": [ { @@ -1649,7 +1649,7 @@ "link": "/cn/explanation/payments-guides" }, { - "text": "移动 USDT0", + "text": "转移 USDT0", "collapsed": true, "items": [ { @@ -1679,7 +1679,7 @@ "link": "/cn/how-to/build-p2p-payments" }, { - "text": "订阅和收款", + "text": "订阅与收款", "link": "/cn/how-to/subscribe-and-collect" }, { @@ -1725,7 +1725,7 @@ ] }, { - "text": "部署合约", + "text": "发布合约", "collapsed": true, "items": [ { @@ -1807,7 +1807,7 @@ "link": "/cn/how-to/track-unbonding" }, { - "text": "索引验证器数据", + "text": "索引验证者数据", "link": "/cn/how-to/index-validator-data" } ] @@ -1879,19 +1879,19 @@ ] }, { - "text": "Gas 豁免服务", + "text": "Gas 减免服务", "collapsed": true, "items": [ { - "text": "集成 Gas 豁免", + "text": "集成 Gas 减免", "link": "/cn/how-to/integrate-gas-waiver" }, { - "text": "自托管 Gas 豁免", + "text": "自托管 Gas 减免", "link": "/cn/how-to/self-hosted-gas-waiver" }, { - "text": "Gas 豁免 API", + "text": "Gas 减免 API", "link": "/cn/reference/gas-waiver-api" } ] @@ -1901,11 +1901,11 @@ "collapsed": true, "items": [ { - "text": "桥", + "text": "跨链桥", "link": "/cn/reference/bridges" }, { - "text": "去中心化交易所 (DEX)", + "text": "DEX", "link": "/cn/reference/dexes" }, { @@ -1921,7 +1921,7 @@ "link": "/cn/reference/network-routing" }, { - "text": "坡道", + "text": "兑换", "link": "/cn/reference/ramps" }, { @@ -1983,7 +1983,7 @@ "link": "/cn/how-to/use-node-snapshots" }, { - "text": "运行验证器", + "text": "运行验证者节点", "link": "/cn/how-to/run-validator" }, { @@ -2017,7 +2017,7 @@ "collapsed": true, "items": [ { - "text": "x402", + "text": "X402", "link": "/cn/explanation/x402" }, { @@ -2037,7 +2037,7 @@ "link": "/cn/how-to/build-mpp-endpoint" }, { - "text": "使用 MCP 支付", + "text": "通过 MCP 支付", "link": "/cn/how-to/pay-with-mcp" } ] @@ -2047,7 +2047,7 @@ "collapsed": true, "items": [ { - "text": "使用 AI 开发", + "text": "用 AI 进行开发", "link": "/cn/how-to/develop-with-ai" }, { From 6327f912a5ad9608978da296605fea4decc60973 Mon Sep 17 00:00:00 2001 From: bastienrp Date: Fri, 17 Jul 2026 15:43:20 +0200 Subject: [PATCH 20/20] docs: link the @stablechain/enterprise npm package Add the npm package link to the Enterprise SDK overview (body + next steps) and the reference install section, mirroring the Stable SDK docs. Co-Authored-By: Claude Opus 4.8 --- docs/pages/en/explanation/enterprise-sdk.mdx | 3 +++ docs/pages/en/reference/enterprise-sdk.mdx | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/pages/en/explanation/enterprise-sdk.mdx b/docs/pages/en/explanation/enterprise-sdk.mdx index a632f3b..01045da 100644 --- a/docs/pages/en/explanation/enterprise-sdk.mdx +++ b/docs/pages/en/explanation/enterprise-sdk.mdx @@ -36,6 +36,8 @@ The SDK exposes three features, one per module. Each is optional and independent Every feature offers the same four methods: `send` and `sendBatch` for the custodial path where the SDK signs, and `relay` and `relayBatch` for the non-custodial path where the user signs elsewhere and hands you only the signed hex. +The SDK is published on npm as [`@stablechain/enterprise`](https://www.npmjs.com/package/@stablechain/enterprise) and requires `viem >= 2.0.0` as a peer dependency. + ## Access The Enterprise SDK is currently available on Stable Testnet only. @@ -63,6 +65,7 @@ Reach for the Enterprise SDK when you operate a backend and want to sponsor user ## Next recommended +- [**Install from npm**](https://www.npmjs.com/package/@stablechain/enterprise): View the package on npmjs.com and check the latest version. - [**Gas waiver protocol**](/en/reference/gas-waiver-api): Transaction formats, marker routing, and governance controls. - [**Stable SDK**](/en/explanation/sdk-overview): The general-purpose client for transfers, bridging, swaps, and yield. - [**Connect to Stable**](/en/reference/connect): Chain IDs, RPC endpoints, and explorers for testnet. diff --git a/docs/pages/en/reference/enterprise-sdk.mdx b/docs/pages/en/reference/enterprise-sdk.mdx index d0bc44d..9d6954f 100644 --- a/docs/pages/en/reference/enterprise-sdk.mdx +++ b/docs/pages/en/reference/enterprise-sdk.mdx @@ -26,7 +26,7 @@ npm install @stablechain/enterprise viem added 2 packages, audited 3 packages in 2s ``` -`viem >= 2.0.0` is a peer dependency. The package re-exports `stable` and `stableTestnet` from `viem/chains`, so you don't import them separately. +`viem >= 2.0.0` is a peer dependency. The package is published as [`@stablechain/enterprise`](https://www.npmjs.com/package/@stablechain/enterprise) and re-exports `stable` and `stableTestnet` from `viem/chains`, so you don't import them separately. ## `createStableEnterprise(config)`