lucidAGENTS
Migration Guides

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 PackageNew PackageVersion
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 FormatNew 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/evm

Lucid 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);

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:84532

Update your environment variable documentation:

/**
 * Required environment variables:
 *   - PAYMENTS_NETWORK - CAIP-2 identifier (for example, eip155:84532)
 */

Breaking Changes Summary

Required Changes

  1. Update packages: Replace all x402* packages with @x402/*.
  2. Update networks: Convert to CAIP-2 format (for example, "base""eip155:8453").
  3. Update imports: Change import paths from x402/types to the owning scoped package.
  4. Update tests: Mock v2 facilitator responses and use CAIP-2 networks.

Optional (If Using Raw x402 Client)

  1. Update client creation: Create x402Client, then register the selected exact scheme helper.
  2. 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 Mainnet
  • eip155:84532 - Base Sepolia
  • eip155:1 - Ethereum Mainnet
  • eip155:11155111 - Ethereum Sepolia

Solana Networks

  • solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp - Solana Mainnet
  • solana: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:

On this page