가스 면제 릴레이
@stablechain/enterprise를 사용하여 사용자의 가스를 후원하세요. 화이트리스트에 등록된 면제 계정은 사용자의 제로 가스 트랜잭션(InnerTx)을 래핑하여 브로드캐스트하므로, 사용자는 USDT0를 보유하지 않고도 트랜잭션을 수행할 수 있습니다. gasWaiver 모듈은 한 번의 호출로 빌드, 서명 및 릴레이를 수행하므로, 각 작업당 하나의 메서드를 호출합니다.
모든 메서드는 사용자의 트랜잭션 해시인 H_inner를 반환하며, 이를 전달한 래퍼는 반환하지 않습니다.
전제 조건
- Node.js 20 이상, 그리고
@stablechain/enterprise와viem이 설치되어 있어야 합니다. Enterprise SDK 참조를 참조하세요. - 거버넌스에 등록된 면제 키. Enterprise SDK는 Stable Mainnet 및 Stable Testnet에서 실행되며, 액세스가 제한됩니다. 화이트리스트에 등록된 면제 키를 받으려면 Stable에 문의하세요.
1. 가스 면제 모듈로 클라이언트 생성
gasWaiver: { account }를 createStableEnterprise에 전달합니다. 여기서 account는 화이트리스트에 등록된 면제 키입니다. 모듈은 구성할 때만 클라이언트에 존재합니다.
import { createStableEnterprise, stable } from "@stablechain/enterprise";
import { privateKeyToAccount } from "viem/accounts";
const enterprise = createStableEnterprise({
chain: stable,
gasWaiver: { account: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`) },
});
const gw = enterprise.gasWaiver;StableEnterpriseClient { gasWaiver, guaranteedBlock: undefined, guaranteedWaiver: undefined }rpcEndpoints 옵션은 선택 사항입니다. 설정하지 않으면 클라이언트는 체인의 내장 RPC를 사용합니다.
2. 단일 트랜잭션 릴레이
사용자 계정과 가변 필드를 사용하여 send를 호출합니다. gasPrice: 0, 레거시 유형, chainId, 그리고 보류 중인 nonce는 자동으로 처리되므로, to만 전달하고 선택적으로 data, value, gas를 전달합니다.
const user = privateKeyToAccount(process.env.USER_PRIVATE_KEY as `0x${string}`);
const { txHash } = await gw.send(user, { to: token, data, gas: 150_000n });
console.log("H_inner:", txHash);H_inner: 0x8f3a...2d41사용자는 USDT0가 필요하지 않습니다. 면제 계정이 가스를 후원합니다. gas는 토큰 전송 또는 승인을 처리하는 150_000n(DEFAULT_INNER_GAS)으로 기본 설정됩니다. 더 많은 가스를 사용하는 호출에는 명시적인 gas를 전달하세요.
3. 배치 릴레이
sendBatch를 호출하여 하나의 계정에서 여러 트랜잭션을 릴레이합니다. Nonce는 계정의 보류 중인 nonce에서 자동으로 시퀀싱되며, 입력 순서대로 입력당 하나의 결과를 얻습니다.
const results = await gw.sendBatch(user, [
{ to: token, data: dataA, gas: 150_000n },
{ to: token, data: dataB, gas: 150_000n },
]);
for (const r of results) {
console.log(r.success ? `[${r.index}] ✔ ${r.txHash}` : `[${r.index}] ✖ ${r.error?.code}`);
}[0] ✔ 0x8f3a...2d41
[1] ✔ 0x2b7c...9e04배치는 예외를 발생시키는 대신 result.error에 항목별 실패를 보고하므로, 하나의 잘못된 트랜잭션이 나머지를 망가뜨리지 않습니다.
4. 파트너별 정책 한도 적용
정책 한도를 구성에 추가하여 면제 키가 후원할 수 있는 항목을 제한합니다. 한도를 위반하는 InnerTx는 브로드캐스트 전에 거부됩니다.
const enterprise = createStableEnterprise({
chain: stable,
gasWaiver: {
account: privateKeyToAccount(process.env.WAIVER_PRIVATE_KEY as `0x${string}`),
maxGasLimit: 500_000n,
maxDataLength: 4_096,
allowedTargets: [
{ address: token, selectors: ["0xa9059cbb"] }, // ERC-20 전송만
],
},
});allowedTargets 외의 계약으로의 트랜잭션은 TARGET_NOT_ALLOWED 오류와 함께 실패합니다. maxGasLimit을 초과하는 트랜잭션은 GAS_LIMIT_EXCEEDED 오류와 함께 실패합니다. address로 "*"를 사용하여 모든 계약을 허용하고, selectors를 생략하여 모든 메서드를 허용할 수 있습니다.
5. 사전 서명된 트랜잭션 릴레이
비관리형 흐름의 경우, 사용자는 자신의 환경에서 InnerTx에 서명하고 서명된 헥스만 제공하므로, 사용자의 키를 볼 필요가 없습니다. buildWaiverInnerTx로 빌드한 다음 relay로 릴레이합니다.
import { buildWaiverInnerTx, toSigner } from "@stablechain/enterprise";
// 사용자 측에서 — buildWaiverInnerTx는 서명자를 통해 서명합니다; toSigner는 viem 계정을 조정합니다
const signed = await buildWaiverInnerTx(toSigner(user), stable.id, { to: token, data, gas: 150_000n, nonce });
// 백엔드에서
const { txHash } = await gw.relay(signed);
console.log("H_inner:", txHash);H_inner: 0x8f3a...2d41여러 개의 사전 서명된 트랜잭션의 경우, sendBatch처럼 입력당 하나의 결과를 반환하는 relayBatch를 사용합니다.
거부 처리
send 및 relay는 거부 시 StableEnterpriseRelayError를 throw하며, 분기할 수 있는 code를 포함합니다.
import { StableEnterpriseRelayError } from "@stablechain/enterprise";
try {
await gw.send(user, { to: token, data });
} catch (err) {
if (err instanceof StableEnterpriseRelayError && err.code === "TARGET_NOT_ALLOWED") {
// InnerTx 대상이 구성된 허용 목록 외부에 있습니다
}
throw err;
}StableEnterpriseRelayError: relay failed [TARGET_NOT_ALLOWED]: target 0x... not allowed모든 거부 이유에 대한 전체 ErrorCode 표를 참조하세요.
다음 단계
- 보장된 트랜잭션 전송: 예약된 Enterprise-lane 블록 공간에 트랜잭션을 전송하고 가스 면제와 결합합니다.
- Enterprise SDK 참조: 모든 메서드, 구성 옵션 및 오류 클래스에 대한 자세한 정보.
- 가스 면제: 프로토콜 수준에서 제로 가스 트랜잭션이 작동하는 방식.
- 가스 없는 트랜잭션 활성화: 자체 면제 키를 등록하는 대신 Stable에서 호스팅하는 면제 서버를 사용합니다.

