Skip to content

Quick Start

This guide walks you through issuing your first LedgerFlow warrant and verifying an x402 payment with authorization.

Prerequisites

  • Rust (1.75+)
  • Basic understanding of x402 payment protocol
  • Familiarity with Ed25519 signatures

Step 1: Install

git clone https://github.com/akjong/ledgerflow.git
cd ledgerflow
cargo build

Step 2: Generate Keys

Generate an issuer key pair and an agent key pair:

# Generate issuer key (Ed25519)
cargo run -p ledgerflow-cli -- gen-key --label issuer

# Generate agent key (Ed25519)
cargo run -p ledgerflow-cli -- gen-key --label agent

Step 3: Issue a Warrant

Create a warrant authorizing the agent to make payments:

cargo run -p ledgerflow-cli -- issue-warrant \
  --issuer-keys issuer.key \
  --agent-keys agent.key \
  --merchant "api.example.com" \
  --max-amount 10.00 \
  --asset USDC \
  --ttl 3600 \
  --tools "web_search,code_execution"

This creates a warrant that:

  • Is signed by the issuer
  • Authorizes the agent identified by agent.key
  • Restricts to merchant api.example.com
  • Limits spending to $10 USDC per request
  • Expires in 1 hour
  • Restricts to web_search and code_execution tools

Step 4: Build the x402 Payment

When the agent receives an x402 402 Payment Required response:

cargo run -p ledgerflow-cli -- build-payment \
  --warrant warrant.cbor \
  --agent-keys agent.key \
  --challenge-id "01HV7W8M7BX3Q6P0WJ7T5QK1V2" \
  --accepted-hash "sha256:abc123..." \
  --request-hash "sha256:def456..."

This produces the x402 payment payload with the LedgerFlow extension attached.

Step 5: Verify (Merchant Side)

The merchant middleware verifies the authorization:

cargo run -p ledgerflow-cli -- verify \
  --payment payment.json \
  --request-context request.json

Verification checks:

  • Warrant signature validity
  • Proof signature validity
  • Warrant temporal validity
  • Audience scope
  • All constraints
  • Proof binding
  • Replay protection

Programmatic Usage

Issue a Warrant

use ledgerflow_core::{Warrant, SignerRef, Constraint};

let warrant = Warrant::builder()
    .issuer(issuer_signer)
    .subject_signer(agent_signer)
    .payment_subjects(vec![payment_subject])
    .audience(AudienceScope::MerchantIds(vec!["api.example.com".into()]))
    .not_before(now_ms)
    .expires_at(now_ms + 3600_000)
    .delegation(DelegationPolicy { can_delegate: true, max_depth: 2 })
    .constraints(vec![
        Constraint::Merchant(MerchantConstraint {
            host_suffixes: vec![".example.com".into()],
            ..Default::default()
        }),
        Constraint::Payment(PaymentConstraint {
            max_per_request: AmountLimit { amount: "10000000".into(), asset: "USDC".into() },
            ..Default::default()
        }),
    ])
    .sign(&issuer_key)?;

Verify Authorization

use ledgerflow_x402::{verify_authorization, VerifierContext};

let ctx = VerifierContext::new()
    .with_challenge_id(challenge_id)
    .with_request(request)
    .with_accepted(accepted);

let result = verify_authorization(&extension, &ctx)?;
match result {
    AuthzResult::Authorized { warrant_id, .. } => {
        // Proceed with x402 settlement
    }
    AuthzResult::Denied { reason, .. } => {
        // Reject the payment
    }
}

Integration Patterns

Pattern 1: Gateway Middleware

Place LedgerFlow verification in your x402 middleware layer:

Request → x402 Middleware → LedgerFlow Verifier → Settlement

Pattern 2: Sidecar

Run LedgerFlow verification as a sidecar service:

Request → Gateway → Sidecar (LedgerFlow) → Backend

Pattern 3: MCP Proxy

For Model Context Protocol integrations, verify at the MCP proxy layer:

Agent → MCP Proxy (LedgerFlow) → Tool Server

Testing

Run the acceptance scenarios:

just test
just bdd
just test-all

Next Steps