Background
#42 fixed a filter that had been dropping every event: GraphQL renders Move's
TypeName as a plain string, but Events.getEvents read .typename.name
(JSON-RPC's shape), so the comparison was "0x" + undefined !== typeName for every
event on every page.
The bug itself is fixed and pinned by __tests__/eventFilter.test.ts. What is not
fixed is the property that let it go unnoticed: the failure was completely
silent. Nothing logged, nothing threw. fetchStSuiAPR/fetchStSuiAPY returned
the string "0" and getMintEvents returned [], which are also the legitimate
values for "no activity in this window" — so from the outside a total outage of
event reads is indistinguishable from a quiet week.
Proposal
Make a total filter miss loud in Events.getEvents (src/common/events.ts).
The query is already server-side filtered by eventType, so every node in a page is
an Event<…::liquid_staking::<EventName>> by construction. If a page comes back
non-empty and zero of its events pass the typename check, that is a shape
mismatch, not a data condition — the only realistic cause is that the rendering
changed again.
Suggested shape:
let matchedAny = false;
// … inside the loop, on a successful typename match: matchedAny = true;
// after draining a page:
if (eventData.data.length > 0 && !matchedAny) {
console.error(
`[stsui-sdk] ${eventData.data.length} ${eventName}(s) returned but none matched ` +
`typeName=${params.typeName} — the typename rendering may have changed again ` +
`(see #42). Returning an empty result.`,
);
}
Open questions for whoever picks this up:
- Log or throw? Callers in
utils.ts wrap everything in try/catch → "0", so a
throw would be swallowed into the same silent zero unless those catches are
changed too. A console.error is visibly weaker but survives the existing
call sites; throwing is only useful together with a caller-side change.
- Per page or per call? Per-page is noisier but catches a partial-shape drift
(e.g. one event variant changing); per-call (events.length === 0 && sawAnyNode)
is quieter.
- Worth considering the same guard in
scripts/migration-snapshot.ts, which
serialized the all-empty event snapshots as valid results and so did not flag the
regression during the GraphQL migration.
Not urgent
Advisory follow-up from the review of #42, not a blocker — the shape is correct
today and covered by tests. This is about failure visibility the next time it
drifts.
Background
#42 fixed a filter that had been dropping every event: GraphQL renders Move's
TypeNameas a plain string, butEvents.getEventsread.typename.name(JSON-RPC's shape), so the comparison was
"0x" + undefined !== typeNamefor everyevent on every page.
The bug itself is fixed and pinned by
__tests__/eventFilter.test.ts. What is notfixed is the property that let it go unnoticed: the failure was completely
silent. Nothing logged, nothing threw.
fetchStSuiAPR/fetchStSuiAPYreturnedthe string
"0"andgetMintEventsreturned[], which are also the legitimatevalues for "no activity in this window" — so from the outside a total outage of
event reads is indistinguishable from a quiet week.
Proposal
Make a total filter miss loud in
Events.getEvents(src/common/events.ts).The query is already server-side filtered by
eventType, so every node in a page isan
Event<…::liquid_staking::<EventName>>by construction. If a page comes backnon-empty and zero of its events pass the
typenamecheck, that is a shapemismatch, not a data condition — the only realistic cause is that the rendering
changed again.
Suggested shape:
Open questions for whoever picks this up:
utils.tswrap everything intry/catch → "0", so athrow would be swallowed into the same silent zero unless those catches are
changed too. A
console.erroris visibly weaker but survives the existingcall sites; throwing is only useful together with a caller-side change.
(e.g. one event variant changing); per-call (
events.length === 0 && sawAnyNode)is quieter.
scripts/migration-snapshot.ts, whichserialized the all-empty event snapshots as valid results and so did not flag the
regression during the GraphQL migration.
Not urgent
Advisory follow-up from the review of #42, not a blocker — the shape is correct
today and covered by tests. This is about failure visibility the next time it
drifts.