Join the discussion on Telegram
Why this matters
The Soroban contract now emits two governance events that are never indexed:
Both are emitted with a single-element topic ((Symbol,)), but SorobanEventWorker.processEvent bails out early for any event with fewer than 2 topics:
// backend/src/workers/soroban-event-worker.ts:250
if (!event.topic || event.topic.length < 2) return;
So these events are dropped before they ever reach the switch, and the switch has no case for them anyway (only the 8 stream-lifecycle events are handled). The result: a treasury/fee-rate change or an admin rotation produces no StreamEvent row, no SSE broadcast, and no audit trail in the backend, even though the chain recorded it. The event-type taxonomy (backend/src/routes/v1/events.routes.ts, stream.controller.ts validEventTypes, and the frontend EVENT_STYLES) also has no entries for these.
These are protocol-level governance actions; not surfacing them is a real observability/audit gap, and the events were just added to the contract this cycle.
Acceptance criteria
Files to touch
backend/src/workers/soroban-event-worker.ts
backend/src/routes/v1/events.routes.ts
backend/src/controllers/stream.controller.ts
backend/src/__tests__/integration/streams.test.ts
Out of scope
- Frontend rendering of governance events (a small follow-up to add
EVENT_STYLES entries can be a separate issue).
- Changing the contract event shapes.
Join the discussion on Telegram
Why this matters
The Soroban contract now emits two governance events that are never indexed:
fee_config_updated->FeeConfigUpdatedEvent(added for [Contracts] Emit an event when update_fee_config changes treasury or fee rate #458) — emitted fromupdate_fee_configincontracts/stream_contract/src/lib.rs:108.admin_transferred->AdminTransferredEvent(added for [Contracts] Add transfer_admin so protocol ownership can be rotated #459) — emitted fromtransfer_adminincontracts/stream_contract/src/lib.rs:151.Both are emitted with a single-element topic (
(Symbol,)), butSorobanEventWorker.processEventbails out early for any event with fewer than 2 topics:So these events are dropped before they ever reach the
switch, and theswitchhas nocasefor them anyway (only the 8 stream-lifecycle events are handled). The result: a treasury/fee-rate change or an admin rotation produces noStreamEventrow, no SSE broadcast, and no audit trail in the backend, even though the chain recorded it. The event-type taxonomy (backend/src/routes/v1/events.routes.ts,stream.controller.tsvalidEventTypes, and the frontendEVENT_STYLES) also has no entries for these.These are protocol-level governance actions; not surfacing them is a real observability/audit gap, and the events were just added to the contract this cycle.
Acceptance criteria
processEvent(handletopic.length === 1for protocol events while still requiringstreamIdtopic for per-stream events).fee_config_updatedhandler that persists aFEE_CONFIG_UPDATEDrecord (decodeadmin,old_treasury,new_treasury,old_fee_rate_bps,new_fee_rate_bps).admin_transferredhandler that persists anADMIN_TRANSFERREDrecord (decodeprevious_admin,new_admin).backend/src/routes/v1/events.routes.tsandvalidEventTypesinbackend/src/controllers/stream.controller.ts.streamId).Files to touch
backend/src/workers/soroban-event-worker.tsbackend/src/routes/v1/events.routes.tsbackend/src/controllers/stream.controller.tsbackend/src/__tests__/integration/streams.test.tsOut of scope
EVENT_STYLESentries can be a separate issue).