x402-sdk

Crates.iox402-sdk
lib.rsx402-sdk
version0.3.0
created_at2025-10-26 22:52:21.631618+00
updated_at2025-10-27 14:13:43.134213+00
descriptionaptos network tool.
homepage
repositoryhttps://github.com/0xhappyboy/x402-sdk
max_upload_size
id1901985
size273,022
happy₿oy (0xhappyboy)

documentation

README

x402 SDK

A Rust implementation of the x402 protocol, inspired by @coinbase/x402. X402 is a blockchain payment protocol SDK based on the HTTP 402 Payment Required status code, providing developers with a complete on-chain payment verification solution.

License License License

简体中文 | English

Depend

cargo add x402-sdk

Architecture overview

┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
│ client request  │──▶│    X402 Core     │ ──▶│  Pay validator  │
└─────────────────┘    └──────────────────┘    └─────────────────┘
         │                       │                       │
         ▼                       ▼                       ▼
┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
│ HTTP 402 Status │    │  Session Cache   │    │   Block SDK     │
└─────────────────┘    └──────────────────┘    └─────────────────┘

🚀Multi-chain Support

OrderType progress
Ethereum
Base
BSC
Solana
Aptos
Sui

Example

Axum

use axum::{extract::State, http::StatusCode, response::Json, Router};
use std::sync::Arc;
use x402::core::X402;

struct AppState {
    x402_engine: Arc<X402>,
}

// http pay interface request processing
async fn access_premium_content(
    State(state): State<Arc<AppState>>,
    headers: axum::http::HeaderMap,
    axum::extract::Path(resource_path): axum::extract::Path<String>,
) -> Result<Json<serde_json::Value>, StatusCode> {
    // Get the user address and payment nonce from the request header specified by X402
    let user_address = headers
        .get("x-402-user-address")
        .and_then(|h| h.to_str().ok())
        .ok_or(StatusCode::BAD_REQUEST)?;
    let payment_nonce = headers
        .get("x-402-payment-nonce")
        .and_then(|h| h.to_str().ok());
    let result = state.x402_engine
        .handle_access_request(user_address, &resource_path, payment_nonce, None)
        .await
        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
    if result.should_serve_content {
        // Paid, return content
        Ok(Json(serde_json::json!({
            "status": "success",
            "content": format!("...", resource_path)
        })))
    } else {
        // Payment is required, return payment information
        let payment_info = result.x402_response.unwrap();
        Ok(Json(serde_json::json!({
            "status": "payment_required",
            "amount": payment_info.payment_required.amount,
            "recipient": payment_info.payment_required.recipient,
            "nonce": payment_info.payment_required.nonce
        })))
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let x402_engine = X402::from_default_config()?;
    // Register the specified chain
    x402_engine.register_chain_verifier(
        x402::types::ChainType::ethereum(),
        "https://eth.llamarpc.com".to_string()
    ).await?;
    let app = Router::new()
        .route("/premium", axum::routing::get(access_premium_content))
        .with_state(Arc::new(AppState {
            x402_engine: Arc::new(x402_engine)
        }));
    axum::serve(
        tokio::net::TcpListener::bind("0.0.0.0:3000").await?,
        app
    ).await?;
    Ok(())
}
Commit count: 0

cargo fmt