@t2000/x402
v0.3.0
Published
x402 payment protocol client for AI agents on Sui — pay for API resources with USDC
Downloads
1,508
Maintainers
Readme
@t2000/x402
x402 payment protocol client and facilitator for AI agents on Sui. Pay for API resources with USDC micropayments — the first x402 implementation on Sui.
What is x402?
The x402 protocol enables machine-to-machine payments for API access. When a server returns HTTP 402 Payment Required, the client automatically pays with USDC and retries — no API keys, no subscriptions, no human approval.
t2000 is the first x402 client on Sui, built on the Sui Payment Kit for on-chain payment verification with Move-level replay protection.
Installation
npm install @t2000/x402
# or
pnpm add @t2000/x402
# or
yarn add @t2000/x402Requirements: Node.js 18+ · @t2000/sdk (peer dependency)
Quick Start — Client
import { x402Client } from '@t2000/x402';
import { T2000 } from '@t2000/sdk';
const agent = await T2000.create({ pin: 'my-secret' });
const client = new x402Client(agent);
// Fetch a paid API — handles the full 402 handshake
const response = await client.fetch('https://api.example.com/data', {
maxPrice: 0.10, // max USDC per request (default: $1.00)
timeout: 30_000, // request timeout in ms (default: 30s)
});
const data = await response.json();Quick Start — CLI
# Pay for an API request (handles 402 automatically)
t2000 pay https://api.example.com/data
# With max price limit
t2000 pay https://api.example.com/premium --max-price 0.10
# POST request with JSON body
t2000 pay https://api.example.com/analyze --method POST --data '{"text":"hello"}'How It Works
Agent API Server Facilitator (t2000)
│ │ │
│── GET /data ────────────>│ │
│<── 402 Payment Required ─│ │
│ (amount, recipient) │ │
│ │ │
│── Sign & broadcast ─────────────────────────────────│
│ USDC payment on Sui │ │
│ │ │
│── GET /data ────────────>│ │
│ + X-PAYMENT header │── POST /x402/verify ────>│
│ │<── { valid: true } ──────│
│<── 200 OK + data ────────│ │
│ │── POST /x402/settle ────>│
│ │<── { settled: true } ────│Total round-trip: ~820ms.
Client API
new x402Client(wallet)
Creates an x402 client with the given wallet. Per-request options like maxPrice and timeout are passed to client.fetch().
const client = new x402Client(wallet);client.fetch(url, init?)
Makes an HTTP request, automatically handling 402 Payment Required responses.
const res = await client.fetch('https://api.example.com/data', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: 'hello' }),
});parsePaymentRequired(headerValue, maxPrice?)
Parses the PAYMENT-REQUIRED header from a 402 response into structured payment terms. Validates network (must be sui), asset (must be USDC), expiry, and price limit.
import { parsePaymentRequired } from '@t2000/x402';
const headerValue = response.headers.get('payment-required');
const terms = parsePaymentRequired(headerValue, 1.0);
// { amount: '0.01', payTo: '0x...', network: 'sui', nonce: '...', expiresAt: 1709... }Facilitator API (Server-Side)
For API providers who want to accept x402 payments:
verifyPayment(client, request)
Verify that an on-chain payment transaction is valid. Checks the transaction for a PaymentReceipt event and validates amount, recipient, and nonce.
import { verifyPayment } from '@t2000/x402';
import { SuiJsonRpcClient, getJsonRpcFullnodeUrl } from '@mysten/sui/jsonRpc';
const client = new SuiJsonRpcClient({ url: getJsonRpcFullnodeUrl('mainnet'), network: 'mainnet' });
const result = await verifyPayment(client, {
txHash: 'ABC123...',
amount: '0.01',
asset: 'USDC',
payTo: '0x...',
nonce: 'unique-nonce',
expiresAt: 1709500000,
network: 'sui',
});
if (result.verified) {
// Payment verified — serve the resource
}Settlement
Settlement (marking payments as used) is handled server-side by the t2000 facilitator API. The /x402/settle endpoint records the payment in the database to prevent double-use. See the server source for implementation details.
Payment Kit Integration
Payments are executed on-chain via the Sui Payment Kit, which provides:
- Atomic payments — pay and verify in a single Sui transaction
- Move-level nonce enforcement —
EDuplicatePaymentabort prevents replay attacks - On-chain receipts —
PaymentReceiptevents for auditing
import { buildPaymentTransaction } from '@t2000/x402';
import { SuiJsonRpcClient, getJsonRpcFullnodeUrl } from '@mysten/sui/jsonRpc';
const client = new SuiJsonRpcClient({ url: getJsonRpcFullnodeUrl('mainnet'), network: 'mainnet' });
// Build a payment transaction (advanced usage)
const tx = await buildPaymentTransaction(client, senderAddress, {
nonce: 'unique-nonce',
amount: '0.01', // USDC as string (converted to raw internally)
payTo: '0x...',
});Configuration
| Environment Variable | Description | Default |
|---------------------|-------------|---------|
| PAYMENT_KIT_PACKAGE | Payment Kit Move package ID | Mainnet default |
| T2000_PAYMENT_REGISTRY_ID | PaymentRegistry object ID | t2000 mainnet registry |
| X402_FACILITATOR_URL | Facilitator base URL | https://api.t2000.ai/x402 |
Safety
- Price limits — payments refused if amount exceeds
maxPrice(default $1.00) - Network validation — only Sui payments are accepted
- Replay protection — on-chain nonce enforcement via Sui Payment Kit
- Timeout — requests abort after configurable timeout (default 30s)
Wallet Interface
Any wallet implementing X402Wallet can be used as a payment source:
interface X402Wallet {
client: SuiJsonRpcClient;
keypair: Ed25519Keypair;
address(): string;
signAndExecute(tx: unknown): Promise<{ digest: string }>;
}The T2000 class from @t2000/sdk implements this interface.
Testing
# Unit tests (27 tests)
pnpm --filter @t2000/x402 test
# Integration tests (requires funded mainnet wallet)
T2000_PRIVATE_KEY='suiprivkey1q...' INTEGRATION=true pnpm --filter @t2000/x402 testIntegration tests execute real on-chain transactions to verify the full payment flow and replay protection. See the root README for details.
License
MIT — see LICENSE
