MCPcopy Index your code
hub / github.com/bitrouter/x402-kit

github.com/bitrouter/x402-kit @x402-core-v2.5.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release x402-core-v2.5.0 ↗ · + Follow
369 symbols 652 edges 63 files 78 documented · 21% updated 3mo ago★ 522 open issues
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

X402 Kit

Build status Crates.io Documentation Twitter Follow Discord

A fully modular, framework-agnostic, easy-to-extend SDK for building complex X402 payment integrations.

📦 Crates

Crate Description
x402-kit Main SDK with network definitions, payment schemes, and facilitator client
x402-signer Buyer-side signing SDK with reqwest middleware for automatic x402 payments
x402-core Core traits, types, and transport mechanisms for the X402 protocol
x402-paywall Framework-agnostic HTTP paywall middleware

📚 Developer Docs

Docs are available at docs.rs

💡 Core Pain Points Solved

X402-kit is not a facilitator — it's a composable SDK for buyers (signers) and sellers (servers) to build custom business logic. Future support for modular facilitator components is planned.

Beyond Static Pricing and Payment Gateway Middlewares

Existing X402 SDKs only support static prices per API route. X402-kit's fully modular architecture enables complex, dynamic pricing logic while maximizing code reuse.

Complete Modularity

All internal fields and methods are public by design. Compose and extend functionality freely without fighting the framework.

Layered Type Safety

  • Transport Layer: Uses generalized String types to prevent serialization failures and ensure service availability
  • Network + Scheme Layer: Leverages traits and generics for compile-time type checking without runtime overhead

Ship New Networks Without PRs

Implement a new asset, network, or scheme entirely in your codebase and plug it into the SDK immediately—no upstream pull request or waiting period required thanks to trait-driven extension points.

However, we still recommend contributing back any useful implementations to the main repository to help grow the ecosystem!

Production-Ready Design

Minimize runtime errors through compile-time guarantees while maintaining the flexibility needed for real-world business logic.

🧪 Usage Examples

Using x402-paywall with Axum

The x402-paywall crate (re-exported via x402-kit) provides a composable PayWall that handles the complete X402 payment flow. Run the example:

FACILITATOR_URL=https://your-facilitator.example \
  cargo run -p x402-kit --example axum_seller

Standard Payment Flow

The handle_payment method provides a complete flow: update accepts from facilitator, verify payment, run handler, and settle on success.

use alloy::primitives::address;
use axum::{extract::{Request, State}, middleware::Next, response::{IntoResponse, Response}};
use url_macro::url;
use x402_kit::{
    core::Resource,
    facilitator_client::FacilitatorClient,
    networks::evm::assets::UsdcBaseSepolia,
    paywall::paywall::PayWall,
    schemes::exact_evm::ExactEvm,
};

async fn paywall_middleware(State(state): State<AppState>, req: Request, next: Next) -> Response {
    let paywall = PayWall::builder()
        .facilitator(state.facilitator)
        .accepts(
            ExactEvm::builder()
                .amount(1000)
                .asset(UsdcBaseSepolia)
                .pay_to(address!("0x3CB9B3bBfde8501f411bB69Ad3DC07908ED0dE20"))
                .build(),
        )
        .resource(
            Resource::builder()
                .url(url!("https://example.com/resource"))
                .description("X402 payment protected resource")
                .mime_type("application/json")
                .build(),
        )
        .build();

    paywall
        .handle_payment(req, |req| next.run(req))
        .await
        .unwrap_or_else(|err| err.into_response())
}

Multiple Payment Options

Accept payments on multiple networks (EVM and SVM):

use x402_kit::{
    networks::{evm::assets::UsdcBaseSepolia, svm::assets::UsdcSolanaDevnet},
    schemes::{exact_evm::ExactEvm, exact_svm::ExactSvm},
    transport::Accepts,
};

let paywall = PayWall::builder()
    .facilitator(facilitator)
    .accepts(
        Accepts::new()
            .push(
                ExactEvm::builder()
                    .amount(1000)
                    .asset(UsdcBaseSepolia)
                    .pay_to(address!("0x3CB9B3bBfde8501f411bB69Ad3DC07908ED0dE20"))
                    .build(),
            )
            .push(
                ExactSvm::builder()
                    .amount(1000)
                    .asset(UsdcSolanaDevnet)
                    .pay_to(pubkey!("Ge3jkza5KRfXvaq3GELNLh6V1pjjdEKNpEdGXJgjjKUR"))
                    .build(),
            ),
    )
    .resource(/* ... */)
    .build();

Custom Payment Flow

For fine-grained control, use the step-by-step API:

// Skip verification, settle before running handler
let response = paywall
    .process_request(req)?
    .settle()
    .await?
    .run_handler(|req| next.run(req))
    .await?
    .response();

Access Payment State in Handlers

The PayWall injects PaymentState into request extensions:

use axum::{Extension, Json};
use x402_kit::paywall::processor::PaymentState;

async fn handler(Extension(payment_state): Extension<PaymentState>) -> Json<Value> {
    Json(json!({
        "message": "Premium content accessed!",
        "payer": payment_state.verified.map(|v| v.payer),
        "transaction": payment_state.settled.map(|s| s.transaction),
    }))
}

Custom Facilitator Client

Customize request/response types for your facilitator.

Note: The default facilitator client uses Url::join("verify") etc. to construct endpoint URLs from the base URL. This means trailing slashes matter. For example, when using the Coinbase facilitator:

bash export FACILITATOR_URL=https://www.x402.org/facilitator/

use x402_kit::facilitator_client::{FacilitatorClient, IntoVerifyResponse, IntoSettleResponse};

#[derive(Serialize, Deserialize)]
struct CustomSettleRequest { /* ... */ }

#[derive(Deserialize)]
struct CustomSettleResponse { /* ... */ }

impl IntoSettleResponse for CustomSettleResponse {
    fn into_settle_response(self) -> SettleResult { /* ... */ }
}

let facilitator = FacilitatorClient::from_url(facilitator_url)
    .with_settle_request_type::<CustomSettleRequest>()
    .with_settle_response_type::<CustomSettleResponse>();

Buyer-Side Signing with x402-signer

The x402-signer crate provides a reqwest middleware that automatically handles the x402 payment flow: intercept HTTP 402 → sign payment → retry with payment header.

You need some testnet USDC on Solana devnet or Base Sepolia to run signer examples. You can get some at Circle testnet faucet

EVM Client

EVM_PRIVATE_KEY=0x... RESOURCE_URL=http://localhost:3000/resource/standard \
  cargo run -p x402-signer --example evm_client
use alloy::signers::local::PrivateKeySigner;
use reqwest_middleware::ClientBuilder;
use x402_signer::{X402Client, evm::EvmPaymentSigner, middleware::X402PaymentMiddleware};

let wallet: PrivateKeySigner = "0x...".parse().unwrap();
let signer = EvmPaymentSigner::new(wallet);
let middleware = X402PaymentMiddleware::new(X402Client::new(signer));

let client = ClientBuilder::new(reqwest::Client::new())
    .with(middleware)
    .build();

// Any 402 response is automatically signed and retried
let response = client.post("http://localhost:3000/resource/standard").send().await?;

SVM Client

SOLANA_PRIVATE_KEY=<base58> SOLANA_RPC_URL=https://api.devnet.solana.com \
  RESOURCE_URL=http://localhost:3000/resource/multi_payments \
  cargo run -p x402-signer --example svm_client
use solana_keypair::Keypair;
use solana_rpc_client::nonblocking::rpc_client::RpcClient;
use reqwest_middleware::ClientBuilder;
use x402_signer::{X402Client, svm::SvmPaymentSigner, middleware::X402PaymentMiddleware};

let keypair = Keypair::from_base58_string("<base58-private-key>");
let rpc = RpcClient::new("https://api.devnet.solana.com".to_string());
let signer = SvmPaymentSigner::new(keypair, rpc);
let middleware = X402PaymentMiddleware::new(X402Client::new(signer));

let client = ClientBuilder::new(reqwest::Client::new())
    .with(middleware)
    .build();

let response = client.post("http://localhost:3000/resource/multi_payments").send().await?;

🚀 Next Steps

  • More networks / assets / schemes
  • MCP / A2A transport support
  • Facilitator components support

🤝 Contributing

We welcome all contributions to x402-kit! Here's how you can get involved:

  • Star this repository
  • 🐛 Open issues to report bugs or suggest features
  • 🔧 Submit PRs to improve the codebase

Contributors will receive priority access and rewards at AIMO Network's Beta launch (coming soon)!

Extension points exported contracts — how you extend this code

PaymentSigner (Interface)
High-level trait for signing x402 payments. Implementors can match against `PaymentRequirements` and produce a signed ` [5 …
x402-signer/src/signer.rs
ExtensionInfo (Interface)
Trait for typed extension info with compile-time schema generation. Implement this trait for your extension's info type [4 …
x402-core/src/types/extensions.rs
ExplicitSvmNetwork (Interface)
(no doc) [5 implementers]
x402-networks/src/svm/mod.rs
HttpRequest (Interface)
(no doc) [2 implementers]
x402-paywall/src/lib.rs
IntoVerifyResponse (Interface)
(no doc) [1 implementers]
x402-kit/src/facilitator_client.rs
SvmRpc (Interface)
Async RPC operations needed for SVM transaction building. Users provide their own implementation backed by their prefer [2 …
x402-signer/src/svm/rpc.rs
NetworkFamily (Interface)
A series of network families, e.g. EVM, SVM, etc. [3 implementers]
x402-core/src/core.rs
ExplicitSvmAsset (Interface)
(no doc) [3 implementers]
x402-networks/src/svm/mod.rs

Core symbols most depended-on inside this repo

into_pair
called by 11
x402-core/src/types/extensions.rs
pubkey
called by 10
x402-signer/src/svm/wallet.rs
push
called by 10
x402-core/src/transport.rs
as_ref
called by 8
x402-core/src/transport.rs
derive_ata
called by 6
x402-signer/src/svm/transaction.rs
sign_payment
called by 5
x402-signer/src/signer.rs
send
called by 5
x402-signer/examples/svm_swig_delegation.rs
into_iter
called by 4
x402-core/src/transport.rs

Shape

Method 146
Class 95
Function 88
Enum 20
Interface 20

Languages

Rust100%

Modules by API surface

x402-kit/src/facilitator_client.rs23 symbols
x402-core/src/types/extensions.rs22 symbols
x402-core/src/facilitator.rs21 symbols
x402-signer/tests/signing.rs19 symbols
x402-networks/src/svm/mod.rs17 symbols
x402-kit/tests/define_networks_assets.rs17 symbols
x402-core/src/types/schema.rs17 symbols
x402-extensions/src/bazaar.rs16 symbols
x402-core/src/transport.rs16 symbols
x402-networks/src/evm/exact.rs14 symbols
x402-networks/src/evm/mod.rs13 symbols
x402-paywall/src/errors.rs12 symbols

For agents

$ claude mcp add x402-kit \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page