Skip to content

feat: implement getEvents#38

Open
RaoulSchaffranek wants to merge 3 commits into
mainfrom
feat/get-events
Open

feat: implement getEvents#38
RaoulSchaffranek wants to merge 3 commits into
mainfrom
feat/get-events

Conversation

@RaoulSchaffranek

Copy link
Copy Markdown
Member

Implements the getEvents RPC method per the official stellar-rpc OpenRPC spec.

What changed

  • Event capture (src/komet_node/kdist/node.md): the upstream soroban semantics implement the contract_event host function ("x"/"1") as a no-op that drops topics and data. A priority(40) rule now shadows it: it resolves the topics vector and data value from the host objects and stages one JSON record per event in events_staged.jsonl, mirroring how the tracer appends trace records. After a successful sendTransaction the server converts the staged records into one events/events_<ledger>.json per ledger in the spec's Event shape (_finalize_events — base64 SCVal XDR, strkey contract ids, and TOID-style event ids are XDR work K cannot do).
  • getEvents dispatch (node.md): validates the requested window against the chain tip (startLedger beyond the tip is -32600 with the same message real stellar-rpc uses), scans the per-ledger event files over the [startLedger, endLedger) window, applies the spec's filters (type, contractIds, topics with * and trailing ** matchers), and paginates with TOID-style cursors. Adds #respondError as the error-shaped counterpart of #respond.
  • Parameter validation (server.py): structural checks live next to the existing param validation — filter/topic-segment counts, cursor format, limit 1–10000, xdrFormat (json rejected as unsupported, consistent with the repo's policy), cursor exclusive with startLedger/endLedger.
  • scval_from_json (scval.py): inverse of scval_to_json for turning the staged K-side ScVal JSON into stellar_sdk XDR values.
  • Docs updated: server.md, architecture.md, node-semantics.md, notes.md (including documented limitations: no system events — the semantics have no source of them; events with values that have no staging representation are dropped with a warning; a topic filter of just ["**"] is rejected; a degenerate window returns an empty result).

Why

getEvents is part of the required stellar-rpc surface and was missing entirely; dapp tooling uses it to ingest contract events. latestLedger and ledger are JSON numbers, topic/value are base64 SCVal XDR, and event ids follow the SEP-35 TOID format, matching real stellar-rpc serialization.

Testing

  • New src/tests/integration/test_get_events.py (9 tests) with a dedicated events.wat contract that publishes an event via contract_event: request validation, empty-window shape, the exact Event shape (independently computed XDR, TOID id, strkey contract id, ISO-8601 close time), endLedger exclusivity, filtering by contract id / type / topics, and cursor pagination.
  • Full test_server.py suite passes (26 tests, no regressions); make check is clean apart from the two mypy findings already present on main.
  • Manually drove the running server over HTTP for edge cases not in the suite: ** topic matchers, cursor+endLedger rejection, limit bounds, degenerate windows, and resuming a persisted io-dir.

Cover the getEvents surface from the official OpenRPC spec: request
validation (startLedger/cursor rules, filter and topic limits, xdrFormat),
the result shape (events array, latestLedger as a JSON number, cursor
string), event objects for a contract event published via the
contract_event host function (TOID-style id, base64 SCVal topics/value,
ISO-8601 close time), filtering by contract id, type and topics, and
cursor-based pagination.

The emitting contract (data/wasm/events.wat) builds its topics vector with
vec_new/vec_push_back and runs successfully through the semantics today;
the tests fail only because getEvents is not implemented yet.
The upstream soroban semantics implement the contract_event host
function as a no-op, so node.md now shadows it: the interception rule
resolves the topics vector and data value from the host objects and
stages one JSON record per event in events_staged.jsonl, alongside how
the tracer appends trace records. After a successful sendTransaction
the server converts the staged records into one finished
events/events_<ledger>.json per ledger (base64 SCVal XDR, strkey
contract ids, and TOID-style event ids are XDR work K cannot do).

getEvents itself is dispatched in K: it validates the requested window
against the chain tip, scans the per-ledger event files, applies the
spec's filters (type, contractIds, topics with * and ** wildcards), and
paginates with TOID-style cursors. Structural parameter validation
(filter and segment counts, cursor format, xdrFormat - 'json' is
rejected as unsupported) lives in the server next to the existing param
checks. System events are never emitted, and events whose values have
no staging representation (maps, errors, 256-bit ints) are dropped with
a warning instead of fabricating XDR.

Covered by the getEvents integration tests; the full test_server.py
suite still passes.
@RaoulSchaffranek RaoulSchaffranek changed the title Implement getEvents with contract event capture feat: implement getEvents Jul 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant