SDK Reference
Complete API reference for @zan_team/x402
Installation
npm install @zan_team/x402 viemSolana optional dependencies (only needed for SVM auth/payment):
npm install @solana/web3.js @solana/spl-token bs58 tweetnaclRequires Node.js >= 18.
Client creation
import { createX402Client } from '@zan_team/x402';
// EVM wallet
const client = await createX402Client({
gatewayUrl: 'https://x402.zan.top',
privateKey: process.env.PRIVATE_KEY as `0x${string}`,
autoPayment: true,
preAuth: true,
});
// Solana wallet
const svmClient = await createX402Client({
gatewayUrl: 'https://x402.zan.top',
svmPrivateKey: process.env.SOLANA_KEY, // Base58
chainType: 'SVM',
autoPayment: true,
preAuth: true,
});Configuration
interface X402ClientConfig {
gatewayUrl: string;
// EVM
wallet?: WalletClient;
privateKey?: `0x${string}`;
// SVM
svmPrivateKey?: string; // Base58
paymentNetwork?: string; // CAIP-2, e.g. "eip155:8453"
solanaRpcUrl?: string;
// Behavior
chainType?: 'EVM' | 'SVM'; // auto-detected from keys
autoPayment?: boolean; // default: false
defaultBundle?: BundleType; // default: 'default'
preAuth?: boolean; // pre-authenticate on creation
timeout?: number; // ms, default: 30000
aiTimeout?: number; // ms, default: 120000 (AI calls)
fetch?: typeof fetch; // custom fetch implementation
}| Parameter | Type | Default | Description |
|---|---|---|---|
gatewayUrl | string | — | Gateway URL (required) |
privateKey | 0x${string} | — | EVM private key |
svmPrivateKey | string | — | Solana private key (Base58) |
chainType | 'EVM' | 'SVM' | auto-detect | Wallet type |
autoPayment | boolean | false | Automatically handle 402 payments |
preAuth | boolean | false | Authenticate on client creation |
defaultBundle | string | 'default' | Bundle used for auto-purchase |
paymentNetwork | string | — | Payment network (CAIP-2 format) |
timeout | number | 30000 | General request timeout (ms) |
aiTimeout | number | 120000 | AI call timeout (ms) |
solanaRpcUrl | string | — | Solana RPC for building transactions |
Architecture
X402Client
├── auth AuthModule SIWE/SIWS + JWT lifecycle
├── credits CreditsModule balance · purchase · usage · payment status
├── rpc RpcModule JSON-RPC · batch · generic provider forward
├── ai AiModule AI model chat · rolling settlement · history · stats
└── discovery DiscoveryModule health · providers · networks · bundles · AI models
Subpath exports for tree-shaking: @zan_team/x402/auth, @zan_team/x402/credits, @zan_team/x402/rpc, @zan_team/x402/ai.
Core API
createX402Client(config): Promise<X402Client>
createX402Client(config): Promise<X402Client>Creates and initializes the client. If preAuth: true, performs SIWE/SIWS authentication before returning.
const client = await createX402Client({ gatewayUrl, privateKey, autoPayment: true, preAuth: true });client.call(ecosystem, network, method, params?): Promise<JsonRpcResponse>
client.call(ecosystem, network, method, params?): Promise<JsonRpcResponse>Calls a JSON-RPC method on the specified chain. Credits are deducted per method weight.
const block = await client.call('eth', 'mainnet', 'eth_blockNumber');
const balance = await client.call('eth', 'mainnet', 'eth_getBalance', ['0x...', 'latest']);
const slot = await client.call('solana', 'mainnet', 'getSlot');With autoPayment: true, automatically purchases credits if balance is insufficient.
client.chat(model, options): Promise<AiResponse>
client.chat(model, options): Promise<AiResponse>Calls an AI model. Uses rolling settlement: first call is free, subsequent calls settle the previous call's token cost.
const response = await client.chat('deepseek-v4-flash', {
messages: [{ role: 'user', content: 'Hello' }],
max_tokens: 1024,
});
console.log(response.data.content); // AI response text
console.log(response.data.model); // model used
console.log(response.data.usage); // { prompt_tokens, completion_tokens, total_tokens }
console.log(response.data.finish_reason); // "stop"
console.log(response.txHash); // payment tx hash (null on first call)
console.log(response.paymentNetwork); // "eip155:8453" (null on first call)With autoPayment: true, automatically signs payment for previous call's token cost.
client.getBalance(): Promise<BalanceResponse>
client.getBalance(): Promise<BalanceResponse>Returns current credit balance and usage statistics.
const bal = await client.getBalance();
console.log(bal.balance); // current credits
console.log(bal.totalPurchased); // lifetime purchased
console.log(bal.totalConsumed); // lifetime consumed
console.log(bal.wallet); // wallet address
console.log(bal.tier); // "trial" | "standard"client.purchaseCredits(bundle): Promise<PurchaseReceipt>
client.purchaseCredits(bundle): Promise<PurchaseReceipt>Explicitly purchases a credit bundle via x402 payment.
const receipt = await client.purchaseCredits('default');
console.log(receipt.creditsPurchased); // 100000
console.log(receipt.balance); // new balance
console.log(receipt.txHash); // on-chain tx hash
console.log(receipt.paymentNetwork); // "eip155:8453"client.listBundles(): Promise<BundlesResponse>
client.listBundles(): Promise<BundlesResponse>Lists available credit bundles and their pricing.
const { bundles } = await client.listBundles();
// [{ name: 'default', credits: 100000, price: '0.015', description: '~5,000 RPC calls' }]client.fetch(path, options): Promise<Response>
client.fetch(path, options): Promise<Response>Low-level HTTP method with automatic JWT injection. Use for custom endpoints.
const response = await client.fetch('/credits/usage?limit=50', { method: 'GET' });Discovery API
All discovery methods are available without authentication.
client.discovery.health(): Promise<HealthResponse>
client.discovery.health(): Promise<HealthResponse>const health = await client.discovery.health();
// { status: "ok", uptime: 3600 }client.discovery.listProviders(): Promise<ProvidersResponse>
client.discovery.listProviders(): Promise<ProvidersResponse>const { providers } = await client.discovery.listProviders();
// [{ id: "zan-rpc", name: "ZAN Multi-chain RPC", type: "PROXY", routes: [...] }]client.discovery.listNetworks(): Promise<NetworksResponse>
client.discovery.listNetworks(): Promise<NetworksResponse>const { networks } = await client.discovery.listNetworks();
// [{ ecosystem: "eth", network: "mainnet", providerId: "zan-rpc" }, ...]client.discovery.listBundles(): Promise<BundlesResponse>
client.discovery.listBundles(): Promise<BundlesResponse>const { bundles } = await client.discovery.listBundles();client.discovery.listAiModels(): Promise<AiModelsResponse>
client.discovery.listAiModels(): Promise<AiModelsResponse>const { models } = await client.discovery.listAiModels();
models.forEach(m => {
console.log(`${m.id}: input=${m.inputPricePerToken}, output=${m.outputPricePerToken}`);
});Error hierarchy
All errors extend X402Error with typed code and optional statusCode.
import { X402Error, AuthenticationError, InsufficientCreditsError } from '@zan_team/x402';
try {
await client.call('eth', 'mainnet', 'eth_blockNumber');
} catch (err) {
if (err instanceof InsufficientCreditsError) {
console.log(`Need ${err.required} credits, have ${err.balance}`);
} else if (err instanceof X402Error) {
console.log(`x402 error: ${err.code} (HTTP ${err.statusCode})`);
}
}| Error | HTTP | Scenario | SDK behavior with autoPayment: true |
|---|---|---|---|
AuthenticationError | 401 | SIWE/SIWS signature rejected | Throws (cannot auto-fix) |
SessionExpiredError | 401 | JWT expired | Auto re-authenticates and retries |
InsufficientCreditsError | 402 | Not enough credits | Auto purchases credits and retries |
InsufficientFundsError | 402 | On-chain USDC too low | Throws (cannot auto-fix) |
PaymentRejectedError | 402 | Facilitator rejected payment | Throws |
MethodNotAllowedError | 403 | Method blocked by gateway | Throws (cannot retry) |
ProviderNotFoundError | 404 | No matching route | Throws |
AiModelNotFoundError | 404 | AI model not supported | Throws |
AiPaymentRequiredError | 402 | AI payment needed | Auto signs and retries |
AiUpstreamError | 502/504 | AI upstream failure | Throws (not charged) |
UpstreamError | 504 | Provider failure | Throws (credits refunded) |
NetworkError | — | Transport / timeout | Throws |
Auto-payment flows
RPC (credit-based)
client.call()
│
▼
POST /rpc/{eco}/{net} → 402 insufficient_credits
│
▼ [autoPayment: true]
POST /credits/purchase/default → 402 + PAYMENT-REQUIRED
│
▼ [SDK signs EIP-3009 or Solana SPL]
POST /credits/purchase/default + PAYMENT-SIGNATURE → 200
│
▼ [credits topped up]
POST /rpc/{eco}/{net} (retry) → 200 + result
AI (rolling settlement)
client.chat() [first call]
│
▼
POST /ai/{model} → 200 + response (free, usage recorded as pending)
client.chat() [subsequent call]
│
▼
POST /ai/{model} → 402 (settle previous token cost)
│
▼ [autoPayment: true, SDK signs payment]
POST /ai/{model} + PAYMENT-SIGNATURE → 200 + response + txHash
Advanced patterns
Custom payment network
const client = await createX402Client({
gatewayUrl: 'https://x402.zan.top',
privateKey: '0x...',
autoPayment: true,
paymentNetwork: 'eip155:8453', // Base Mainnet
});Solana client
const client = await createX402Client({
gatewayUrl: 'https://x402.zan.top',
svmPrivateKey: '<Base58 secret key>',
chainType: 'SVM',
paymentNetwork: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', // Mainnet
solanaRpcUrl: 'https://api.mainnet-beta.solana.com',
autoPayment: true,
preAuth: true,
});Manual payment control
const client = await createX402Client({
gatewayUrl: 'https://x402.zan.top',
privateKey: '0x...',
autoPayment: false, // handle payments yourself
preAuth: true,
});
// Check balance before calling
const { balance } = await client.getBalance();
if (balance < 100) {
await client.purchaseCredits('default');
}
// Now call (will throw InsufficientCreditsError if still not enough)
const block = await client.call('eth', 'mainnet', 'eth_blockNumber');Error handling pattern
import {
InsufficientFundsError,
AiUpstreamError,
NetworkError,
} from '@zan_team/x402';
async function reliableCall(client, model, messages) {
try {
return await client.chat(model, { messages, max_tokens: 1024 });
} catch (err) {
if (err instanceof InsufficientFundsError) {
// Wallet needs more USDC — alert user
console.error('Wallet USDC balance too low for payment');
throw err;
}
if (err instanceof AiUpstreamError) {
// Upstream model failed — not charged, safe to retry with different model
return await client.chat('deepseek-v4-flash', { messages, max_tokens: 1024 });
}
if (err instanceof NetworkError) {
// Transient network issue — retry after delay
await new Promise(r => setTimeout(r, 2000));
return await client.chat(model, { messages, max_tokens: 1024 });
}
throw err;
}
}Next steps
- Quick Start — Get running in 3 minutes
- AI Models — Model catalog and rolling settlement details
- Node Service — Supported chains and methods
- x402 Payment — Payment protocol internals
Updated about 10 hours ago
