Skip to content

[Feature] Implement Webhook System for Contract Event Notifications to External Services #13

Description

@KarenZita01

Description

The EquipChain platform needs to notify external services when specific on-chain events occur, such as meter reading submissions, contract state changes, or system alerts. This issue implements a webhook system that allows registered external URLs to receive HTTP POST notifications containing event data in JSON format.

The webhook system must include: Webhook Registration — an admin endpoint to register webhooks with a URL, event type filter, optional secret for HMAC signing, and active/inactive status; Event Dispatching — an internal event emitter that dispatches events to all matching registered webhooks. The dispatch should be asynchronous and non-blocking, using a background queue (Issue #18) for reliable delivery with retry logic; Payload Signing — each webhook request must include an HMAC-SHA256 signature header (X-Webhook-Signature) computed from the request body and the shared secret, allowing the recipient to verify authenticity; Retry and Logging — failed deliveries (non-2xx responses or timeouts) should be retried up to 3 times with exponential backoff (1min, 5min, 15min). All delivery attempts and results should be logged for audit and debugging.

The webhook event format should follow a standard structure: { id: "evt_...", type: "meter.reading.created", created: "ISO8601 timestamp", data: { ... event-specific payload }, webhookId: "wh_..." }. The system should support at least the following event types: meter.reading.created, meter.reading.updated, contract.state.changed, system.alert.high, user.registered, and admin.action.

Technical Context & Impact

  • Dependencies: node:crypto for HMAC signing (built-in). A background job mechanism from Issue [Feature] Implement Background Job Queue for Scheduled Tasks (Billing, Reports, Sync) #18 (or a simple in-memory queue for initial implementation). Node.js built-in events module for the event emitter.
  • Architecture: New src/services/webhook.js containing webhook registration store, event emitter, and dispatch logic. New src/routes/admin/webhooks.js for CRUD operations on webhook registrations. Webhook delivery runs in the background to avoid blocking API responses.
  • Impact: Webhooks are a critical integration point for external partners. This feature enables real-time data synchronization with external systems, automated billing triggers, and integration with third-party monitoring services.

Step-by-Step Implementation Guide

  1. Create Webhook Service: Write src/services/webhook.js implementing: registerWebhook(url, events, secret), unregisterWebhook(id), listWebhooks(), dispatchEvent(eventType, payload), deliverWebhook(webhook, event). Use an in-memory store for initial implementation (upgrade to database later). Implement the delivery function with fetch() (Node 18+) and HMAC signing.
  2. Implement Retry Logic: Add retry logic to deliverWebhook() using a queue. On failure, schedule retry with setTimeout (or use Issue [Feature] Implement Background Job Queue for Scheduled Tasks (Billing, Reports, Sync) #18's job queue). Track delivery attempts with a max of 3 retries. Log each attempt with timestamp, status, and response body.
  3. Create Admin Webhook Routes: Write src/routes/admin/webhooks.js with POST /api/admin/webhooks (register), GET /api/admin/webhooks (list), DELETE /api/admin/webhooks/:id (unregister), PATCH /api/admin/webhooks/:id (update). Mount under admin routes with admin authentication.
  4. Create Event Emitter Integration: Create an event emitter instance accessible across the app. In services that produce events (meter readings, contract changes), emit events that the webhook service listens to. Wire this in src/index.js or an app bootstrap function.
  5. Write Tests: Create tests/unit/webhook.test.js testing registration, event dispatching (using nock or similar to mock HTTP), HMAC signature generation, retry logic, and delivery failure handling. Create tests/integration/webhook.test.js testing full flow via API with a test HTTP server as the webhook receiver.

Verification & Testing Steps

  1. Register a webhook pointing to a webhook testing service (webhook.site or a local listener) via POST /api/admin/webhooks.
  2. Trigger an event (e.g., create a meter reading) and verify the webhook receiver gets a POST request with the correct JSON payload.
  3. Verify the X-Webhook-Signature header is present and valid by computing HMAC-SHA256 on the receiver side and comparing.
  4. Configure a webhook with an invalid URL — verify the system retries 3 times with exponential backoff (check logs).
  5. List registered webhooks via GET /api/admin/webhooks and verify all details are correct. Delete a webhook and verify no further events are dispatched to it.

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions