Skip to content
/ r402 Public

x402 Payment Protocol SDK for Rust.

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

qntx/r402

r402

CI License Rust

Modular Rust SDK for the x402 payment protocol — client signing, server gating, and facilitator settlement over HTTP 402.

r402 provides a production-grade, multi-chain implementation of the x402 protocol with dual-path ERC-3009 / Permit2 transfers, composable lifecycle hooks, MCP (Model Context Protocol) integration for AI agent payments, and 44 built-in chain deployments across EVM and Solana.

See Security before using in production.

Crates

Crate Description
r402 crates.io docs.rs Core library — protocol types, scheme traits, facilitator abstractions, and hook system
r402-evm crates.io docs.rs EVM (EIP-155) — ERC-3009 transfer authorization, multi-signer management, nonce tracking
r402-svm crates.io docs.rs Solana (SVM) — SPL token transfers, program-derived addressing
r402-http crates.io docs.rs HTTP transport — Axum payment gate middleware, reqwest client middleware, facilitator client
r402-mcp crates.io docs.rs MCP integration — paid tool calls for AI agents, with optional rmcp support

See also facilitator — a production-ready facilitator server built on r402.

Quick Start

Protect a Route (Server)

use alloy_primitives::address;
use axum::{Router, routing::get};
use r402_evm::{Eip155Exact, USDC};
use r402_http::server::X402Middleware;

let x402 = X402Middleware::new("https://facilitator.example.com");

let app = Router::new().route(
    "/paid-content",
    get(handler).layer(
        x402.with_price_tag(Eip155Exact::price_tag(
            address!("0xYourPayToAddress"),
            USDC::base().amount(1_000_000u64), // 1 USDC (6 decimals)
        ))
    ),
);

Send Payments (Client)

use alloy_signer_local::PrivateKeySigner;
use r402_evm::Eip155ExactClient;
use r402_http::client::{WithPayments, X402Client};
use std::sync::Arc;

let signer = Arc::new("0x...".parse::<PrivateKeySigner>()?);
let x402 = X402Client::new().register(Eip155ExactClient::new(signer));

let client = reqwest::Client::new().with_payments(x402);

let res = client.get("https://api.example.com/paid").send().await?;

Settlement Modes

X402Middleware supports two settlement strategies, configurable via with_settlement_mode():

Sequential (default)

Verify → execute → settle. The safest mode — on-chain settlement only occurs after the handler succeeds, and the Payment-Response header is included in the same HTTP response.

sequenceDiagram
    participant C as Client
    participant S as Server
    participant F as Facilitator
    participant H as Handler

    C->>S: HTTP Request + Payment-Signature
    S->>F: verify(payment)
    F-->>S: VerifyResponse ✓
    S->>H: execute request
    Note over S,H: Balance verified but NOT locked —<br/>handler executing (variable latency)
    H-->>S: response body
    S->>F: settle(payment)
    Note over S,F: On-chain transfer (2–5 s)
    F-->>S: SettleResponse (tx_hash)
    S-->>C: 200 OK + Payment-Response header
Loading

Concurrent

Verify → (settle ∥ execute) → await both. Reduces total latency by overlapping on-chain settlement with handler execution, saving one facilitator round-trip. On handler error the settlement task is detached (fire-and-forget).

sequenceDiagram
    participant C as Client
    participant S as Server
    participant F as Facilitator
    participant H as Handler

    C->>S: HTTP Request + Payment-Signature
    S->>F: verify(payment)
    F-->>S: VerifyResponse ✓
    par settle ∥ execute
        S->>F: settle(payment)
        Note over S,F: On-chain transfer
        F-->>S: SettleResponse (tx_hash)
    and
        S->>H: execute request
        H-->>S: response body
    end
    S-->>C: 200 OK + Payment-Response header
Loading

Background

Verify → spawn settle (fire-and-forget) → execute → return. Settlement runs entirely in the background — the response is returned to the client as soon as the handler completes, without waiting for on-chain confirmation. Ideal for streaming responses (SSE, LLM token streams) where the client should start receiving data immediately. Settlement errors are logged but do not propagate to the caller. Trade-off: the Payment-Response header is not attached since settlement may still be in progress when the response is sent.

sequenceDiagram
    participant C as Client
    participant S as Server
    participant F as Facilitator
    participant H as Handler

    C->>S: HTTP Request + Payment-Signature
    S->>F: verify(payment)
    F-->>S: VerifyResponse ✓
    S-)F: settle(payment) [fire-and-forget]
    S->>H: execute request
    H-->>S: response body (or stream)
    S-->>C: 200 OK (no Payment-Response header)
    Note over S,F: Settlement completes asynchronously
    F-)S: SettleResponse (logged)
Loading

Comparison

Mode Total latency Safety Payment-Response Best for
Sequential verify + handler + settle Settlement only on handler success ✅ Included Standard request/response APIs
Concurrent verify + max(handler, settle) Settlement may occur on handler failure ✅ Included Latency-sensitive endpoints
Background verify + handler Settlement errors are non-fatal (logged) ❌ Not attached SSE / LLM streaming responses

For full manual control over settlement timing, use the composable Paygate API directly with verify_only() + VerifiedPayment::settle().

Design

Aspect Details
Built-in chains 44 — 42 EVM (EIP-155) + 2 Solana
Transfer methods Dual path — ERC-3009 transferWithAuthorization + Permit2 proxy
Lifecycle hooks FacilitatorHooks (verify/settle) + ClientHooks (payment creation)
Async model Zero async_trait in core — RPITIT / Pin<Box<dyn Future>>
Facilitator trait Unified — dyn-compatible Box<dyn Facilitator> across all schemes
Wire format V2-only server (CAIP-2 chain IDs, Payment-Signature header)
Settlement errors Explicit — failed settle returns 402 with structured error
Network definitions Decoupled — per-chain crate (r402-evm, r402-svm)
Smart wallets EIP-6492 (counterfactual) + EIP-1271 (deployed) + ERC-2098 (compact signatures)
Linting pedantic + nursery + correctness (deny)

Feature Flags

Each chain and transport crate uses feature flags to minimize compile-time dependencies:

Crate server client facilitator telemetry
r402-http Axum payment gate + facilitator client Reqwest middleware tracing spans
r402-evm Price tag generation EIP-712 / EIP-3009 / Permit2 signing On-chain verify & settle tracing spans
r402-svm Price tag generation SPL token signing On-chain verify & settle tracing spans
r402-mcp tracing spans

r402-mcp uses rmcp (optional) for built-in rmcp SDK integration.

Security

See SECURITY.md for disclaimers, supported versions, and vulnerability reporting.

Acknowledgments

License

Licensed under either of:

at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project shall be dual-licensed as above, without any additional terms or conditions.

About

x402 Payment Protocol SDK for Rust.

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

  •