# LedgerFlow LedgerFlow is an open infrastructure project that provides a chain-agnostic x402 v2 facilitator for AI-native payments. It enables resource servers to adopt x402 payment verification once and settle payments across offchain and onchain rails without changing their protocol-facing API. The project addresses settlement fragmentation in x402 adoption by providing a unified architecture that handles both centralized exchange (CEX) / payment service provider (PSP) integrations and blockchain-based settlements through a pluggable adapter system. The system consists of multiple components: the Facilitator service for x402 protocol handling, the Balancer service for order and account management, multi-language SDKs (Rust, Python, TypeScript, WASM), and CLI tools for interacting with smart contract vaults on EVM chains, Sui, and Aptos networks. LedgerFlow uses a dispatch layer with an adapter registry keyed by `(x402Version, scheme, networkPattern)` to route payments to the appropriate settlement backend. --- ## Facilitator API ### POST /verify - Verify x402 Payment Validates an x402 v2 payment payload against the payment requirements without executing settlement. Returns verification status and optional error reason. ```bash # Verify an offchain payment curl -X POST http://localhost:3402/verify \ -H "Content-Type: application/json" \ -d '{ "x402Version": 2, "paymentPayload": { "x402Version": 2, "scheme": "exact", "network": "offchain:binance", "payload": { "signature": "0x...", "authorization": { "from": "cex:user:alice", "to": "cex:user:bob", "value": "1000000", "validAfter": "0", "validBefore": "1735689600", "nonce": "0x0000000000000000000000000000000000000000000000000000000000000001" } } }, "paymentRequirements": { "scheme": "exact", "network": "offchain:binance", "maxAmountRequired": "1000000", "resource": "https://api.example.com/premium", "description": "Premium API access", "mimeType": "application/json", "payTo": "cex:user:bob", "maxTimeoutSeconds": 3600, "asset": "USDC" } }' # Response (valid) { "isValid": true, "payer": "cex:user:alice" } # Response (invalid) { "isValid": false, "invalidReason": "authorization not within valid window" } ``` ### POST /settle - Execute x402 Settlement Processes the actual payment settlement after verification. Dispatches to the appropriate adapter based on scheme and network. ```bash # Settle an EVM on-chain payment curl -X POST http://localhost:3402/settle \ -H "Content-Type: application/json" \ -d '{ "x402Version": 2, "paymentPayload": { "x402Version": 2, "scheme": "exact", "network": "eip155:84532", "payload": { "signature": "0x1234...abcd", "authorization": { "from": "0xSenderAddress", "to": "0xRecipientAddress", "value": "1000000", "validAfter": "0", "validBefore": "1735689600", "nonce": "0x0000000000000000000000000000000000000000000000000000000000000001" } } }, "paymentRequirements": { "scheme": "exact", "network": "eip155:84532", "maxAmountRequired": "1000000", "resource": "https://api.example.com/data", "description": "Data access payment", "mimeType": "application/json", "payTo": "0xRecipientAddress", "maxTimeoutSeconds": 3600, "asset": "0xUSDCContractAddress" } }' # Response (success) { "success": true, "payer": "0xSenderAddress", "transaction": "0xtxhash..." } # Response (failure) { "success": false, "reason": "insufficient balance", "network": "eip155:84532" } ``` ### GET /supported - List Supported Payment Types Returns all payment schemes, networks, and signers supported by the facilitator. ```bash curl http://localhost:3402/supported # Response { "kinds": [ { "x402_version": 2, "scheme": "exact", "network": "offchain:*" }, { "x402_version": 2, "scheme": "exact", "network": "eip155:84532" } ], "extensions": [], "signers": { "eip155:84532": ["0xFacilitatorAddress"] } } ``` ### GET /health - Health Check Returns the current health status of the facilitator service. ```bash curl http://localhost:3402/health # Response { "status": "ok" } ``` --- ## Balancer API ### POST /orders - Create Payment Order Creates a new payment order for an account. Generates a unique keccak256-based order ID. ```bash curl -X POST http://localhost:8080/orders \ -H "Content-Type: application/json" \ -d '{ "account_id": 1, "amount": "100.50", "token_address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "chain_id": 1, "broker_id": "ledgerflow" }' # Response { "order_id": "0xf6a9b4070b02024a5d1e8e278618409cf219dfb7013415b1786896b24a2799e5", "amount": "100.50", "token_address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "chain_id": 1, "status": "pending", "created_at": "2024-01-15T10:30:00Z" } ``` ### GET /orders/{order_id} - Get Order Details Retrieves full details of a specific order by its ID. ```bash curl http://localhost:8080/orders/0xf6a9b4070b02024a5d1e8e278618409cf219dfb7013415b1786896b24a2799e5 # Response { "order_id": "f6a9b4070b02024a5d1e8e278618409cf219dfb7013415b1786896b24a2799e5", "account_id": 1, "amount": "100.50", "token_address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "chain_id": 1, "status": "completed", "created_at": "2024-01-15T10:30:00Z", "updated_at": "2024-01-15T10:35:00Z", "transaction_hash": "0x123abc..." } ``` ### POST /register - Register Account Creates a new account with username, email, Telegram ID, and EVM wallet address. ```bash curl -X POST http://localhost:8080/register \ -H "Content-Type: application/json" \ -d '{ "username": "alice", "email": "alice@example.com", "telegram_id": 123456789, "evm_pk": "0xAliceWalletAddress", "is_admin": false }' # Response { "id": 1, "username": "alice", "email": "alice@example.com", "telegram_id": 123456789, "evm_address": "0xAliceWalletAddress", "is_admin": false, "created_at": "2024-01-15T10:00:00Z", "updated_at": "2024-01-15T10:00:00Z" } ``` ### GET /accounts/{account_id}/balance - Get Account Balance Returns the balance summary and completed orders count for an account. ```bash curl http://localhost:8080/accounts/1/balance # Response { "account_id": 1, "total_balance": "1500.00", "completed_orders_count": 15 } ``` ### GET /admin/orders - List Pending Orders Administrative endpoint to list all pending orders with pagination. ```bash curl "http://localhost:8080/admin/orders?limit=10&offset=0" # Response { "total_count": 5, "orders": [ { "order_id": "abc123...", "account_id": 1, "amount": "50.00", "token_address": "0xUSDC...", "chain_id": 1, "status": "pending", "created_at": "2024-01-15T10:30:00Z", "updated_at": "2024-01-15T10:30:00Z", "transaction_hash": null } ] } ``` --- ## Rust SDK (ledgerflow-sdk-rs) ### LedgerFlowClient - HTTP Client Native Rust client for interacting with the Balancer API. All methods are async and return `Result`. ```rust use ledgerflow_sdk_rs::client::LedgerFlowClient; use ledgerflow_sdk_rs::models::{CreateOrderRequest, RegisterAccountRequest}; #[tokio::main] async fn main() -> Result<(), Box> { // Create client with 30-second timeout let client = LedgerFlowClient::new("http://localhost:8080")?; // Health check let health = client.health_check().await?; println!("Service status: {}", health.status); // Register a new account let account = client.register_account(&RegisterAccountRequest { username: "alice".to_string(), email: "alice@example.com".to_string(), telegram_id: 123456789, evm_pk: "0xAliceWalletAddress".to_string(), is_admin: Some(false), }).await?; println!("Created account ID: {}", account.id); // Create a payment order let order = client.create_order(&CreateOrderRequest { account_id: account.id, amount: Some("100.00".to_string()), token_address: Some("0xUSDC...".to_string()), chain_id: Some(1), broker_id: Some("ledgerflow".to_string()), }).await?; println!("Order ID: {}", order.order_id); // Fetch order details let order_details = client.get_order(&order.order_id).await?; println!("Order status: {:?}", order_details.status); // Get account balance let balance = client.get_balance(account.id).await?; println!("Balance: {}, Orders: {}", balance.total_balance, balance.completed_orders_count); // List pending orders (admin) let pending = client.list_pending_orders(Some(10), Some(0)).await?; println!("Pending orders: {}", pending.total_count); Ok(()) } ``` ### generate_order_id - Deterministic Order ID Generation Generates a unique order ID using keccak256 hash, matching the on-chain smart contract logic. ```rust use ledgerflow_sdk_rs::utils::generate_order_id; fn main() { // Generate deterministic order ID // Matches: keccak256(abi.encodePacked(broker_id, account_id, order_id_num)) let order_id = generate_order_id("ledgerflow", 1, 1); println!("Order ID: 0x{}", order_id); // Output: 0xf6a9b4070b02024a5d1e8e278618409cf219dfb7013415b1786896b24a2799e5 // Different inputs produce different hashes let order_id_2 = generate_order_id("ledgerflow", 1, 2); assert_ne!(order_id, order_id_2); // Empty broker ID is valid let order_id_empty = generate_order_id("", 1, 1); println!("Empty broker order: 0x{}", order_id_empty); } ``` --- ## Python SDK (ledgerflow-sdk-py) ### LedgerFlowClient - Python Bindings PyO3-based Python bindings providing synchronous access to the Balancer API. ```python from ledgerflow_sdk import ( LedgerFlowClient, CreateOrderRequest, RegisterAccountRequest, OrderStatus, generate_order_id, ) # Initialize client client = LedgerFlowClient("http://localhost:8080") # Health check health = client.health_check() print(f"Service: {health.service}, Status: {health.status}") # Register account account = client.register_account(RegisterAccountRequest( username="alice", email="alice@example.com", telegram_id=123456789, evm_pk="0xAliceWalletAddress", is_admin=False, )) print(f"Account ID: {account.id}, Username: {account.username}") # Create order order = client.create_order(CreateOrderRequest( account_id=account.id, amount="100.00", token_address="0xUSDC...", chain_id=1, broker_id="ledgerflow", )) print(f"Order: {order.order_id}, Status: {order.status}") # Get order details details = client.get_order(order.order_id) if details.status == OrderStatus.Completed: print(f"Transaction: {details.transaction_hash}") # Get balance balance = client.get_balance(account.id) print(f"Balance: {balance.total_balance}, Completed: {balance.completed_orders_count}") # Generate order ID (matches on-chain logic) order_id = generate_order_id("ledgerflow", 1, 1) print(f"Generated Order ID: 0x{order_id}") # List pending orders with pagination pending = client.list_pending_orders(limit=10, offset=0) print(f"Total pending: {pending.total_count}") for order in pending.orders: print(f" - {order.order_id}: {order.amount}") ``` --- ## TypeScript/Browser SDK (ledgerflow-sdk-frontend) ### LedgerFlowClient - WASM Bindings Browser-compatible JavaScript SDK using wasm-bindgen for frontend applications. ```javascript import { LedgerFlowClient, generateOrderId } from 'ledgerflow-sdk-frontend'; // Initialize client const client = new LedgerFlowClient("https://api.ledgerflow.dev"); // Health check const health = await client.healthCheck(); console.log(`Service: ${health.service}, Status: ${health.status}`); // Register account const account = await client.registerAccount({ username: "alice", email: "alice@example.com", telegram_id: 123456789, evm_pk: "0xAliceWalletAddress", is_admin: false, }); console.log(`Account ID: ${account.id}`); // Create payment order const order = await client.createOrder({ account_id: account.id, amount: "100.00", token_address: "0xUSDC...", chain_id: 1, broker_id: "ledgerflow", }); console.log(`Order ID: ${order.order_id}, Status: ${order.status}`); // Get order details const details = await client.getOrder(order.order_id); console.log(`Order status: ${details.status}`); // Get account balance const balance = await client.getBalance(account.id); console.log(`Balance: ${balance.total_balance}`); // Lookup account by username const foundAccount = await client.getAccountByUsername("alice"); console.log(`Found: ${foundAccount.email}`); // Generate deterministic order ID (client-side) const orderId = generateOrderId("ledgerflow", 1, 1); console.log(`Generated: 0x${orderId}`); // List pending orders with pagination const pending = await client.listPendingOrders(10, 0); console.log(`Pending orders: ${pending.total_count}`); ``` --- ## EVM CLI (ledgerflow-eth-cli) ### Deposit Command Standard deposit to PaymentVault contract requiring prior USDC approval. ```bash # Set environment variables export RPC_URL="https://sepolia.base.org" export PRIVATE_KEY="0xYourPrivateKey" export VAULT_ADDRESS="0xPaymentVaultAddress" # Deposit 1 USDC (1000000 in micro units) ledgerflow-eth-cli deposit \ --rpc-url "$RPC_URL" \ --private-key "$PRIVATE_KEY" \ --contract-address "$VAULT_ADDRESS" \ --order-id "0xf6a9b4070b02024a5d1e8e278618409cf219dfb7013415b1786896b24a2799e5" \ --amount 1000000 ``` ### DepositWithPermit Command Gas-efficient deposit using ERC-2612 permit signature (no separate approval transaction). ```bash ledgerflow-eth-cli deposit-with-permit \ --rpc-url "$RPC_URL" \ --private-key "$PRIVATE_KEY" \ --contract-address "$VAULT_ADDRESS" \ --order-id "0xOrderIdHash" \ --amount 1000000 \ --deadline 1735689600 ``` ### Withdraw Command Withdraw all USDC from the vault (owner only). ```bash ledgerflow-eth-cli withdraw \ --rpc-url "$RPC_URL" \ --private-key "$PRIVATE_KEY" \ --contract-address "$VAULT_ADDRESS" ``` --- ## Sui CLI (ledgerflow-sui-cli) ### Initialize Configuration Create a sample configuration file for the Sui CLI. ```bash # Create TOML configuration ledgerflow-sui-cli init --path config.toml # Force overwrite existing config ledgerflow-sui-cli init --path config.toml --force # Example config.toml content: # [network] # rpc_url = "https://fullnode.testnet.sui.io:443" # # [account] # private_key = "your_private_key_here" # # [vault] # package_id = "0xPackageId" # vault_object_id = "0xVaultObjectId" # usdc_type = "0x2::sui::SUI" # # [transaction] # gas_budget = 10000000 ``` ### Deposit Command Deposit tokens to the Sui vault with an order ID. ```bash # Deposit 1000 units with specific order ID ledgerflow-sui-cli deposit \ --config config.toml \ --order-id "order_12345" \ --amount 1000 \ --output json # Dry run (simulate without executing) ledgerflow-sui-cli deposit \ --config config.toml \ --order-id "test_order" \ --amount 500 \ --dry-run # Response (JSON output) { "operation": "deposit", "order_id": "order_12345", "amount": 1000, "transaction_hash": "0xTxHash...", "gas_used": 2500000, "status": "success" } ``` ### Withdraw Command Withdraw tokens from the Sui vault. ```bash # Withdraw specific amount ledgerflow-sui-cli withdraw \ --config config.toml \ --recipient "0xRecipientAddress" \ --amount 500 # Withdraw all funds ledgerflow-sui-cli withdraw \ --config config.toml \ --recipient "0xRecipientAddress" \ --all ``` ### Vault Info Command Display vault and account information. ```bash # Get vault info only ledgerflow-sui-cli info --config config.toml # Include account balances ledgerflow-sui-cli info --config config.toml --include-account --output json # Response { "vault": { "address": "0xVaultAddress", "balance": "50000", "owner": "0xOwnerAddress", "created_at": "2024-01-15T10:00:00Z" }, "account": { "address": "0xAccountAddress", "usdc_balance": "10000", "sui_balance": "5000000000" } } ``` ### Intent Transfer Command Create intent-signed transfers for x402 protocol verification and settlement. ```bash # Create intent transfer and verify with facilitator ledgerflow-sui-cli intent-transfer \ --config config.toml \ --recipient "0xRecipientAddress" \ --amount 1000 \ --order-id "order_xyz" \ --facilitator-url "http://localhost:3402" \ --test-settle # Dry run mode ledgerflow-sui-cli intent-transfer \ --config config.toml \ --recipient "0xRecipient" \ --amount 500 \ --order-id "test_intent" \ --facilitator-url "http://localhost:3402" \ --dry-run ``` --- ## Aptos CLI (ledgerflow-aptos-cli-ts) ### Deposit Command Interactive deposit to the Aptos PaymentVault. ```bash # Interactive mode (prompts for private key and amount) ledgerflow-aptos deposit # With command line arguments ledgerflow-aptos deposit \ --private-key "0xYourPrivateKey" \ --amount 1.5 # Output Current Balances: USDC: 100.00 Vault: 50.00 Deposit Summary: Amount: 1.50 USDC Deposit successful! Transaction hash: 0xTxHash... View on explorer: https://explorer.aptoslabs.com/txn/0xTxHash?network=testnet ``` ### Balance Command Check USDC and vault balances. ```bash ledgerflow-aptos balance --private-key "0xYourPrivateKey" # Output Account: 0xYourAddress USDC Balance: 100.00 Vault Balance: 50.00 ``` ### Vault Info Command Display vault contract information. ```bash ledgerflow-aptos vault-info # Output Vault Address: 0xVaultAddress Owner: 0xOwnerAddress Total Deposits: 1000.00 USDC ``` ### Withdraw All Command Withdraw all funds from the vault (owner only). ```bash ledgerflow-aptos withdraw-all --private-key "0xOwnerPrivateKey" ``` --- ## Configuration ### Facilitator Configuration (config.toml) Configure adapters for different payment networks and backends. ```toml # Server settings host = "0.0.0.0" port = 3402 # Rate limiting (requests per second) rate_limit_per_second = 100 # Offchain mock adapter (development) [[adapters]] kind = "offchain" id = "cex-mock" enabled = true x402_version = 2 scheme = "exact" networks = ["offchain:*"] signers = ["offchain-facilitator"] [adapters.backend] type = "mock" payer = "cex:user:alice" transaction_prefix = "cex-tx" # Offchain HTTP adapter (production) [[adapters]] kind = "offchain" id = "binance-bridge" enabled = true x402_version = 2 scheme = "exact" networks = ["offchain:binance"] signers = ["binance-facilitator"] [adapters.backend] type = "http" base_url = "https://payments.company.internal" verify_path = "/api/v1/x402/verify" settle_path = "/api/v1/x402/settle" api_key_env = "BINANCE_BRIDGE_API_KEY" timeout_seconds = 8 # EVM on-chain adapter (Base Sepolia testnet) [[adapters]] kind = "evm" id = "base-sepolia" enabled = true x402_version = 2 scheme = "exact" networks = ["eip155:84532"] rpc_url = "https://sepolia.base.org" chain_id = 84532 signer_key_env = "EVM_SIGNER_PRIVATE_KEY" signers = ["0xYourFacilitatorAddress"] ``` ### Balancer Configuration (config.yaml) Configure database, server, and business rules for the Balancer service. ```yaml database_url: "postgres://user:password@localhost/ledgerflow" server: host: "0.0.0.0" port: 8080 business: max_pending_orders_per_account: 10 x402: kinds: - x402_version: 1 scheme: "exact" network: "eip155:84532" evm: rpc_http: "https://sepolia.base.org" chain_id: 84532 vault_address: "0xVaultContractAddress" facilitator_private_key: "${EVM_FACILITATOR_KEY}" ``` --- ## Summary LedgerFlow provides a complete infrastructure for implementing x402 payments across multiple blockchain networks and offchain payment rails. The primary use cases include: integrating AI agents with payment capabilities through the x402 protocol, building API marketplaces that accept cryptocurrency payments, bridging centralized exchange accounts with decentralized payment flows, and enabling resource servers to monetize their APIs with minimal integration effort. The SDK ecosystem supports native integration in Rust, Python, TypeScript, and browser environments. The architecture follows a clean separation between protocol handling (Facilitator) and business logic (Balancer), with pluggable adapters enabling support for new networks without code changes. Integration patterns include direct REST API calls for simple use cases, SDK integration for type-safe development, CLI tools for operational tasks and testing, and smart contract interaction for on-chain vault management. The system is designed for config-driven expansion, allowing new payment systems to be added through configuration rather than HTTP/API rewrites.