@ensnode/ponder-sdk 1.6.0 → 1.8.0

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.
package/dist/index.d.cts CHANGED
@@ -21,6 +21,10 @@ type BlockRef = z.infer<typeof schemaBlockRef>;
21
21
  /**
22
22
  * Compare two {@link BlockRef} objects to check
23
23
  * if blockA is before blockB.
24
+ *
25
+ * Ordering is determined by block number, which is the canonical
26
+ * ordering on a single chain. Timestamp is not used because EVM
27
+ * chains allow consecutive blocks to share the same timestamp.
24
28
  */
25
29
  declare function isBlockRefBefore(blockA: BlockRef, blockB: BlockRef): boolean;
26
30
  /**
@@ -114,8 +118,9 @@ declare function buildBlockNumberRange(startBlock?: BlockNumber, endBlock?: Bloc
114
118
  * Merge multiple block number ranges into a single range.
115
119
  *
116
120
  * The resulting range is a union that covers all input ranges:
117
- * - Uses the minimum defined start block (undefined if no ranges define a start block)
118
- * - Uses the maximum defined end block (undefined if no ranges define an end block)
121
+ * - Uses the minimum start block when every input range has a start block
122
+ * - Uses the maximum end block when every input range has an end block
123
+ * - Leaves a side unbounded when any input range is unbounded on that side
119
124
  *
120
125
  * Returns an unbounded range if no ranges are provided.
121
126
  *
@@ -205,7 +210,7 @@ type ChainId = z.infer<typeof schemaChainId>;
205
210
  type ChainIdString = string;
206
211
 
207
212
  /**
208
- * Ponder Application Commands
213
+ * Ponder app commands
209
214
  *
210
215
  * Represents the commands that can be used to start a Ponder app.
211
216
  */
@@ -214,6 +219,18 @@ declare const PonderAppCommands: {
214
219
  readonly Start: "start";
215
220
  };
216
221
  type PonderAppCommand = (typeof PonderAppCommands)[keyof typeof PonderAppCommands];
222
+ /**
223
+ * Ponder app context
224
+ *
225
+ * Represents the internal context of a local Ponder app.
226
+ */
227
+ interface PonderAppContext {
228
+ /**
229
+ * Command used to start the Ponder app.
230
+ */
231
+ command: PonderAppCommand;
232
+ }
233
+
217
234
  /**
218
235
  * Ponder Indexing Orderings
219
236
  *
@@ -409,6 +426,101 @@ declare class PonderClient {
409
426
  status(): Promise<PonderIndexingStatus>;
410
427
  }
411
428
 
429
+ /**
430
+ * A utility type that makes all properties of a type optional recursively,
431
+ * including nested objects and arrays.
432
+ *
433
+ * @example
434
+ * ```typescript
435
+ * type Config = {
436
+ * a: string;
437
+ * b: {
438
+ * x: number;
439
+ * y: { z: boolean };
440
+ * };
441
+ * c: { id: string }[];
442
+ * }
443
+ *
444
+ * type PartialConfig = DeepPartial<Config>;
445
+ * // Results in:
446
+ * // {
447
+ * // a?: string;
448
+ * // b?: {
449
+ * // x?: number;
450
+ * // y?: { z?: boolean };
451
+ * // };
452
+ * // c?: { id?: string }[];
453
+ * // }
454
+ *
455
+ * // Usage:
456
+ * const update: PartialConfig = { b: { y: { z: true } } };
457
+ * ```
458
+ */
459
+ type DeepPartial<T> = {
460
+ [P in keyof T]?: T[P] extends (infer U)[] ? DeepPartial<U>[] : T[P] extends object ? DeepPartial<T[P]> : T[P];
461
+ };
462
+ /**
463
+ * Helper type to represent an unvalidated version of a business layer type `T`,
464
+ * where all properties are optional.
465
+ *
466
+ * This is useful for building a validated object `T` from partial input,
467
+ * where the input may be missing required fields or have fields that
468
+ * are not yet validated.
469
+ *
470
+ * For example, transforming serialized representation of type `T` into
471
+ * an unvalidated version of `T` that can be later validated against
472
+ * defined business rules and constraints.
473
+ *
474
+ * ```ts
475
+ * function buildUnvalidatedValue(serialized: SerializedChainId): Unvalidated<ChainId> {
476
+ * // transform serialized chainId into unvalidated number (e.g. parseInt)
477
+ * return parseInt(serialized, 10);
478
+ * }
479
+ *
480
+ * // Later, we can validate the unvalidated value against our business rules
481
+ * function validateChainId(unvalidatedChainId: Unvalidated<ChainId>): ChainId {
482
+ * if (typeof unvalidatedChainId !== "number" || unvalidatedChainId <= 0) {
483
+ * throw new Error("Invalid ChainId");
484
+ * }
485
+ *
486
+ * return unvalidatedChainId as ChainId;
487
+ * }
488
+ *
489
+ * ```
490
+ */
491
+ type Unvalidated<T> = DeepPartial<T>;
492
+
493
+ /**
494
+ * This module provides functionality to deserialize the "raw" context of
495
+ * a local Ponder app into a validated Ponder App Context.
496
+ *
497
+ * The "raw" context is injected by Ponder at runtime as
498
+ * the `PONDER_COMMON` global variable.
499
+ *
500
+ * @see https://github.com/ponder-sh/ponder/blob/6fcc15d4234e43862cb6e21c05f3c57f4c2f7464/packages/core/src/internal/common.ts#L7-L15
501
+ */
502
+
503
+ /**
504
+ * Type representing the "raw" context of a local Ponder app.
505
+ */
506
+ declare const schemaRawPonderAppContext: z.ZodObject<{
507
+ options: z.ZodObject<{
508
+ command: z.ZodString;
509
+ }, z.core.$strip>;
510
+ }, z.core.$strip>;
511
+ /**
512
+ * Type representing the "raw" context of a local Ponder app.
513
+ */
514
+ type RawPonderAppContext = z.infer<typeof schemaRawPonderAppContext>;
515
+ /**
516
+ * Deserialize and validate a Raw Ponder App Context.
517
+ *
518
+ * @param unvalidatedRawPonderAppContext Raw Ponder App Context to be validated.
519
+ * @returns Deserialized and validated Ponder App Context.
520
+ * @throws Error if data cannot be deserialized into a valid Ponder App Context.
521
+ */
522
+ declare function deserializePonderAppContext(unvalidatedRawPonderAppContext: Unvalidated<RawPonderAppContext>): PonderAppContext;
523
+
412
524
  /**
413
525
  * Chain indexing config
414
526
  *
@@ -526,14 +638,21 @@ declare class LocalPonderClient extends PonderClient {
526
638
  * - Does not include entries for non-indexed chains.
527
639
  */
528
640
  private cachedPublicClients;
641
+ /**
642
+ * Ponder App Context
643
+ *
644
+ * The internal context of the local Ponder app.
645
+ */
646
+ private ponderAppContext;
529
647
  /**
530
648
  * @param localPonderAppUrl URL of the local Ponder app to connect to.
531
649
  * @param indexedChainIds Configured indexed chain IDs which are used to validate and filter the Ponder app metadata to only include entries for indexed chains.
532
650
  * @param indexedBlockranges Configured indexing blockrange for each indexed chain.
533
651
  * @param ponderPublicClients All cached public clients provided by the local Ponder app
534
652
  * (may include non-indexed chains).
653
+ * @param ponderAppContext The internal context of the local Ponder app.
535
654
  */
536
- constructor(localPonderAppUrl: URL, indexedChainIds: Set<ChainId>, indexedBlockranges: Map<ChainId, BlockNumberRangeWithStartBlock>, ponderPublicClients: Record<ChainIdString, CachedPublicClient>);
655
+ constructor(localPonderAppUrl: URL, indexedChainIds: Set<ChainId>, indexedBlockranges: Map<ChainId, BlockNumberRangeWithStartBlock>, ponderPublicClients: Record<ChainIdString, CachedPublicClient>, ponderAppContext: PonderAppContext);
537
656
  /**
538
657
  * Get the blockrange that is configured to be indexed for a specific chain ID.
539
658
  *
@@ -558,6 +677,10 @@ declare class LocalPonderClient extends PonderClient {
558
677
  * @throws Error if the response could not be fetched or was invalid.
559
678
  */
560
679
  metrics(): Promise<LocalPonderIndexingMetrics>;
680
+ /**
681
+ * Indicates whether the local Ponder app is running in dev mode.
682
+ */
683
+ get isInDevMode(): boolean;
561
684
  /**
562
685
  * Builds a map of cached public clients based on the Ponder cached public clients.
563
686
  *
@@ -636,4 +759,4 @@ declare const schemaUnixTimestamp: z.ZodNumber;
636
759
  */
637
760
  type UnixTimestamp = z.infer<typeof schemaUnixTimestamp>;
638
761
 
639
- export { type BlockNumber, type BlockNumberRange, type BlockNumberRangeBounded, type BlockNumberRangeLeftBounded, type BlockNumberRangeRightBounded, type BlockNumberRangeUnbounded, type BlockNumberRangeWithStartBlock, type BlockRef, type BlockRefRange, type BlockRefRangeBounded, type BlockRefRangeLeftBounded, type BlockRefRangeRightBounded, type BlockRefRangeUnbounded, type BlockRefRangeWithStartBlock, type ChainId, type ChainIdString, type ChainIndexingConfig, type ChainIndexingMetrics, type ChainIndexingMetricsCompleted, type ChainIndexingMetricsHistorical, type ChainIndexingMetricsRealtime, type ChainIndexingState, ChainIndexingStates, type ChainIndexingStatus, type LocalChainIndexingMetrics, type LocalChainIndexingMetricsHistorical, LocalPonderClient, type LocalPonderIndexingMetrics, type PonderAppCommand, PonderAppCommands, type PonderApplicationSettings, type PonderBlockNumberRange, PonderClient, type PonderIndexingMetrics, type PonderIndexingOrdering, PonderIndexingOrderings, type PonderIndexingStatus, type RangeType, RangeTypeIds, type UnixTimestamp, buildBlockNumberRange, buildBlockRefRange, isBlockRefBefore, isBlockRefBeforeOrEqualTo, isBlockRefEqualTo, mergeBlockNumberRanges, schemaBlockNumber, schemaBlockRef, schemaChainId, schemaInteger, schemaNonnegativeInteger, schemaNonnegativeNumber, schemaNumber, schemaPositiveInteger, schemaPositiveNumber, schemaUnixTimestamp };
762
+ export { type BlockNumber, type BlockNumberRange, type BlockNumberRangeBounded, type BlockNumberRangeLeftBounded, type BlockNumberRangeRightBounded, type BlockNumberRangeUnbounded, type BlockNumberRangeWithStartBlock, type BlockRef, type BlockRefRange, type BlockRefRangeBounded, type BlockRefRangeLeftBounded, type BlockRefRangeRightBounded, type BlockRefRangeUnbounded, type BlockRefRangeWithStartBlock, type ChainId, type ChainIdString, type ChainIndexingConfig, type ChainIndexingMetrics, type ChainIndexingMetricsCompleted, type ChainIndexingMetricsHistorical, type ChainIndexingMetricsRealtime, type ChainIndexingState, ChainIndexingStates, type ChainIndexingStatus, type LocalChainIndexingMetrics, type LocalChainIndexingMetricsHistorical, LocalPonderClient, type LocalPonderIndexingMetrics, type PonderAppCommand, PonderAppCommands, type PonderAppContext, type PonderApplicationSettings, type PonderBlockNumberRange, PonderClient, type PonderIndexingMetrics, type PonderIndexingOrdering, PonderIndexingOrderings, type PonderIndexingStatus, type RangeType, RangeTypeIds, type RawPonderAppContext, type UnixTimestamp, buildBlockNumberRange, buildBlockRefRange, deserializePonderAppContext, isBlockRefBefore, isBlockRefBeforeOrEqualTo, isBlockRefEqualTo, mergeBlockNumberRanges, schemaBlockNumber, schemaBlockRef, schemaChainId, schemaInteger, schemaNonnegativeInteger, schemaNonnegativeNumber, schemaNumber, schemaPositiveInteger, schemaPositiveNumber, schemaUnixTimestamp };
package/dist/index.d.ts CHANGED
@@ -21,6 +21,10 @@ type BlockRef = z.infer<typeof schemaBlockRef>;
21
21
  /**
22
22
  * Compare two {@link BlockRef} objects to check
23
23
  * if blockA is before blockB.
24
+ *
25
+ * Ordering is determined by block number, which is the canonical
26
+ * ordering on a single chain. Timestamp is not used because EVM
27
+ * chains allow consecutive blocks to share the same timestamp.
24
28
  */
25
29
  declare function isBlockRefBefore(blockA: BlockRef, blockB: BlockRef): boolean;
26
30
  /**
@@ -114,8 +118,9 @@ declare function buildBlockNumberRange(startBlock?: BlockNumber, endBlock?: Bloc
114
118
  * Merge multiple block number ranges into a single range.
115
119
  *
116
120
  * The resulting range is a union that covers all input ranges:
117
- * - Uses the minimum defined start block (undefined if no ranges define a start block)
118
- * - Uses the maximum defined end block (undefined if no ranges define an end block)
121
+ * - Uses the minimum start block when every input range has a start block
122
+ * - Uses the maximum end block when every input range has an end block
123
+ * - Leaves a side unbounded when any input range is unbounded on that side
119
124
  *
120
125
  * Returns an unbounded range if no ranges are provided.
121
126
  *
@@ -205,7 +210,7 @@ type ChainId = z.infer<typeof schemaChainId>;
205
210
  type ChainIdString = string;
206
211
 
207
212
  /**
208
- * Ponder Application Commands
213
+ * Ponder app commands
209
214
  *
210
215
  * Represents the commands that can be used to start a Ponder app.
211
216
  */
@@ -214,6 +219,18 @@ declare const PonderAppCommands: {
214
219
  readonly Start: "start";
215
220
  };
216
221
  type PonderAppCommand = (typeof PonderAppCommands)[keyof typeof PonderAppCommands];
222
+ /**
223
+ * Ponder app context
224
+ *
225
+ * Represents the internal context of a local Ponder app.
226
+ */
227
+ interface PonderAppContext {
228
+ /**
229
+ * Command used to start the Ponder app.
230
+ */
231
+ command: PonderAppCommand;
232
+ }
233
+
217
234
  /**
218
235
  * Ponder Indexing Orderings
219
236
  *
@@ -409,6 +426,101 @@ declare class PonderClient {
409
426
  status(): Promise<PonderIndexingStatus>;
410
427
  }
411
428
 
429
+ /**
430
+ * A utility type that makes all properties of a type optional recursively,
431
+ * including nested objects and arrays.
432
+ *
433
+ * @example
434
+ * ```typescript
435
+ * type Config = {
436
+ * a: string;
437
+ * b: {
438
+ * x: number;
439
+ * y: { z: boolean };
440
+ * };
441
+ * c: { id: string }[];
442
+ * }
443
+ *
444
+ * type PartialConfig = DeepPartial<Config>;
445
+ * // Results in:
446
+ * // {
447
+ * // a?: string;
448
+ * // b?: {
449
+ * // x?: number;
450
+ * // y?: { z?: boolean };
451
+ * // };
452
+ * // c?: { id?: string }[];
453
+ * // }
454
+ *
455
+ * // Usage:
456
+ * const update: PartialConfig = { b: { y: { z: true } } };
457
+ * ```
458
+ */
459
+ type DeepPartial<T> = {
460
+ [P in keyof T]?: T[P] extends (infer U)[] ? DeepPartial<U>[] : T[P] extends object ? DeepPartial<T[P]> : T[P];
461
+ };
462
+ /**
463
+ * Helper type to represent an unvalidated version of a business layer type `T`,
464
+ * where all properties are optional.
465
+ *
466
+ * This is useful for building a validated object `T` from partial input,
467
+ * where the input may be missing required fields or have fields that
468
+ * are not yet validated.
469
+ *
470
+ * For example, transforming serialized representation of type `T` into
471
+ * an unvalidated version of `T` that can be later validated against
472
+ * defined business rules and constraints.
473
+ *
474
+ * ```ts
475
+ * function buildUnvalidatedValue(serialized: SerializedChainId): Unvalidated<ChainId> {
476
+ * // transform serialized chainId into unvalidated number (e.g. parseInt)
477
+ * return parseInt(serialized, 10);
478
+ * }
479
+ *
480
+ * // Later, we can validate the unvalidated value against our business rules
481
+ * function validateChainId(unvalidatedChainId: Unvalidated<ChainId>): ChainId {
482
+ * if (typeof unvalidatedChainId !== "number" || unvalidatedChainId <= 0) {
483
+ * throw new Error("Invalid ChainId");
484
+ * }
485
+ *
486
+ * return unvalidatedChainId as ChainId;
487
+ * }
488
+ *
489
+ * ```
490
+ */
491
+ type Unvalidated<T> = DeepPartial<T>;
492
+
493
+ /**
494
+ * This module provides functionality to deserialize the "raw" context of
495
+ * a local Ponder app into a validated Ponder App Context.
496
+ *
497
+ * The "raw" context is injected by Ponder at runtime as
498
+ * the `PONDER_COMMON` global variable.
499
+ *
500
+ * @see https://github.com/ponder-sh/ponder/blob/6fcc15d4234e43862cb6e21c05f3c57f4c2f7464/packages/core/src/internal/common.ts#L7-L15
501
+ */
502
+
503
+ /**
504
+ * Type representing the "raw" context of a local Ponder app.
505
+ */
506
+ declare const schemaRawPonderAppContext: z.ZodObject<{
507
+ options: z.ZodObject<{
508
+ command: z.ZodString;
509
+ }, z.core.$strip>;
510
+ }, z.core.$strip>;
511
+ /**
512
+ * Type representing the "raw" context of a local Ponder app.
513
+ */
514
+ type RawPonderAppContext = z.infer<typeof schemaRawPonderAppContext>;
515
+ /**
516
+ * Deserialize and validate a Raw Ponder App Context.
517
+ *
518
+ * @param unvalidatedRawPonderAppContext Raw Ponder App Context to be validated.
519
+ * @returns Deserialized and validated Ponder App Context.
520
+ * @throws Error if data cannot be deserialized into a valid Ponder App Context.
521
+ */
522
+ declare function deserializePonderAppContext(unvalidatedRawPonderAppContext: Unvalidated<RawPonderAppContext>): PonderAppContext;
523
+
412
524
  /**
413
525
  * Chain indexing config
414
526
  *
@@ -526,14 +638,21 @@ declare class LocalPonderClient extends PonderClient {
526
638
  * - Does not include entries for non-indexed chains.
527
639
  */
528
640
  private cachedPublicClients;
641
+ /**
642
+ * Ponder App Context
643
+ *
644
+ * The internal context of the local Ponder app.
645
+ */
646
+ private ponderAppContext;
529
647
  /**
530
648
  * @param localPonderAppUrl URL of the local Ponder app to connect to.
531
649
  * @param indexedChainIds Configured indexed chain IDs which are used to validate and filter the Ponder app metadata to only include entries for indexed chains.
532
650
  * @param indexedBlockranges Configured indexing blockrange for each indexed chain.
533
651
  * @param ponderPublicClients All cached public clients provided by the local Ponder app
534
652
  * (may include non-indexed chains).
653
+ * @param ponderAppContext The internal context of the local Ponder app.
535
654
  */
536
- constructor(localPonderAppUrl: URL, indexedChainIds: Set<ChainId>, indexedBlockranges: Map<ChainId, BlockNumberRangeWithStartBlock>, ponderPublicClients: Record<ChainIdString, CachedPublicClient>);
655
+ constructor(localPonderAppUrl: URL, indexedChainIds: Set<ChainId>, indexedBlockranges: Map<ChainId, BlockNumberRangeWithStartBlock>, ponderPublicClients: Record<ChainIdString, CachedPublicClient>, ponderAppContext: PonderAppContext);
537
656
  /**
538
657
  * Get the blockrange that is configured to be indexed for a specific chain ID.
539
658
  *
@@ -558,6 +677,10 @@ declare class LocalPonderClient extends PonderClient {
558
677
  * @throws Error if the response could not be fetched or was invalid.
559
678
  */
560
679
  metrics(): Promise<LocalPonderIndexingMetrics>;
680
+ /**
681
+ * Indicates whether the local Ponder app is running in dev mode.
682
+ */
683
+ get isInDevMode(): boolean;
561
684
  /**
562
685
  * Builds a map of cached public clients based on the Ponder cached public clients.
563
686
  *
@@ -636,4 +759,4 @@ declare const schemaUnixTimestamp: z.ZodNumber;
636
759
  */
637
760
  type UnixTimestamp = z.infer<typeof schemaUnixTimestamp>;
638
761
 
639
- export { type BlockNumber, type BlockNumberRange, type BlockNumberRangeBounded, type BlockNumberRangeLeftBounded, type BlockNumberRangeRightBounded, type BlockNumberRangeUnbounded, type BlockNumberRangeWithStartBlock, type BlockRef, type BlockRefRange, type BlockRefRangeBounded, type BlockRefRangeLeftBounded, type BlockRefRangeRightBounded, type BlockRefRangeUnbounded, type BlockRefRangeWithStartBlock, type ChainId, type ChainIdString, type ChainIndexingConfig, type ChainIndexingMetrics, type ChainIndexingMetricsCompleted, type ChainIndexingMetricsHistorical, type ChainIndexingMetricsRealtime, type ChainIndexingState, ChainIndexingStates, type ChainIndexingStatus, type LocalChainIndexingMetrics, type LocalChainIndexingMetricsHistorical, LocalPonderClient, type LocalPonderIndexingMetrics, type PonderAppCommand, PonderAppCommands, type PonderApplicationSettings, type PonderBlockNumberRange, PonderClient, type PonderIndexingMetrics, type PonderIndexingOrdering, PonderIndexingOrderings, type PonderIndexingStatus, type RangeType, RangeTypeIds, type UnixTimestamp, buildBlockNumberRange, buildBlockRefRange, isBlockRefBefore, isBlockRefBeforeOrEqualTo, isBlockRefEqualTo, mergeBlockNumberRanges, schemaBlockNumber, schemaBlockRef, schemaChainId, schemaInteger, schemaNonnegativeInteger, schemaNonnegativeNumber, schemaNumber, schemaPositiveInteger, schemaPositiveNumber, schemaUnixTimestamp };
762
+ export { type BlockNumber, type BlockNumberRange, type BlockNumberRangeBounded, type BlockNumberRangeLeftBounded, type BlockNumberRangeRightBounded, type BlockNumberRangeUnbounded, type BlockNumberRangeWithStartBlock, type BlockRef, type BlockRefRange, type BlockRefRangeBounded, type BlockRefRangeLeftBounded, type BlockRefRangeRightBounded, type BlockRefRangeUnbounded, type BlockRefRangeWithStartBlock, type ChainId, type ChainIdString, type ChainIndexingConfig, type ChainIndexingMetrics, type ChainIndexingMetricsCompleted, type ChainIndexingMetricsHistorical, type ChainIndexingMetricsRealtime, type ChainIndexingState, ChainIndexingStates, type ChainIndexingStatus, type LocalChainIndexingMetrics, type LocalChainIndexingMetricsHistorical, LocalPonderClient, type LocalPonderIndexingMetrics, type PonderAppCommand, PonderAppCommands, type PonderAppContext, type PonderApplicationSettings, type PonderBlockNumberRange, PonderClient, type PonderIndexingMetrics, type PonderIndexingOrdering, PonderIndexingOrderings, type PonderIndexingStatus, type RangeType, RangeTypeIds, type RawPonderAppContext, type UnixTimestamp, buildBlockNumberRange, buildBlockRefRange, deserializePonderAppContext, isBlockRefBefore, isBlockRefBeforeOrEqualTo, isBlockRefEqualTo, mergeBlockNumberRanges, schemaBlockNumber, schemaBlockRef, schemaChainId, schemaInteger, schemaNonnegativeInteger, schemaNonnegativeNumber, schemaNumber, schemaPositiveInteger, schemaPositiveNumber, schemaUnixTimestamp };
package/dist/index.js CHANGED
@@ -498,7 +498,7 @@ var schemaBlockRef = z2.object({
498
498
  timestamp: schemaUnixTimestamp
499
499
  });
500
500
  function isBlockRefBefore(blockA, blockB) {
501
- return blockA.number < blockB.number && blockA.timestamp < blockB.timestamp;
501
+ return blockA.number < blockB.number;
502
502
  }
503
503
  function isBlockRefEqualTo(blockA, blockB) {
504
504
  return blockA.number === blockB.number && blockA.timestamp === blockB.timestamp;
@@ -552,17 +552,28 @@ function mergeBlockNumberRanges(...ranges) {
552
552
  }
553
553
  let minStartBlock;
554
554
  let maxEndBlock;
555
+ let hasUnboundedStart = false;
556
+ let hasUnboundedEnd = false;
555
557
  for (const range of ranges) {
556
- if (range.startBlock !== void 0) {
557
- if (minStartBlock === void 0 || range.startBlock < minStartBlock) {
558
- minStartBlock = range.startBlock;
559
- }
558
+ if (range.startBlock === void 0) {
559
+ hasUnboundedStart = true;
560
+ } else if (minStartBlock === void 0 || range.startBlock < minStartBlock) {
561
+ minStartBlock = range.startBlock;
560
562
  }
561
- if (range.endBlock !== void 0) {
562
- if (maxEndBlock === void 0 || range.endBlock > maxEndBlock) {
563
- maxEndBlock = range.endBlock;
564
- }
563
+ if (range.endBlock === void 0) {
564
+ hasUnboundedEnd = true;
565
+ } else if (maxEndBlock === void 0 || range.endBlock > maxEndBlock) {
566
+ maxEndBlock = range.endBlock;
565
567
  }
568
+ if (hasUnboundedStart && hasUnboundedEnd) {
569
+ return buildBlockNumberRange(void 0, void 0);
570
+ }
571
+ }
572
+ if (hasUnboundedStart) {
573
+ minStartBlock = void 0;
574
+ }
575
+ if (hasUnboundedEnd) {
576
+ maxEndBlock = void 0;
566
577
  }
567
578
  return buildBlockNumberRange(minStartBlock, maxEndBlock);
568
579
  }
@@ -604,10 +615,6 @@ var schemaChainId = schemaPositiveInteger;
604
615
  import { prettifyError, z as z4 } from "zod/v4";
605
616
 
606
617
  // src/indexing-metrics.ts
607
- var PonderAppCommands = {
608
- Dev: "dev",
609
- Start: "start"
610
- };
611
618
  var PonderIndexingOrderings = {
612
619
  Omnichain: "omnichain"
613
620
  };
@@ -617,6 +624,12 @@ var ChainIndexingStates = {
617
624
  Realtime: "realtime"
618
625
  };
619
626
 
627
+ // src/ponder-app-context.ts
628
+ var PonderAppCommands = {
629
+ Dev: "dev",
630
+ Start: "start"
631
+ };
632
+
620
633
  // src/deserialize/chains.ts
621
634
  import { z as z3 } from "zod/v4";
622
635
  import { formatError } from "zod/v4/core";
@@ -1059,6 +1072,29 @@ var PonderClient = class {
1059
1072
  }
1060
1073
  };
1061
1074
 
1075
+ // src/deserialize/ponder-app-context.ts
1076
+ import { prettifyError as prettifyError3, z as z6 } from "zod/v4";
1077
+ var schemaRawPonderAppContext = z6.object({
1078
+ options: z6.object({
1079
+ command: z6.string()
1080
+ })
1081
+ });
1082
+ var schemaPonderAppContext = z6.object({
1083
+ command: z6.enum(PonderAppCommands)
1084
+ });
1085
+ function buildUnvalidatedPonderAppContext(rawPonderAppContext) {
1086
+ return {
1087
+ command: rawPonderAppContext.options.command
1088
+ };
1089
+ }
1090
+ function deserializePonderAppContext(unvalidatedRawPonderAppContext) {
1091
+ const validation = schemaRawPonderAppContext.transform(buildUnvalidatedPonderAppContext).pipe(schemaPonderAppContext).safeParse(unvalidatedRawPonderAppContext);
1092
+ if (!validation.success) {
1093
+ throw new Error(`Invalid raw Ponder App Context: ${prettifyError3(validation.error)}`);
1094
+ }
1095
+ return validation.data;
1096
+ }
1097
+
1062
1098
  // src/local-ponder-client.ts
1063
1099
  var LocalPonderClient = class _LocalPonderClient extends PonderClient {
1064
1100
  /**
@@ -1090,14 +1126,21 @@ var LocalPonderClient = class _LocalPonderClient extends PonderClient {
1090
1126
  * - Does not include entries for non-indexed chains.
1091
1127
  */
1092
1128
  cachedPublicClients;
1129
+ /**
1130
+ * Ponder App Context
1131
+ *
1132
+ * The internal context of the local Ponder app.
1133
+ */
1134
+ ponderAppContext;
1093
1135
  /**
1094
1136
  * @param localPonderAppUrl URL of the local Ponder app to connect to.
1095
1137
  * @param indexedChainIds Configured indexed chain IDs which are used to validate and filter the Ponder app metadata to only include entries for indexed chains.
1096
1138
  * @param indexedBlockranges Configured indexing blockrange for each indexed chain.
1097
1139
  * @param ponderPublicClients All cached public clients provided by the local Ponder app
1098
1140
  * (may include non-indexed chains).
1141
+ * @param ponderAppContext The internal context of the local Ponder app.
1099
1142
  */
1100
- constructor(localPonderAppUrl, indexedChainIds, indexedBlockranges, ponderPublicClients) {
1143
+ constructor(localPonderAppUrl, indexedChainIds, indexedBlockranges, ponderPublicClients, ponderAppContext) {
1101
1144
  super(localPonderAppUrl);
1102
1145
  this.indexedChainIds = indexedChainIds;
1103
1146
  const cachedPublicClients = _LocalPonderClient.buildCachedPublicClients(ponderPublicClients);
@@ -1111,6 +1154,7 @@ var LocalPonderClient = class _LocalPonderClient extends PonderClient {
1111
1154
  cachedPublicClients,
1112
1155
  "Cached Public Clients"
1113
1156
  );
1157
+ this.ponderAppContext = ponderAppContext;
1114
1158
  }
1115
1159
  /**
1116
1160
  * Get the blockrange that is configured to be indexed for a specific chain ID.
@@ -1164,6 +1208,12 @@ var LocalPonderClient = class _LocalPonderClient extends PonderClient {
1164
1208
  });
1165
1209
  return localMetrics;
1166
1210
  }
1211
+ /**
1212
+ * Indicates whether the local Ponder app is running in dev mode.
1213
+ */
1214
+ get isInDevMode() {
1215
+ return this.ponderAppContext.command === PonderAppCommands.Dev;
1216
+ }
1167
1217
  /**
1168
1218
  * Builds a map of cached public clients based on the Ponder cached public clients.
1169
1219
  *
@@ -1277,6 +1327,7 @@ export {
1277
1327
  RangeTypeIds,
1278
1328
  buildBlockNumberRange,
1279
1329
  buildBlockRefRange,
1330
+ deserializePonderAppContext,
1280
1331
  isBlockRefBefore,
1281
1332
  isBlockRefBeforeOrEqualTo,
1282
1333
  isBlockRefEqualTo,