Skip to main content
The capture adapter for the x402 payment SDK. Attach it to an x402 instance and it records every lifecycle-hook firing — strictly passively, so it can observe a payment but never alter it. Zero runtime dependencies beyond @usehaia/trace-core.

Install

Connect it

Call trace() once, passing your x402 instance — a client, resource server, facilitator, or MCP client:
trace() inspects the instance’s method set to resolve its kind, attaches to that kind’s lifecycle hooks, and logs the context each hook is handed, tagging every line with the observing role (client / server / facilitator). It works the same on either side of a payment:
Detection is pure duck-typing — no @x402 value is imported at runtime — so API-compatible forks are covered too.

Passivity — the load-bearing guarantee

x402 lifecycle hooks can steer the payment flow through their return value ({ abort }, { skip }, { recovered }, …). Every handler this adapter registers is wrapped in try/catch and always returns undefined, and hooks are chainable, so the recorder runs alongside your own hooks and never displaces them. The worst case of a recorder bug is “capture stopped”, never “payment blocked”.
Set HAIA_TRACE_DISABLE=1 in the environment to make trace() a no-op.

Options

Each logged line has the shape { hook, role, context }.

Attestation

trace() returns a TraceAttestation describing what it connected to — so a caller can tell “no payment events happened” apart from “the recorder never wired up”:

Recognized kinds

Status

This adapter currently records hook firings as raw context. Two pieces are still on the roadmap, and until they land it’s meant for local development and wiring, not a production or real-money flow:
  • Normalized events + local sink — mapping firings to the Event Contract’s event_types (x402.payment.required, …) and writing them to .trace/events/*.ndjson, so trace(...) feeds haia-trace build end-to-end.
  • Redaction — the raw context can contain signatures and credentials; an allowlist-based redaction pass is not in place yet.