x402 Facilitator
Octo x402 Protocol Documentation
Overview
Octo x402 is a decentralized payment protocol that enables instant micropayments for digital content and API access. It supports both EVM (Ethereum Virtual Machine) and SVM (Solana Virtual Machine) networks, allowing merchants to accept USDC payments seamlessly across multiple blockchains.
Protocol Version: x402 v1
Facilitator URL: https://facilitator.octox402.xyz
Status: Production Ready (12 networks) | Testing Phase (BSC, Ethereum, and more)
Architecture
The x402 protocol consists of three main components:
1. Facilitator
URL:
https://facilitator.octox402.xyzVerifies payment signatures and requirements
Submits transactions to blockchain
EVM Networks: Facilitator pays gas fees (~$0.001-0.01)
SVM Networks: Facilitator only verifies; consumer pays transaction fees (~$0.000005)
2. Merchant
Exposes content behind payment requirements
Returns HTTP 402 with payment requirements when payment is needed
Verifies payments via facilitator
Serves content after successful payment settlement
3. Consumer
Signs payment authorizations using wallet
Sends payments via
X-PAYMENTheaderReceives content after payment verification
Supported Networks
⚡ Production Ready (12 Networks)
EVM Networks (10 networks)
Base
base
8453
Mainnet
✅ Live
Base Sepolia
base-sepolia
84532
Testnet
✅ Live
Abstract
abstract
-
Mainnet
✅ Live
Abstract Testnet
abstract-testnet
-
Testnet
✅ Live
Polygon
polygon
137
Mainnet
✅ Live
Polygon Amoy
polygon-amoy
80002
Testnet
✅ Live
Avalanche C-Chain
avalanche
43114
Mainnet
✅ Live
Avalanche Fuji
avalanche-fuji
43113
Testnet
✅ Live
SEI
sei
-
Mainnet
✅ Live
SEI Testnet
sei-testnet
-
Testnet
✅ Live
IoTeX
iotex
4689
Mainnet
✅ Live
Peaq
peaq
-
Mainnet
✅ Live
SVM Networks (2 networks)
Solana
solana
Mainnet
✅ Live
Solana Devnet
solana-devnet
Testnet
✅ Live
🚧 Coming Soon (Testing Phase)
BSC (Binance Smart Chain) - Chain ID: 56
Ethereum Mainnet - Chain ID: 1
Optimism - Layer 2
Arbitrum - Layer 2
Additional EVM-compatible chains
Network Details
USDC Contract Addresses
EVM Networks
Base:
0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913Polygon:
0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359Avalanche:
0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E
SVM Networks
Solana:
EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
Transaction Fees
Base
~$0.001
Facilitator
~2 seconds
Polygon
~$0.001
Facilitator
~2 seconds
Avalanche
~$0.01
Facilitator
~2 seconds
Solana
~$0.000005
Consumer
~400ms
Getting Started
Prerequisites
npm install axios ethers @solana/web3.js @solana/spl-token bs58 dotenv expressEnvironment Variables
Create a .env file:
# Consumer Configuration
CONSUMER_PRIVATE_KEY=your_evm_private_key_here # For EVM networks
CONSUMER_PRIVATE_KEY_BS58=your_solana_key_here # For Solana networks
MERCHANT_URL=https://your-merchant-url.com
# Merchant Configuration
MERCHANT_WALLET_ADDRESS=your_wallet_address # Your receiving wallet
FACILITATOR_URL=https://facilitator.octox402.xyz
# Network Selection (choose one)
NETWORK=base # Options: base, polygon, avalanche, solana, etc.
CHAIN_ID=8453 # For EVM networks only
# Optional: Custom RPC URLs
SOLANA_RPC=https://api.mainnet-beta.solana.com
BASE_RPC=https://mainnet.base.org
POLYGON_RPC=https://polygon-rpc.comQuick Start
1. Check Supported Networks
curl https://facilitator.octox402.xyz/supported2. Test Health
curl https://facilitator.octox402.xyz/health3. Implement Consumer (See examples below)
EVM Implementation
Consumer (Base Mainnet)
import axios from 'axios';
import { ethers } from 'ethers';
const CONSUMER_PRIVATE_KEY = process.env.CONSUMER_PRIVATE_KEY;
const MERCHANT_URL = process.env.MERCHANT_URL;
const NETWORK = 'base';
const CHAIN_ID = 8453;
const wallet = new ethers.Wallet(CONSUMER_PRIVATE_KEY);
async function createPayment(requirements: any): Promise<string> {
// EIP-712 domain for USDC
const domain = {
name: 'USD Coin',
version: '2',
chainId: CHAIN_ID,
verifyingContract: requirements.asset,
};
// EIP-712 types for USDC transferWithAuthorization
const types = {
TransferWithAuthorization: [
{ name: 'from', type: 'address' },
{ name: 'to', type: 'address' },
{ name: 'value', type: 'uint256' },
{ name: 'validAfter', type: 'uint256' },
{ name: 'validBefore', type: 'uint256' },
{ name: 'nonce', type: 'bytes32' },
],
};
const validAfter = 0;
const validBefore = Math.floor(Date.now() / 1000) + 3600;
const nonce = ethers.hexlify(ethers.randomBytes(32));
const value = {
from: wallet.address,
to: requirements.payTo,
value: requirements.maxAmountRequired,
validAfter,
validBefore,
nonce,
};
const signature = await wallet.signTypedData(domain, types, value);
const paymentPayload = {
x402Version: 1,
scheme: 'exact',
network: NETWORK,
payload: {
authorization: {
from: wallet.address,
to: requirements.payTo,
value: requirements.maxAmountRequired,
validAfter: validAfter.toString(),
validBefore: validBefore.toString(),
nonce: nonce,
},
signature: signature // String, not {v, r, s} object
}
};
return Buffer.from(JSON.stringify(paymentPayload)).toString('base64');
}
async function fetchWithPayment(url: string) {
let response = await axios.get(url, {
validateStatus: () => true
});
if (response.status === 402) {
const requirements = response.data;
const paymentHeader = await createPayment(requirements);
response = await axios.get(url, {
headers: { 'X-PAYMENT': paymentHeader },
validateStatus: () => true
});
}
return response.data;
}Merchant (Base Mainnet)
import express from 'express';
import axios from 'axios';
const app = express();
app.use(express.json());
const MERCHANT_WALLET = process.env.MERCHANT_WALLET_ADDRESS;
const MERCHANT_URL = process.env.MERCHANT_URL;
const FACILITATOR_URL = 'https://facilitator.octox402.xyz';
const NETWORK = 'base';
const USDC_ADDRESS = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
async function checkPayment(req: any, res: any, next: any) {
const paymentHeader = req.headers['x-payment'];
const paymentRequirements = {
scheme: 'exact',
network: NETWORK,
maxAmountRequired: '10000', // $0.01 USDC (6 decimals)
payTo: MERCHANT_WALLET,
asset: USDC_ADDRESS,
resource: `${MERCHANT_URL}${req.path}`,
description: 'Premium content access',
mimeType: 'application/json',
maxTimeoutSeconds: 300
};
if (!paymentHeader) {
return res.status(402).json(paymentRequirements);
}
try {
const decoded = Buffer.from(paymentHeader, 'base64').toString('utf-8');
const paymentPayload = JSON.parse(decoded);
// Step 1: Verify
const verifyResponse = await axios.post(
`${FACILITATOR_URL}/verify`,
{ paymentPayload, paymentRequirements },
{ headers: { 'Content-Type': 'application/json' } }
);
const verifyData = verifyResponse.data.success
? verifyResponse.data.data
: verifyResponse.data;
if (!verifyData.isValid) {
return res.status(402).json({
error: 'Payment verification failed',
reason: verifyData.invalidReason
});
}
// Step 2: Settle
const settleResponse = await axios.post(
`${FACILITATOR_URL}/settle`,
{ paymentPayload, paymentRequirements },
{ headers: { 'Content-Type': 'application/json' } }
);
const settleData = settleResponse.data.success
? settleResponse.data.data
: settleResponse.data;
if (!settleData.success) {
return res.status(402).json({
error: 'Payment settlement failed'
});
}
next();
} catch (error: any) {
return res.status(500).json({
error: 'Payment processing failed',
message: error.message
});
}
}
// Protected endpoint
app.get('/premium-content', checkPayment, (req, res) => {
res.json({ data: 'Your premium content here' });
});
app.listen(3000);SVM Implementation
Consumer (Solana Mainnet)
Important: On Solana, the consumer pays their own transaction fees (~$0.000005). The facilitator only verifies the payment.
import axios from 'axios';
import {
Keypair,
PublicKey,
Connection,
TransactionMessage,
VersionedTransaction
} from '@solana/web3.js';
import {
getAssociatedTokenAddress,
createTransferInstruction
} from '@solana/spl-token';
import bs58 from 'bs58';
const CONSUMER_PRIVATE_KEY_BS58 = process.env.CONSUMER_PRIVATE_KEY_BS58;
const MERCHANT_URL = process.env.MERCHANT_URL;
const NETWORK = 'solana';
const RPC_URL = process.env.SOLANA_RPC || 'https://api.mainnet-beta.solana.com';
const keypair = Keypair.fromSecretKey(bs58.decode(CONSUMER_PRIVATE_KEY_BS58));
const connection = new Connection(RPC_URL, 'confirmed');
async function createPayment(requirements: any): Promise<string> {
const fromPubkey = keypair.publicKey;
const toPubkey = new PublicKey(requirements.payTo);
const mintPubkey = new PublicKey(requirements.asset);
const amount = BigInt(requirements.maxAmountRequired);
// Get associated token accounts
const fromTokenAccount = await getAssociatedTokenAddress(mintPubkey, fromPubkey);
const toTokenAccount = await getAssociatedTokenAddress(mintPubkey, toPubkey);
// Create transfer instruction
const transferInstruction = createTransferInstruction(
fromTokenAccount,
toTokenAccount,
fromPubkey,
amount
);
// Get recent blockhash
const { blockhash } = await connection.getLatestBlockhash('finalized');
// Create v0 versioned transaction
const messageV0 = new TransactionMessage({
payerKey: fromPubkey, // Consumer pays fees
recentBlockhash: blockhash,
instructions: [transferInstruction],
}).compileToV0Message();
const transaction = new VersionedTransaction(messageV0);
transaction.sign([keypair]);
// Serialize transaction
const serializedTx = transaction.serialize();
const base64Tx = Buffer.from(serializedTx).toString('base64');
const paymentPayload = {
x402Version: 1,
scheme: 'exact',
network: NETWORK,
payload: {
transaction: base64Tx
}
};
return Buffer.from(JSON.stringify(paymentPayload)).toString('base64');
}
async function fetchWithPayment(url: string) {
let response = await axios.get(url, {
validateStatus: () => true
});
if (response.status === 402) {
const requirements = response.data;
const paymentHeader = await createPayment(requirements);
response = await axios.get(url, {
headers: { 'X-PAYMENT': paymentHeader },
validateStatus: () => true
});
}
return response.data;
}Merchant (Solana Mainnet)
import express from 'express';
import axios from 'axios';
const app = express();
app.use(express.json());
const MERCHANT_WALLET = process.env.MERCHANT_WALLET_ADDRESS;
const MERCHANT_URL = process.env.MERCHANT_URL;
const FACILITATOR_URL = 'https://facilitator.octox402.xyz';
const NETWORK = 'solana';
const USDC_ADDRESS = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
async function checkPayment(req: any, res: any, next: any) {
const paymentHeader = req.headers['x-payment'];
const paymentRequirements = {
scheme: 'exact',
network: NETWORK,
maxAmountRequired: '10000', // $0.01 USDC (6 decimals)
payTo: MERCHANT_WALLET,
asset: USDC_ADDRESS,
resource: `${MERCHANT_URL}${req.path}`,
description: 'Premium content access',
mimeType: 'application/json',
maxTimeoutSeconds: 300
};
if (!paymentHeader) {
return res.status(402).json(paymentRequirements);
}
try {
const decoded = Buffer.from(paymentHeader, 'base64').toString('utf-8');
const paymentPayload = JSON.parse(decoded);
// Step 1: Verify
const verifyResponse = await axios.post(
`${FACILITATOR_URL}/verify`,
{ paymentPayload, paymentRequirements },
{ headers: { 'Content-Type': 'application/json' } }
);
const verifyData = verifyResponse.data.success
? verifyResponse.data.data
: verifyResponse.data;
if (!verifyData.isValid) {
return res.status(402).json({
error: 'Payment verification failed',
reason: verifyData.invalidReason
});
}
// Step 2: Settle (Facilitator only verifies, does not pay fees)
const settleResponse = await axios.post(
`${FACILITATOR_URL}/settle`,
{ paymentPayload, paymentRequirements },
{ headers: { 'Content-Type': 'application/json' } }
);
const settleData = settleResponse.data.success
? settleResponse.data.data
: settleResponse.data;
if (!settleData.success) {
return res.status(402).json({
error: 'Payment settlement failed'
});
}
next();
} catch (error: any) {
return res.status(500).json({
error: 'Payment processing failed',
message: error.message
});
}
}
// Protected endpoint
app.get('/premium-content', checkPayment, (req, res) => {
res.json({ data: 'Your premium content here' });
});
app.listen(3000);Payment Flow
1. Initial Request
Consumer → Merchant: GET /premium-content2. Payment Required
Merchant → Consumer: HTTP 402 Payment Required
{
"scheme": "exact",
"network": "base",
"maxAmountRequired": "10000",
"payTo": "MERCHANT_WALLET",
"asset": "USDC_ADDRESS",
"resource": "https://merchant.com/premium-content",
"description": "Premium content access",
"mimeType": "application/json",
"maxTimeoutSeconds": 300
}3. Payment Creation
Consumer creates signed payment:
- EVM: EIP-712 signature for USDC transferWithAuthorization
- SVM: Signed versioned transaction (v0)4. Payment Submission
Consumer → Merchant: GET /premium-content
Headers: { "X-PAYMENT": "base64EncodedPayment" }5. Payment Verification
Merchant → Facilitator: POST /verify
{
"paymentPayload": {...},
"paymentRequirements": {...}
}6. Payment Settlement
Merchant → Facilitator: POST /settle
{
"paymentPayload": {...},
"paymentRequirements": {...}
}
Facilitator → Blockchain: Submit transaction7. Content Delivery
Merchant → Consumer: HTTP 200 OK
{ "data": "Your premium content" }Facilitator API Reference
Base URL: https://facilitator.octox402.xyz
Endpoints Overview
/
GET
Service information
No
/health
GET
Health check
No
/supported
GET
List supported networks
No
/stats
GET
Facilitator statistics
No
/verify
GET
Verify endpoint info
No
/verify
POST
Verify payment signature
Optional
/settle
GET
Settle endpoint info
No
/settle
POST
Settle payment on blockchain
Optional
GET /supported
Returns all supported payment networks and schemes.
Response:
{
"kinds": [
{
"x402Version": 1,
"scheme": "exact",
"network": "base",
"extra": {
"feePayer": "0x..."
}
},
{
"x402Version": 1,
"scheme": "exact",
"network": "solana",
"extra": {
"feePayer": "..."
}
}
],
"facilitator": "Octo x402 Facilitator",
"version": 1,
"supportedChains": {
"evm": [
"Base",
"Abstract",
"Polygon",
"Avalanche",
"SEI",
"IoTeX",
"Peaq"
],
"svm": [
"Solana"
]
},
"requestId": "unique-request-id",
"timestamp": "2025-11-04T12:00:00.000Z"
}GET /stats
Returns facilitator statistics and performance metrics.
Response:
{
"facilitator": "Octo x402 Facilitator",
"version": "1.0.0",
"x402Version": 1,
"uptime": 86400,
"uptimeFormatted": "1d 0h 0m 0s",
"capabilities": {
"evmEnabled": true,
"svmEnabled": true,
"apiKeyRequired": false
},
"memoryUsage": {
"rss": "150MB",
"heapUsed": "85MB",
"heapTotal": "120MB",
"external": "10MB"
},
"requestId": "unique-request-id",
"timestamp": "2025-11-04T12:00:00.000Z"
}POST /verify
Verifies payment signature and requirements without settling on blockchain.
Request Headers:
Content-Type: application/json
X-API-Key: your-api-key (optional)Request Body:
{
"x402Version": 1,
"paymentPayload": {
"x402Version": 1,
"scheme": "exact",
"network": "base",
"payload": {
"authorization": {
"from": "consumer_wallet_address",
"to": "merchant_wallet_address",
"value": "10000",
"validAfter": "0",
"validBefore": "1730736000",
"nonce": "0x..."
},
"signature": "0x..."
}
},
"paymentRequirements": {
"scheme": "exact",
"network": "base",
"maxAmountRequired": "10000",
"payTo": "merchant_wallet_address",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"resource": "https://merchant.com/premium-content",
"description": "Premium content access",
"mimeType": "application/json",
"maxTimeoutSeconds": 300
}
}Success Response (200):
{
"success": true,
"data": {
"isValid": true
},
"requestId": "unique-request-id",
"timestamp": "2025-11-04T12:00:00.000Z"
}Failure Response (200):
{
"success": true,
"data": {
"isValid": false,
"invalidReason": "Insufficient amount: 5000, expected: 10000"
},
"requestId": "unique-request-id",
"timestamp": "2025-11-04T12:00:00.000Z"
}Error Response (400/500):
{
"success": false,
"error": "Error message",
"requestId": "unique-request-id",
"timestamp": "2025-11-04T12:00:00.000Z"
}POST /settle
Verifies and settles payment on blockchain. For EVM networks, facilitator pays gas fees. For SVM networks, facilitator only submits the pre-signed transaction.
Request Headers:
Content-Type: application/json
X-API-Key: your-api-key (optional)Request Body: Same as /verify
Success Response (200):
{
"success": true,
"data": {
"success": true,
"transaction": "0x1f00f9d92d433c29472354853f77c3a97398b01f4e0820c13a068e29daebdd2c",
"networkId": "base"
},
"requestId": "unique-request-id",
"timestamp": "2025-11-04T12:00:00.000Z"
}For Solana (SVM):
{
"success": true,
"data": {
"success": true,
"signature": "4haFW9Zp7cB8tgqPgASvyEJhPYfZaNKcLVHdhCKPhiKuCWudtSHEQWQhMDuWzhBEeg9F9LVED4ZC6E8hYU4CPWMi",
"networkId": "solana"
},
"requestId": "unique-request-id",
"timestamp": "2025-11-04T12:00:00.000Z"
}Failure Response (200):
{
"success": true,
"data": {
"success": false,
"error": "Transaction simulation failed",
"txHash": null,
"networkId": "base"
},
"requestId": "unique-request-id",
"timestamp": "2025-11-04T12:00:00.000Z"
}Sample Transactions
EVM Transaction Example (Base Mainnet)
Transaction Hash:
0x1f00f9d92d433c29472354853f77c3a97398b01f4e0820c13a068e29daebdd2c
Explorer Link: View on Basescan
Transaction Details:
Network: Base Mainnet
From: Consumer Wallet
To: USDC Contract (transferWithAuthorization)
Amount: $0.01 USDC
Gas Fee: ~$0.001 (paid by facilitator)
Confirmation Time: ~2 seconds
Total Cost to Consumer: $0.01 USDC
SVM Transaction Example (Solana Mainnet)
Transaction Signature:
4haFW9Zp7cB8tgqPgASvyEJhPYfZaNKcLVHdhCKPhiKuCWudtSHEQWQhMDuWzhBEeg9F9LVED4ZC6E8hYU4CPWMi
Explorer Link: View on Solana Explorer
Transaction Details:
Network: Solana Mainnet
Transaction Type: SPL Token Transfer (v0 versioned transaction)
From: Consumer Token Account
To: Merchant Token Account
Amount: $0.01 USDC
Transaction Fee: ~$0.000005 (paid by consumer)
Confirmation Time: ~400ms
Total Cost to Consumer: $0.010005 USDC
Important Note: Solana transactions use versioned transactions (v0) which are more efficient and support lookup tables for reduced transaction size.
Advanced Examples
Multi-Network Consumer (Universal)
This example shows how to create a universal consumer that works across all supported networks:
import axios from 'axios';
import { ethers } from 'ethers';
import { Keypair, Connection, TransactionMessage, VersionedTransaction, PublicKey } from '@solana/web3.js';
import { getAssociatedTokenAddress, createTransferInstruction } from '@solana/spl-token';
import bs58 from 'bs58';
interface NetworkConfig {
type: 'evm' | 'svm';
chainId?: number;
rpcUrl?: string;
usdcAddress: string;
}
const NETWORKS: Record<string, NetworkConfig> = {
'base': {
type: 'evm',
chainId: 8453,
usdcAddress: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'
},
'polygon': {
type: 'evm',
chainId: 137,
usdcAddress: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359'
},
'avalanche': {
type: 'evm',
chainId: 43114,
usdcAddress: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E'
},
'solana': {
type: 'svm',
rpcUrl: 'https://api.mainnet-beta.solana.com',
usdcAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
}
};
class UniversalX402Consumer {
private evmWallet?: ethers.Wallet;
private svmKeypair?: Keypair;
private svmConnection?: Connection;
constructor(
evmPrivateKey?: string,
svmPrivateKey?: string
) {
if (evmPrivateKey) {
this.evmWallet = new ethers.Wallet(evmPrivateKey);
}
if (svmPrivateKey) {
this.svmKeypair = Keypair.fromSecretKey(bs58.decode(svmPrivateKey));
this.svmConnection = new Connection('https://api.mainnet-beta.solana.com', 'confirmed');
}
}
async createEVMPayment(requirements: any, network: string): Promise<string> {
if (!this.evmWallet) throw new Error('EVM wallet not configured');
const config = NETWORKS[network];
const domain = {
name: 'USD Coin',
version: '2',
chainId: config.chainId,
verifyingContract: requirements.asset,
};
const types = {
TransferWithAuthorization: [
{ name: 'from', type: 'address' },
{ name: 'to', type: 'address' },
{ name: 'value', type: 'uint256' },
{ name: 'validAfter', type: 'uint256' },
{ name: 'validBefore', type: 'uint256' },
{ name: 'nonce', type: 'bytes32' },
],
};
const value = {
from: this.evmWallet.address,
to: requirements.payTo,
value: requirements.maxAmountRequired,
validAfter: 0,
validBefore: Math.floor(Date.now() / 1000) + 3600,
nonce: ethers.hexlify(ethers.randomBytes(32)),
};
const signature = await this.evmWallet.signTypedData(domain, types, value);
const paymentPayload = {
x402Version: 1,
scheme: 'exact',
network: network,
payload: {
authorization: {
from: this.evmWallet.address,
to: requirements.payTo,
value: requirements.maxAmountRequired,
validAfter: value.validAfter.toString(),
validBefore: value.validBefore.toString(),
nonce: value.nonce,
},
signature: signature
}
};
return Buffer.from(JSON.stringify(paymentPayload)).toString('base64');
}
async createSVMPayment(requirements: any): Promise<string> {
if (!this.svmKeypair || !this.svmConnection) {
throw new Error('SVM wallet not configured');
}
const fromPubkey = this.svmKeypair.publicKey;
const toPubkey = new PublicKey(requirements.payTo);
const mintPubkey = new PublicKey(requirements.asset);
const amount = BigInt(requirements.maxAmountRequired);
const fromTokenAccount = await getAssociatedTokenAddress(mintPubkey, fromPubkey);
const toTokenAccount = await getAssociatedTokenAddress(mintPubkey, toPubkey);
const transferInstruction = createTransferInstruction(
fromTokenAccount,
toTokenAccount,
fromPubkey,
amount
);
const { blockhash } = await this.svmConnection.getLatestBlockhash('finalized');
const messageV0 = new TransactionMessage({
payerKey: fromPubkey,
recentBlockhash: blockhash,
instructions: [transferInstruction],
}).compileToV0Message();
const transaction = new VersionedTransaction(messageV0);
transaction.sign([this.svmKeypair]);
const serializedTx = transaction.serialize();
const base64Tx = Buffer.from(serializedTx).toString('base64');
const paymentPayload = {
x402Version: 1,
scheme: 'exact',
network: 'solana',
payload: {
transaction: base64Tx
}
};
return Buffer.from(JSON.stringify(paymentPayload)).toString('base64');
}
async fetchWithPayment(url: string, preferredNetwork?: string): Promise<any> {
let response = await axios.get(url, { validateStatus: () => true });
if (response.status === 402) {
const requirements = response.data;
const network = preferredNetwork || requirements.network;
const config = NETWORKS[network];
if (!config) {
throw new Error(`Unsupported network: ${network}`);
}
console.log(`💳 Payment required: ${requirements.maxAmountRequired} on ${network}`);
let paymentHeader: string;
if (config.type === 'evm') {
paymentHeader = await this.createEVMPayment(requirements, network);
} else {
paymentHeader = await this.createSVMPayment(requirements);
}
response = await axios.get(url, {
headers: { 'X-PAYMENT': paymentHeader },
validateStatus: () => true
});
if (response.status === 200) {
console.log('✅ Payment successful!');
} else {
throw new Error(`Payment failed: ${JSON.stringify(response.data)}`);
}
}
return response.data;
}
}
// Usage
const consumer = new UniversalX402Consumer(
process.env.EVM_PRIVATE_KEY,
process.env.SVM_PRIVATE_KEY
);
// Use with Base
await consumer.fetchWithPayment('https://merchant.com/premium', 'base');
// Use with Polygon
await consumer.fetchWithPayment('https://merchant.com/premium', 'polygon');
// Use with Solana
await consumer.fetchWithPayment('https://merchant.com/premium', 'solana');Polygon Payment Example
import axios from 'axios';
import { ethers } from 'ethers';
const POLYGON_CONFIG = {
network: 'polygon',
chainId: 137,
usdcAddress: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',
rpcUrl: 'https://polygon-rpc.com'
};
const wallet = new ethers.Wallet(process.env.CONSUMER_PRIVATE_KEY);
const MERCHANT_URL = process.env.MERCHANT_URL;
async function createPolygonPayment(requirements: any): Promise<string> {
const domain = {
name: 'USD Coin',
version: '2',
chainId: POLYGON_CONFIG.chainId,
verifyingContract: requirements.asset,
};
const types = {
TransferWithAuthorization: [
{ name: 'from', type: 'address' },
{ name: 'to', type: 'address' },
{ name: 'value', type: 'uint256' },
{ name: 'validAfter', type: 'uint256' },
{ name: 'validBefore', type: 'uint256' },
{ name: 'nonce', type: 'bytes32' },
],
};
const value = {
from: wallet.address,
to: requirements.payTo,
value: requirements.maxAmountRequired,
validAfter: 0,
validBefore: Math.floor(Date.now() / 1000) + 3600,
nonce: ethers.hexlify(ethers.randomBytes(32)),
};
const signature = await wallet.signTypedData(domain, types, value);
const paymentPayload = {
x402Version: 1,
scheme: 'exact',
network: 'polygon',
payload: {
authorization: {
from: wallet.address,
to: requirements.payTo,
value: requirements.maxAmountRequired,
validAfter: value.validAfter.toString(),
validBefore: value.validBefore.toString(),
nonce: value.nonce,
},
signature: signature
}
};
return Buffer.from(JSON.stringify(paymentPayload)).toString('base64');
}
// Usage
async function buyContent() {
let response = await axios.get(MERCHANT_URL + '/premium', {
validateStatus: () => true
});
if (response.status === 402) {
const requirements = response.data;
const paymentHeader = await createPolygonPayment(requirements);
response = await axios.get(MERCHANT_URL + '/premium', {
headers: { 'X-PAYMENT': paymentHeader },
validateStatus: () => true
});
}
return response.data;
}Avalanche Payment Example
import axios from 'axios';
import { ethers } from 'ethers';
const AVALANCHE_CONFIG = {
network: 'avalanche',
chainId: 43114,
usdcAddress: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',
rpcUrl: 'https://api.avax.network/ext/bc/C/rpc'
};
const wallet = new ethers.Wallet(process.env.CONSUMER_PRIVATE_KEY);
async function createAvalanchePayment(requirements: any): Promise<string> {
const domain = {
name: 'USD Coin',
version: '2',
chainId: AVALANCHE_CONFIG.chainId,
verifyingContract: requirements.asset,
};
const types = {
TransferWithAuthorization: [
{ name: 'from', type: 'address' },
{ name: 'to', type: 'address' },
{ name: 'value', type: 'uint256' },
{ name: 'validAfter', type: 'uint256' },
{ name: 'validBefore', type: 'uint256' },
{ name: 'nonce', type: 'bytes32' },
],
};
const value = {
from: wallet.address,
to: requirements.payTo,
value: requirements.maxAmountRequired,
validAfter: 0,
validBefore: Math.floor(Date.now() / 1000) + 3600,
nonce: ethers.hexlify(ethers.randomBytes(32)),
};
const signature = await wallet.signTypedData(domain, types, value);
const paymentPayload = {
x402Version: 1,
scheme: 'exact',
network: 'avalanche',
payload: {
authorization: {
from: wallet.address,
to: requirements.payTo,
value: requirements.maxAmountRequired,
validAfter: value.validAfter.toString(),
validBefore: value.validBefore.toString(),
nonce: value.nonce,
},
signature: signature
}
};
return Buffer.from(JSON.stringify(paymentPayload)).toString('base64');
}Multi-Endpoint Merchant
This example shows a merchant that accepts payments on multiple networks:
import express from 'express';
import axios from 'axios';
const app = express();
app.use(express.json());
const MERCHANT_CONFIG = {
walletAddress: process.env.MERCHANT_WALLET_ADDRESS,
facilitatorUrl: 'https://facilitator.octox402.xyz',
supportedNetworks: ['base', 'polygon', 'avalanche', 'solana']
};
const USDC_ADDRESSES = {
base: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
polygon: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',
avalanche: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',
solana: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
};
async function createPaymentMiddleware(
network: string,
amount: string,
description: string
) {
return async (req: any, res: any, next: any) => {
const paymentHeader = req.headers['x-payment'];
const paymentRequirements = {
scheme: 'exact',
network: network,
maxAmountRequired: amount,
payTo: MERCHANT_CONFIG.walletAddress,
asset: USDC_ADDRESSES[network as keyof typeof USDC_ADDRESSES],
resource: `${req.protocol}://${req.get('host')}${req.originalUrl}`,
description: description,
mimeType: 'application/json',
maxTimeoutSeconds: 300
};
if (!paymentHeader) {
return res.status(402).json(paymentRequirements);
}
try {
const decoded = Buffer.from(paymentHeader, 'base64').toString('utf-8');
const paymentPayload = JSON.parse(decoded);
// Verify
const verifyResponse = await axios.post(
`${MERCHANT_CONFIG.facilitatorUrl}/verify`,
{ paymentPayload, paymentRequirements }
);
if (!verifyResponse.data.data.isValid) {
return res.status(402).json({
error: 'Payment verification failed',
reason: verifyResponse.data.data.invalidReason
});
}
// Settle
const settleResponse = await axios.post(
`${MERCHANT_CONFIG.facilitatorUrl}/settle`,
{ paymentPayload, paymentRequirements }
);
if (!settleResponse.data.data.success) {
return res.status(402).json({
error: 'Payment settlement failed'
});
}
console.log(`✅ Payment received on ${network}:`, settleResponse.data.data.transaction);
next();
} catch (error: any) {
return res.status(500).json({
error: 'Payment processing failed',
message: error.message
});
}
};
}
// Endpoints with different networks
app.get('/premium-base',
await createPaymentMiddleware('base', '10000', 'Premium content on Base'),
(req, res) => {
res.json({
content: 'Your premium content',
network: 'base',
paid: true
});
}
);
app.get('/premium-polygon',
await createPaymentMiddleware('polygon', '10000', 'Premium content on Polygon'),
(req, res) => {
res.json({
content: 'Your premium content',
network: 'polygon',
paid: true
});
}
);
app.get('/premium-avalanche',
await createPaymentMiddleware('avalanche', '10000', 'Premium content on Avalanche'),
(req, res) => {
res.json({
content: 'Your premium content',
network: 'avalanche',
paid: true
});
}
);
app.get('/premium-solana',
await createPaymentMiddleware('solana', '10000', 'Premium content on Solana'),
(req, res) => {
res.json({
content: 'Your premium content',
network: 'solana',
paid: true
});
}
);
app.listen(3000, () => {
console.log('✅ Multi-network merchant running on port 3000');
console.log('Supported networks:', MERCHANT_CONFIG.supportedNetworks);
});Security
Never expose private keys in code or version control
Use environment variables for sensitive configuration
Validate all payment requirements match expected values
Implement rate limiting on merchant endpoints
Use HTTPS for all production deployments
Performance
Cache payment verification results where appropriate
Implement request timeouts (recommended: 30 seconds)
Use connection pooling for RPC endpoints
Monitor facilitator health regularly
Error Handling
Always validate payment payload format before processing
Return clear error messages to consumers
Log all payment attempts for debugging
Implement retry logic for network failures
Handle expired signatures gracefully
Cost Optimization
EVM (Base)
Gas fees: ~$0.001 per transaction (paid by facilitator)
Payment amount: $0.01+ USDC
Total consumer cost: Payment amount only
SVM (Solana)
Transaction fees: ~$0.000005 per transaction (paid by consumer)
Payment amount: $0.01+ USDC
Total consumer cost: Payment amount + ~$0.000005
Support
Quick Links
Facilitator URL:
https://facilitator.octox402.xyzDocumentation: https://docs.octonet.ai/key-features/octo-x402
Website: https://octonet.ai
Protocol Version: x402 v1
Network Status
Production Ready: Base, Base Sepolia, Abstract, Abstract Testnet, Polygon, Polygon Amoy, Avalanche, Avalanche Fuji, SEI, SEI Testnet, IoTeX, Peaq, Solana, Solana Devnet (12 networks)
Testing Phase: BSC (Binance Smart Chain), Ethereum Mainnet, Optimism, Arbitrum
Key Features
✅ 12 production-ready networks across EVM and SVM
✅ Instant micropayments with USDC
✅ HTTP 402 payment protocol
✅ EIP-712 signatures for EVM
✅ Versioned transactions (v0) for Solana
✅ Facilitator pays gas on EVM networks
✅ Consumer pays minimal fees on Solana (~$0.000005)
✅ Production-grade facilitator with 99.9% uptime
Sample Transactions
EVM (Base): 0x1f00f9... SVM (Solana): 4haFW9...
Last updated