ponder 0.9.2 → 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/bin/ponder.js +1933 -1606
  2. package/dist/bin/ponder.js.map +1 -1
  3. package/dist/{chunk-IFTUFVCL.js → chunk-LHCA5XFV.js} +2 -5
  4. package/dist/chunk-LHCA5XFV.js.map +1 -0
  5. package/dist/index.d.ts +5 -2
  6. package/dist/index.js +1 -1
  7. package/dist/index.js.map +1 -1
  8. package/package.json +1 -1
  9. package/src/bin/commands/codegen.ts +8 -10
  10. package/src/bin/commands/dev.ts +30 -42
  11. package/src/bin/commands/list.ts +9 -14
  12. package/src/bin/commands/serve.ts +26 -39
  13. package/src/bin/commands/start.ts +29 -42
  14. package/src/bin/utils/{shutdown.ts → exit.ts} +23 -37
  15. package/src/bin/utils/run.ts +275 -175
  16. package/src/bin/utils/runServer.ts +1 -5
  17. package/src/build/index.ts +3 -8
  18. package/src/build/pre.ts +3 -0
  19. package/src/config/index.ts +5 -2
  20. package/src/database/index.ts +72 -72
  21. package/src/drizzle/kit/index.ts +3 -3
  22. package/src/indexing/index.ts +0 -4
  23. package/src/indexing/service.ts +31 -93
  24. package/src/indexing-store/historical.ts +2 -4
  25. package/src/internal/common.ts +2 -0
  26. package/src/internal/errors.ts +9 -9
  27. package/src/internal/logger.ts +1 -1
  28. package/src/internal/metrics.ts +75 -103
  29. package/src/internal/shutdown.ts +25 -0
  30. package/src/internal/telemetry.ts +16 -18
  31. package/src/internal/types.ts +9 -1
  32. package/src/server/index.ts +3 -5
  33. package/src/sync/events.ts +4 -4
  34. package/src/sync/filter.ts +1 -0
  35. package/src/sync/index.ts +1046 -805
  36. package/src/sync-historical/index.ts +0 -37
  37. package/src/sync-realtime/index.ts +48 -48
  38. package/src/sync-store/encoding.ts +5 -5
  39. package/src/sync-store/index.ts +5 -23
  40. package/src/ui/index.ts +2 -11
  41. package/src/utils/checkpoint.ts +17 -3
  42. package/src/utils/chunk.ts +7 -0
  43. package/src/utils/generators.ts +66 -0
  44. package/src/utils/mutex.ts +34 -0
  45. package/src/utils/partition.ts +41 -0
  46. package/src/utils/requestQueue.ts +19 -10
  47. package/src/utils/zipper.ts +80 -0
  48. package/dist/chunk-IFTUFVCL.js.map +0 -1
@@ -13,7 +13,6 @@ import {
13
13
  UniqueConstraintError,
14
14
  } from "@/internal/errors.js";
15
15
  import type { SchemaBuild } from "@/internal/types.js";
16
- import { encodeCheckpoint, zeroCheckpoint } from "@/utils/checkpoint.js";
17
16
  import { prettyPrint } from "@/utils/print.js";
18
17
  import { createQueue } from "@ponder/common";
19
18
  import {
@@ -146,12 +145,12 @@ export const createHistoricalIndexingStore = ({
146
145
  common,
147
146
  schemaBuild: { schema },
148
147
  database,
149
- initialCheckpoint,
148
+ isDatabaseEmpty,
150
149
  }: {
151
150
  common: Common;
152
151
  schemaBuild: Pick<SchemaBuild, "schema">;
153
152
  database: Database;
154
- initialCheckpoint: string;
153
+ isDatabaseEmpty: boolean;
155
154
  }): IndexingStore<"historical"> => {
156
155
  // Operation queue to make sure all queries are run in order, circumventing race conditions
157
156
  const queue = createQueue<unknown, () => Promise<unknown>>({
@@ -302,7 +301,6 @@ export const createHistoricalIndexingStore = ({
302
301
  return size;
303
302
  };
304
303
 
305
- let isDatabaseEmpty = initialCheckpoint === encodeCheckpoint(zeroCheckpoint);
306
304
  /** Estimated number of bytes used by cache. */
307
305
  let cacheBytes = 0;
308
306
  /** LRU counter. */
@@ -1,6 +1,7 @@
1
1
  import type { Logger } from "./logger.js";
2
2
  import type { MetricsService } from "./metrics.js";
3
3
  import type { Options } from "./options.js";
4
+ import type { Shutdown } from "./shutdown.js";
4
5
  import type { Telemetry } from "./telemetry.js";
5
6
 
6
7
  export type Common = {
@@ -8,4 +9,5 @@ export type Common = {
8
9
  logger: Logger;
9
10
  metrics: MetricsService;
10
11
  telemetry: Telemetry;
12
+ shutdown: Shutdown;
11
13
  };
@@ -35,15 +35,6 @@ export class NonRetryableError extends BaseError {
35
35
  }
36
36
  }
37
37
 
38
- export class IgnorableError extends BaseError {
39
- override name = "IgnorableError";
40
-
41
- constructor(message?: string | undefined) {
42
- super(message);
43
- Object.setPrototypeOf(this, IgnorableError.prototype);
44
- }
45
- }
46
-
47
38
  // Indexing store errors
48
39
 
49
40
  export class StoreError extends NonRetryableError {
@@ -126,3 +117,12 @@ export class FlushError extends NonRetryableError {
126
117
  Object.setPrototypeOf(this, FlushError.prototype);
127
118
  }
128
119
  }
120
+
121
+ export class ShutdownError extends NonRetryableError {
122
+ override name = "ShutdownError";
123
+
124
+ constructor(message?: string | undefined) {
125
+ super(message);
126
+ Object.setPrototypeOf(this, ShutdownError.prototype);
127
+ }
128
+ }
@@ -72,7 +72,7 @@ export function createLogger({
72
72
  trace(options: Omit<Log, "level" | "time">) {
73
73
  logger.trace(options);
74
74
  },
75
- async kill() {},
75
+ flush: () => new Promise((resolve) => logger.flush(resolve)),
76
76
  };
77
77
  }
78
78
 
@@ -17,14 +17,17 @@ const httpRequestSizeBytes = [
17
17
 
18
18
  export class MetricsService {
19
19
  registry: prometheus.Registry;
20
+ start_timestamp: number;
21
+ rps: { [network: string]: { count: number; timestamp: number }[] };
20
22
 
21
- ponder_indexing_total_seconds: prometheus.Gauge;
22
- ponder_indexing_completed_seconds: prometheus.Gauge;
23
- ponder_indexing_completed_events: prometheus.Gauge<"event">;
23
+ ponder_historical_total_indexing_seconds: prometheus.Gauge<"network">;
24
+ ponder_historical_cached_indexing_seconds: prometheus.Gauge<"network">;
25
+ ponder_historical_completed_indexing_seconds: prometheus.Gauge<"network">;
24
26
 
25
- ponder_indexing_completed_timestamp: prometheus.Gauge;
26
- ponder_indexing_has_error: prometheus.Gauge;
27
+ ponder_indexing_timestamp: prometheus.Gauge<"network">;
28
+ ponder_indexing_has_error: prometheus.Gauge<"network">;
27
29
 
30
+ ponder_indexing_completed_events: prometheus.Gauge<"event">;
28
31
  ponder_indexing_function_duration: prometheus.Histogram<"event">;
29
32
  ponder_indexing_abi_decoding_duration: prometheus.Histogram;
30
33
 
@@ -64,15 +67,25 @@ export class MetricsService {
64
67
 
65
68
  constructor() {
66
69
  this.registry = new prometheus.Registry();
70
+ this.start_timestamp = Date.now();
71
+ this.rps = {};
67
72
 
68
- this.ponder_indexing_total_seconds = new prometheus.Gauge({
69
- name: "ponder_indexing_total_seconds",
73
+ this.ponder_historical_total_indexing_seconds = new prometheus.Gauge({
74
+ name: "ponder_historical_total_indexing_seconds",
70
75
  help: "Total number of seconds that are required",
76
+ labelNames: ["network"] as const,
77
+ registers: [this.registry],
78
+ });
79
+ this.ponder_historical_cached_indexing_seconds = new prometheus.Gauge({
80
+ name: "ponder_historical_cached_indexing_seconds",
81
+ help: "Number of seconds that have been cached",
82
+ labelNames: ["network"] as const,
71
83
  registers: [this.registry],
72
84
  });
73
- this.ponder_indexing_completed_seconds = new prometheus.Gauge({
74
- name: "ponder_indexing_completed_seconds",
85
+ this.ponder_historical_completed_indexing_seconds = new prometheus.Gauge({
86
+ name: "ponder_historical_completed_indexing_seconds",
75
87
  help: "Number of seconds that have been completed",
88
+ labelNames: ["network"] as const,
76
89
  registers: [this.registry],
77
90
  });
78
91
  this.ponder_indexing_completed_events = new prometheus.Gauge({
@@ -81,9 +94,10 @@ export class MetricsService {
81
94
  labelNames: ["network", "event"] as const,
82
95
  registers: [this.registry],
83
96
  });
84
- this.ponder_indexing_completed_timestamp = new prometheus.Gauge({
85
- name: "ponder_indexing_completed_timestamp",
97
+ this.ponder_indexing_timestamp = new prometheus.Gauge({
98
+ name: "ponder_indexing_timestamp",
86
99
  help: "Timestamp through which all events have been completed",
100
+ labelNames: ["network"] as const,
87
101
  registers: [this.registry],
88
102
  });
89
103
  this.ponder_indexing_has_error = new prometheus.Gauge({
@@ -245,10 +259,14 @@ export class MetricsService {
245
259
  }
246
260
 
247
261
  resetIndexingMetrics() {
248
- this.ponder_indexing_total_seconds.reset();
249
- this.ponder_indexing_completed_seconds.reset();
262
+ this.start_timestamp = Date.now();
263
+ this.rps = {};
264
+
265
+ this.ponder_historical_total_indexing_seconds.reset();
266
+ this.ponder_historical_cached_indexing_seconds.reset();
267
+ this.ponder_historical_completed_indexing_seconds.reset();
250
268
  this.ponder_indexing_completed_events.reset();
251
- this.ponder_indexing_completed_timestamp.reset();
269
+ this.ponder_indexing_timestamp.reset();
252
270
  this.ponder_indexing_has_error.reset();
253
271
  this.ponder_indexing_function_duration.reset();
254
272
  this.ponder_indexing_abi_decoding_duration.reset();
@@ -284,8 +302,6 @@ export class MetricsService {
284
302
  }
285
303
  }
286
304
 
287
- const rps: { [network: string]: { count: number; timestamp: number }[] } = {};
288
-
289
305
  export async function getSyncProgress(metrics: MetricsService): Promise<
290
306
  {
291
307
  networkName: string;
@@ -338,14 +354,14 @@ export async function getSyncProgress(metrics: MetricsService): Promise<
338
354
  }
339
355
 
340
356
  for (const [networkName, count] of Object.entries(requestCount)) {
341
- if (rps[networkName] === undefined) {
342
- rps[networkName] = [{ count, timestamp: Date.now() }];
357
+ if (metrics.rps[networkName] === undefined) {
358
+ metrics.rps[networkName] = [{ count, timestamp: Date.now() }];
343
359
  } else {
344
- rps[networkName]!.push({ count, timestamp: Date.now() });
360
+ metrics.rps[networkName]!.push({ count, timestamp: Date.now() });
345
361
  }
346
362
 
347
- if (rps[networkName]!.length > 100) {
348
- rps[networkName]!.shift();
363
+ if (metrics.rps[networkName]!.length > 100) {
364
+ metrics.rps[networkName]!.shift();
349
365
  }
350
366
  }
351
367
 
@@ -365,9 +381,9 @@ export async function getSyncProgress(metrics: MetricsService): Promise<
365
381
  // The ETA is low quality if we've completed only one or two blocks.
366
382
  const eta = completedBlocks >= 3 ? total - elapsed : undefined;
367
383
 
368
- const _length = rps[labels.network!]!.length;
369
- const _firstRps = rps[labels.network!]![0]!;
370
- const _lastRps = rps[labels.network!]![_length - 1]!;
384
+ const _length = metrics.rps[labels.network!]!.length;
385
+ const _firstRps = metrics.rps[labels.network!]![0]!;
386
+ const _lastRps = metrics.rps[labels.network!]![_length - 1]!;
371
387
 
372
388
  const requests = _lastRps.count - (_length > 1 ? _firstRps.count : 0);
373
389
  const seconds =
@@ -389,16 +405,33 @@ export async function getIndexingProgress(metrics: MetricsService) {
389
405
  .values[0]?.value;
390
406
  const hasError = hasErrorMetric === 1;
391
407
 
392
- const totalSeconds =
393
- (await metrics.ponder_indexing_total_seconds.get()).values[0]?.value ?? 0;
408
+ const sum = (x: number[]) => x.reduce((a, b) => a + b, 0);
409
+ const max = (x: number[]) => x.reduce((a, b) => Math.max(a, b), 0);
410
+
411
+ const totalSeconds = await metrics.ponder_historical_total_indexing_seconds
412
+ .get()
413
+ .then(({ values }) => values.map(({ value }) => value))
414
+ .then(sum);
415
+ const cachedSeconds = await metrics.ponder_historical_cached_indexing_seconds
416
+ .get()
417
+ .then(({ values }) => values.map(({ value }) => value))
418
+ .then(sum);
394
419
  const completedSeconds =
395
- (await metrics.ponder_indexing_completed_seconds.get()).values[0]?.value ??
396
- 0;
397
- const completedToTimestamp =
398
- (await metrics.ponder_indexing_completed_timestamp.get()).values[0]!
399
- .value ?? 0;
420
+ await metrics.ponder_historical_completed_indexing_seconds
421
+ .get()
422
+ .then(({ values }) => values.map(({ value }) => value))
423
+ .then(sum);
424
+ const timestamp = await metrics.ponder_indexing_timestamp
425
+ .get()
426
+ .then(({ values }) => values.map(({ value }) => value))
427
+ .then(max);
400
428
 
401
- const progress = totalSeconds === 0 ? 0 : completedSeconds / totalSeconds;
429
+ const progress =
430
+ timestamp === 0
431
+ ? 0
432
+ : totalSeconds === 0
433
+ ? 1
434
+ : (completedSeconds + cachedSeconds) / totalSeconds;
402
435
 
403
436
  const indexingCompletedEventsMetric = (
404
437
  await metrics.ponder_indexing_completed_events.get()
@@ -433,10 +466,10 @@ export async function getIndexingProgress(metrics: MetricsService) {
433
466
  return {
434
467
  hasError,
435
468
  overall: {
436
- completedSeconds,
437
469
  totalSeconds,
470
+ cachedSeconds,
471
+ completedSeconds,
438
472
  progress,
439
- completedToTimestamp,
440
473
  totalEvents,
441
474
  },
442
475
  events,
@@ -444,86 +477,25 @@ export async function getIndexingProgress(metrics: MetricsService) {
444
477
  }
445
478
 
446
479
  export async function getAppProgress(metrics: MetricsService): Promise<{
447
- mode: "historical" | "realtime" | "complete" | undefined;
480
+ mode: "historical" | "realtime" | undefined;
448
481
  progress: number;
449
482
  eta: number | undefined;
450
483
  }> {
451
- const sync = await getSyncProgress(metrics);
452
484
  const indexing = await getIndexingProgress(metrics);
453
- const decodingSum = await metrics.ponder_indexing_abi_decoding_duration
454
- .get()
455
- .then(
456
- (m) =>
457
- m.values.find(
458
- (v) => v.metricName === "ponder_indexing_abi_decoding_duration_sum",
459
- )?.value,
460
- );
461
- const getEventsSum = await metrics.ponder_database_method_duration
462
- .get()
463
- .then(
464
- (m) =>
465
- m.values.find(
466
- (v) =>
467
- v.labels.method === "getEvents" &&
468
- v.metricName === "ponder_database_method_duration_sum",
469
- )?.value,
470
- );
471
- const indexingSum = indexing.events.reduce(
472
- (acc, cur) => acc + cur.averageDuration * cur.count,
473
- 0,
474
- );
475
-
476
- let maxSync: (typeof sync)[number] | undefined;
477
- for (const networkSync of sync) {
478
- if (
479
- maxSync === undefined ||
480
- maxSync.eta === undefined ||
481
- (networkSync.eta && networkSync.eta > maxSync.eta)
482
- ) {
483
- maxSync = networkSync;
484
- }
485
- }
486
485
 
487
486
  const remainingSeconds =
488
- indexing.overall.totalSeconds - indexing.overall.completedSeconds;
487
+ indexing.overall.totalSeconds -
488
+ (indexing.overall.completedSeconds + indexing.overall.cachedSeconds);
489
+ const elapsedSeconds = (Date.now() - metrics.start_timestamp) / 1_000;
489
490
 
490
- const indexingEta =
491
+ const eta =
491
492
  indexing.overall.completedSeconds === 0
492
- ? undefined
493
- : (((decodingSum ?? 0) + (getEventsSum ?? 0) + indexingSum) *
494
- remainingSeconds) /
495
- indexing.overall.completedSeconds;
496
-
497
- const eta = sync.every((n) => n.progress === 1)
498
- ? indexingEta
499
- : maxSync?.eta === undefined && indexingEta === undefined
500
- ? undefined
501
- : maxSync?.eta === undefined && maxSync?.progress !== undefined
502
- ? undefined
503
- : Math.max(maxSync?.eta ?? 0, indexingEta ?? 0);
504
-
505
- // Edge case: If all matched events occurred in the same unix timestamp (second), progress will
506
- // be zero, even though indexing is complete. When this happens, totalEvents will be non-zero.
507
- const indexingProgress =
508
- indexing.overall.progress === 0 && indexing.overall.totalEvents > 0
509
- ? 1
510
- : indexing.overall.progress;
511
-
512
- const progress = sync.every((n) => n.progress === 1)
513
- ? indexingProgress
514
- : maxSync?.progress === undefined
515
493
  ? 0
516
- : maxSync!.progress * indexingProgress;
494
+ : (elapsedSeconds / indexing.overall.completedSeconds) * remainingSeconds;
517
495
 
518
496
  return {
519
- mode: sync.some((n) => n.status === "realtime")
520
- ? "realtime"
521
- : sync.every((n) => n.status === "complete")
522
- ? "complete"
523
- : sync.length === 0
524
- ? undefined
525
- : "historical",
526
- progress,
497
+ mode: indexing.overall.progress === 1 ? "realtime" : "historical",
498
+ progress: indexing.overall.progress,
527
499
  eta,
528
500
  };
529
501
  }
@@ -0,0 +1,25 @@
1
+ export type Shutdown = {
2
+ add: (callback: () => unknown | Promise<unknown>) => void;
3
+ kill: () => Promise<void>;
4
+ isKilled: boolean;
5
+ abortController: AbortController;
6
+ };
7
+
8
+ export const createShutdown = (): Shutdown => {
9
+ const abortController = new AbortController();
10
+ const callbacks: (() => unknown | Promise<unknown>)[] = [];
11
+
12
+ return {
13
+ add: (callback) => {
14
+ callbacks.push(callback);
15
+ },
16
+ kill: async () => {
17
+ abortController.abort();
18
+ await Promise.all(callbacks.map((callback) => callback()));
19
+ },
20
+ get isKilled() {
21
+ return abortController.signal.aborted;
22
+ },
23
+ abortController,
24
+ };
25
+ };
@@ -6,11 +6,12 @@ import path from "node:path";
6
6
  import { promisify } from "node:util";
7
7
  import type { Options } from "@/internal/options.js";
8
8
  import { startClock } from "@/utils/timer.js";
9
- import { wait } from "@/utils/wait.js";
10
9
  import { createQueue } from "@ponder/common";
11
10
  import Conf from "conf";
12
11
  import { type PM, detect, getNpmVersion } from "detect-package-manager";
12
+ import { ShutdownError } from "./errors.js";
13
13
  import type { Logger } from "./logger.js";
14
+ import type { Shutdown } from "./shutdown.js";
14
15
  import type { IndexingBuild } from "./types.js";
15
16
  import type { PreBuild, SchemaBuild } from "./types.js";
16
17
 
@@ -65,12 +66,12 @@ export type Telemetry = ReturnType<typeof createTelemetry>;
65
66
  export function createTelemetry({
66
67
  options,
67
68
  logger,
68
- }: { options: Options; logger: Logger }) {
69
+ shutdown,
70
+ }: { options: Options; logger: Logger; shutdown: Shutdown }) {
69
71
  if (options.telemetryDisabled) {
70
72
  return {
71
73
  record: (_event: TelemetryEvent) => {},
72
74
  flush: async () => {},
73
- kill: async () => {},
74
75
  };
75
76
  }
76
77
 
@@ -156,13 +157,12 @@ export function createTelemetry({
156
157
  let context: Awaited<ReturnType<typeof buildContext>> | undefined = undefined;
157
158
  const contextPromise = buildContext();
158
159
 
159
- const controller = new AbortController();
160
- let isKilled = false;
161
-
162
160
  const queue = createQueue({
163
161
  initialStart: true,
164
162
  concurrency: 10,
165
163
  worker: async (event: TelemetryEvent) => {
164
+ if (shutdown.isKilled) return;
165
+
166
166
  const endClock = startClock();
167
167
  try {
168
168
  if (context === undefined) context = await contextPromise;
@@ -182,7 +182,6 @@ export function createTelemetry({
182
182
  method: "POST",
183
183
  headers: { "Content-Type": "application/json" },
184
184
  body,
185
- signal: controller.signal,
186
185
  });
187
186
  logger.trace({
188
187
  service: "telemetry",
@@ -190,6 +189,11 @@ export function createTelemetry({
190
189
  });
191
190
  } catch (error_) {
192
191
  const error = error_ as Error;
192
+
193
+ if (shutdown.isKilled) {
194
+ throw new ShutdownError();
195
+ }
196
+
193
197
  logger.trace({
194
198
  service: "telemetry",
195
199
  msg: `Failed to send '${event.name}' event after ${endClock()}ms`,
@@ -200,7 +204,6 @@ export function createTelemetry({
200
204
  });
201
205
 
202
206
  const record = (event: TelemetryEvent) => {
203
- if (isKilled) return;
204
207
  queue.add(event);
205
208
  };
206
209
 
@@ -211,21 +214,16 @@ export function createTelemetry({
211
214
  });
212
215
  }, HEARTBEAT_INTERVAL_MS);
213
216
 
217
+ shutdown.add(() => {
218
+ clearInterval(heartbeatInterval);
219
+ });
220
+
214
221
  // Note that this method is only used for testing.
215
222
  const flush = async () => {
216
223
  await queue.onIdle();
217
224
  };
218
225
 
219
- const kill = async () => {
220
- clearInterval(heartbeatInterval);
221
- isKilled = true;
222
- // If there are any events in the queue that have not started, drop them.
223
- queue.clear();
224
- // Wait at most 1 second for any in-flight events to complete.
225
- await Promise.race([queue.onIdle(), wait(1_000)]);
226
- };
227
-
228
- return { record, flush, kill };
226
+ return { record, flush };
229
227
  }
230
228
 
231
229
  async function getPackageManager() {
@@ -284,8 +284,8 @@ export type BlockMetadata = {
284
284
  export type Network = {
285
285
  name: string;
286
286
  chainId: number;
287
- chain: Chain;
288
287
  transport: ReturnType<Transport>;
288
+ chain: Chain;
289
289
  pollingInterval: number;
290
290
  maxRequestsPerSecond: number;
291
291
  finalityBlockCount: number;
@@ -306,6 +306,8 @@ export type NamespaceBuild = string;
306
306
  export type PreBuild = {
307
307
  /** Database type and configuration */
308
308
  databaseConfig: DatabaseConfig;
309
+ /** Ordering of events */
310
+ ordering: "omnichain" | "multichain";
309
311
  };
310
312
 
311
313
  export type SchemaBuild = {
@@ -344,6 +346,12 @@ export type Status = {
344
346
  };
345
347
  };
346
348
 
349
+ // Seconds
350
+
351
+ export type Seconds = {
352
+ [network: string]: { start: number; end: number; cached: number };
353
+ };
354
+
347
355
  // Events
348
356
 
349
357
  export type RawEvent = {
@@ -13,7 +13,6 @@ import { onError } from "./error.js";
13
13
 
14
14
  export type Server = {
15
15
  hono: Hono;
16
- kill: () => Promise<void>;
17
16
  };
18
17
 
19
18
  export async function createServer({
@@ -145,8 +144,7 @@ export async function createServer({
145
144
  gracefulTerminationTimeout: 1000,
146
145
  });
147
146
 
148
- return {
149
- hono,
150
- kill: () => terminator.terminate(),
151
- };
147
+ common.shutdown.add(() => terminator.terminate());
148
+
149
+ return { hono };
152
150
  }
@@ -23,9 +23,9 @@ import type {
23
23
  } from "@/types/sync.js";
24
24
  import {
25
25
  EVENT_TYPES,
26
+ MAX_CHECKPOINT,
27
+ ZERO_CHECKPOINT,
26
28
  encodeCheckpoint,
27
- maxCheckpoint,
28
- zeroCheckpoint,
29
29
  } from "@/utils/checkpoint.js";
30
30
  import { never } from "@/utils/never.js";
31
31
  import { startClock } from "@/utils/timer.js";
@@ -329,9 +329,9 @@ export const buildEvents = ({
329
329
  blockTimestamp: hexToNumber(block.timestamp),
330
330
  chainId: BigInt(filter.chainId),
331
331
  blockNumber: hexToBigInt(block.number),
332
- transactionIndex: maxCheckpoint.transactionIndex,
332
+ transactionIndex: MAX_CHECKPOINT.transactionIndex,
333
333
  eventType: EVENT_TYPES.blocks,
334
- eventIndex: zeroCheckpoint.eventIndex,
334
+ eventIndex: ZERO_CHECKPOINT.eventIndex,
335
335
  }),
336
336
  block: convertBlock(block),
337
337
  log: undefined,
@@ -484,6 +484,7 @@ export const defaultTransactionReceiptInclude: `transactionReceipt.${keyof Trans
484
484
 
485
485
  const defaultTraceInclude: `trace.${keyof UserTrace}`[] = [
486
486
  "trace.id",
487
+ "trace.traceIndex",
487
488
  "trace.type",
488
489
  "trace.from",
489
490
  "trace.to",