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.
| Crate | Description | |
|---|---|---|
r402 |
Core library — protocol types, scheme traits, facilitator abstractions, and hook system | |
r402-evm |
EVM (EIP-155) — ERC-3009 transfer authorization, multi-signer management, nonce tracking | |
r402-svm |
Solana (SVM) — SPL token transfers, program-derived addressing | |
r402-http |
HTTP transport — Axum payment gate middleware, reqwest client middleware, facilitator client | |
r402-mcp |
MCP integration — paid tool calls for AI agents, with optional rmcp support |
See also facilitator — a production-ready facilitator server built on r402.
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)
))
),
);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?;X402Middleware supports two settlement strategies, configurable via with_settlement_mode():
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
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
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)
| 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
PaygateAPI directly withverify_only()+VerifiedPayment::settle().
| 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) |
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.
See SECURITY.md for disclaimers, supported versions, and vulnerability reporting.
- x402 Protocol Specification — protocol design by Coinbase
- coinbase/x402 — official reference implementations (TypeScript, Python, Go)
- x402-rs/x402-rs — community Rust implementation
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
- MIT License (LICENSE-MIT or https://opensource.org/licenses/MIT)
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.