Skip to content

Facilitator Architecture

The Facilitator is where settlement rails converge. It extends the standard x402 Facilitator with rail-agnostic routing, allowing a single merchant API to accept payments from any settlement backend.

Design Philosophy

The merchant never knows the rail. The Facilitator abstracts all rail complexity. The agent presents one interface regardless of how it pays.

Rail Adapter Interface

pub trait RailAdapter {
    fn kind(&self) -> PaymentRail;
    async fn quote(&self, request: &SettlementIntent) -> Result<RailQuote>;
    async fn settle(&self, request: &SettlementIntent) -> Result<SettlementReceipt>;
    async fn verify(&self, receipt: &SettlementReceipt) -> Result<VerificationResult>;
}

Each rail adapter implements the same interface. The Facilitator selects adapters based on:

  • The warrant's allowed_rails constraint
  • The payment subject kind
  • Merchant settlement preferences
  • Current rail availability and fees

Supported Rails

Onchain

Direct blockchain settlement via smart contracts or native transfers.

Chain Asset Mechanism
Ethereum / EVM USDC, USDT, ETH x402 smart contract or EIP-3009
Solana USDC, SOL SPL token transfer
Base USDC x402 contract deployment
Arbitrum USDC L2 x402 contract

Exchange

Settlement through exchange internal balances, no on-chain transaction required.

Exchange Mechanism Latency
Binance Internal transfer via API Sub-second
OKX Sub-account transfer Sub-second
Bybit Internal transfer Sub-second

Custodial

Settlement through custodial ledger accounts managed by the Facilitator.

Provider Mechanism Use Case
Facilitator-internal Ledger entries Testing, development
Institutional custodian API-settled Enterprise

Traditional Gateway (Future)

Settlement through traditional payment processors.

Gateway Mechanism Use Case
Stripe Payment intent Credit card backstop
PayPal API payment Fiat fallback

Settlement Routing

The Facilitator receives:

  • Standard x402 payment requirements and payload
  • Normalized LedgerFlow authorization result
  • Resolved payment subject
  • Merchant settlement preferences

It does not need the merchant to understand the underlying rail.

Routing Algorithm

1. Extract payment subject from LedgerFlow extension
2. Determine subject kind (Caip10, ExchangeAccount, etc.)
3. Filter available rails by warrant's allowed_rails constraint
4. Filter by merchant's preferred rails
5. Select rail with lowest cost and sufficient liquidity
6. Execute quote and settlement
7. Return normalized x402 settlement result

Example: Same Merchant, Different Rails

Merchant: "Pay $5 for this API call"

Agent A (Base wallet):
  → payment_subject: caip10:eip155:8453:0xabc...
  → Rail: Onchain (Base USDC via x402 contract)

Agent B (Binance user):
  → payment_subject: binance:uid:12345678
  → Rail: Exchange (Binance internal transfer)

Agent C (OKX user):
  → payment_subject: okx:subacct:agent-alpha
  → Rail: Exchange (OKX sub-account transfer)

All three: same x402 flow, same merchant code, different rails.

Payment Subject Resolution

The Facilitator resolves the payment subject to a concrete settlement identity:

pub struct PaymentSubjectRef {
    pub kind: PaymentSubjectKind,
    pub value: String,
}
Kind Resolution Example
Caip10 Direct on-chain address 0xabc... on Base
FacilitatorAccount Internal ledger lookup Account ID 42
ExchangeAccount Exchange API lookup Binance UID 12345678
Opaque Custom resolution Provider-specific

Extensibility

New rails can be added by implementing the RailAdapter trait:

  1. Create a new module in crates/ledgerflow-facilitator/src/rails/
  2. Implement RailAdapter for the new rail
  3. Register the adapter in the Facilitator routing table
  4. Add the rail to PaymentRail enum

No changes to x402, LedgerFlow core, or merchant code are required.

See Also