Documentation

TypeScript SDK (Deprecated)

Add x402 payments to JavaScript/TypeScript applications. Supports Express, Hono, and Next.js.

This documentation is deprecated. You are viewing docs for the v0.x SDK which is no longer maintained. Please see the current v1.0.0 TypeScript SDK documentation for new projects.

npm @primersystems/x402

Installation

bash
npm install @primersystems/x402

Quick Start (CLI)

Manage wallets, probe URLs, and make payments from the command line:

bash
# Create a new wallet
npx @primersystems/x402 wallet create

# Check wallet balance
npx @primersystems/x402 wallet balance 0xYourAddress

# Check if a URL requires payment (and get price)
npx @primersystems/x402 probe https://api.example.com/paid

# Preview payment without paying
npx @primersystems/x402 pay https://api.example.com/paid --dry-run

# Make a payment
X402_PRIVATE_KEY=0x... npx @primersystems/x402 pay https://api.example.com/paid --max-amount 0.10

CLI Commands

Command Description
wallet createCreate a new wallet (address, private key, mnemonic)
wallet balance <address>Check USDC balance
wallet from-mnemonicRestore wallet from mnemonic
probe <url>Check if URL requires payment
pay <url>Make a payment (requires X402_PRIVATE_KEY)
pay <url> --dry-runPreview payment without paying
networksList supported networks
openclaw initSet up for OpenClaw agents
create <template> [dir]Scaffold a project from template

Environment Variables

Variable Description
X402_PRIVATE_KEYWallet private key (required for payments)
X402_NETWORKDefault network (default: base)
X402_MAX_AMOUNTDefault max payment amount in USDC
X402_FACILITATORCustom facilitator URL

Wallet Utilities

Programmatic wallet management:

javascript
const { createWallet, walletFromMnemonic, getBalance, x402Probe } = require('@primersystems/x402');

// Create a new wallet
const wallet = createWallet();
console.log(wallet.address);     // 0x...
console.log(wallet.privateKey);  // 0x...
console.log(wallet.mnemonic);    // "word1 word2 ..."

// Restore from mnemonic
const restored = walletFromMnemonic('word1 word2 ...');

// Check balance
const balance = await getBalance('0x...', 'base', 'USDC');
console.log(balance.balance);  // "100.50"

// Probe a URL for x402 support
const probe = await x402Probe('https://api.example.com/paid');
if (probe.supports402) {
  console.log('Payment required:', probe.requirements);
}

Error Handling

Structured errors for programmatic handling:

javascript
const { X402Error, ErrorCodes } = require('@primersystems/x402');

try {
  const response = await x402Fetch(url, signer, { maxAmount: '0.10' });
} catch (error) {
  if (error instanceof X402Error) {
    switch (error.code) {
      case ErrorCodes.INSUFFICIENT_FUNDS:
        console.log('Need more funds:', error.details);
        break;
      case ErrorCodes.AMOUNT_EXCEEDS_MAX:
        console.log('Payment too expensive:', error.details);
        break;
      case ErrorCodes.SETTLEMENT_FAILED:
        console.log('Settlement failed:', error.details);
        break;
    }
  }
}

Error Codes

Code Description
INSUFFICIENT_FUNDSWallet balance too low
AMOUNT_EXCEEDS_MAXPayment exceeds maxAmount
SETTLEMENT_FAILEDFacilitator settlement failed
INVALID_RESPONSEMalformed 402 response
MISSING_PRIVATE_KEYPrivate key not provided
UNSUPPORTED_NETWORKNetwork not supported

Payer (Client)

Wrap fetch or axios to automatically handle 402 responses:

javascript
const { createSigner, x402Fetch } = require('@primersystems/x402');

// Create a signer with CAIP-2 network format
const signer = await createSigner('eip155:8453', process.env.PRIVATE_KEY);

// Wrap fetch to handle 402 automatically
const fetch402 = x402Fetch(fetch, signer, { maxAmount: '1.00' });

// Use like normal fetch — payments happen automatically
const response = await fetch402('https://api.example.com/paid-endpoint');

With Axios

javascript
const { createSigner, x402Axios } = require('@primersystems/x402');

const signer = await createSigner('eip155:8453', process.env.PRIVATE_KEY);
const axios402 = x402Axios(axios.create(), signer, { maxAmount: '1.00' });

const response = await axios402.get('https://api.example.com/paid-endpoint');

With viem

javascript
import { createWalletClient, http } from 'viem';
import { base } from 'viem/chains';
import { privateKeyToAccount } from 'viem/accounts';
import { createSigner, x402Fetch } from '@primersystems/x402';

// Create a viem wallet client
const walletClient = createWalletClient({
  account: privateKeyToAccount(process.env.PRIVATE_KEY),
  chain: base,
  transport: http()
});

// Pass the wallet client directly to createSigner
const signer = await createSigner(walletClient);
const fetch402 = x402Fetch(fetch, signer, { maxAmount: '1.00' });

Payer Options

Option Required Description
maxAmount Yes Maximum payment per request (e.g., '1.00')
facilitator No Custom facilitator URL
verify No Verify payment before sending (default: true)

Payee (Server)

Add payment requirements to your API routes using middleware.

Express

javascript
const { x402Express } = require('@primersystems/x402');

app.use(x402Express('0xYourWalletAddress', {
  '/api/premium': {
    amount: '0.01',                                     // $0.01 USDC
    asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',  // USDC on Base
    network: 'eip155:8453'                              // Base mainnet
  },
  '/api/data/*': {
    amount: '0.001',
    asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
    network: 'eip155:8453'
  }
}));

Hono

javascript
const { x402Hono } = require('@primersystems/x402');

app.use('*', x402Hono('0xYourWalletAddress', {
  '/api/premium': {
    amount: '0.01',
    asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
    network: 'eip155:8453'
  }
}));

Next.js (App Router)

javascript
import { x402Next } from '@primersystems/x402';

async function handler(req) {
  return Response.json({ data: 'premium content' });
}

export const GET = x402Next(handler, {
  payTo: '0xYourWalletAddress',
  amount: '0.01',
  asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
  network: 'eip155:8453'
});

Single Route Protection

For protecting individual routes without full middleware:

javascript
const { x402Protect } = require('@primersystems/x402');

app.get('/api/premium',
  x402Protect('0xYourWallet', '0.01', '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', 'eip155:8453'),
  (req, res) => {
    res.json({ data: 'premium content' });
  }
);

Token Approval (ERC-20)

For non-EIP-3009 tokens, approve the Prism contract once:

javascript
const { createSigner, approveToken } = require('@primersystems/x402');

const signer = await createSigner('eip155:8453', process.env.PRIVATE_KEY);

// One-time approval (requires gas)
await approveToken(signer, '0xTokenAddress');

// Now payments with this token are gasless

Custom Facilitator

For non-Base networks, specify your own facilitator:

javascript
// Payee
app.use(x402Express('0xAddress', routes, {
  facilitator: 'https://your-facilitator.com'
}));

// Payer
const fetch402 = x402Fetch(fetch, signer, {
  maxAmount: '1.00',
  facilitator: 'https://your-facilitator.com'
});

Testing

The SDK includes utilities for testing without real payments:

javascript
const { createMockFacilitator, createTestPayment } = require('@primersystems/x402/testing');

describe('paid endpoint', () => {
  let mock;

  beforeAll(async () => {
    mock = await createMockFacilitator({ mode: 'approve' });
  });

  afterAll(() => mock.close());

  test('accepts payment', async () => {
    const payment = createTestPayment({ amount: '10000' });

    const res = await fetch('/api/premium', {
      headers: { 'PAYMENT-SIGNATURE': payment }
    });

    expect(res.status).toBe(200);
  });
});

Debug Logging

bash
DEBUG=x402:* node app.js
DEBUG=x402:payer,x402:payee node app.js

Bittensor Integration

Build pay-per-inference proxies for Bittensor subnets. The SDK includes templates for wrapping Bittensor APIs with x402 payments, starting with Chutes (Subnet 64).

bash
# Scaffold a Chutes AI proxy
npx @primersystems/x402 create chutes-proxy my-ai-proxy
cd my-ai-proxy
npm install

# Configure and run
cp .env.example .env
npm run dev

The generated proxy accepts USDC payments on Base and forwards requests to Chutes for AI inference. Deploy free on Cloudflare Workers:

bash
wrangler secret put CHUTES_API_KEY
wrangler secret put WALLET_ADDRESS
npm run deploy

See the Bittensor Integration guide for full documentation.

OpenClaw Integration

This SDK is compatible with OpenClaw AI agents. Set up your agent with one command:

bash
npx @primersystems/x402 openclaw init

This creates a wallet, configures the network, and installs the x402 skill. Check status with:

bash
npx @primersystems/x402 openclaw status