Rust (Axum)
Rust integration with Axum framework using x402-axum
Complete examples for integrating x402 payments with Rust using the x402-axum middleware and FareSide facilitator.
Dependencies
Add these to your Cargo.toml:
[dependencies]
alloy-primitives = "1.4"
axum = "0.8"
serde_json = "1"
solana-pubkey = "4.0"
tokio = { version = "1", features = ["full"] }
x402-axum = "1.0"
x402-chain-eip155 = { version = "1.0", features = ["server"] }
x402-chain-solana = { version = "1.0", features = ["server"] }
x402-types = "1.0"
Basic Setup
use axum::{routing::get, Router};
use axum::http::StatusCode;
use axum::response::IntoResponse;
use serde_json::json;
use alloy_primitives::address;
use x402_axum::X402Middleware;
use x402_chain_eip155::{V2Eip155Exact, KnownNetworkEip155};
use x402_types::networks::USDC;
#[tokio::main]
async fn main() {
// Configure FareSide facilitator
let x402 = X402Middleware::try_from(
"https://facilitator.fareside.com/YOUR_API_KEY"
).unwrap();
// Configure USDC on Base Sepolia with your receiving address
let usdc = USDC::base_sepolia();
let wallet = address!("0xYourWalletAddress");
let app = Router::new()
.route("/weather", get(weather_handler).layer(
x402.with_price_tag(
V2Eip155Exact::price_tag(
wallet,
usdc.amount(10_000u64) // 0.01 USDC
)
)
.with_description("Weather API access".to_string())
.with_mime_type("application/json".to_string())
));
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
println!("Server running on http://localhost:3000");
axum::serve(listener, app).await.unwrap();
}
async fn weather_handler() -> impl IntoResponse {
(StatusCode::OK, axum::Json(json!({
"location": "San Francisco",
"temperature": 68,
"conditions": "Sunny"
})))
}
Multiple Networks
Accept payments on multiple networks for the same endpoint using .with_price_tag() multiple times:
use axum::{routing::get, Router};
use alloy_primitives::address;
use solana_pubkey::pubkey;
use x402_axum::X402Middleware;
use x402_chain_eip155::{V2Eip155Exact, KnownNetworkEip155};
use x402_chain_solana::{V2SolanaExact, KnownNetworkSolana};
use x402_types::networks::USDC;
#[tokio::main]
async fn main() {
let x402 = X402Middleware::try_from(
"https://facilitator.fareside.com/YOUR_API_KEY"
).unwrap();
let evm_wallet = address!("0xYourEVMWallet");
let sol_wallet = pubkey!("YourSolanaWalletAddress");
let app = Router::new().route(
"/api/data",
get(data_handler).layer(
// Accept payment on Base ...
x402.with_price_tag(V2Eip155Exact::price_tag(
evm_wallet,
USDC::base().amount(10_000u64),
))
// ... OR Solana
.with_price_tag(V2SolanaExact::price_tag(
sol_wallet,
USDC::solana().amount(10_000u64),
))
.with_description("Multi-chain API".to_string()),
),
);
/* ... serve app ... */
}
Dynamic Pricing
Use with_dynamic_price to calculate price based on request parameters:
let app = Router::new().route(
"/api/data",
get(handler).layer(x402.with_dynamic_price(|_headers, uri, _base_url| {
// Check for discount query parameter
let has_discount = uri.query().map(|q| q.contains("discount")).unwrap_or(false);
let amount = if has_discount { 5_000u64 } else { 10_000u64 };
async move {
vec![V2Eip155Exact::price_tag(
address!("0xYourWallet"),
USDC::base().amount(amount),
)]
}
})),
);
Telemetry
X402Middleware supports telemetry via the tracing crate. When you have a tracing subscriber configured in your application, the middleware will automatically emit spans and events for payment verification, facilitator communication, and error handling.
Simply add tracing and your preferred subscriber to your dependencies:
[dependencies]
tracing = "0.1"
tracing-subscriber = "0.3"
The middleware integrates seamlessly with any tracing-compatible observability stack (OpenTelemetry, Jaeger, Datadog, etc.).
Full Example
See the complete working example at x402-axum-example.
Next Steps
- Making Payments - Build x402 clients with x402-reqwest
- Self-Hosting - Run your own facilitator