Skip to content

Real-Time Soroban Log Event Parser and Decoded Alert Pipeline #8

Description

@JamesEjembi

Problem Statement

Contract logs are retrieved as raw cryptographic hex strings from the Soroban RPC getTransaction response. The current implementation displays these hex strings directly in the dashboard notification panel, forcing operators to manually decode each event by cross-referencing the Soroban contract specification. This adds 30-60 seconds of friction per alert and makes the real-time monitoring dashboard nearly unusable during high-attestation periods.

Technical Bounds & Invariants

  • Soroban event topics: 4 topics per event (ContractId, Signature, Key, Value), each 32-byte hex
  • Event body: SCVal encoded as XDR base64 (~200-500 bytes per event)
  • Supported event types: approve_attestation, reject_attestation, slash_node, reward_distributed, node_registered, node_deregistered, parameter_changed
  • Decoding latency budget: < 10ms per event client-side
  • Must handle unknown event types gracefully (display raw hex with a "not recognized" label)

Codebase Navigation Guide

  • Primary target: /src/hooks/useLedgerEvents.ts
  • Hex decoder utilities: /src/utils/hexDecoder.ts (to be created)
  • Alert notification component: /src/components/alerts/AlertBanner.tsx
  • Event type definitions: /src/types/ledgerEvents.ts

Step-by-Step Resolution Blueprint

  1. Define a TypeScript discriminated union LedgerEvent = ApproveAttestationEvent | RejectAttestationEvent | SlashNodeEvent | RewardDistributedEvent | NodeRegisteredEvent | NodeDeregisteredEvent | ParameterChangedEvent | UnknownEvent in /src/types/ledgerEvents.ts
  2. Build decodeLedgerEvent(rawHexTopics: string[], rawBase64Body: string): LedgerEvent in /src/utils/hexDecoder.ts that: (a) parses topic[0] as the event signature via scval_decode(topic[0]) using the @stellar/stellar-sdk xdr.ScVal.fromXDR method, (b) matches the signature against known event types using a lookup table, (c) decodes topic[1..3] and the body according to the matched type's schema, (d) returns a typed event object
  3. Create a React hook useDecodedLedgerEvents() that wraps useLedgerEvents and applies decodeLedgerEvent to each incoming event via useMemo; memoize the decoded array with a Map<eventId, LedgerEvent> to avoid re-decoding events that have already been processed
  4. Build an AlertBanner component that renders each LedgerEvent with: (a) human-readable title derived from the event type (e.g., "Node Slashed" for slash_node), (b) severity color coding (red for slash/error, yellow for warning, green for approval/reward), (c) actionable details link, (d) timestamp relative to now
  5. For UnknownEvent types, render a fallback display: "Unknown Event — Raw: 0x{hexTopics[0].slice(0, 16)}..." with a "Copy Raw" button and a "Report Unknown Event" feedback action that logs the event shape to Sentry
  6. Add a notification sound (configurable, off by default) for high-severity events (slash_node, reject_attestation) using the Web Audio API with a preloaded short buffer to avoid network requests
  7. Write unit tests using vitest that encode known event structures with @stellar/stellar-sdk, decode them, and assert that: (a) each known type produces the correct human-readable output, (b) an unknown hex string produces an UnknownEvent without throwing, (c) decoding 1,000 events completes in under 100ms

Metadata

Metadata

Assignees

Labels

Complexity: HardcoreExtremely difficult, high-complexity engineering taskGrantFox OSSIssue tracked in GrantFox OSSLayer: UI-CoreCore UI layer architectural concernMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial CampaignCampaign: Official CampaignType: Web3-IntegrationWeb3 wallet and blockchain integration issue

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions