@altaga/x402-sui
v1.0.9
Published
Modular x402 implementation for Sui Sponsored Transactions
Maintainers
Readme
@altaga/x402-sui
x402 v2 implementation for Sui Sponsored Transactions (gas-station style), with client + server compatibility.
This package provides an SDK for the x402 v2 “Payment Required” HTTP pattern, targeting the Sui blockchain. It includes compatible implementations for:
- Client (buyer): build/sign payment payloads and replay HTTP requests with
PAYMENT-SIGNATURE - Server (resource): emit 402 challenges, verify/settle payments, and expose paid endpoints via middleware
- Facilitator (gas sponsor): co-sign and submit sponsored transactions (gas-station model)
The bundled exact:sui:* scheme uses Sui’s sponsored transaction model: the buyer signs the payment intent, the facilitator co-signs as the gas owner, and the resource server never touches a private key.
Compatibility
x402 version: v2
chain: Sui (testnet/mainnet via network selector)
roles: client (buyer) + server (resource) + facilitator (sponsor)
transport: HTTP (Payment Required challenge/response)
scheme: exact (Sui sponsored transactions)Installation
npm install @altaga/x402-suiYou also need the peer dependencies in your project:
npm install @mysten/sui @mysten/bcs expressQuick Start
1. Resource Server (the paid API)
import express from "express";
import {
x402ResourceServer,
HTTPFacilitatorClient,
x402HTTPResourceServer,
ExactSuiServerScheme
} from "@altaga/x402-sui";
const app = express();
// The server is configured with the URL of a trusted facilitator
const facilitator = new HTTPFacilitatorClient({ url: "https://facilitator.example.com" });
const resourceServer = new x402ResourceServer(facilitator);
// Register scheme(s) you want to accept. Wildcards ("sui:*", "*:*") are OK.
resourceServer.register("exact:sui:mainnet", new ExactSuiServerScheme());
// Declare which routes are paid, and what they cost
const routes = {
"GET /premium": {
accepts: {
scheme: "exact",
network: "sui:mainnet",
asset: "0x2::sui::SUI",
payTo: "0xYOUR_RECEIVING_ADDRESS",
maxAmountRequired: "1000000", // 0.001 SUI
description: "Premium data feed"
}
}
};
app.use(new x402HTTPResourceServer(resourceServer, routes).middleware());
// The actual handler — req.payment is populated by the middleware
app.get("/premium", (req, res) => {
res.json({ ok: true, paid: req.payment });
});
app.listen(3000);2. Facilitator (the gas station)
import express from "express";
import { SuiClient } from "@mysten/sui/client";
import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
import { x402Facilitator, ExactSuiFacilitatorScheme } from "@altaga/x402-sui";
const client = new SuiClient({ url: "https://fullnode.mainnet.sui.io" });
const keypair = Ed25519Keypair.fromSecretKey(process.env.FACILITATOR_SECRET);
const facilitator = new x402Facilitator();
facilitator.register("exact:sui:mainnet", new ExactSuiFacilitatorScheme(client, keypair));
const app = express();
app.use(express.json());
// Sponsor: client posts { txBytes, sender, scheme, network }
app.post("/sponsor", async (req, res) => {
try {
const result = await facilitator.sponsor(req.body.scheme, req.body.network, {
txBytes: req.body.txBytes,
sender: req.body.sender,
});
res.json(result); // { sponsoredTxBytes, sponsorSignature }
} catch (e) {
res.status(400).json({ error: e.message });
}
});
// Verify: dry-run the candidate transaction
app.post("/verify", async (req, res) => {
try {
const result = await facilitator.verify(req.body.paymentPayload, req.body.paymentRequirement);
res.json(result); // { isValid: true }
} catch (e) {
res.status(400).json({ isValid: false, error: e.message });
}
});
// Settle: submit the transaction to the chain
app.post("/settle", async (req, res) => {
try {
const result = await facilitator.settle(req.body.paymentPayload, req.body.paymentRequirement);
res.json(result); // { transactionDigest }
} catch (e) {
res.status(400).json({ error: e.message });
}
});
app.listen(4000);3. Client (the buyer)
import { SuiClient } from "@mysten/sui/client";
import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
import { x402Client, x402HTTPClient, ExactSuiClientScheme } from "@altaga/x402-sui";
const sui = new SuiClient({ url: "https://fullnode.mainnet.sui.io" });
const keypair = Ed25519Keypair.fromSecretKey(process.env.BUYER_SECRET);
const core = new x402Client();
core.register("exact:sui:mainnet", new ExactSuiClientScheme(sui, keypair));
const http = new x402HTTPClient(core);
// 1. Hit the protected endpoint
let res = await fetch("https://api.example.com/premium");
if (res.status === 402) {
// 2. Parse the challenge
const paymentRequired = http.getPaymentRequiredResponse(
(name) => res.headers.get(name),
null,
);
// 3. Build + sign + sponsor the payment
const payload = await http.createPaymentPayload(paymentRequired);
// 4. Replay the request with PAYMENT-SIGNATURE
res = await fetch("https://api.example.com/premium", {
headers: http.encodePaymentSignatureHeader(payload),
});
}
const settleInfo = http.getPaymentSettleResponse((n) => res.headers.get(n));
console.log("data:", await res.json(), "settle:", settleInfo);API Reference
Client Setup (x402Client & x402HTTPClient)
import { x402Client, x402HTTPClient } from "@altaga/x402-sui";
const core = new x402Client();
core.register("exact:sui:mainnet", schemeImpl); // exact match
core.register("exact:sui:*", wildcardImpl); // any network
core.register("*:*", catchAllImpl); // any scheme/network
const http = new x402HTTPClient(core);
// Decode a 402 response
const paymentRequired = http.getPaymentRequiredResponse(
(name) => res.headers.get(name),
null
);
// Build + sign + sponsor the payment
const payload = await http.createPaymentPayload(paymentRequired);
// Read the settlement info from the final response
const settleInfo = http.getPaymentSettleResponse((n) => res.headers.get(n));Server Setup (x402ResourceServer & x402HTTPResourceServer)
import express from "express";
import { x402ResourceServer, HTTPFacilitatorClient, x402HTTPResourceServer } from "@altaga/x402-sui";
const app = express();
const facilitator = new HTTPFacilitatorClient({ url: "https://facilitator.example.com" });
const resourceServer = new x402ResourceServer(facilitator);
resourceServer.register("exact:sui:mainnet", new ExactSuiServerScheme());
await resourceServer.initialize();
const routes = {
"GET /premium": { accepts: { /* ... */ } },
"POST /upload": { accepts: { /* ... */ } },
};
app.use(new x402HTTPResourceServer(resourceServer, routes).middleware());Facilitator Setup (x402Facilitator)
import { x402Facilitator } from "@altaga/x402-sui";
const facilitator = new x402Facilitator();
facilitator.register("exact:sui:mainnet", new ExactSuiFacilitatorScheme(sui, keypair));
// Sponsor — turn a raw client PTB into a gas-sponsored transaction
const { sponsoredTxBytes, sponsorSignature } = await facilitator.sponsor("exact", "sui:mainnet", { txBytes, sender });
// Verify — must return { isValid: true } or throw
const verify = await facilitator.verify(paymentPayload, paymentRequirements);
// Settle — must return { transactionDigest } or throw
const { transactionDigest } = await facilitator.settle(paymentPayload, paymentRequirements);Sui Exact Scheme
Provides the native implementations for the exact payment scheme on Sui:
import { ExactSuiClientScheme, ExactSuiServerScheme, ExactSuiFacilitatorScheme } from "@altaga/x402-sui";
// Buyer
core.register("exact:sui:mainnet", new ExactSuiClientScheme(sui, buyerKeypair));
// Server
resourceServer.register("exact:sui:mainnet", new ExactSuiServerScheme());
// Facilitator
facilitator.register("exact:sui:mainnet", new ExactSuiFacilitatorScheme(sui, sponsorKeypair));