
Security News
/Research
Popular node-ipc npm Package Infected with Credential Stealer
Socket detected malicious node-ipc versions with obfuscated stealer/backdoor behavior in a developing npm supply chain attack.
xClaw02 - x402 payments SDK for OpenClaw agents. Pay and charge for APIs with stablecoins.
TypeScript SDK for x402 HTTP payments by Primer. OpenClaw compatible 🦞
Easily add pay-per-request monetization to your JavaScript/TypeScript APIs using the x402 protocol. Accept stablecoin payments (USDC, EURC) or any ERC-20 token with gasless transactions—payers never pay gas fees.
# Create a new wallet
xclaw02 wallet create
# Check balance
xclaw02 wallet balance 0xYourAddress
# Probe a URL for x402 support
xclaw02 probe https://api.example.com/paid
# Set up for OpenClaw
xclaw02 openclaw init
transferWithAuthorizationnpm install xclaw02
Wrap fetch or axios to automatically handle 402 responses:
const { createSigner, x402Fetch, x402Axios } = require('xclaw02');
// Create a signer (use CAIP-2 network format)
const signer = await createSigner('eip155:8453', process.env.PRIVATE_KEY);
// Wrap fetch
const fetch402 = x402Fetch(fetch, signer, { maxAmount: '1.00' });
const response = await fetch402('https://example.com/api/paywall');
// Or wrap axios
const axios402 = x402Axios(axios.create(), signer, { maxAmount: '1.00' });
const response = await axios402.get('https://example.com/api/paywall');
| 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) |
Middleware for Express, Hono, and Next.js:
const { x402Express } = require('xclaw02');
app.use(x402Express('0xYourAddress', {
'/api/paywall': {
amount: '0.01',
asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
network: 'eip155:8453' // CAIP-2 format
},
'/api/data/*': {
amount: '0.001',
asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
network: 'eip155:8453' // CAIP-2 format
}
}));
const { x402Hono } = require('xclaw02');
app.use('*', x402Hono('0xYourAddress', {
'/api/paywall': { amount: '0.01', asset: '0x...', network: 'eip155:8453' }
}));
// App Router (Next.js 13+)
import { x402Next } from 'xclaw02';
async function handler(req) {
return Response.json({ data: 'paywall' });
}
export const GET = x402Next(handler, {
payTo: '0xYourAddress',
amount: '0.01',
asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
network: 'eip155:8453' // CAIP-2 format
});
These tokens support gasless transfers natively via transferWithAuthorization. The payer signs an authorization, and the facilitator executes the transfer—payer pays zero gas.
For other ERC-20 tokens, Primer's Prism contract enables gasless payments:
const { createSigner, approveToken } = require('xclaw02');
const signer = await createSigner('eip155:8453', process.env.PRIVATE_KEY);
// One-time approval (this transaction requires gas)
await approveToken(signer, '0xTokenAddress');
// Now you can make gasless payments with this token
Networks use CAIP-2 identifiers (e.g., eip155:8453 for Base).
| Network (CAIP-2) | Chain ID | Legacy Name | Default Facilitator |
|---|---|---|---|
| eip155:8453 | 8453 | base | ✓ Primer |
| eip155:84532 | 84532 | base-sepolia | ✓ Primer |
| eip155:1 | 1 | ethereum | Custom required |
| eip155:11155111 | 11155111 | sepolia | Custom required |
| eip155:42161 | 42161 | arbitrum | Custom required |
| eip155:421614 | 421614 | arbitrum-sepolia | Custom required |
| eip155:10 | 10 | optimism | Custom required |
| eip155:11155420 | 11155420 | optimism-sepolia | Custom required |
| eip155:137 | 137 | polygon | Custom required |
| eip155:80002 | 80002 | polygon-amoy | Custom required |
Note: Legacy network names (e.g.,
'base') are still accepted for backward compatibility but CAIP-2 format is recommended.
For non-Base networks, you must provide your own facilitator:
// Payee
app.use(x402Express('0xYourAddress', {
'/api/paywall': { amount: '0.01', asset: '0x...', network: 'eip155:1' }
}, { facilitator: 'https://your-facilitator.com' }));
// Payer
const fetch402 = x402Fetch(fetch, signer, {
maxAmount: '1.00',
facilitator: 'https://your-facilitator.com'
});
DEBUG=x402:* node app.js
DEBUG=x402:payer,x402:payee node app.js
The SDK provides testing utilities to help you test your x402 integration without making real payments. Import from xclaw02/testing:
const {
createMockFacilitator,
createTestPayment,
createTest402Response,
fixtures
} = require('xclaw02/testing');
| Utility | Purpose |
|---|---|
createMockFacilitator() | Fake payment server that approves/rejects without blockchain |
createTestPayment() | Generate valid X-PAYMENT headers without a real wallet |
createTest402Response() | Generate 402 responses for testing client code |
fixtures | Pre-built test addresses, route configs, and sample payloads |
If you've built an API with x402 payments, test it like this:
// my-api.test.js
const request = require('supertest');
const app = require('./my-app');
const { createMockFacilitator, createTestPayment } = require('xclaw02/testing');
describe('My Paid API', () => {
let mockFac;
beforeAll(async () => {
// Start a fake facilitator on port 3001
mockFac = await createMockFacilitator({ port: 3001 });
});
afterAll(async () => {
await mockFac.close();
});
test('returns 402 when no payment provided', async () => {
const res = await request(app).get('/api/premium');
expect(res.status).toBe(402);
expect(res.headers['payment-required']).toBeDefined();
});
test('returns 200 when valid payment provided', async () => {
const payment = createTestPayment({ amount: '10000' }); // 0.01 USDC
const res = await request(app)
.get('/api/premium')
.set('X-PAYMENT', payment);
expect(res.status).toBe(200);
});
test('rejects insufficient payment', async () => {
const payment = createTestPayment({ amount: '1' }); // way too little
const res = await request(app)
.get('/api/premium')
.set('X-PAYMENT', payment);
expect(res.status).toBe(402);
});
});
Important: Point your middleware at the mock facilitator during tests:
// In your app setup for tests
const middleware = x402Express(payTo, routes, {
facilitator: 'http://127.0.0.1:3001' // Mock facilitator URL
});
If you've built a client that pays for APIs, test the 402 handling:
const { createTest402Response, fixtures } = require('xclaw02/testing');
test('client handles 402 response', async () => {
// Create a mock server that returns 402
const server = setupMockServer((req, res) => {
const body = createTest402Response({
amount: '10000',
payTo: fixtures.TEST_ADDRESSES.payee,
resource: '/api/data'
});
res.status(402)
.set('PAYMENT-REQUIRED', Buffer.from(JSON.stringify(body)).toString('base64'))
.end();
});
// Test your client handles it correctly
const result = await myClient.fetchWithPayment('/api/data');
expect(result).toBeDefined();
});
// Auto-approve all payments (default)
const mock = await createMockFacilitator({ mode: 'approve' });
// Reject all payments
const mock = await createMockFacilitator({ mode: 'reject' });
// Custom logic
const mock = await createMockFacilitator({
mode: 'custom',
handler: (payload) => {
const amount = payload.paymentRequirements?.maxAmountRequired;
if (parseInt(amount) > 1000000) {
return { success: false, error: 'Amount too high for test' };
}
return { success: true, transaction: '0x' + 'f'.repeat(64) };
}
});
// Add artificial latency (for timeout testing)
const mock = await createMockFacilitator({ latencyMs: 5000 });
The mock facilitator records all requests for assertions:
const mock = await createMockFacilitator();
// ... run your test ...
// Check what was sent to the facilitator
expect(mock.requests.length).toBe(1);
expect(mock.lastRequest().payload.paymentRequirements.network).toBe('eip155:8453');
// Clear between tests
mock.clearRequests();
createTestPayment({
amount: '10000', // Amount in smallest units (default: '10000')
from: '0x...', // Payer address (default: test address)
to: '0x...', // Payee address (default: test address)
network: 'eip155:84532', // Network in CAIP-2 format (default: 'eip155:8453')
validForSeconds: 7200 // Validity window (default: 3600)
});
const { fixtures } = require('xclaw02/testing');
fixtures.TEST_ADDRESSES.payer // '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'
fixtures.TEST_ADDRESSES.payee // '0x70997970C51812dc3A010C7d01b50e0d17dc79C8'
fixtures.USDC_ADDRESSES['eip155:8453'] // USDC on Base mainnet
fixtures.USDC_ADDRESSES['eip155:84532'] // USDC on Base Sepolia
fixtures.sampleRouteConfig // Example route config for middleware
fixtures.sample402ResponseBody // Example 402 response structure
fixtures.samplePaymentPayload // Example payment payload structure
The SDK includes a command-line interface for wallet management, probing, and OpenClaw integration.
xclaw02 <command> [options]
| Command | Description |
|---|---|
wallet create | Create a new wallet (address, private key, mnemonic) |
wallet balance <address> | Check USDC/ETH balance |
wallet from-mnemonic | Restore wallet from mnemonic phrase |
probe <url> | Check if URL supports x402 payments |
pay <url> | Make a payment to a 402 endpoint |
pay <url> --dry-run | Preview payment without paying |
networks | List supported networks |
facilitator | Show facilitator info |
openclaw init | Set up x402 for OpenClaw agents |
openclaw status | Check OpenClaw x402 status |
| Variable | Description |
|---|---|
XCLAW02_PRIVATE_KEY | Wallet private key |
XCLAW02_NETWORK | Default network (default: base) |
XCLAW02_MAX_AMOUNT | Default max payment amount |
XCLAW02_FACILITATOR | Facilitator URL override |
# Create wallet and save output
xclaw02 wallet create --json > wallet.json
# Check balance on Arbitrum
xclaw02 wallet balance 0x... --network arbitrum
# Preview payment (dry run)
xclaw02 pay https://api.example.com/data --dry-run
# Pay for an API
XCLAW02_PRIVATE_KEY=0x... xclaw02 pay https://api.example.com/data --max-amount 0.10
const {
createWallet,
walletFromMnemonic,
getBalance,
x402Probe
} = require('xclaw02');
// 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);
}
The SDK provides structured errors for programmatic handling:
const { X402Error, ErrorCodes } = require('xclaw02');
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;
}
}
}
| Code | Description |
|---|---|
INVALID_CONFIG | Missing or invalid configuration |
MISSING_PRIVATE_KEY | Private key not provided |
UNSUPPORTED_NETWORK | Network not supported |
INSUFFICIENT_FUNDS | Wallet balance too low |
AMOUNT_EXCEEDS_MAX | Payment exceeds maxAmount |
PAYMENT_FAILED | Payment transaction failed |
SETTLEMENT_FAILED | Facilitator settlement failed |
INVALID_RESPONSE | Malformed 402 response |
MISSING_PAYMENT_HEADER | No payment requirements header |
npm install xclaw02
xclaw02 openclaw init
Or install skill from ClawHub: clawhub install xclaw02
MIT - Primer Systems
FAQs
xClaw02 - x402 payments SDK for OpenClaw agents. Pay and charge for APIs with stablecoins.
We found that xclaw02 demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
/Research
Socket detected malicious node-ipc versions with obfuscated stealer/backdoor behavior in a developing npm supply chain attack.

Security News
TeamPCP and BreachForums are promoting a Shai-Hulud supply chain attack contest with a $1,000 prize for the biggest package compromise.

Security News
Packagist urges PHP projects to update Composer after a GitHub token format change exposed some GitHub Actions tokens in CI logs.