You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The EquipChain platform relies on smart contracts deployed on the Stellar/Soroban network to manage meter readings, billing, and protocol configuration. To keep the backend state synchronized with on-chain data, a contract event listener service is required that continuously monitors the Soroban blockchain for events emitted by EquipChain smart contracts and processes them in real-time.
The event listener must support: Event Polling — periodically query the Soroban RPC endpoint for contract events using getEvents() with filters for the EquipChain contract ID, event types, and a starting ledger sequence; Event Processing — for each event received, parse the event data (values are serialized as SCVals — Soroban Contract Values), transform to JSON, and dispatch to the appropriate handler based on event type; Cursor Management — track the last processed ledger sequence and event cursor so the listener can resume from where it left off after restarts; Error Handling — handle RPC errors gracefully, implement exponential backoff for polling failures, and alert on prolonged sync failures; Performance — support multiple polling intervals (real-time: every 5 seconds, near-real-time: every 30 seconds) depending on event criticality.
Event types to handle: meter_reading_submitted (update local meter reading store), config_updated (update local protocol config cache), user_role_changed (update user permissions), billing_cycle_completed (trigger report generation), system_alert (dispatch to WebSocket broadcast and admin notification).
The listener should run as a background service within the Node.js process (or as a separate process for scalability), updating local state via the repository layer (Issue #22).
Architecture: New src/services/eventListener.js implementing the polling loop. New src/services/eventHandlers.js mapping event types to handler functions. Initialization in src/index.js after server starts.
Impact: This service is the bridge between on-chain state and the API's local data. Without it, the API would only return cached data that could become stale, or would need to query the blockchain on every request (expensive and slow). This is essential for data freshness.
Step-by-Step Implementation Guide
Create Event Handlers: Write src/services/eventHandlers.js with handler functions for each event type: handleMeterReadingSubmitted(event), handleConfigUpdated(event), handleUserRoleChanged(event), handleBillingCycleCompleted(event), handleSystemAlert(event). Each handler parses the SCVal payload, transforms to JSON, and updates the corresponding repository.
Implement Cursor Management: On each poll, retrieve the last processed cursor from Redis. Use it as the cursor parameter in getEvents(). After processing, save the new cursor. On first start with no cursor, start from the current ledger (or a configurable lookback period).
Integrate with Application: In src/index.js, after the server starts, instantiate and start the event listener. Register a graceful shutdown handler that stops the listener on SIGTERM/SIGINT. Log listener status changes (started, stopped, sync progress).
Add Health Check Integration: Update the health endpoint (GET /api/health) to include event listener status: lastPolledLedger, lastEventTimestamp, eventsProcessed, status (syncing, synced, error).
Start the server with a connection to Soroban testnet (or mock). Verify the event listener starts automatically and logs: "Event listener started, polling every 5s".
Submit a transaction on the Soroban testnet that emits a known event type — verify the listener picks it up within the polling interval and the handler processes it (check logs for "Processing event: meter_reading_submitted").
Simulate an RPC failure by temporarily stopping the Soroban mock — verify the listener logs a warning, retries with backoff, and recovers when the RPC endpoint becomes available.
Restart the server — verify the listener resumes from the last saved cursor (no duplicate processing of previously handled events).
Check the health endpoint — verify it shows the event listener status with correct eventsProcessed count and lastPolledLedger.
Description
The EquipChain platform relies on smart contracts deployed on the Stellar/Soroban network to manage meter readings, billing, and protocol configuration. To keep the backend state synchronized with on-chain data, a contract event listener service is required that continuously monitors the Soroban blockchain for events emitted by EquipChain smart contracts and processes them in real-time.
The event listener must support: Event Polling — periodically query the Soroban RPC endpoint for contract events using
getEvents()with filters for the EquipChain contract ID, event types, and a starting ledger sequence; Event Processing — for each event received, parse the event data (values are serialized as SCVals — Soroban Contract Values), transform to JSON, and dispatch to the appropriate handler based on event type; Cursor Management — track the last processed ledger sequence and event cursor so the listener can resume from where it left off after restarts; Error Handling — handle RPC errors gracefully, implement exponential backoff for polling failures, and alert on prolonged sync failures; Performance — support multiple polling intervals (real-time: every 5 seconds, near-real-time: every 30 seconds) depending on event criticality.Event types to handle:
meter_reading_submitted(update local meter reading store),config_updated(update local protocol config cache),user_role_changed(update user permissions),billing_cycle_completed(trigger report generation),system_alert(dispatch to WebSocket broadcast and admin notification).The listener should run as a background service within the Node.js process (or as a separate process for scalability), updating local state via the repository layer (Issue #22).
Technical Context & Impact
getEvents()and SCVal parsing. Background job queue (Issue [Feature] Implement Background Job Queue for Scheduled Tasks (Billing, Reports, Sync) #18) for dispatching event processing tasks. Redis (Issue [Performance] Add Redis Caching Layer for Frequent Blockchain Data Queries #12) for cursor persistence.src/services/eventListener.jsimplementing the polling loop. Newsrc/services/eventHandlers.jsmapping event types to handler functions. Initialization insrc/index.jsafter server starts.Step-by-Step Implementation Guide
src/services/eventHandlers.jswith handler functions for each event type:handleMeterReadingSubmitted(event),handleConfigUpdated(event),handleUserRoleChanged(event),handleBillingCycleCompleted(event),handleSystemAlert(event). Each handler parses the SCVal payload, transforms to JSON, and updates the corresponding repository.src/services/eventListener.jsexportingclass EventListener. Constructor accepts Soroban server (Issue [Feature] Integrate Soroban SDK for Direct Blockchain Data Access and Contract Interaction #3), contract ID, and polling interval. Implementstart()which begins a polling loop usingsetInterval. In each iteration: callserver.getEvents()with filters, process new events, update cursor. Implementstop()to cleanly shut down the loop. Store cursor in Redis (Issue [Performance] Add Redis Caching Layer for Frequent Blockchain Data Queries #12) for persistence across restarts.getEvents(). After processing, save the new cursor. On first start with no cursor, start from the current ledger (or a configurable lookback period).src/index.js, after the server starts, instantiate and start the event listener. Register a graceful shutdown handler that stops the listener onSIGTERM/SIGINT. Log listener status changes (started, stopped, sync progress).GET /api/health) to include event listener status:lastPolledLedger,lastEventTimestamp,eventsProcessed,status(syncing, synced, error).tests/unit/eventListener.test.jswith mocked SorobangetEvents()responses. Test: event polling, cursor advancement, handler dispatch, error recovery (RPC failure → retry). Createtests/unit/eventHandlers.test.jstesting SCVal parsing and repository updates.Verification & Testing Steps
eventsProcessedcount andlastPolledLedger.