This example demonstrates the simplest way to integrate Snack Money payments using axios with the x402 v2 payment client. Perfect for most web applications.
Overview
@x402/axios v2 wraps the popular axios HTTP client with automatic x402 payment negotiation. When the API returns 402 Payment Required, the client handles the payment flow automatically.
Features
- ✅ Base (EVM) and Solana (SVM) network support
- ✅ Automatic payment negotiation
- ✅ Simple axios-based API
- ✅ Type-safe TypeScript
- ✅ Minimal setup
Prerequisites
- Node.js 18+
- USDC balance on Base or Solana network
- EVM private key (for Base) or SVM private key (for Solana)
Installation
npm install axios @x402/axios @x402/evm @x402/svm viem
Quick Start
1. Set Up Environment
Create a .env file:
# For Base network
EVM_PRIVATE_KEY=0x...
# For Solana network
SVM_PRIVATE_KEY=base58_key...
# Common
RECEIVER=your_x_username
AMOUNT=0.01
Important: Use your own X (Twitter) account as the receiver to test the integration safely.
2. Implement Base (EVM) Payment
Create base-send.ts:
import axios from "axios";
import { privateKeyToAccount } from "viem/accounts";
import {
x402Client,
wrapAxiosWithPayment,
decodePaymentResponseHeader,
} from "@x402/axios";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
// Load environment variables
const evmPrivateKey = process.env.EVM_PRIVATE_KEY as `0x${string}`;
const receiver = process.env.RECEIVER as string;
const amount = parseFloat(process.env.AMOUNT || "0.01");
async function sendPayment() {
console.log("🚀 Starting Snack Money payment example with x402-axios v2\n");
console.log("ℹ️ Network: Base (EVM)\n");
// Create Base signer
const evmAccount = privateKeyToAccount(evmPrivateKey);
console.log("✅ Base signer created:", evmAccount.address);
// Create x402 client and register EVM scheme
const client = new x402Client();
registerExactEvmScheme(client, { signer: evmAccount });
console.log("✅ Registered EVM payment scheme\n");
// Create axios instance with x402 payment interceptor
const api = wrapAxiosWithPayment(
axios.create({ baseURL: "https://api.snack.money" }),
client
);
console.log(`💸 Sending ${amount} USDC to @${receiver} on X via Base...\n`);
try {
const response = await api.post("/payments/x/pay", {
amount,
currency: "USDC",
receiver,
description: "Payment via x402-axios v2 (Base)"
});
console.log("✅ Payment successful!");
console.log("\n📊 Response:", JSON.stringify(response.data, null, 2));
// Decode and display payment response header (v2 uses payment-response)
const paymentResponseHeader = response.headers["payment-response"];
if (paymentResponseHeader) {
const paymentResponse = decodePaymentResponseHeader(paymentResponseHeader);
console.log("\n🔐 Payment Response Details:", JSON.stringify(paymentResponse, null, 2));
}
} catch (error) {
console.error("❌ Payment failed:", error);
throw error;
}
}
sendPayment();
3. Implement Solana (SVM) Payment
Create solana-send.ts:
import axios from "axios";
import {
x402Client,
wrapAxiosWithPayment,
decodePaymentResponseHeader,
} from "@x402/axios";
import { registerExactSvmScheme } from "@x402/svm/exact/client";
import { createKeyPairSignerFromBytes } from "@solana/kit";
import bs58 from "bs58";
// Load environment variables
const svmPrivateKey = process.env.SVM_PRIVATE_KEY as string;
const receiver = process.env.RECEIVER as string;
const amount = parseFloat(process.env.AMOUNT || "0.01");
async function sendPayment() {
console.log("🚀 Starting Snack Money payment example with x402-axios v2\n");
console.log("ℹ️ Network: Solana (SVM)\n");
// Create Solana signer
console.log("🔧 Creating Solana signer...");
const privateKeyBytes = bs58.decode(svmPrivateKey);
const solanaSigner = await createKeyPairSignerFromBytes(privateKeyBytes);
console.log("✅ Solana signer created:", solanaSigner.address);
// Create x402 client and register Solana scheme
const client = new x402Client();
registerExactSvmScheme(client, { signer: solanaSigner });
console.log("✅ Registered Solana payment scheme\n");
// Create axios instance with x402 payment interceptor
const api = wrapAxiosWithPayment(
axios.create({ baseURL: "https://api.snack.money" }),
client
);
console.log(`💸 Sending ${amount} USDC to @${receiver} on X via Solana...\n`);
try {
const response = await api.post("/payments/x/pay", {
amount,
currency: "USDC",
receiver,
description: "Payment via x402-axios v2 (Solana)"
});
console.log("✅ Payment successful!");
console.log("\n📊 Response:", JSON.stringify(response.data, null, 2));
// Decode and display payment response header
const paymentResponseHeader = response.headers["payment-response"];
if (paymentResponseHeader) {
const paymentResponse = decodePaymentResponseHeader(paymentResponseHeader);
console.log("\n🔐 Payment Response Details:", JSON.stringify(paymentResponse, null, 2));
}
} catch (error) {
console.error("❌ Payment failed:", error);
throw error;
}
}
sendPayment();
4. Run the Example
For Base network:
npm run base
# or
npx tsx base-send.ts
For Solana network:
npm run solana
# or
npx tsx solana-send.ts
Expected Output
🚀 Starting Snack Money payment example with x402-axios
✅ Base signer created
💸 Sending 0.01 USDC to @username on X...
✅ Payment successful!
📊 Response: {
"code": 200,
"msg": "0.01 USDC sent successfully",
"data": {
"txn_id": "0xabc...def",
"amount": 0.01,
"receipt": "https://snack.money/x/username?txn=..."
}
}
How It Works
- Create Signer: Generate account from your private key (EVM or SVM)
- Create x402 Client: Initialize the x402 client
- Register Scheme: Register the appropriate payment scheme (EVM or SVM)
- Wrap Axios: Add x402 payment wrapper
- Make Request: POST to
/payments/x/pay
- Auto Payment: Client handles 402 response automatically
- Retry: Request retries with payment proof
- Success: Receive confirmation and receipt
Supported Endpoints
await api.post("/payments/x/pay", {
amount: 0.01,
currency: "USDC",
receiver: "username",
description: "Payment description"
});
Farcaster Payments
await api.post("/payments/farcaster/pay", {
amount: 0.5,
currency: "USDC",
receiver: "username",
description: "Payment description"
});
GitHub Payments
await api.post("/payments/github/pay", {
amount: 1.0,
currency: "USDC",
receiver: "username",
description: "Payment description"
});
Configuration Options
Custom Axios Instance
const api = withPaymentInterceptor(
axios.create({
baseURL: "https://api.snack.money",
timeout: 30000,
headers: {
"Content-Type": "application/json"
}
}),
account as never
);
Request Options
const response = await api.post(
"/payments/x/pay",
{
amount: 0.01,
currency: "USDC",
receiver: "username",
description: "Payment description"
},
{
timeout: 60000 // Custom timeout for this request
}
);
Error Handling
try {
const response = await api.post("/payments/x/pay", {
amount: 0.01,
currency: "USDC",
receiver: "username"
});
console.log("Payment successful:", response.data);
} catch (error) {
if (axios.isAxiosError(error)) {
if (error.response?.status === 402) {
console.error("Payment required but failed to process");
} else if (error.response?.status === 404) {
console.error("User not found");
} else {
console.error("API error:", error.response?.data);
}
} else {
console.error("Unexpected error:", error);
}
}
Common Errors
Insufficient USDC Balance
Ensure your wallet has enough USDC on Base network.
Check balance at: https://basescan.org/
Invalid Private Key
Private key must be a valid hex string starting with 0x
Format: 0x followed by 64 hex characters
User Not Found
The receiver username doesn't exist on the platform.
Verify the username is correct.
Testing Tips
- Start small: Use 0.01 USDC for initial tests
- Test on yourself: Send to your own X account
- Check balance: Verify USDC balance before sending
- Save receipts: Keep receipt URLs for records
Full Example Repository
View the complete example with configuration files:
View on GitHub →
The repository includes:
- Complete TypeScript implementation
- Environment configuration template
- package.json with all dependencies
- Detailed README
Next Steps
Dependencies
{
"dependencies": {
"axios": "^1.7.9",
"@x402/axios": "^2.0.0",
"@x402/evm": "^2.0.0",
"@x402/svm": "^2.0.0",
"viem": "^2.39.3",
"bs58": "^6.0.0",
"dotenv": "^16.4.7"
},
"devDependencies": {
"@types/bs58": "^5.0.0",
"@types/node": "^22.0.0",
"typescript": "^5.9.0"
}
}
Learn More