Skip to content

Commit c0ecf52

Browse files
fix(backend): align event indexer with Stellar SDK v14 types
- Split getEvents pagination into ledger-range (first page) and cursor (subsequent pages) modes, which the SDK now enforces as mutually exclusive - Treat EventResponse.ledger as a number instead of parsing it as a string 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
1 parent 8ad2711 commit c0ecf52

1 file changed

Lines changed: 28 additions & 15 deletions

File tree

backend/src/services/eventIndexer.ts

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -221,17 +221,30 @@ export class EventIndexer {
221221
let response: rpc.Api.GetEventsResponse;
222222

223223
try {
224-
response = await this.rpc.getEvents({
225-
startLedger,
226-
filters: [
227-
{
228-
type: 'contract',
229-
contractIds: [contractId],
230-
},
231-
],
232-
cursor,
233-
limit: 200,
234-
});
224+
// RPC pagination modes are mutually exclusive: use the ledger range
225+
// for the first page and the cursor for subsequent pages.
226+
response = cursor
227+
? await this.rpc.getEvents({
228+
filters: [
229+
{
230+
type: 'contract',
231+
contractIds: [contractId],
232+
},
233+
],
234+
cursor,
235+
limit: 200,
236+
})
237+
: await this.rpc.getEvents({
238+
filters: [
239+
{
240+
type: 'contract',
241+
contractIds: [contractId],
242+
},
243+
],
244+
startLedger,
245+
endLedger,
246+
limit: 200,
247+
});
235248
} catch (rpcErr: any) {
236249
logger.error(`[EventIndexer] RPC getEvents error for contract ${contractId}: ${rpcErr?.message}`);
237250
return;
@@ -242,18 +255,18 @@ export class EventIndexer {
242255

243256
// Filter to the requested ledger window (the RPC may return beyond endLedger)
244257
const inWindow = events.filter((e) => {
245-
const ledger = parseInt(e.ledger, 10);
258+
const ledger = e.ledger;
246259
return ledger >= startLedger && ledger <= endLedger;
247260
});
248261

249262
await this.persistBatch(contractId, inWindow);
250263

251264
// Pagination: the RPC returns a cursor for the next page
252-
cursor = (response as any).cursor ?? undefined;
265+
cursor = response.cursor;
253266

254267
// Stop paginating if there are no more events or we've gone past the window
255268
const allBeyondWindow = events.length > 0 &&
256-
events.every((e) => parseInt(e.ledger, 10) > endLedger);
269+
events.every((e) => e.ledger > endLedger);
257270

258271
if (!cursor || events.length === 0 || allBeyondWindow) break;
259272
} while (true);
@@ -305,7 +318,7 @@ export class EventIndexer {
305318
contractId: string,
306319
raw: rpc.Api.EventResponse,
307320
): Promise<void> {
308-
const ledger = parseInt(raw.ledger, 10);
321+
const ledger = raw.ledger;
309322

310323
// event_index: Soroban event IDs are <ledger>-<txIndex>-<eventIndex>
311324
const parts = raw.id.split('-');

0 commit comments

Comments
 (0)