A local debugger for x402 on Base.

Detects timeout-reconciliation gaps, validates Bazaar listings, diffs facilitators, and explains 402s. Read-only. Runs on your laptop. No keys handled.

View on GitHub
version0.3.1runtimenode ≥ 20networkbase-sepolialicenseapache-2.0
$ npx x402trace proxy --reconcile --log payments.jsonl

[14:23:08] proxy listening :8402  upstream=https://api.example.com
[14:23:12] X-PAYMENT received  id=35d9aea1  payer=0xADEe…B895
[14:23:12] /verify → {200} payer=0xADEe…B895
[14:23:13] /settle → {200} success=true
[14:23:25] upstream timeout {502}  id=35d9aea1
[14:23:31] chain.Transfer matched  tx=0x116ccf73…ba52  value=1000

{RECONCILED ⚠ settled-but-server-thinks-not  id=35d9aea1}
  tx=0x116ccf73…ba52  value=1000  gap=11904ms
  payer=0xADEe…B895 → payee=0xADEe…B895
livetx0x116ccf73…ba52verified on-chain

Two views of the same transaction.

Your buyer signs an EIP-3009 authorization. The facilitator settles on-chain. Your upstream times out. The buyer's wallet is debited and your server thinks nothing happened.

your-server.loglooks like a 502
14:23:12 POST /paid-endpoint     → pending
14:23:12 facilitator.verify      200
14:23:13 facilitator.settle      200
14:23:25 upstream timeout (10s)
14:23:25 response                502 Bad Gateway

# nothing to reconcile. user retries. user
# pays twice. support ticket arrives Monday.
x402trace --reconcilecatches the gap
14:23:12 X-PAYMENT received      id=35d9aea1
14:23:13 /settle                 200
14:23:25 upstream                502
14:23:31 chain.Transfer matched  tx=0x116c…ba52

{RECONCILED ⚠ settled-but-server-thinks-not}
  id=35d9aea1
  gap=11904ms  value=1000 (=$0.001 USDC)
  → refund flow or replay upstream

Same payment. Different conclusions. Reconciled by coinbase/x402#1062.

A read-only proxy between client and service.

x402trace intercepts X-PAYMENT exchanges, captures them to JSONL, and joins them against the chain. Your service code does not change.

  1. client walletx402trace proxy
    X-PAYMENT (EIP-3009)
  2. x402trace proxyyour service
    forward (verify / settle)
  3. onx402trace proxy
    capture → JSONL
  4. x402trace proxyBase RPC
    chain.Transfer query
  5. onx402trace proxy
    reconcile if on-chain ≠ server
  • 01Intercepts every X-PAYMENT exchange and writes a typed JSONL trail.
  • 02Reconciles server outcome against Base USDC Transfer events.
  • 03Explains deltas offline, using 15 rules. Zero keys read.

Four headline subcommands. One audit trail.

Each runs locally. None handles keys. All read-only. Two more (inspect, versions) in --help.

x402trace proxy
primary

Capture every X-PAYMENT exchange to JSONL. Optional --reconcile joins against Base USDC Transfer events to detect the #1062 gap in real time.

$ x402trace proxy --port 8402 \
    --upstream http://localhost:3000 \
    --reconcile
x402trace validate

Pre-flight a wallet against a service's 402 challenge. With --diff, runs the payload through multiple facilitators in parallel and surfaces drift.

$ x402trace validate \
    --diff cdp,xpay,x402.org \
    <wallet> <service-url>
x402trace explain

Plain-English diagnosis of a captured JSONL log. 15 rules cover CDP min-amount, self-payment, throttling, missing EXTENSION-RESPONSES, gas-estimation failure, and more.

$ x402trace explain payments.jsonl
x402trace bazaar-check

Validates .well-known/x402, extensions.bazaar, and the indexing query. Returns one of looks_correct / implementation_issue / upstream_issue (#2207).

$ x402trace bazaar-check https://my-service.example.com

15 rules. All offline.

The explain subcommand runs every rule against your JSONL log. No network calls.

src/diagnose/rules.ts
  1. [01]
    cdpMinAmountRule

    CDP facilitator rejects amounts below $0.001 USDC.

  2. [02]
    selfPaymentRule

    Payer address equals payee address.

  3. [03]
    facilitatorThrottlingRule

    403/429 without a documented rate limit.

  4. [04]
    extensionResponsesMissingRule

    Settle succeeded but EXTENSION-RESPONSES header absent (#2207).

  5. [05]
    gasEstimationFailureRule

    Intermittent "unable to estimate gas" on Base mainnet (#1065).

  6. [06–15]ten more in source

Verified on-chain.

One canonical demo. Two more reconciliations linked from the README.

Base Sepolia · x402-15 demoreconciled
0x116ccf73…ba52
value
$0.001 USDC
gap
11,904 ms
scheme
exact
payer=0xADEe…B895 → payee=0xADEe…B895Two more on-chain captures

30-second quickstart.

Three commands. The last runs the canonical Base Sepolia demo end-to-end against a funded test wallet.

Requires Node ≥20 and pnpm. Demo wallet setup in examples/README.md.

# 1. Install + run
$ npx x402trace --version

# 2. Diagnose a captured log
$ x402trace explain ./payments.jsonl

# 3. Run the canonical Base Sepolia demo
$ git clone https://github.com/fardinvahdat/x402trace.git
$ cd x402trace && pnpm install
$ ./examples/e2e-timeout-reconciliation.sh

Not for you if…

  • You need a hosted dashboard or multi-tenant SaaS.

    x402trace is local-only.

  • You're paying on a chain other than Base.

    x402trace is Base-only.

  • You want a wallet, a facilitator, or a payment SDK.

    x402trace is none of those — use x402.