@fastxyz/x402-client
v1.0.7
Published
Client SDK for the x402 HTTP Payment Protocol — pay for x402-protected content
Keywords
Readme
@fastxyz/x402-client
Client SDK for the x402 HTTP Payment Protocol. Automatically handles HTTP 402 Payment Required responses by signing and paying for content.
Supports:
- Fast networks — via wallet
rpcUrl - EVM networks — via EIP-3009 transferWithAuthorization
- Auto-bridge — Fast USDC → EVM USDC when EVM balance insufficient
Use Cases
- Pay for a 402-protected API endpoint
- Handle HTTP 402 Payment Required responses automatically
- Auto-bridge Fast USDC → EVM USDC for EVM payments
- Check Fast balance or bridge funds manually
Out of scope: Protecting API routes → @fastxyz/x402-server · Running a facilitator → @fastxyz/x402-facilitator · General wallet operations → @fastxyz/sdk
Installation
pnpm add @fastxyz/x402-clientQuick Start
Fast Payment
import { x402Pay } from '@fastxyz/x402-client';
const result = await x402Pay({
url: 'https://api.example.com/premium',
wallet: {
type: 'fast',
privateKey: '0x...',
publicKey: '0x...',
address: 'fast1...',
rpcUrl: 'https://api.fast.xyz/proxy-rest',
},
});
console.log(result.body); // Paid contentEVM Payment
import { x402Pay } from '@fastxyz/x402-client';
const result = await x402Pay({
url: 'https://api.example.com/premium',
wallet: {
type: 'evm',
privateKey: '0x...',
address: '0x...',
},
evmNetworks: {
'arbitrum-sepolia': {
chainId: 421614,
rpcUrl: 'https://sepolia-rollup.arbitrum.io/rpc',
usdcAddress: '0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d',
},
},
});Auto-Bridge (Fast → EVM)
When both wallet types and a bridgeConfig are provided, the client will automatically bridge Fast USDC to EVM if the EVM wallet has insufficient balance.
interface BridgeConfig {
rpcUrl: string; // Fast network RPC URL
fastBridgeAddress: string; // Fast address of the AllSet bridge contract
relayerUrl: string; // AllSet relayer URL
crossSignUrl: string; // AllSet cross-sign service URL
tokenEvmAddress: string; // USDC address on the EVM side (e.g., '0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d')
tokenFastTokenId: string; // USDC token ID on the Fast network (hex, no 0x)
networkId: string; // Fast network ID (e.g., 'fast:testnet')
}
const result = await x402Pay({
url: 'https://api.example.com/premium',
wallet: [fastWallet, evmWallet],
evmNetworks: { ... },
bridgeConfig: {
rpcUrl: 'https://rpc.testnet.fast.co',
fastBridgeAddress: 'fast1bridge...',
relayerUrl: 'https://relayer.example.com',
crossSignUrl: 'https://crosssign.example.com',
tokenEvmAddress: '0x...',
tokenFastTokenId: 'abc123...',
networkId: 'fast:testnet',
},
});API
x402Pay(params: X402PayParams): Promise<X402PayResult>
Main entry point. Fetches the URL, and if a 402 is returned, handles payment automatically.
Parameters (X402PayParams):
| Field | Type | Required | Description |
| -------------- | -------------------------------- | -------- | ----------------------------------------------- |
| url | string | Yes | URL of the 402-protected resource |
| method | string | No | HTTP method (default: GET) |
| headers | Record<string, string> | No | Custom headers |
| body | string | No | Request body |
| wallet | Wallet \| Wallet[] | Yes | Wallet(s) for payment |
| evmNetworks | Record<string, EvmChainConfig> | No* | EVM chain configs (*required for EVM payments) |
| bridgeConfig | BridgeConfig | No | Bridge config for auto-bridge |
| verbose | boolean | No | Enable verbose logging |
Result (X402PayResult.payment):
For Fast-network payments, payment.amount is the raw integer amount in
the asset's smallest unit (a string, mirroring maxAmountRequired from the
server's payment requirement). The PaymentRequirement wire format does not
carry token decimals, so the client cannot humanize the value on its own —
consumers needing a display string must humanize using their own
token-decimals registry (for example, by looking up payment.asset against a
known token list).
EVM-network payments currently still humanize payment.amount with the USDC
6-decimals assumption baked in; this asymmetry will be resolved in a future
release. New downstream code should treat payment.amount as a raw
smallest-unit string regardless of network and humanize explicitly when
needed.
bridgeFastusdcToUsdc(params)
Manually bridge Fast USDC to EVM USDC using a single params object.
import { bridgeFastusdcToUsdc } from '@fastxyz/x402-client';
const result = await bridgeFastusdcToUsdc({
fastWallet,
evmReceiverAddress: evmWallet.address,
amount: 1000000n,
rpcUrl: bridgeConfig.rpcUrl,
fastBridgeAddress: bridgeConfig.fastBridgeAddress,
relayerUrl: bridgeConfig.relayerUrl,
crossSignUrl: bridgeConfig.crossSignUrl,
tokenEvmAddress: bridgeConfig.tokenEvmAddress,
tokenFastTokenId: bridgeConfig.tokenFastTokenId,
networkId: bridgeConfig.networkId,
});
console.log(result.txHash); // Bridge transaction hashgetFastBalance(wallet: FastWallet, options: { rpcUrl: string; tokenId: string }): Promise<bigint>
Get a token balance on the Fast network.
import { getFastBalance } from '@fastxyz/x402-client';
const balance = await getFastBalance(fastWallet, {
rpcUrl: 'https://api.fast.xyz/proxy-rest',
tokenId: 'abc123...',
});
console.log('Fast USDC balance:', balance); // bigint (smallest units)Low-Level Utilities
parse402Response(response: Response): Promise<PaymentRequired>
Parse a raw HTTP 402 response into a typed PaymentRequired object. Throws if the response status is not 402.
import { parse402Response } from '@fastxyz/x402-client';
const paymentReq = await parse402Response(response);
console.log(paymentReq.accepts); // Array of accepted payment methodsbuildPaymentHeader(payload: unknown): string
Build a base64-encoded X-PAYMENT header value from a payment payload object. Useful for manual payment flows where you construct the payload yourself.
import { buildPaymentHeader } from '@fastxyz/x402-client';
const header = buildPaymentHeader({
x402Version: 1,
scheme: 'exact',
// ...payment payload fields
});
// Use as: headers['X-PAYMENT'] = headerparsePaymentHeader(header: string): unknown
Parse a base64-encoded X-PAYMENT header string back into a decoded object. Inverse of buildPaymentHeader.
import { parsePaymentHeader } from '@fastxyz/x402-client';
const payload = parsePaymentHeader('eyJ4NDAyVmVyc2lvbiI6MS...');Common Pitfalls
- DO NOT omit
rpcUrlonFastWallet— it is required, not optional. - DO NOT omit
evmNetworkswhen using an EVM wallet — the SDK has no hardcoded chains. - DO NOT forget
bridgeConfigwhen using auto-bridge — it must includenetworkId. - DO NOT pass a single wallet when auto-bridge is needed — pass
[fastWallet, evmWallet]as an array.
Design
- No hardcoded network configs — all chain/network info provided via
evmNetworksparameter - Wallet-type dispatch — automatically routes to Fast or EVM handler based on
wallet.type - Progressive enhancement — start with a single wallet, add auto-bridge later
