x402 v2 Migration Guide
Complete guide for migrating from x402 v1 to x402 v2 protocol
This guide covers migrating from x402 v1 to x402 v2 in Lucid Agents.
Versions:
- Migrating from: Lucid Agents v2.2.x (using x402 v1)
- Migrating to: Lucid Agents v2.4.0+ (using x402 v2)
Overview
The x402 protocol has been upgraded from v1 to v2, bringing:
- Scoped packages - New
@x402/*package naming - CAIP-2 network format - Standard network identifiers (e.g.,
eip155:8453) - Improved verification - Enhanced payment protocol and facilitator support
What Changed
Package Updates
All x402-related packages have been migrated to scoped @x402/* packages:
| Old Package | New Package | Version |
|---|---|---|
x402 | @x402/core | ^2.2.0 |
x402-fetch | @x402/fetch | ^2.2.0 |
| N/A | @x402/evm | ^2.2.0 |
x402-hono | @x402/hono | ^2.2.0 |
x402-express | @x402/express | ^2.2.0 |
x402-next | @x402/next | ^2.2.0 |
Network Format (CAIP-2)
Network identifiers now use the CAIP-2 standard:
| Old Format | New Format (CAIP-2) | Network |
|---|---|---|
"base" | "eip155:8453" | Base Mainnet |
"base-sepolia" | "eip155:84532" | Base Sepolia |
"ethereum" | "eip155:1" | Ethereum Mainnet |
"sepolia" | "eip155:11155111" | Ethereum Sepolia |
"solana" | "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" | Solana Mainnet |
"solana-devnet" | "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1" | Solana Devnet |
Import Path Changes
Import paths have changed from x402/types to @x402/core/*:
// Before
import type { Network, RouteConfig } from 'x402/types';
// After
import type { Network } from '@x402/core/types';
import type { RouteConfig } from '@x402/core/server';Migration Steps
1. Update Dependencies
Update your package.json to use the new scoped packages:
# Remove old packages
bun remove x402 x402-fetch x402-hono x402-express x402-next
# Install only the low-level packages your direct integration uses
bun add @x402/core @x402/fetch @x402/evmLucid Agents applications normally install @lucid-agents/payments and let the runtime own server-side verification. Add @x402/hono, @x402/express, or @x402/next only for a separate raw x402 integration; Lucid's adapters do not require them.
Or update your package.json directly:
{
"dependencies": {
"@x402/core": "^2.2.0",
"@x402/fetch": "^2.2.0",
"@x402/evm": "^2.2.0"
}
}2. Update Network Identifiers
Replace all old network strings with CAIP-2 format:
// Before
const config: PaymentsConfig = {
payTo: '0x...',
network: 'base-sepolia',
facilitatorUrl: 'https://YOUR_FACILITATOR_URL',
};
// After
const config: PaymentsConfig = {
payTo: '0x...',
network: 'eip155:84532', // Base Sepolia in CAIP-2 format
facilitatorUrl: 'https://YOUR_FACILITATOR_URL',
};3. Update Import Statements
Type Imports
// Before
import type { Network, Money, RouteConfig, RoutesConfig } from 'x402/types';
// After: import each type from the scoped package that owns it.
import type { Network } from '@x402/core/types';
import type { RouteConfig } from '@x402/core/server';Payment Middleware Imports
These import changes apply only when your application uses the raw framework middleware directly. Lucid Agents runtimes should migrate to the unified extension shown below.
Hono:
// Before
import { paymentMiddleware } from 'x402-hono';
// After
import { paymentMiddleware } from '@x402/hono';Express:
// Before
import { paymentMiddleware } from 'x402-express';
// After
import { paymentMiddleware } from '@x402/express';Next.js:
// Before
import { paymentMiddleware } from 'x402-next';
// After
import { paymentMiddleware } from '@x402/next';4. Update Manual x402 Client Usage
If you're using x402 client directly (not through Lucid Agents helpers), update to the new API:
// Before
import { wrapFetchWithX402, createWallet } from 'x402-fetch';
const wallet = createWallet(privateKey, 'base');
const x402Fetch = wrapFetchWithX402(fetch, wallet);
// After
import { x402Client } from '@x402/core/client';
import { registerExactEvmScheme } from '@x402/evm/exact/client';
import { wrapFetchWithPayment } from '@x402/fetch';
import { privateKeyToAccount } from 'viem/accounts';
const client = new x402Client();
registerExactEvmScheme(client, {
signer: privateKeyToAccount(privateKey),
networks: ['eip155:84532'],
});
const x402Fetch = wrapFetchWithPayment(fetch, client);5. Using Lucid Agents Helpers (Recommended)
If you use Lucid Agents payment helpers, minimal changes are needed:
import { createRuntimePaymentContext } from '@lucid-agents/payments';
// The helpers now use @x402/* packages internally
const paymentContext = await createRuntimePaymentContext({
runtime,
network: 'eip155:84532', // Just update to CAIP-2 format
});
// Use the payment-enabled fetch
if (!paymentContext.fetchWithPayment) {
throw new Error('No compatible buyer wallet is configured');
}
const response = await paymentContext.fetchWithPayment(url, options);Test Updates
Mock Facilitator Responses
Tests now need to mock v2 facilitator responses:
import { beforeAll, afterAll } from 'bun:test';
const mockFacilitatorResponse = {
kinds: [
{
scheme: 'exact',
network: 'eip155:84532', // CAIP-2 format
asset: {
address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',
decimals: 6,
eip712: {
name: 'USDC',
version: '2',
},
},
},
],
};
let originalFetch: typeof globalThis.fetch;
beforeAll(() => {
originalFetch = globalThis.fetch;
globalThis.fetch = async (input, init) => {
const url =
typeof input === 'string'
? input
: input instanceof URL
? input.toString()
: input.url;
if (url.includes('/supported')) {
return new Response(JSON.stringify(mockFacilitatorResponse), {
status: 200,
headers: { 'Content-Type': 'application/json' },
});
}
return originalFetch(input, init);
};
});
afterAll(() => {
globalThis.fetch = originalFetch;
});Network Identifiers in Tests
Update all network strings in test fixtures:
// Before
const payments: PaymentsConfig = {
payTo: '0x...',
network: 'base-sepolia',
facilitatorUrl: 'https://facilitator.test',
};
// After
const payments: PaymentsConfig = {
payTo: '0x...',
network: 'eip155:84532',
facilitatorUrl: 'https://facilitator.test',
};Environment Variables
If you're using environment variables for network configuration, update them:
# Before
NETWORK=base-sepolia
# After
PAYMENTS_NETWORK=eip155:84532Update your environment variable documentation:
/**
* Required environment variables:
* - PAYMENTS_NETWORK - CAIP-2 identifier (for example, eip155:84532)
*/Breaking Changes Summary
Required Changes
- Update packages: Replace all
x402*packages with@x402/*. - Update networks: Convert to CAIP-2 format (for example,
"base"→"eip155:8453"). - Update imports: Change import paths from
x402/typesto the owning scoped package. - Update tests: Mock v2 facilitator responses and use CAIP-2 networks.
Optional (If Using Raw x402 Client)
- Update client creation: Create
x402Client, then register the selected exact scheme helper. - Update signer: Supply the chain-compatible signer required by that scheme helper.
Supported Networks
After migration, these networks are supported:
EVM Networks
eip155:8453- Base Mainneteip155:84532- Base Sepoliaeip155:1- Ethereum Mainneteip155:11155111- Ethereum Sepolia
Solana Networks
solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp- Solana Mainnetsolana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1- Solana Devnet
Troubleshooting
TypeScript Errors
Error: Type '"base-sepolia"' is not assignable to type '${string}:${string}'
Solution: Update the network string to CAIP-2 format:
network: 'eip155:84532'; // Instead of 'base-sepolia'Error: Cannot find module 'x402/types'
Solution: Update import to use scoped package:
import type { Network } from '@x402/core/types';Runtime Errors
Error: Network 'base' is not supported
Solution: Register the network in CAIP-2 format:
const client = new x402Client();
registerExactEvmScheme(client, {
signer,
networks: ['eip155:8453'],
});Test Failures
Error: Facilitator mock not working
Solution: Update mock to return v2 format with kinds array (see Test Updates section)
Additional Resources
Need Help?
If you encounter issues:
- Check GitHub Issues
- Join our Discord
- Review the payments changelog