Skip to content

Soroban Event Stream Inspector: Contract Event Decoder, Filter Engine & Replay Tool #78

Description

@grantfox-oss

Overview

Soroban contracts emit events that are indexed by Stellar's RPC node and queryable via getEvents. These events are the primary mechanism for off-chain systems to react to on-chain state changes — but they arrive as raw ScVal XDR and require SDK decoding to be meaningful. No tooling exists to query, decode, filter, and replay Soroban contract events visually. A developer building an indexer or a UI on top of a Soroban contract needs to see exactly which events their contract emits, with decoded values, without writing a script.

What needs to be built

apps/api/src/modules/contracts/events.service.ts

  • GET /contracts/events?contractId=<id>&startLedger=<n>&limit=<n>:

    • Calls sorobanRpc.getEvents({ startLedger, filters: [{ type: 'contract', contractIds: [contractId] }] })
    • For each event: decodes topic[] and value from ScVal XDR into typed human-readable values
    • Returns: { events: [{ ledger, txHash, contractId, type, topics: DecodedScVal[], value: DecodedScVal, raw: string }] }
    • DecodedScVal = { type: string, value: string | number | object, raw: string } — handles all 15 ScVal types including nested Map and Vec
  • POST /contracts/events/filter — accepts a filter spec and a list of events; applies client-side filters without a new Horizon call:

    • Filter types: topic_contains, value_type_is, value_equals, ledger_range
    • Returns the filtered subset with matching criteria highlighted per event
  • POST /contracts/events/replay — accepts a list of event payloads; re-submits them to a user-specified webhook URL with HMAC signature — used for testing indexers against historical events
    apps/web/src/app/contracts/events/

  • Contract ID input + Start Ledger input + Limit selector (10 / 50 / 200)

  • "Fetch Events" button — calls the events endpoint

  • Event list — each event as a card: ledger number, tx hash (truncated + copy), event type badge (contract | system | diagnostic); topics rendered as typed chips; value rendered inline with type annotation; "Expand Raw XDR" accordion

  • Filter bar above the list: topic contains, value type selector, ledger range inputs — applied client-side instantly

  • "Replay to Webhook" button — opens a modal to enter a webhook URL + HMAC secret; replays all currently-visible events

Acceptance criteria

  • All 15 ScVal types decode without errors — validated against a contract that emits one event of each type in a test transaction
  • Nested Map<Symbol, I128> value decodes to a readable { key: value } structure — not raw bytes
  • Topic filter Symbol("transfer") correctly narrows the event list to only transfer events for the loaded contract
  • Replay sends each event as a POST to the webhook URL with a valid X-SaviTools-Signature HMAC header — verified by a test receiver endpoint
  • Fetching 200 events for a high-traffic contract returns within 3 seconds
  • Raw XDR accordion shows the original undecoded XDR string exactly as returned by the RPC node

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Maybe RewardedIssue may be eligible for a GrantFox rewardThird CampaignCampaign: Third CampaignenhancementNew feature or requesthelp wantedExtra attention is needed

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions