Skip to content

vela-webhook

The webhook event verifier package for VelaPay. Published as @velapay/webhook (v0.1.0). Despite the name, this repo ships a library — not a standalone Worker. The actual fan-out runtime lives inside vela-dashboard/worker/ and consumes @velapay/webhook to verify signatures and reify event types.

Purpose and Role

  • Provide an isomorphic (Node + edge) HMAC-SHA256 verifier for Vela's webhook delivery format (Stripe-compatible wire format).
  • Expose Zod-typed discriminated union over every Vela event so consumers get exhaustive switch coverage in TypeScript.
  • Wrap raw Helius Enhanced webhook payloads into typed Vela events — consumers parse Vela domain events, not raw Helius bytes.
  • Centralize retry, dedup, and idempotency primitives so the dashboard fan-out and any future delivery surface use the same logic.
  • Ship test fixtures so consumers can build dispatch tests without re-deriving valid signed payloads.
  • Parse v1.9 Payment Intent and refund events produced by the dashboard transactional outbox.

Tech Stack

TechnologyVersionPurpose
TypeScript^5.8.xLanguage
Bun1.3.xRuntime + package manager + test runner
Zod^3.xEvent schema validation (consumes @velapay/sdk/events)
Web Crypto APIHMAC-SHA256 verification (works in Workers, Node, Bun)
BiomelatestLint + format

Built into dual CommonJS + ESM with build.ts (Bun bundler).

Package Surface

ExportPurpose
verify(payload, signature, secret)HMAC-SHA256 signature verification (constant-time compare)
parseEvent(rawBody)Parse a verified body into a typed Vela event (Zod-discriminated)
EventType enumAll supported event types (mandate.created, mandate.cancelled, pull.executed, stream.settled, plan.changed, …)
RetryPolicySvix-style retry schedule (exponential backoff with jitter, max attempts)
IdempotencyKey helpersDedup key generation + collision detection
DLQEventWrapper for events that exhausted retries
Test fixturesPre-signed payloads under test-fixtures/ for downstream tests

Directory Structure

vela-webhook/
├── src/
│   ├── verify.ts              # HMAC verification (Web Crypto)
│   ├── parse.ts               # Raw body → typed Vela event
│   ├── retry.ts               # Retry schedule + jitter
│   ├── idempotency.ts         # Dedup key derivation
│   └── index.ts
├── schemas/                   # Zod schemas (re-exported from @velapay/sdk/events)
├── test-fixtures/             # Signed sample payloads for downstream tests
├── tests/                     # bun:test unit tests
├── build.ts                   # Bun bundler (CJS + ESM dual output)
├── package.json
└── tsconfig.json

Consumers

ConsumerHow
vela-dashboard (worker)Verifies inbound Helius webhook signatures, parses payloads into typed events, queues dispatch. Replaces inline Helius parsing that v1.0–v1.7 carried.
External merchantsInstall @velapay/webhook to verify deliveries in their own backends.

Deployment Target

  • npm (when published) — currently versioned but unpublished.
  • Workspace consumption — linked into vela-dashboard via the @vela/webhook alias for local development.

Notable Design Decisions

Library, not Worker

The fan-out runtime lives where the data does — in the dashboard's Worker, alongside D1 (for delivery state) and Queues (for retries). Splitting it into a separate Worker would have introduced a service-binding hop without a clear win. The package shape lets external merchants verify deliveries in their own infrastructure too.

Wrap Helius, Don't Replace It

This repo deliberately does not introduce a new event feed. Helius Enhanced webhooks are still the source of truth for on-chain events. @velapay/webhook only types and re-shapes them — so on-chain truth and merchant-facing webhooks never drift.

Commerce OS is the exception to the ingest origin, not the schema boundary: the dashboard produces commerce events from verified business transitions and routes them directly by merchant_id. The package still supplies the canonical schemas and verifier. Commerce consumers deduplicate by UUID event ID, never by transaction signature.

Stripe Wire Format

Signatures use the Stripe-compatible t=...,v1=... header format. Merchants migrating from Stripe can reuse existing signature-verification utilities or move to @velapay/webhook with no payload-shape surprises.

Schema-Diff CI Gate

Event schemas are co-versioned with @velapay/sdk/events. CI enforces additive-only schema evolution — a removal or rename fails the build. This protects every downstream consumer from silent breaking changes.

Internal knowledge base for the Vela Labs workspace.