@usehaia/trace-core.
Status: early. The full pipeline is implemented — verification, envelope
validation, deduplication, and a default
circle.* event vocabulary — and
exercised end to end by replay tests. It has been run against live Arc testnet
traffic, and the shipped fixtures include captured deliveries alongside
synthetic ones; no capture of a failed transaction exists yet.Install
Handle a delivery
createWebhookHandler composes the pieces and returns the HTTP decision; the
surrounding server only relays it:
One handler serves any number of route paths: Circle requires a unique URL per
subscription, but a delivery’s source is identified by
notification_type, not
by the URL it arrived on.
The event vocabulary
Events are recorded in the defaultcircle.* vocabulary (see
normalizeNotification). Terminal wallet transactions become
circle.transaction.{inbound|outbound}.{complete|failed} — with CONFIRMED and
COMPLETE folded together, since chains with instant finality can skip
CONFIRMED. Monitored contract events become
circle.contract.{payment_created|withdrawal|refund}.
Payloads are strictly allowlisted, occurred_at is the fact’s own time from the
payload rather than the delivery time (a transaction’s updateDate, a contract
event’s firstConfirmDate), and context_id is the escrow contract’s address.
A first verified delivery also records one session-level trace.attached
attestation, so “no events” can never be mistaken for “the receiver was never
wired up”. Pass your own normalize to use a different vocabulary.
The pieces below are what the handler composes — usable directly if you need a
different pipeline.
Verify a notification
Every v2 notification is signed (ECDSA P-256 / SHA-256) over the raw request body. Verification must run on the bytes exactly as received — re-serializing parsed JSON can change them and break a valid signature.Validate the envelope and deduplicate
notificationId) and
unordered — so deduplicate before writing, and key any processing off the
state inside the payload, never off arrival order.