@ensnode/ensnode-sdk 1.0.3 → 1.2.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.cjs CHANGED
@@ -34,6 +34,7 @@ __export(index_exports, {
34
34
  ATTR_PROTOCOL_NAME: () => ATTR_PROTOCOL_NAME,
35
35
  ATTR_PROTOCOL_STEP: () => ATTR_PROTOCOL_STEP,
36
36
  ATTR_PROTOCOL_STEP_RESULT: () => ATTR_PROTOCOL_STEP_RESULT,
37
+ AssetNamespaces: () => AssetNamespaces,
37
38
  BASENAMES_NODE: () => BASENAMES_NODE,
38
39
  ChainIndexingConfigTypeIds: () => ChainIndexingConfigTypeIds,
39
40
  ChainIndexingStatusIds: () => ChainIndexingStatusIds,
@@ -47,26 +48,31 @@ __export(index_exports, {
47
48
  ETH_COIN_TYPE: () => ETH_COIN_TYPE,
48
49
  ETH_NODE: () => ETH_NODE,
49
50
  ForwardResolutionProtocolStep: () => ForwardResolutionProtocolStep,
50
- ITEMS_PER_PAGE_DEFAULT: () => ITEMS_PER_PAGE_DEFAULT,
51
- ITEMS_PER_PAGE_MAX: () => ITEMS_PER_PAGE_MAX,
52
51
  IndexingStatusResponseCodes: () => IndexingStatusResponseCodes,
53
52
  LINEANAMES_NODE: () => LINEANAMES_NODE,
54
53
  LruCache: () => LruCache,
54
+ NFTMintStatuses: () => NFTMintStatuses,
55
+ NFTTransferTypes: () => NFTTransferTypes,
55
56
  OmnichainIndexingStatusIds: () => OmnichainIndexingStatusIds,
56
57
  PROTOCOL_ATTRIBUTE_PREFIX: () => PROTOCOL_ATTRIBUTE_PREFIX,
57
- PaginatedAggregatedReferrersResponseCodes: () => PaginatedAggregatedReferrersResponseCodes,
58
58
  PluginName: () => PluginName,
59
+ RECORDS_PER_PAGE_DEFAULT: () => RECORDS_PER_PAGE_DEFAULT,
60
+ RECORDS_PER_PAGE_MAX: () => RECORDS_PER_PAGE_MAX,
59
61
  ROOT_NODE: () => ROOT_NODE,
62
+ ReferrerDetailResponseCodes: () => ReferrerDetailResponseCodes,
63
+ ReferrerLeaderboardPageResponseCodes: () => ReferrerLeaderboardPageResponseCodes,
60
64
  RegistrarActionTypes: () => RegistrarActionTypes,
61
65
  RegistrarActionsFilterTypes: () => RegistrarActionsFilterTypes,
62
66
  RegistrarActionsOrders: () => RegistrarActionsOrders,
63
67
  RegistrarActionsResponseCodes: () => RegistrarActionsResponseCodes,
64
68
  ResolutionStatusIds: () => ResolutionStatusIds,
65
69
  ReverseResolutionProtocolStep: () => ReverseResolutionProtocolStep,
70
+ SWRCache: () => SWRCache,
66
71
  TheGraphCannotFallbackReasonSchema: () => TheGraphCannotFallbackReasonSchema,
67
72
  TheGraphFallbackSchema: () => TheGraphFallbackSchema,
68
73
  TraceableENSProtocol: () => TraceableENSProtocol,
69
74
  TtlCache: () => TtlCache,
75
+ ZERO_ENCODED_REFERRER: () => ZERO_ENCODED_REFERRER,
70
76
  accountIdEqual: () => accountIdEqual,
71
77
  addDuration: () => addDuration,
72
78
  addPrices: () => addPrices,
@@ -75,6 +81,7 @@ __export(index_exports, {
75
81
  beautifyName: () => beautifyName,
76
82
  bigIntToNumber: () => bigIntToNumber,
77
83
  bigintToCoinType: () => bigintToCoinType,
84
+ buildAssetId: () => buildAssetId,
78
85
  buildEnsRainbowClientLabelSet: () => buildEnsRainbowClientLabelSet,
79
86
  buildLabelSetId: () => buildLabelSetId,
80
87
  buildLabelSetVersion: () => buildLabelSetVersion,
@@ -96,6 +103,7 @@ __export(index_exports, {
96
103
  deserializeBlockrange: () => deserializeBlockrange,
97
104
  deserializeChainId: () => deserializeChainId,
98
105
  deserializeChainIndexingStatusSnapshot: () => deserializeChainIndexingStatusSnapshot,
106
+ deserializeConfigResponse: () => deserializeConfigResponse,
99
107
  deserializeCrossChainIndexingStatusSnapshot: () => deserializeCrossChainIndexingStatusSnapshot,
100
108
  deserializeDatetime: () => deserializeDatetime,
101
109
  deserializeDuration: () => deserializeDuration,
@@ -104,17 +112,21 @@ __export(index_exports, {
104
112
  deserializeErrorResponse: () => deserializeErrorResponse,
105
113
  deserializeIndexingStatusResponse: () => deserializeIndexingStatusResponse,
106
114
  deserializeOmnichainIndexingStatusSnapshot: () => deserializeOmnichainIndexingStatusSnapshot,
107
- deserializePaginatedAggregatedReferrersResponse: () => deserializePaginatedAggregatedReferrersResponse,
108
115
  deserializeRealtimeIndexingStatusProjection: () => deserializeRealtimeIndexingStatusProjection,
116
+ deserializeReferrerDetailResponse: () => deserializeReferrerDetailResponse,
117
+ deserializeReferrerLeaderboardPageResponse: () => deserializeReferrerLeaderboardPageResponse,
109
118
  deserializeRegistrarActionsResponse: () => deserializeRegistrarActionsResponse,
110
119
  deserializeUnixTimestamp: () => deserializeUnixTimestamp,
111
120
  deserializeUrl: () => deserializeUrl,
112
121
  durationBetween: () => durationBetween,
113
122
  encodeLabelHash: () => encodeLabelHash,
114
123
  evmChainIdToCoinType: () => evmChainIdToCoinType,
124
+ formatNFTTransferEventMetadata: () => formatNFTTransferEventMetadata,
115
125
  getCurrencyInfo: () => getCurrencyInfo,
116
126
  getENSRootChainId: () => import_datasources2.getENSRootChainId,
117
127
  getEthnamesSubregistryId: () => getEthnamesSubregistryId,
128
+ getLatestIndexedBlockRef: () => getLatestIndexedBlockRef,
129
+ getNFTTransferType: () => getNFTTransferType,
118
130
  getNameHierarchy: () => getNameHierarchy,
119
131
  getOmnichainIndexingCursor: () => getOmnichainIndexingCursor,
120
132
  getOmnichainIndexingStatus: () => getOmnichainIndexingStatus,
@@ -152,8 +164,10 @@ __export(index_exports, {
152
164
  registrarActionsPrerequisites: () => registrarActionsPrerequisites,
153
165
  reverseName: () => reverseName,
154
166
  serializeAccountId: () => serializeAccountId,
167
+ serializeAssetId: () => serializeAssetId,
155
168
  serializeChainId: () => serializeChainId,
156
169
  serializeChainIndexingSnapshots: () => serializeChainIndexingSnapshots,
170
+ serializeConfigResponse: () => serializeConfigResponse,
157
171
  serializeCrossChainIndexingStatusSnapshotOmnichain: () => serializeCrossChainIndexingStatusSnapshotOmnichain,
158
172
  serializeDatetime: () => serializeDatetime,
159
173
  serializeENSApiPublicConfig: () => serializeENSApiPublicConfig,
@@ -162,10 +176,11 @@ __export(index_exports, {
162
176
  serializeIndexingStatusResponse: () => serializeIndexingStatusResponse,
163
177
  serializeNamedRegistrarAction: () => serializeNamedRegistrarAction,
164
178
  serializeOmnichainIndexingStatusSnapshot: () => serializeOmnichainIndexingStatusSnapshot,
165
- serializePaginatedAggregatedReferrersResponse: () => serializePaginatedAggregatedReferrersResponse,
166
179
  serializePrice: () => serializePrice,
167
180
  serializePriceEth: () => serializePriceEth,
168
181
  serializeRealtimeIndexingStatusProjection: () => serializeRealtimeIndexingStatusProjection,
182
+ serializeReferrerDetailResponse: () => serializeReferrerDetailResponse,
183
+ serializeReferrerLeaderboardPageResponse: () => serializeReferrerLeaderboardPageResponse,
169
184
  serializeRegistrarAction: () => serializeRegistrarAction,
170
185
  serializeRegistrarActionPricing: () => serializeRegistrarActionPricing,
171
186
  serializeRegistrarActionsResponse: () => serializeRegistrarActionsResponse,
@@ -173,24 +188,21 @@ __export(index_exports, {
173
188
  serializeSubregistry: () => serializeSubregistry,
174
189
  serializeUrl: () => serializeUrl,
175
190
  sortChainStatusesByStartBlockAsc: () => sortChainStatusesByStartBlockAsc,
176
- staleWhileRevalidate: () => staleWhileRevalidate,
177
191
  stripNullBytes: () => stripNullBytes,
178
192
  translateDefaultableChainIdToChainId: () => translateDefaultableChainIdToChainId,
179
193
  uint256ToHex32: () => uint256ToHex32,
180
194
  uniq: () => uniq,
181
- validateSupportedLabelSetAndVersion: () => validateSupportedLabelSetAndVersion,
182
- zeroEncodedReferrer: () => zeroEncodedReferrer
195
+ validateSupportedLabelSetAndVersion: () => validateSupportedLabelSetAndVersion
183
196
  });
184
197
  module.exports = __toCommonJS(index_exports);
185
198
 
186
- // src/api/deserialize.ts
187
- var import_v49 = require("zod/v4");
199
+ // src/ensapi/config/deserialize.ts
200
+ var import_v45 = require("zod/v4");
188
201
 
189
- // src/api/zod-schemas.ts
190
- var import_viem12 = require("viem");
191
- var import_v48 = __toESM(require("zod/v4"), 1);
202
+ // src/ensapi/config/zod-schemas.ts
203
+ var import_v44 = require("zod/v4");
192
204
 
193
- // src/ensindexer/indexing-status/zod-schemas.ts
205
+ // src/ensindexer/config/zod-schemas.ts
194
206
  var import_v43 = __toESM(require("zod/v4"), 1);
195
207
 
196
208
  // src/ens/is-normalized.ts
@@ -223,8 +235,58 @@ function asLowerCaseAddress(address) {
223
235
  return address.toLowerCase();
224
236
  }
225
237
 
226
- // src/shared/cache.ts
238
+ // src/shared/cache/lru-cache.ts
239
+ var LruCache = class {
240
+ _cache = /* @__PURE__ */ new Map();
241
+ _capacity;
242
+ /**
243
+ * Create a new LRU cache with the given capacity.
244
+ *
245
+ * @param capacity The maximum number of items in the cache. If set to 0, the cache is effectively disabled.
246
+ * @throws Error if capacity is not a non-negative integer.
247
+ */
248
+ constructor(capacity) {
249
+ if (!Number.isInteger(capacity)) {
250
+ throw new Error(
251
+ `LruCache requires capacity to be an integer but a capacity of ${capacity} was requested.`
252
+ );
253
+ }
254
+ if (capacity < 0) {
255
+ throw new Error(
256
+ `LruCache requires a non-negative capacity but a capacity of ${capacity} was requested.`
257
+ );
258
+ }
259
+ this._capacity = capacity;
260
+ }
261
+ set(key, value) {
262
+ this._cache.set(key, value);
263
+ if (this._cache.size > this._capacity) {
264
+ const oldestKey = this._cache.keys().next().value;
265
+ this._cache.delete(oldestKey);
266
+ }
267
+ }
268
+ get(key) {
269
+ const value = this._cache.get(key);
270
+ if (value) {
271
+ this._cache.delete(key);
272
+ this._cache.set(key, value);
273
+ }
274
+ return value;
275
+ }
276
+ clear() {
277
+ this._cache.clear();
278
+ }
279
+ get size() {
280
+ return this._cache.size;
281
+ }
282
+ get capacity() {
283
+ return this._capacity;
284
+ }
285
+ };
286
+
287
+ // src/shared/cache/swr-cache.ts
227
288
  var import_date_fns = require("date-fns");
289
+ var import_getUnixTime = require("date-fns/getUnixTime");
228
290
 
229
291
  // src/shared/deserialize.ts
230
292
  var import_v42 = require("zod/v4");
@@ -473,6 +535,13 @@ function reinterpretName(name) {
473
535
  }
474
536
 
475
537
  // src/shared/zod-schemas.ts
538
+ var makeFiniteNonNegativeNumberSchema = (valueLabel = "Value") => import_v4.default.number({
539
+ // NOTE: Zod's implementation of `number` automatically rejects NaN and Infinity values.
540
+ // and therefore the finite check is implicit.
541
+ error: `${valueLabel} must be a finite number.`
542
+ }).nonnegative({
543
+ error: `${valueLabel} must be a non-negative number (>=0).`
544
+ });
476
545
  var makeIntegerSchema = (valueLabel = "Value") => import_v4.default.int({
477
546
  error: `${valueLabel} must be an integer.`
478
547
  });
@@ -547,13 +616,13 @@ var makePriceCurrencySchema = (currency, valueLabel = "Price Currency") => impor
547
616
  });
548
617
  var makePriceEthSchema = (valueLabel = "Price ETH") => makePriceCurrencySchema(CurrencyIds.ETH, valueLabel).transform((v) => v);
549
618
  var makeAccountIdSchema = (valueLabel = "AccountId") => import_v4.default.strictObject({
550
- chainId: makeChainIdStringSchema(`${valueLabel} chain ID`),
619
+ chainId: makeChainIdSchema(`${valueLabel} chain ID`),
551
620
  address: makeLowercaseAddressSchema(`${valueLabel} address`)
552
621
  });
553
622
  var makeSerializedAccountIdSchema = (valueLabel = "Account ID") => import_v4.default.coerce.string().transform((v) => {
554
623
  const result = new import_caip.AccountId(v);
555
624
  return {
556
- chainId: result.chainId.reference,
625
+ chainId: Number(result.chainId.reference),
557
626
  address: result.address
558
627
  };
559
628
  }).pipe(makeAccountIdSchema(valueLabel));
@@ -691,54 +760,185 @@ function addDuration(timestamp, duration) {
691
760
  return deserializeUnixTimestamp(timestamp + duration, "UnixTimestamp");
692
761
  }
693
762
 
694
- // src/shared/cache.ts
695
- var LruCache = class {
696
- _cache = /* @__PURE__ */ new Map();
697
- _capacity;
763
+ // src/shared/cache/background-revalidation-scheduler.ts
764
+ var BackgroundRevalidationScheduler = class {
765
+ activeSchedules = /* @__PURE__ */ new Map();
698
766
  /**
699
- * Create a new LRU cache with the given capacity.
767
+ * Schedule a revalidation function to run on a recurring interval.
700
768
  *
701
- * @param capacity The maximum number of items in the cache. If set to 0, the cache is effectively disabled.
702
- * @throws Error if capacity is not a non-negative integer.
769
+ * @param config Configuration object for the schedule
770
+ * @returns The revalidate function that can be passed to `cancel()` to stop the schedule
703
771
  */
704
- constructor(capacity) {
705
- if (!Number.isInteger(capacity)) {
706
- throw new Error(
707
- `LruCache requires capacity to be an integer but a capacity of ${capacity} was requested.`
708
- );
772
+ schedule(config) {
773
+ const { revalidate, interval, initialDelay = 0, onError } = config;
774
+ if (this.activeSchedules.has(revalidate)) {
775
+ return revalidate;
709
776
  }
710
- if (capacity < 0) {
711
- throw new Error(
712
- `LruCache requires a non-negative capacity but a capacity of ${capacity} was requested.`
713
- );
777
+ const metadata = {
778
+ config,
779
+ timeoutId: null,
780
+ inProgress: false
781
+ };
782
+ this.activeSchedules.set(revalidate, metadata);
783
+ const executeRevalidation = async () => {
784
+ if (metadata.inProgress) return;
785
+ metadata.inProgress = true;
786
+ try {
787
+ await revalidate();
788
+ } catch (error) {
789
+ onError?.(error);
790
+ } finally {
791
+ metadata.inProgress = false;
792
+ }
793
+ };
794
+ const scheduleNext = () => {
795
+ if (!this.activeSchedules.has(revalidate)) return;
796
+ metadata.timeoutId = setTimeout(() => {
797
+ if (this.activeSchedules.has(revalidate)) {
798
+ executeRevalidation().then(() => scheduleNext());
799
+ }
800
+ }, interval);
801
+ };
802
+ if (initialDelay > 0) {
803
+ metadata.timeoutId = setTimeout(() => {
804
+ if (this.activeSchedules.has(revalidate)) {
805
+ executeRevalidation().then(() => scheduleNext());
806
+ }
807
+ }, initialDelay);
808
+ } else {
809
+ scheduleNext();
714
810
  }
715
- this._capacity = capacity;
811
+ return revalidate;
716
812
  }
717
- set(key, value) {
718
- this._cache.set(key, value);
719
- if (this._cache.size > this._capacity) {
720
- const oldestKey = this._cache.keys().next().value;
721
- this._cache.delete(oldestKey);
813
+ /**
814
+ * Cancel a scheduled revalidation by its revalidate function.
815
+ *
816
+ * @param revalidate The revalidation function returned from `schedule()`
817
+ */
818
+ cancel(revalidate) {
819
+ const metadata = this.activeSchedules.get(revalidate);
820
+ if (!metadata) return;
821
+ if (metadata.timeoutId !== null) {
822
+ clearTimeout(metadata.timeoutId);
722
823
  }
824
+ this.activeSchedules.delete(revalidate);
723
825
  }
724
- get(key) {
725
- const value = this._cache.get(key);
726
- if (value) {
727
- this._cache.delete(key);
728
- this._cache.set(key, value);
826
+ /**
827
+ * Cancel all active schedules.
828
+ */
829
+ cancelAll() {
830
+ for (const [, metadata] of this.activeSchedules) {
831
+ if (metadata.timeoutId !== null) {
832
+ clearTimeout(metadata.timeoutId);
833
+ }
729
834
  }
730
- return value;
835
+ this.activeSchedules.clear();
731
836
  }
732
- clear() {
733
- this._cache.clear();
837
+ /**
838
+ * Get the count of active schedules.
839
+ * Useful for debugging and monitoring.
840
+ *
841
+ * @returns The number of currently active schedules
842
+ */
843
+ getActiveScheduleCount() {
844
+ return this.activeSchedules.size;
734
845
  }
735
- get size() {
736
- return this._cache.size;
846
+ };
847
+
848
+ // src/shared/cache/swr-cache.ts
849
+ var bgRevalidationScheduler = new BackgroundRevalidationScheduler();
850
+ var SWRCache = class _SWRCache {
851
+ options;
852
+ cache;
853
+ /**
854
+ * Optional promise of the current in-progress attempt to revalidate the `cache`.
855
+ *
856
+ * If null, no revalidation attempt is currently in progress.
857
+ * If not null, identifies the revalidation attempt that is currently in progress.
858
+ *
859
+ * Used to enforce no concurrent revalidation attempts.
860
+ */
861
+ inProgressRevalidate;
862
+ /**
863
+ * The callback function being managed by `BackgroundRevalidationScheduler`.
864
+ *
865
+ * If null, no background revalidation is scheduled.
866
+ * If not null, identifies the background revalidation that is currently scheduled.
867
+ *
868
+ * Used to enforce no concurrent background revalidation attempts.
869
+ */
870
+ scheduledBackgroundRevalidate;
871
+ constructor(options) {
872
+ this.cache = null;
873
+ this.inProgressRevalidate = null;
874
+ this.scheduledBackgroundRevalidate = null;
875
+ this.options = options;
737
876
  }
738
- get capacity() {
739
- return this._capacity;
877
+ /**
878
+ * Asynchronously create a new `SWRCache` instance.
879
+ *
880
+ * @param options - The {@link SWRCacheOptions} for the SWR cache.
881
+ * @returns a new `SWRCache` instance.
882
+ */
883
+ static async create(options) {
884
+ const cache = new _SWRCache(options);
885
+ if (cache.options.proactivelyInitialize) {
886
+ cache.readCache();
887
+ }
888
+ return cache;
740
889
  }
890
+ revalidate = async () => {
891
+ if (this.inProgressRevalidate) {
892
+ return this.inProgressRevalidate;
893
+ }
894
+ return this.options.fn().then((value) => {
895
+ this.cache = {
896
+ value,
897
+ updatedAt: (0, import_getUnixTime.getUnixTime)(/* @__PURE__ */ new Date())
898
+ };
899
+ return this.cache;
900
+ }).catch(() => {
901
+ return null;
902
+ }).finally(() => {
903
+ this.inProgressRevalidate = null;
904
+ if (this.options.revalidationInterval === void 0) {
905
+ return;
906
+ }
907
+ if (this.scheduledBackgroundRevalidate) {
908
+ bgRevalidationScheduler.cancel(this.scheduledBackgroundRevalidate);
909
+ }
910
+ const backgroundRevalidate = async () => {
911
+ this.revalidate();
912
+ };
913
+ this.scheduledBackgroundRevalidate = bgRevalidationScheduler.schedule({
914
+ revalidate: backgroundRevalidate,
915
+ interval: (0, import_date_fns.secondsToMilliseconds)(this.options.revalidationInterval)
916
+ });
917
+ });
918
+ };
919
+ /**
920
+ * Read the most recently cached `CachedValue` from the `SWRCache`.
921
+ *
922
+ * @returns a `CachedValue` holding a `value` of `ValueType` that was most recently successfully returned by `fn`
923
+ * or `null` if `fn` has never successfully returned and has always thrown an error,
924
+ */
925
+ readCache = async () => {
926
+ if (!this.cache) {
927
+ this.inProgressRevalidate = this.revalidate();
928
+ return this.inProgressRevalidate;
929
+ }
930
+ if (durationBetween(this.cache.updatedAt, (0, import_getUnixTime.getUnixTime)(/* @__PURE__ */ new Date())) <= this.options.ttl) {
931
+ return this.cache;
932
+ }
933
+ if (!this.inProgressRevalidate) {
934
+ this.inProgressRevalidate = this.revalidate();
935
+ }
936
+ return this.cache;
937
+ };
741
938
  };
939
+
940
+ // src/shared/cache/ttl-cache.ts
941
+ var import_getUnixTime2 = require("date-fns/getUnixTime");
742
942
  var TtlCache = class {
743
943
  _cache = /* @__PURE__ */ new Map();
744
944
  _ttl;
@@ -751,7 +951,7 @@ var TtlCache = class {
751
951
  this._ttl = ttl;
752
952
  }
753
953
  _cleanup() {
754
- const now = (0, import_date_fns.getUnixTime)(/* @__PURE__ */ new Date());
954
+ const now = (0, import_getUnixTime2.getUnixTime)(/* @__PURE__ */ new Date());
755
955
  for (const [key, entry] of this._cache.entries()) {
756
956
  if (entry.expiresAt <= now) {
757
957
  this._cache.delete(key);
@@ -760,7 +960,7 @@ var TtlCache = class {
760
960
  }
761
961
  set(key, value) {
762
962
  this._cleanup();
763
- const expiresAt = addDuration((0, import_date_fns.getUnixTime)(/* @__PURE__ */ new Date()), this._ttl);
963
+ const expiresAt = addDuration((0, import_getUnixTime2.getUnixTime)(/* @__PURE__ */ new Date()), this._ttl);
764
964
  this._cache.set(key, { value, expiresAt });
765
965
  }
766
966
  get(key) {
@@ -769,7 +969,7 @@ var TtlCache = class {
769
969
  if (!entry) {
770
970
  return void 0;
771
971
  }
772
- if (entry.expiresAt <= (0, import_date_fns.getUnixTime)(/* @__PURE__ */ new Date())) {
972
+ if (entry.expiresAt <= (0, import_getUnixTime2.getUnixTime)(/* @__PURE__ */ new Date())) {
773
973
  this._cache.delete(key);
774
974
  return void 0;
775
975
  }
@@ -791,7 +991,7 @@ var TtlCache = class {
791
991
  if (!entry) {
792
992
  return false;
793
993
  }
794
- if (entry.expiresAt <= (0, import_date_fns.getUnixTime)(/* @__PURE__ */ new Date())) {
994
+ if (entry.expiresAt <= (0, import_getUnixTime2.getUnixTime)(/* @__PURE__ */ new Date())) {
795
995
  this._cache.delete(key);
796
996
  return false;
797
997
  }
@@ -801,39 +1001,6 @@ var TtlCache = class {
801
1001
  return this._cache.delete(key);
802
1002
  }
803
1003
  };
804
- function staleWhileRevalidate(options) {
805
- const { fn, ttl } = options;
806
- let cache = null;
807
- let cacheInitializer = null;
808
- return async () => {
809
- if (!cache) {
810
- if (cacheInitializer) {
811
- return cacheInitializer;
812
- }
813
- cacheInitializer = fn().then((value) => {
814
- cache = { value, updatedAt: (0, import_date_fns.getUnixTime)(/* @__PURE__ */ new Date()) };
815
- cacheInitializer = null;
816
- return value;
817
- }).catch(() => {
818
- cacheInitializer = null;
819
- return null;
820
- });
821
- return cacheInitializer;
822
- }
823
- const isStale = durationBetween(cache.updatedAt, (0, import_date_fns.getUnixTime)(/* @__PURE__ */ new Date())) > ttl;
824
- if (!isStale) return cache.value;
825
- if (cache.inProgressRevalidation) return cache.value;
826
- const revalidationPromise = fn().then((value) => {
827
- cache = { value, updatedAt: (0, import_date_fns.getUnixTime)(/* @__PURE__ */ new Date()) };
828
- }).catch(() => {
829
- if (cache) {
830
- cache.inProgressRevalidation = void 0;
831
- }
832
- });
833
- cache.inProgressRevalidation = revalidationPromise;
834
- return cache.value;
835
- };
836
- }
837
1004
 
838
1005
  // src/shared/collections.ts
839
1006
  var uniq = (arr) => [...new Set(arr)];
@@ -911,105 +1078,371 @@ function isWebSocketProtocol(url) {
911
1078
  return ["ws:", "wss:"].includes(url.protocol);
912
1079
  }
913
1080
 
914
- // src/ensindexer/indexing-status/types.ts
915
- var ChainIndexingConfigTypeIds = {
916
- /**
917
- * Represents that indexing of the chain should be performed for an indefinite range.
918
- */
919
- Indefinite: "indefinite",
920
- /**
921
- * Represents that indexing of the chain should be performed for a definite range.
922
- */
923
- Definite: "definite"
924
- };
925
- var ChainIndexingStatusIds = {
926
- /**
927
- * Represents that indexing of the chain is not ready to begin yet because:
928
- * - ENSIndexer is in its initialization phase and the data to build a
929
- * "true" {@link ChainIndexingSnapshot} for the chain is still being loaded; or
930
- * - ENSIndexer is using an omnichain indexing strategy and the
931
- * `omnichainIndexingCursor` is <= `config.startBlock.timestamp` for the chain's
932
- * {@link ChainIndexingSnapshot}.
933
- */
934
- Queued: "chain-queued",
935
- /**
936
- * Represents that indexing of the chain is in progress and under a special
937
- * "backfill" phase that optimizes for accelerated indexing until reaching the
938
- * "fixed target" `backfillEndBlock`.
939
- */
940
- Backfill: "chain-backfill",
941
- /**
942
- * Represents that the "backfill" phase of indexing the chain is completed
943
- * and that the chain is configured to be indexed for an indefinite range.
944
- * Therefore, indexing of the chain remains indefinitely in progress where
945
- * ENSIndexer will continuously work to discover and index new blocks as they
946
- * are added to the chain across time.
947
- */
948
- Following: "chain-following",
949
- /**
950
- * Represents that indexing of the chain is completed as the chain is configured
951
- * to be indexed for a definite range and the indexing of all blocks through
952
- * that definite range is completed.
953
- */
954
- Completed: "chain-completed"
955
- };
956
- var OmnichainIndexingStatusIds = {
957
- /**
958
- * Represents that omnichain indexing is not ready to begin yet because
959
- * ENSIndexer is in its initialization phase and the data to build a "true"
960
- * {@link OmnichainIndexingStatusSnapshot} is still being loaded.
961
- */
962
- Unstarted: "omnichain-unstarted",
963
- /**
964
- * Represents that omnichain indexing is in an overall "backfill" status because
965
- * - At least one indexed chain has a `chainStatus` of
966
- * {@link ChainIndexingStatusIds.Backfill}; and
967
- * - No indexed chain has a `chainStatus` of {@link ChainIndexingStatusIds.Following}.
968
- */
969
- Backfill: "omnichain-backfill",
970
- /**
971
- * Represents that omnichain indexing is in an overall "following" status because
972
- * at least one indexed chain has a `chainStatus` of
973
- * {@link ChainIndexingStatusIds.Following}.
974
- */
975
- Following: "omnichain-following",
976
- /**
977
- * Represents that omnichain indexing has completed because all indexed chains have
978
- * a `chainStatus` of {@link ChainIndexingStatusIds.Completed}.
979
- */
980
- Completed: "omnichain-completed"
981
- };
982
- var CrossChainIndexingStrategyIds = {
983
- /**
984
- * Represents that the indexing of events across all indexed chains will
985
- * proceed in a deterministic "omnichain" ordering by block timestamp, chain ID,
986
- * and block number.
987
- *
988
- * This strategy is "deterministic" in that the order of processing cross-chain indexed
989
- * events and each resulting indexed data state transition recorded in ENSDb is always
990
- * the same for each ENSIndexer instance operating with an equivalent
991
- * `ENSIndexerConfig` and ENSIndexer version. However it also has the drawbacks of:
992
- * - increased indexing latency that must wait for the slowest indexed chain to
993
- * add new blocks or to discover new blocks through the configured RPCs.
994
- * - if any indexed chain gets "stuck" due to chain or RPC failures, all indexed chains
995
- * will be affected.
996
- */
997
- Omnichain: "omnichain"
998
- };
1081
+ // src/ensindexer/config/is-subgraph-compatible.ts
1082
+ var import_datasources3 = require("@ensnode/datasources");
999
1083
 
1000
- // src/shared/block-ref.ts
1001
- function isBefore(blockA, blockB) {
1002
- return blockA.number < blockB.number && blockA.timestamp < blockB.timestamp;
1003
- }
1004
- function isEqualTo(blockA, blockB) {
1005
- return blockA.number === blockB.number && blockA.timestamp === blockB.timestamp;
1006
- }
1007
- function isBeforeOrEqualTo(blockA, blockB) {
1008
- return isBefore(blockA, blockB) || isEqualTo(blockA, blockB);
1009
- }
1084
+ // src/ensindexer/config/types.ts
1085
+ var PluginName = /* @__PURE__ */ ((PluginName2) => {
1086
+ PluginName2["Subgraph"] = "subgraph";
1087
+ PluginName2["Basenames"] = "basenames";
1088
+ PluginName2["Lineanames"] = "lineanames";
1089
+ PluginName2["ThreeDNS"] = "threedns";
1090
+ PluginName2["ProtocolAcceleration"] = "protocol-acceleration";
1091
+ PluginName2["Registrars"] = "registrars";
1092
+ PluginName2["TokenScope"] = "tokenscope";
1093
+ return PluginName2;
1094
+ })(PluginName || {});
1010
1095
 
1011
- // src/ensindexer/indexing-status/helpers.ts
1012
- function getOmnichainIndexingStatus(chains) {
1096
+ // src/ensindexer/config/is-subgraph-compatible.ts
1097
+ function isSubgraphCompatible(config) {
1098
+ const onlySubgraphPluginActivated = config.plugins.length === 1 && config.plugins[0] === "subgraph" /* Subgraph */;
1099
+ const isSubgraphLabelSet = config.labelSet.labelSetId === "subgraph" && config.labelSet.labelSetVersion === 0;
1100
+ const isEnsTestEnvLabelSet = config.labelSet.labelSetId === "ens-test-env" && config.labelSet.labelSetVersion === 0;
1101
+ const labelSetIsSubgraphCompatible = isSubgraphLabelSet || config.namespace === import_datasources3.ENSNamespaceIds.EnsTestEnv && isEnsTestEnvLabelSet;
1102
+ return onlySubgraphPluginActivated && labelSetIsSubgraphCompatible;
1103
+ }
1104
+
1105
+ // src/ensindexer/config/validations.ts
1106
+ function invariant_ensDbVersionIsSameAsEnsIndexerVersion(ctx) {
1107
+ const versionInfo = ctx.value;
1108
+ if (versionInfo.ensDb !== versionInfo.ensIndexer) {
1109
+ ctx.issues.push({
1110
+ code: "custom",
1111
+ input: versionInfo,
1112
+ message: "`ensDb` version must be same as `ensIndexer` version"
1113
+ });
1114
+ }
1115
+ }
1116
+
1117
+ // src/ensindexer/config/zod-schemas.ts
1118
+ var makeIndexedChainIdsSchema = (valueLabel = "Indexed Chain IDs") => import_v43.default.array(makeChainIdSchema(valueLabel), {
1119
+ error: `${valueLabel} must be an array.`
1120
+ }).min(1, { error: `${valueLabel} list must include at least one element.` }).transform((v) => new Set(v));
1121
+ var makePluginsListSchema = (valueLabel = "Plugins") => import_v43.default.array(import_v43.default.string(), {
1122
+ error: `${valueLabel} must be a list of strings.`
1123
+ }).min(1, {
1124
+ error: `${valueLabel} must be a list of strings with at least one string value`
1125
+ }).refine((arr) => arr.length === uniq(arr).length, {
1126
+ error: `${valueLabel} cannot contain duplicate values.`
1127
+ });
1128
+ var makeDatabaseSchemaNameSchema = (valueLabel = "Database schema name") => import_v43.default.string({ error: `${valueLabel} must be a string` }).trim().nonempty({
1129
+ error: `${valueLabel} is required and must be a non-empty string.`
1130
+ });
1131
+ var makeLabelSetIdSchema = (valueLabel) => {
1132
+ return import_v43.default.string({ error: `${valueLabel} must be a string` }).min(1, { error: `${valueLabel} must be 1-50 characters long` }).max(50, { error: `${valueLabel} must be 1-50 characters long` }).regex(/^[a-z-]+$/, {
1133
+ error: `${valueLabel} can only contain lowercase letters (a-z) and hyphens (-)`
1134
+ });
1135
+ };
1136
+ var makeLabelSetVersionSchema = (valueLabel) => {
1137
+ return import_v43.default.coerce.number({ error: `${valueLabel} must be an integer.` }).pipe(makeNonNegativeIntegerSchema(valueLabel));
1138
+ };
1139
+ var makeFullyPinnedLabelSetSchema = (valueLabel = "Label set") => {
1140
+ let valueLabelLabelSetId = valueLabel;
1141
+ let valueLabelLabelSetVersion = valueLabel;
1142
+ if (valueLabel === "LABEL_SET") {
1143
+ valueLabelLabelSetId = "LABEL_SET_ID";
1144
+ valueLabelLabelSetVersion = "LABEL_SET_VERSION";
1145
+ } else {
1146
+ valueLabelLabelSetId = `${valueLabel}.labelSetId`;
1147
+ valueLabelLabelSetVersion = `${valueLabel}.labelSetVersion`;
1148
+ }
1149
+ return import_v43.default.object({
1150
+ labelSetId: makeLabelSetIdSchema(valueLabelLabelSetId),
1151
+ labelSetVersion: makeLabelSetVersionSchema(valueLabelLabelSetVersion)
1152
+ });
1153
+ };
1154
+ var makeNonEmptyStringSchema = (valueLabel = "Value") => import_v43.default.string().nonempty({ error: `${valueLabel} must be a non-empty string.` });
1155
+ var makeENSIndexerVersionInfoSchema = (valueLabel = "Value") => import_v43.default.strictObject(
1156
+ {
1157
+ nodejs: makeNonEmptyStringSchema(),
1158
+ ponder: makeNonEmptyStringSchema(),
1159
+ ensDb: makeNonEmptyStringSchema(),
1160
+ ensIndexer: makeNonEmptyStringSchema(),
1161
+ ensNormalize: makeNonEmptyStringSchema(),
1162
+ ensRainbow: makeNonEmptyStringSchema(),
1163
+ ensRainbowSchema: makePositiveIntegerSchema()
1164
+ },
1165
+ {
1166
+ error: `${valueLabel} must be a valid ENSIndexerVersionInfo object.`
1167
+ }
1168
+ ).check(invariant_ensDbVersionIsSameAsEnsIndexerVersion);
1169
+ function invariant_isSubgraphCompatibleRequirements(ctx) {
1170
+ const { value: config } = ctx;
1171
+ if (config.isSubgraphCompatible && !isSubgraphCompatible(config)) {
1172
+ ctx.issues.push({
1173
+ code: "custom",
1174
+ input: config,
1175
+ message: `'isSubgraphCompatible' requires only the '${"subgraph" /* Subgraph */}' plugin to be active and labelSet must be {labelSetId: "subgraph", labelSetVersion: 0}`
1176
+ });
1177
+ }
1178
+ }
1179
+ var makeENSIndexerPublicConfigSchema = (valueLabel = "ENSIndexerPublicConfig") => import_v43.default.object({
1180
+ labelSet: makeFullyPinnedLabelSetSchema(`${valueLabel}.labelSet`),
1181
+ indexedChainIds: makeIndexedChainIdsSchema(`${valueLabel}.indexedChainIds`),
1182
+ isSubgraphCompatible: import_v43.default.boolean({ error: `${valueLabel}.isSubgraphCompatible` }),
1183
+ namespace: makeENSNamespaceIdSchema(`${valueLabel}.namespace`),
1184
+ plugins: makePluginsListSchema(`${valueLabel}.plugins`),
1185
+ databaseSchemaName: makeDatabaseSchemaNameSchema(`${valueLabel}.databaseSchemaName`),
1186
+ versionInfo: makeENSIndexerVersionInfoSchema(`${valueLabel}.versionInfo`)
1187
+ }).check(invariant_isSubgraphCompatibleRequirements);
1188
+
1189
+ // src/ensapi/config/zod-schemas.ts
1190
+ var TheGraphCannotFallbackReasonSchema = import_v44.z.enum({
1191
+ NotSubgraphCompatible: "not-subgraph-compatible",
1192
+ NoApiKey: "no-api-key",
1193
+ NoSubgraphUrl: "no-subgraph-url"
1194
+ });
1195
+ var TheGraphFallbackSchema = import_v44.z.strictObject({
1196
+ canFallback: import_v44.z.boolean(),
1197
+ reason: TheGraphCannotFallbackReasonSchema.nullable()
1198
+ });
1199
+ function makeENSApiPublicConfigSchema(valueLabel) {
1200
+ const label = valueLabel ?? "ENSApiPublicConfig";
1201
+ return import_v44.z.strictObject({
1202
+ version: import_v44.z.string().min(1, `${label}.version must be a non-empty string`),
1203
+ theGraphFallback: TheGraphFallbackSchema,
1204
+ ensIndexerPublicConfig: makeENSIndexerPublicConfigSchema(`${label}.ensIndexerPublicConfig`)
1205
+ });
1206
+ }
1207
+
1208
+ // src/ensapi/config/deserialize.ts
1209
+ function deserializeENSApiPublicConfig(maybeConfig, valueLabel) {
1210
+ const schema = makeENSApiPublicConfigSchema(valueLabel);
1211
+ try {
1212
+ return schema.parse(maybeConfig);
1213
+ } catch (error) {
1214
+ if (error instanceof import_v45.ZodError) {
1215
+ throw new Error(`Cannot deserialize ENSApiPublicConfig:
1216
+ ${(0, import_v45.prettifyError)(error)}
1217
+ `);
1218
+ }
1219
+ throw error;
1220
+ }
1221
+ }
1222
+
1223
+ // src/ensindexer/config/deserialize.ts
1224
+ var import_v46 = require("zod/v4");
1225
+ function deserializeENSIndexerPublicConfig(maybeConfig, valueLabel) {
1226
+ const schema = makeENSIndexerPublicConfigSchema(valueLabel);
1227
+ const parsed = schema.safeParse(maybeConfig);
1228
+ if (parsed.error) {
1229
+ throw new Error(`Cannot deserialize ENSIndexerPublicConfig:
1230
+ ${(0, import_v46.prettifyError)(parsed.error)}
1231
+ `);
1232
+ }
1233
+ return parsed.data;
1234
+ }
1235
+
1236
+ // src/ensindexer/config/label-utils.ts
1237
+ var import_viem10 = require("viem");
1238
+ function labelHashToBytes(labelHash) {
1239
+ try {
1240
+ if (labelHash.length !== 66) {
1241
+ throw new Error(`Invalid labelHash length ${labelHash.length} characters (expected 66)`);
1242
+ }
1243
+ if (labelHash !== labelHash.toLowerCase()) {
1244
+ throw new Error("Labelhash must be in lowercase");
1245
+ }
1246
+ if (!labelHash.startsWith("0x")) {
1247
+ throw new Error("Labelhash must be 0x-prefixed");
1248
+ }
1249
+ const bytes = (0, import_viem10.hexToBytes)(labelHash);
1250
+ if (bytes.length !== 32) {
1251
+ throw new Error(`Invalid labelHash length ${bytes.length} bytes (expected 32)`);
1252
+ }
1253
+ return bytes;
1254
+ } catch (e) {
1255
+ if (e instanceof Error) {
1256
+ throw e;
1257
+ }
1258
+ throw new Error("Invalid hex format");
1259
+ }
1260
+ }
1261
+
1262
+ // src/ensindexer/config/labelset-utils.ts
1263
+ function buildLabelSetId(maybeLabelSetId) {
1264
+ return makeLabelSetIdSchema("LabelSetId").parse(maybeLabelSetId);
1265
+ }
1266
+ function buildLabelSetVersion(maybeLabelSetVersion) {
1267
+ return makeLabelSetVersionSchema("LabelSetVersion").parse(maybeLabelSetVersion);
1268
+ }
1269
+ function buildEnsRainbowClientLabelSet(labelSetId, labelSetVersion) {
1270
+ if (labelSetVersion !== void 0 && labelSetId === void 0) {
1271
+ throw new Error("When a labelSetVersion is defined, labelSetId must also be defined.");
1272
+ }
1273
+ return { labelSetId, labelSetVersion };
1274
+ }
1275
+ function validateSupportedLabelSetAndVersion(serverSet, clientSet) {
1276
+ if (clientSet.labelSetId === void 0) {
1277
+ return;
1278
+ }
1279
+ if (serverSet.labelSetId !== clientSet.labelSetId) {
1280
+ throw new Error(
1281
+ `Server label set ID "${serverSet.labelSetId}" does not match client's requested label set ID "${clientSet.labelSetId}".`
1282
+ );
1283
+ }
1284
+ if (clientSet.labelSetVersion !== void 0 && serverSet.highestLabelSetVersion < clientSet.labelSetVersion) {
1285
+ throw new Error(
1286
+ `Server highest label set version ${serverSet.highestLabelSetVersion} is less than client's requested version ${clientSet.labelSetVersion} for label set ID "${clientSet.labelSetId}".`
1287
+ );
1288
+ }
1289
+ }
1290
+
1291
+ // src/ensindexer/config/parsing.ts
1292
+ function parseNonNegativeInteger(maybeNumber) {
1293
+ const trimmed = maybeNumber.trim();
1294
+ if (!trimmed) {
1295
+ throw new Error("Input cannot be empty");
1296
+ }
1297
+ if (trimmed === "-0") {
1298
+ throw new Error("Negative zero is not a valid non-negative integer");
1299
+ }
1300
+ const num = Number(maybeNumber);
1301
+ if (Number.isNaN(num)) {
1302
+ throw new Error(`"${maybeNumber}" is not a valid number`);
1303
+ }
1304
+ if (!Number.isFinite(num)) {
1305
+ throw new Error(`"${maybeNumber}" is not a finite number`);
1306
+ }
1307
+ if (!Number.isInteger(num)) {
1308
+ throw new Error(`"${maybeNumber}" is not an integer`);
1309
+ }
1310
+ if (num < 0) {
1311
+ throw new Error(`"${maybeNumber}" is not a non-negative integer`);
1312
+ }
1313
+ return num;
1314
+ }
1315
+
1316
+ // src/ensindexer/config/serialize.ts
1317
+ function serializeIndexedChainIds(indexedChainIds) {
1318
+ return Array.from(indexedChainIds);
1319
+ }
1320
+ function serializeENSIndexerPublicConfig(config) {
1321
+ const {
1322
+ labelSet,
1323
+ indexedChainIds,
1324
+ databaseSchemaName,
1325
+ isSubgraphCompatible: isSubgraphCompatible2,
1326
+ namespace,
1327
+ plugins,
1328
+ versionInfo
1329
+ } = config;
1330
+ return {
1331
+ labelSet,
1332
+ indexedChainIds: serializeIndexedChainIds(indexedChainIds),
1333
+ databaseSchemaName,
1334
+ isSubgraphCompatible: isSubgraphCompatible2,
1335
+ namespace,
1336
+ plugins,
1337
+ versionInfo
1338
+ };
1339
+ }
1340
+
1341
+ // src/ensindexer/indexing-status/deserialize.ts
1342
+ var import_v48 = require("zod/v4");
1343
+
1344
+ // src/ensindexer/indexing-status/zod-schemas.ts
1345
+ var import_v47 = __toESM(require("zod/v4"), 1);
1346
+
1347
+ // src/ensindexer/indexing-status/types.ts
1348
+ var ChainIndexingConfigTypeIds = {
1349
+ /**
1350
+ * Represents that indexing of the chain should be performed for an indefinite range.
1351
+ */
1352
+ Indefinite: "indefinite",
1353
+ /**
1354
+ * Represents that indexing of the chain should be performed for a definite range.
1355
+ */
1356
+ Definite: "definite"
1357
+ };
1358
+ var ChainIndexingStatusIds = {
1359
+ /**
1360
+ * Represents that indexing of the chain is not ready to begin yet because:
1361
+ * - ENSIndexer is in its initialization phase and the data to build a
1362
+ * "true" {@link ChainIndexingSnapshot} for the chain is still being loaded; or
1363
+ * - ENSIndexer is using an omnichain indexing strategy and the
1364
+ * `omnichainIndexingCursor` is <= `config.startBlock.timestamp` for the chain's
1365
+ * {@link ChainIndexingSnapshot}.
1366
+ */
1367
+ Queued: "chain-queued",
1368
+ /**
1369
+ * Represents that indexing of the chain is in progress and under a special
1370
+ * "backfill" phase that optimizes for accelerated indexing until reaching the
1371
+ * "fixed target" `backfillEndBlock`.
1372
+ */
1373
+ Backfill: "chain-backfill",
1374
+ /**
1375
+ * Represents that the "backfill" phase of indexing the chain is completed
1376
+ * and that the chain is configured to be indexed for an indefinite range.
1377
+ * Therefore, indexing of the chain remains indefinitely in progress where
1378
+ * ENSIndexer will continuously work to discover and index new blocks as they
1379
+ * are added to the chain across time.
1380
+ */
1381
+ Following: "chain-following",
1382
+ /**
1383
+ * Represents that indexing of the chain is completed as the chain is configured
1384
+ * to be indexed for a definite range and the indexing of all blocks through
1385
+ * that definite range is completed.
1386
+ */
1387
+ Completed: "chain-completed"
1388
+ };
1389
+ var OmnichainIndexingStatusIds = {
1390
+ /**
1391
+ * Represents that omnichain indexing is not ready to begin yet because
1392
+ * ENSIndexer is in its initialization phase and the data to build a "true"
1393
+ * {@link OmnichainIndexingStatusSnapshot} is still being loaded.
1394
+ */
1395
+ Unstarted: "omnichain-unstarted",
1396
+ /**
1397
+ * Represents that omnichain indexing is in an overall "backfill" status because
1398
+ * - At least one indexed chain has a `chainStatus` of
1399
+ * {@link ChainIndexingStatusIds.Backfill}; and
1400
+ * - No indexed chain has a `chainStatus` of {@link ChainIndexingStatusIds.Following}.
1401
+ */
1402
+ Backfill: "omnichain-backfill",
1403
+ /**
1404
+ * Represents that omnichain indexing is in an overall "following" status because
1405
+ * at least one indexed chain has a `chainStatus` of
1406
+ * {@link ChainIndexingStatusIds.Following}.
1407
+ */
1408
+ Following: "omnichain-following",
1409
+ /**
1410
+ * Represents that omnichain indexing has completed because all indexed chains have
1411
+ * a `chainStatus` of {@link ChainIndexingStatusIds.Completed}.
1412
+ */
1413
+ Completed: "omnichain-completed"
1414
+ };
1415
+ var CrossChainIndexingStrategyIds = {
1416
+ /**
1417
+ * Represents that the indexing of events across all indexed chains will
1418
+ * proceed in a deterministic "omnichain" ordering by block timestamp, chain ID,
1419
+ * and block number.
1420
+ *
1421
+ * This strategy is "deterministic" in that the order of processing cross-chain indexed
1422
+ * events and each resulting indexed data state transition recorded in ENSDb is always
1423
+ * the same for each ENSIndexer instance operating with an equivalent
1424
+ * `ENSIndexerConfig` and ENSIndexer version. However it also has the drawbacks of:
1425
+ * - increased indexing latency that must wait for the slowest indexed chain to
1426
+ * add new blocks or to discover new blocks through the configured RPCs.
1427
+ * - if any indexed chain gets "stuck" due to chain or RPC failures, all indexed chains
1428
+ * will be affected.
1429
+ */
1430
+ Omnichain: "omnichain"
1431
+ };
1432
+
1433
+ // src/shared/block-ref.ts
1434
+ function isBefore(blockA, blockB) {
1435
+ return blockA.number < blockB.number && blockA.timestamp < blockB.timestamp;
1436
+ }
1437
+ function isEqualTo(blockA, blockB) {
1438
+ return blockA.number === blockB.number && blockA.timestamp === blockB.timestamp;
1439
+ }
1440
+ function isBeforeOrEqualTo(blockA, blockB) {
1441
+ return isBefore(blockA, blockB) || isEqualTo(blockA, blockB);
1442
+ }
1443
+
1444
+ // src/ensindexer/indexing-status/helpers.ts
1445
+ function getOmnichainIndexingStatus(chains) {
1013
1446
  if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing(chains)) {
1014
1447
  return OmnichainIndexingStatusIds.Following;
1015
1448
  }
@@ -1109,6 +1542,16 @@ function sortChainStatusesByStartBlockAsc(chains) {
1109
1542
  );
1110
1543
  return chains;
1111
1544
  }
1545
+ function getLatestIndexedBlockRef(indexingStatus, chainId) {
1546
+ const chainIndexingStatus = indexingStatus.omnichainSnapshot.chains.get(chainId);
1547
+ if (chainIndexingStatus === void 0) {
1548
+ return null;
1549
+ }
1550
+ if (chainIndexingStatus.chainStatus === ChainIndexingStatusIds.Queued) {
1551
+ return null;
1552
+ }
1553
+ return chainIndexingStatus.latestIndexedBlock;
1554
+ }
1112
1555
 
1113
1556
  // src/ensindexer/indexing-status/validations.ts
1114
1557
  function invariant_chainSnapshotQueuedBlocks(ctx) {
@@ -1355,52 +1798,52 @@ function invariant_realtimeIndexingStatusProjectionWorstCaseDistanceIsCorrect(ct
1355
1798
  }
1356
1799
 
1357
1800
  // src/ensindexer/indexing-status/zod-schemas.ts
1358
- var makeChainIndexingConfigSchema = (valueLabel = "Value") => import_v43.default.discriminatedUnion("configType", [
1359
- import_v43.default.strictObject({
1360
- configType: import_v43.default.literal(ChainIndexingConfigTypeIds.Indefinite),
1801
+ var makeChainIndexingConfigSchema = (valueLabel = "Value") => import_v47.default.discriminatedUnion("configType", [
1802
+ import_v47.default.strictObject({
1803
+ configType: import_v47.default.literal(ChainIndexingConfigTypeIds.Indefinite),
1361
1804
  startBlock: makeBlockRefSchema(valueLabel)
1362
1805
  }),
1363
- import_v43.default.strictObject({
1364
- configType: import_v43.default.literal(ChainIndexingConfigTypeIds.Definite),
1806
+ import_v47.default.strictObject({
1807
+ configType: import_v47.default.literal(ChainIndexingConfigTypeIds.Definite),
1365
1808
  startBlock: makeBlockRefSchema(valueLabel),
1366
1809
  endBlock: makeBlockRefSchema(valueLabel)
1367
1810
  })
1368
1811
  ]);
1369
- var makeChainIndexingStatusSnapshotQueuedSchema = (valueLabel = "Value") => import_v43.default.strictObject({
1370
- chainStatus: import_v43.default.literal(ChainIndexingStatusIds.Queued),
1812
+ var makeChainIndexingStatusSnapshotQueuedSchema = (valueLabel = "Value") => import_v47.default.strictObject({
1813
+ chainStatus: import_v47.default.literal(ChainIndexingStatusIds.Queued),
1371
1814
  config: makeChainIndexingConfigSchema(valueLabel)
1372
1815
  }).check(invariant_chainSnapshotQueuedBlocks);
1373
- var makeChainIndexingStatusSnapshotBackfillSchema = (valueLabel = "Value") => import_v43.default.strictObject({
1374
- chainStatus: import_v43.default.literal(ChainIndexingStatusIds.Backfill),
1816
+ var makeChainIndexingStatusSnapshotBackfillSchema = (valueLabel = "Value") => import_v47.default.strictObject({
1817
+ chainStatus: import_v47.default.literal(ChainIndexingStatusIds.Backfill),
1375
1818
  config: makeChainIndexingConfigSchema(valueLabel),
1376
1819
  latestIndexedBlock: makeBlockRefSchema(valueLabel),
1377
1820
  backfillEndBlock: makeBlockRefSchema(valueLabel)
1378
1821
  }).check(invariant_chainSnapshotBackfillBlocks);
1379
- var makeChainIndexingStatusSnapshotCompletedSchema = (valueLabel = "Value") => import_v43.default.strictObject({
1380
- chainStatus: import_v43.default.literal(ChainIndexingStatusIds.Completed),
1381
- config: import_v43.default.strictObject({
1382
- configType: import_v43.default.literal(ChainIndexingConfigTypeIds.Definite),
1822
+ var makeChainIndexingStatusSnapshotCompletedSchema = (valueLabel = "Value") => import_v47.default.strictObject({
1823
+ chainStatus: import_v47.default.literal(ChainIndexingStatusIds.Completed),
1824
+ config: import_v47.default.strictObject({
1825
+ configType: import_v47.default.literal(ChainIndexingConfigTypeIds.Definite),
1383
1826
  startBlock: makeBlockRefSchema(valueLabel),
1384
1827
  endBlock: makeBlockRefSchema(valueLabel)
1385
1828
  }),
1386
1829
  latestIndexedBlock: makeBlockRefSchema(valueLabel)
1387
1830
  }).check(invariant_chainSnapshotCompletedBlocks);
1388
- var makeChainIndexingStatusSnapshotFollowingSchema = (valueLabel = "Value") => import_v43.default.strictObject({
1389
- chainStatus: import_v43.default.literal(ChainIndexingStatusIds.Following),
1390
- config: import_v43.default.strictObject({
1391
- configType: import_v43.default.literal(ChainIndexingConfigTypeIds.Indefinite),
1831
+ var makeChainIndexingStatusSnapshotFollowingSchema = (valueLabel = "Value") => import_v47.default.strictObject({
1832
+ chainStatus: import_v47.default.literal(ChainIndexingStatusIds.Following),
1833
+ config: import_v47.default.strictObject({
1834
+ configType: import_v47.default.literal(ChainIndexingConfigTypeIds.Indefinite),
1392
1835
  startBlock: makeBlockRefSchema(valueLabel)
1393
1836
  }),
1394
1837
  latestIndexedBlock: makeBlockRefSchema(valueLabel),
1395
1838
  latestKnownBlock: makeBlockRefSchema(valueLabel)
1396
1839
  }).check(invariant_chainSnapshotFollowingBlocks);
1397
- var makeChainIndexingStatusSnapshotSchema = (valueLabel = "Value") => import_v43.default.discriminatedUnion("chainStatus", [
1840
+ var makeChainIndexingStatusSnapshotSchema = (valueLabel = "Value") => import_v47.default.discriminatedUnion("chainStatus", [
1398
1841
  makeChainIndexingStatusSnapshotQueuedSchema(valueLabel),
1399
1842
  makeChainIndexingStatusSnapshotBackfillSchema(valueLabel),
1400
1843
  makeChainIndexingStatusSnapshotCompletedSchema(valueLabel),
1401
1844
  makeChainIndexingStatusSnapshotFollowingSchema(valueLabel)
1402
1845
  ]);
1403
- var makeChainIndexingStatusesSchema = (valueLabel = "Value") => import_v43.default.record(makeChainIdStringSchema(), makeChainIndexingStatusSnapshotSchema(valueLabel), {
1846
+ var makeChainIndexingStatusesSchema = (valueLabel = "Value") => import_v47.default.record(makeChainIdStringSchema(), makeChainIndexingStatusSnapshotSchema(valueLabel), {
1404
1847
  error: "Chains indexing statuses must be an object mapping valid chain IDs to their indexing status snapshots."
1405
1848
  }).transform((serializedChainsIndexingStatus) => {
1406
1849
  const chainsIndexingStatus = /* @__PURE__ */ new Map();
@@ -1409,29 +1852,29 @@ var makeChainIndexingStatusesSchema = (valueLabel = "Value") => import_v43.defau
1409
1852
  }
1410
1853
  return chainsIndexingStatus;
1411
1854
  });
1412
- var makeOmnichainIndexingStatusSnapshotUnstartedSchema = (valueLabel) => import_v43.default.strictObject({
1413
- omnichainStatus: import_v43.default.literal(OmnichainIndexingStatusIds.Unstarted),
1855
+ var makeOmnichainIndexingStatusSnapshotUnstartedSchema = (valueLabel) => import_v47.default.strictObject({
1856
+ omnichainStatus: import_v47.default.literal(OmnichainIndexingStatusIds.Unstarted),
1414
1857
  chains: makeChainIndexingStatusesSchema(valueLabel).check(invariant_omnichainSnapshotUnstartedHasValidChains).transform((chains) => chains),
1415
1858
  omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
1416
1859
  });
1417
- var makeOmnichainIndexingStatusSnapshotBackfillSchema = (valueLabel) => import_v43.default.strictObject({
1418
- omnichainStatus: import_v43.default.literal(OmnichainIndexingStatusIds.Backfill),
1860
+ var makeOmnichainIndexingStatusSnapshotBackfillSchema = (valueLabel) => import_v47.default.strictObject({
1861
+ omnichainStatus: import_v47.default.literal(OmnichainIndexingStatusIds.Backfill),
1419
1862
  chains: makeChainIndexingStatusesSchema(valueLabel).check(invariant_omnichainStatusSnapshotBackfillHasValidChains).transform(
1420
1863
  (chains) => chains
1421
1864
  ),
1422
1865
  omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
1423
1866
  });
1424
- var makeOmnichainIndexingStatusSnapshotCompletedSchema = (valueLabel) => import_v43.default.strictObject({
1425
- omnichainStatus: import_v43.default.literal(OmnichainIndexingStatusIds.Completed),
1867
+ var makeOmnichainIndexingStatusSnapshotCompletedSchema = (valueLabel) => import_v47.default.strictObject({
1868
+ omnichainStatus: import_v47.default.literal(OmnichainIndexingStatusIds.Completed),
1426
1869
  chains: makeChainIndexingStatusesSchema(valueLabel).check(invariant_omnichainStatusSnapshotCompletedHasValidChains).transform((chains) => chains),
1427
1870
  omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
1428
1871
  });
1429
- var makeOmnichainIndexingStatusSnapshotFollowingSchema = (valueLabel) => import_v43.default.strictObject({
1430
- omnichainStatus: import_v43.default.literal(OmnichainIndexingStatusIds.Following),
1872
+ var makeOmnichainIndexingStatusSnapshotFollowingSchema = (valueLabel) => import_v47.default.strictObject({
1873
+ omnichainStatus: import_v47.default.literal(OmnichainIndexingStatusIds.Following),
1431
1874
  chains: makeChainIndexingStatusesSchema(valueLabel),
1432
1875
  omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
1433
1876
  });
1434
- var makeOmnichainIndexingStatusSnapshotSchema = (valueLabel = "Omnichain Indexing Snapshot") => import_v43.default.discriminatedUnion("omnichainStatus", [
1877
+ var makeOmnichainIndexingStatusSnapshotSchema = (valueLabel = "Omnichain Indexing Snapshot") => import_v47.default.discriminatedUnion("omnichainStatus", [
1435
1878
  makeOmnichainIndexingStatusSnapshotUnstartedSchema(valueLabel),
1436
1879
  makeOmnichainIndexingStatusSnapshotBackfillSchema(valueLabel),
1437
1880
  makeOmnichainIndexingStatusSnapshotCompletedSchema(valueLabel),
@@ -1439,242 +1882,278 @@ var makeOmnichainIndexingStatusSnapshotSchema = (valueLabel = "Omnichain Indexin
1439
1882
  ]).check(invariant_omnichainSnapshotStatusIsConsistentWithChainSnapshot).check(invariant_omnichainIndexingCursorLowerThanEarliestStartBlockAcrossQueuedChains).check(
1440
1883
  invariant_omnichainIndexingCursorLowerThanOrEqualToLatestBackfillEndBlockAcrossBackfillChains
1441
1884
  ).check(invariant_omnichainIndexingCursorIsEqualToHighestLatestIndexedBlockAcrossIndexedChain);
1442
- var makeCrossChainIndexingStatusSnapshotOmnichainSchema = (valueLabel = "Cross-chain Indexing Status Snapshot Omnichain") => import_v43.default.strictObject({
1443
- strategy: import_v43.default.literal(CrossChainIndexingStrategyIds.Omnichain),
1885
+ var makeCrossChainIndexingStatusSnapshotOmnichainSchema = (valueLabel = "Cross-chain Indexing Status Snapshot Omnichain") => import_v47.default.strictObject({
1886
+ strategy: import_v47.default.literal(CrossChainIndexingStrategyIds.Omnichain),
1444
1887
  slowestChainIndexingCursor: makeUnixTimestampSchema(valueLabel),
1445
1888
  snapshotTime: makeUnixTimestampSchema(valueLabel),
1446
1889
  omnichainSnapshot: makeOmnichainIndexingStatusSnapshotSchema(valueLabel)
1447
1890
  }).check(invariant_slowestChainEqualsToOmnichainSnapshotTime).check(invariant_snapshotTimeIsTheHighestKnownBlockTimestamp);
1448
- var makeCrossChainIndexingStatusSnapshotSchema = (valueLabel = "Cross-chain Indexing Status Snapshot") => import_v43.default.discriminatedUnion("strategy", [
1891
+ var makeCrossChainIndexingStatusSnapshotSchema = (valueLabel = "Cross-chain Indexing Status Snapshot") => import_v47.default.discriminatedUnion("strategy", [
1449
1892
  makeCrossChainIndexingStatusSnapshotOmnichainSchema(valueLabel)
1450
1893
  ]);
1451
- var makeRealtimeIndexingStatusProjectionSchema = (valueLabel = "Realtime Indexing Status Projection") => import_v43.default.strictObject({
1894
+ var makeRealtimeIndexingStatusProjectionSchema = (valueLabel = "Realtime Indexing Status Projection") => import_v47.default.strictObject({
1452
1895
  projectedAt: makeUnixTimestampSchema(valueLabel),
1453
1896
  worstCaseDistance: makeDurationSchema(valueLabel),
1454
1897
  snapshot: makeCrossChainIndexingStatusSnapshotSchema(valueLabel)
1455
1898
  }).check(invariant_realtimeIndexingStatusProjectionProjectedAtIsAfterOrEqualToSnapshotTime).check(invariant_realtimeIndexingStatusProjectionWorstCaseDistanceIsCorrect);
1456
1899
 
1457
- // src/ensindexer/config/zod-schemas.ts
1458
- var import_v44 = __toESM(require("zod/v4"), 1);
1459
-
1460
- // src/ensindexer/config/is-subgraph-compatible.ts
1461
- var import_datasources3 = require("@ensnode/datasources");
1462
-
1463
- // src/ensindexer/config/types.ts
1464
- var PluginName = /* @__PURE__ */ ((PluginName2) => {
1465
- PluginName2["Subgraph"] = "subgraph";
1466
- PluginName2["Basenames"] = "basenames";
1467
- PluginName2["Lineanames"] = "lineanames";
1468
- PluginName2["ThreeDNS"] = "threedns";
1469
- PluginName2["ProtocolAcceleration"] = "protocol-acceleration";
1470
- PluginName2["Registrars"] = "registrars";
1471
- PluginName2["TokenScope"] = "tokenscope";
1472
- return PluginName2;
1473
- })(PluginName || {});
1474
-
1475
- // src/ensindexer/config/is-subgraph-compatible.ts
1476
- function isSubgraphCompatible(config) {
1477
- const onlySubgraphPluginActivated = config.plugins.length === 1 && config.plugins[0] === "subgraph" /* Subgraph */;
1478
- const isSubgraphLabelSet = config.labelSet.labelSetId === "subgraph" && config.labelSet.labelSetVersion === 0;
1479
- const isEnsTestEnvLabelSet = config.labelSet.labelSetId === "ens-test-env" && config.labelSet.labelSetVersion === 0;
1480
- const labelSetIsSubgraphCompatible = isSubgraphLabelSet || config.namespace === import_datasources3.ENSNamespaceIds.EnsTestEnv && isEnsTestEnvLabelSet;
1481
- return onlySubgraphPluginActivated && labelSetIsSubgraphCompatible;
1900
+ // src/ensindexer/indexing-status/deserialize.ts
1901
+ function deserializeChainIndexingStatusSnapshot(maybeSnapshot, valueLabel) {
1902
+ const schema = makeChainIndexingStatusSnapshotSchema(valueLabel);
1903
+ const parsed = schema.safeParse(maybeSnapshot);
1904
+ if (parsed.error) {
1905
+ throw new Error(
1906
+ `Cannot deserialize into ChainIndexingStatusSnapshot:
1907
+ ${(0, import_v48.prettifyError)(parsed.error)}
1908
+ `
1909
+ );
1910
+ }
1911
+ return parsed.data;
1482
1912
  }
1483
-
1484
- // src/ensindexer/config/validations.ts
1485
- function invariant_ensDbVersionIsSameAsEnsIndexerVersion(ctx) {
1486
- const versionInfo = ctx.value;
1487
- if (versionInfo.ensDb !== versionInfo.ensIndexer) {
1488
- ctx.issues.push({
1489
- code: "custom",
1490
- input: versionInfo,
1491
- message: "`ensDb` version must be same as `ensIndexer` version"
1492
- });
1913
+ function deserializeOmnichainIndexingStatusSnapshot(maybeSnapshot, valueLabel) {
1914
+ const schema = makeOmnichainIndexingStatusSnapshotSchema(valueLabel);
1915
+ const parsed = schema.safeParse(maybeSnapshot);
1916
+ if (parsed.error) {
1917
+ throw new Error(
1918
+ `Cannot deserialize into OmnichainIndexingStatusSnapshot:
1919
+ ${(0, import_v48.prettifyError)(parsed.error)}
1920
+ `
1921
+ );
1493
1922
  }
1923
+ return parsed.data;
1494
1924
  }
1495
-
1496
- // src/ensindexer/config/zod-schemas.ts
1497
- var makeIndexedChainIdsSchema = (valueLabel = "Indexed Chain IDs") => import_v44.default.array(makeChainIdSchema(valueLabel), {
1498
- error: `${valueLabel} must be an array.`
1499
- }).min(1, { error: `${valueLabel} list must include at least one element.` }).transform((v) => new Set(v));
1500
- var makePluginsListSchema = (valueLabel = "Plugins") => import_v44.default.array(import_v44.default.string(), {
1501
- error: `${valueLabel} must be a list of strings.`
1502
- }).min(1, {
1503
- error: `${valueLabel} must be a list of strings with at least one string value`
1504
- }).refine((arr) => arr.length === uniq(arr).length, {
1505
- error: `${valueLabel} cannot contain duplicate values.`
1506
- });
1507
- var makeDatabaseSchemaNameSchema = (valueLabel = "Database schema name") => import_v44.default.string({ error: `${valueLabel} must be a string` }).trim().nonempty({
1508
- error: `${valueLabel} is required and must be a non-empty string.`
1509
- });
1510
- var makeLabelSetIdSchema = (valueLabel) => {
1511
- return import_v44.default.string({ error: `${valueLabel} must be a string` }).min(1, { error: `${valueLabel} must be 1-50 characters long` }).max(50, { error: `${valueLabel} must be 1-50 characters long` }).regex(/^[a-z-]+$/, {
1512
- error: `${valueLabel} can only contain lowercase letters (a-z) and hyphens (-)`
1513
- });
1514
- };
1515
- var makeLabelSetVersionSchema = (valueLabel) => {
1516
- return import_v44.default.coerce.number({ error: `${valueLabel} must be an integer.` }).pipe(makeNonNegativeIntegerSchema(valueLabel));
1517
- };
1518
- var makeFullyPinnedLabelSetSchema = (valueLabel = "Label set") => {
1519
- let valueLabelLabelSetId = valueLabel;
1520
- let valueLabelLabelSetVersion = valueLabel;
1521
- if (valueLabel === "LABEL_SET") {
1522
- valueLabelLabelSetId = "LABEL_SET_ID";
1523
- valueLabelLabelSetVersion = "LABEL_SET_VERSION";
1524
- } else {
1525
- valueLabelLabelSetId = `${valueLabel}.labelSetId`;
1526
- valueLabelLabelSetVersion = `${valueLabel}.labelSetVersion`;
1925
+ function deserializeCrossChainIndexingStatusSnapshot(maybeSnapshot, valueLabel) {
1926
+ const schema = makeCrossChainIndexingStatusSnapshotSchema(valueLabel);
1927
+ const parsed = schema.safeParse(maybeSnapshot);
1928
+ if (parsed.error) {
1929
+ throw new Error(
1930
+ `Cannot deserialize into CrossChainIndexingStatusSnapshot:
1931
+ ${(0, import_v48.prettifyError)(parsed.error)}
1932
+ `
1933
+ );
1527
1934
  }
1528
- return import_v44.default.object({
1529
- labelSetId: makeLabelSetIdSchema(valueLabelLabelSetId),
1530
- labelSetVersion: makeLabelSetVersionSchema(valueLabelLabelSetVersion)
1531
- });
1532
- };
1533
- var makeNonEmptyStringSchema = (valueLabel = "Value") => import_v44.default.string().nonempty({ error: `${valueLabel} must be a non-empty string.` });
1534
- var makeENSIndexerVersionInfoSchema = (valueLabel = "Value") => import_v44.default.strictObject(
1535
- {
1536
- nodejs: makeNonEmptyStringSchema(),
1537
- ponder: makeNonEmptyStringSchema(),
1538
- ensDb: makeNonEmptyStringSchema(),
1539
- ensIndexer: makeNonEmptyStringSchema(),
1540
- ensNormalize: makeNonEmptyStringSchema(),
1541
- ensRainbow: makeNonEmptyStringSchema(),
1542
- ensRainbowSchema: makePositiveIntegerSchema()
1543
- },
1544
- {
1545
- error: `${valueLabel} must be a valid ENSIndexerVersionInfo object.`
1935
+ return parsed.data;
1936
+ }
1937
+ function deserializeRealtimeIndexingStatusProjection(maybeProjection, valueLabel) {
1938
+ const schema = makeRealtimeIndexingStatusProjectionSchema(valueLabel);
1939
+ const parsed = schema.safeParse(maybeProjection);
1940
+ if (parsed.error) {
1941
+ throw new Error(
1942
+ `Cannot deserialize into RealtimeIndexingStatusProjection:
1943
+ ${(0, import_v48.prettifyError)(parsed.error)}
1944
+ `
1945
+ );
1546
1946
  }
1547
- ).check(invariant_ensDbVersionIsSameAsEnsIndexerVersion);
1548
- function invariant_isSubgraphCompatibleRequirements(ctx) {
1549
- const { value: config } = ctx;
1550
- if (config.isSubgraphCompatible && !isSubgraphCompatible(config)) {
1551
- ctx.issues.push({
1552
- code: "custom",
1553
- input: config,
1554
- message: `'isSubgraphCompatible' requires only the '${"subgraph" /* Subgraph */}' plugin to be active and labelSet must be {labelSetId: "subgraph", labelSetVersion: 0}`
1555
- });
1947
+ return parsed.data;
1948
+ }
1949
+
1950
+ // src/ensindexer/indexing-status/projection.ts
1951
+ function createRealtimeIndexingStatusProjection(snapshot, now) {
1952
+ const projectedAt = Math.max(now, snapshot.snapshotTime);
1953
+ return {
1954
+ projectedAt,
1955
+ worstCaseDistance: projectedAt - snapshot.slowestChainIndexingCursor,
1956
+ snapshot
1957
+ };
1958
+ }
1959
+
1960
+ // src/ensindexer/indexing-status/serialize.ts
1961
+ function serializeCrossChainIndexingStatusSnapshotOmnichain({
1962
+ strategy,
1963
+ slowestChainIndexingCursor,
1964
+ snapshotTime,
1965
+ omnichainSnapshot
1966
+ }) {
1967
+ return {
1968
+ strategy,
1969
+ slowestChainIndexingCursor,
1970
+ snapshotTime,
1971
+ omnichainSnapshot: serializeOmnichainIndexingStatusSnapshot(omnichainSnapshot)
1972
+ };
1973
+ }
1974
+ function serializeRealtimeIndexingStatusProjection(indexingProjection) {
1975
+ return {
1976
+ projectedAt: indexingProjection.projectedAt,
1977
+ worstCaseDistance: indexingProjection.worstCaseDistance,
1978
+ snapshot: serializeCrossChainIndexingStatusSnapshotOmnichain(indexingProjection.snapshot)
1979
+ };
1980
+ }
1981
+ function serializeChainIndexingSnapshots(chains) {
1982
+ const serializedSnapshots = {};
1983
+ for (const [chainId, snapshot] of chains.entries()) {
1984
+ serializedSnapshots[serializeChainId(chainId)] = snapshot;
1985
+ }
1986
+ return serializedSnapshots;
1987
+ }
1988
+ function serializeOmnichainIndexingStatusSnapshot(indexingStatus) {
1989
+ switch (indexingStatus.omnichainStatus) {
1990
+ case OmnichainIndexingStatusIds.Unstarted:
1991
+ return {
1992
+ omnichainStatus: OmnichainIndexingStatusIds.Unstarted,
1993
+ chains: serializeChainIndexingSnapshots(indexingStatus.chains),
1994
+ omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
1995
+ };
1996
+ case OmnichainIndexingStatusIds.Backfill:
1997
+ return {
1998
+ omnichainStatus: OmnichainIndexingStatusIds.Backfill,
1999
+ chains: serializeChainIndexingSnapshots(indexingStatus.chains),
2000
+ omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
2001
+ };
2002
+ case OmnichainIndexingStatusIds.Completed: {
2003
+ return {
2004
+ omnichainStatus: OmnichainIndexingStatusIds.Completed,
2005
+ chains: serializeChainIndexingSnapshots(indexingStatus.chains),
2006
+ omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
2007
+ };
2008
+ }
2009
+ case OmnichainIndexingStatusIds.Following:
2010
+ return {
2011
+ omnichainStatus: OmnichainIndexingStatusIds.Following,
2012
+ chains: serializeChainIndexingSnapshots(indexingStatus.chains),
2013
+ omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
2014
+ };
1556
2015
  }
1557
2016
  }
1558
- var makeENSIndexerPublicConfigSchema = (valueLabel = "ENSIndexerPublicConfig") => import_v44.default.object({
1559
- labelSet: makeFullyPinnedLabelSetSchema(`${valueLabel}.labelSet`),
1560
- indexedChainIds: makeIndexedChainIdsSchema(`${valueLabel}.indexedChainIds`),
1561
- isSubgraphCompatible: import_v44.default.boolean({ error: `${valueLabel}.isSubgraphCompatible` }),
1562
- namespace: makeENSNamespaceIdSchema(`${valueLabel}.namespace`),
1563
- plugins: makePluginsListSchema(`${valueLabel}.plugins`),
1564
- databaseSchemaName: makeDatabaseSchemaNameSchema(`${valueLabel}.databaseSchemaName`),
1565
- versionInfo: makeENSIndexerVersionInfoSchema(`${valueLabel}.versionInfo`)
1566
- }).check(invariant_isSubgraphCompatibleRequirements);
1567
2017
 
1568
- // src/shared/config/build-rpc-urls.ts
1569
- var import_chains = require("viem/chains");
2018
+ // src/ensapi/config/serialize.ts
2019
+ function serializeENSApiPublicConfig(config) {
2020
+ const { version, theGraphFallback, ensIndexerPublicConfig } = config;
2021
+ return {
2022
+ version,
2023
+ theGraphFallback,
2024
+ ensIndexerPublicConfig: serializeENSIndexerPublicConfig(ensIndexerPublicConfig)
2025
+ };
2026
+ }
1570
2027
 
1571
- // src/shared/config/rpc-configs-from-env.ts
1572
- var import_datasources4 = require("@ensnode/datasources");
2028
+ // src/api/config/deserialize.ts
2029
+ function deserializeConfigResponse(serializedResponse) {
2030
+ return deserializeENSApiPublicConfig(serializedResponse);
2031
+ }
1573
2032
 
1574
- // src/shared/config/validatons.ts
1575
- var import_datasources5 = require("@ensnode/datasources");
1576
- function invariant_rpcEndpointConfigIncludesAtLeastOneHTTPProtocolURL(ctx) {
1577
- const endpoints = ctx.value;
1578
- const httpEndpoints = endpoints.filter(isHttpProtocol);
1579
- if (httpEndpoints.length < 1) {
1580
- ctx.issues.push({
1581
- code: "custom",
1582
- input: endpoints,
1583
- message: `RPC endpoint configuration for a chain must include at least one http/https protocol URL.`
1584
- });
1585
- }
2033
+ // src/api/config/serialize.ts
2034
+ function serializeConfigResponse(response) {
2035
+ return serializeENSApiPublicConfig(response);
1586
2036
  }
1587
- function invariant_rpcEndpointConfigIncludesAtMostOneWebSocketsProtocolURL(ctx) {
1588
- const endpoints = ctx.value;
1589
- const wsEndpoints = endpoints.filter(isWebSocketProtocol);
1590
- if (wsEndpoints.length > 1) {
2037
+
2038
+ // src/api/indexing-status/deserialize.ts
2039
+ var import_v416 = require("zod/v4");
2040
+
2041
+ // src/api/indexing-status/zod-schemas.ts
2042
+ var import_v415 = __toESM(require("zod/v4"), 1);
2043
+
2044
+ // src/api/registrar-actions/zod-schemas.ts
2045
+ var import_ens5 = require("viem/ens");
2046
+ var import_v410 = __toESM(require("zod/v4"), 1);
2047
+
2048
+ // src/api/shared/errors/zod-schemas.ts
2049
+ var import_v49 = __toESM(require("zod/v4"), 1);
2050
+ var ErrorResponseSchema = import_v49.default.object({
2051
+ message: import_v49.default.string(),
2052
+ details: import_v49.default.optional(import_v49.default.unknown())
2053
+ });
2054
+
2055
+ // src/api/registrar-actions/response.ts
2056
+ var RegistrarActionsResponseCodes = {
2057
+ /**
2058
+ * Represents that Registrar Actions are available.
2059
+ */
2060
+ Ok: "ok",
2061
+ /**
2062
+ * Represents that Registrar Actions are unavailable.
2063
+ */
2064
+ Error: "error"
2065
+ };
2066
+
2067
+ // src/api/registrar-actions/zod-schemas.ts
2068
+ function invariant_registrationLifecycleNodeMatchesName(ctx) {
2069
+ const { name, action } = ctx.value;
2070
+ const expectedNode = action.registrationLifecycle.node;
2071
+ const actualNode = (0, import_ens5.namehash)(name);
2072
+ if (actualNode !== expectedNode) {
1591
2073
  ctx.issues.push({
1592
2074
  code: "custom",
1593
- input: endpoints,
1594
- message: `RPC endpoint configuration for a chain must include at most one websocket (ws/wss) protocol URL.`
2075
+ input: ctx.value,
2076
+ message: `The 'action.registrationLifecycle.node' must match namehash of 'name'`
1595
2077
  });
1596
2078
  }
1597
2079
  }
1598
-
1599
- // src/shared/config/zod-schemas.ts
1600
- var import_v45 = require("zod/v4");
1601
- var import_datasources6 = require("@ensnode/datasources");
1602
- var DatabaseSchemaNameSchema = import_v45.z.string({
1603
- error: "DATABASE_SCHEMA is required."
1604
- }).trim().min(1, {
1605
- error: "DATABASE_SCHEMA is required and cannot be an empty string."
1606
- });
1607
- var RpcConfigSchema = import_v45.z.string().transform((val) => val.split(",")).pipe(import_v45.z.array(makeUrlSchema("RPC URL"))).check(invariant_rpcEndpointConfigIncludesAtLeastOneHTTPProtocolURL).check(invariant_rpcEndpointConfigIncludesAtMostOneWebSocketsProtocolURL);
1608
- var RpcConfigsSchema = import_v45.z.record(makeChainIdStringSchema("RPC URL"), RpcConfigSchema, {
1609
- error: "Chains configuration must be an object mapping valid chain IDs to their configs."
1610
- }).transform((records) => {
1611
- const rpcConfigs = /* @__PURE__ */ new Map();
1612
- for (const [chainIdString, rpcConfig] of Object.entries(records)) {
1613
- const httpRPCs = rpcConfig.filter(isHttpProtocol);
1614
- const websocketRPC = rpcConfig.find(isWebSocketProtocol);
1615
- rpcConfigs.set(deserializeChainId(chainIdString), {
1616
- httpRPCs,
1617
- websocketRPC
1618
- });
1619
- }
1620
- return rpcConfigs;
2080
+ var makeNamedRegistrarActionSchema = (valueLabel = "Named Registrar Action") => import_v410.default.object({
2081
+ action: makeRegistrarActionSchema(valueLabel),
2082
+ name: makeReinterpretedNameSchema(valueLabel)
2083
+ }).check(invariant_registrationLifecycleNodeMatchesName);
2084
+ var makeRegistrarActionsResponseOkSchema = (valueLabel = "Registrar Actions Response OK") => import_v410.default.strictObject({
2085
+ responseCode: import_v410.default.literal(RegistrarActionsResponseCodes.Ok),
2086
+ registrarActions: import_v410.default.array(makeNamedRegistrarActionSchema(valueLabel))
1621
2087
  });
1622
- var EnsIndexerUrlSchema = makeUrlSchema("ENSINDEXER_URL");
1623
- var ENSNamespaceSchema = import_v45.z.enum(import_datasources6.ENSNamespaceIds, {
1624
- error: ({ input }) => `Invalid NAMESPACE. Got '${input}', but supported ENS namespaces are: ${Object.keys(import_datasources6.ENSNamespaceIds).join(", ")}`
2088
+ var makeRegistrarActionsResponseErrorSchema = (_valueLabel = "Registrar Actions Response Error") => import_v410.default.strictObject({
2089
+ responseCode: import_v410.default.literal(RegistrarActionsResponseCodes.Error),
2090
+ error: ErrorResponseSchema
1625
2091
  });
1626
- var PortSchema = import_v45.z.coerce.number({ error: "PORT must be a number." }).min(1, { error: "PORT must be greater than 1." }).max(65535, { error: "PORT must be less than 65535" }).optional();
1627
- var TheGraphApiKeySchema = import_v45.z.string().optional();
1628
-
1629
- // src/shared/datasources-with-resolvers.ts
1630
- var import_datasources7 = require("@ensnode/datasources");
1631
- var DATASOURCE_NAMES_WITH_RESOLVERS = [
1632
- import_datasources7.DatasourceNames.ENSRoot,
1633
- import_datasources7.DatasourceNames.Basenames,
1634
- import_datasources7.DatasourceNames.Lineanames,
1635
- import_datasources7.DatasourceNames.ThreeDNSOptimism,
1636
- import_datasources7.DatasourceNames.ThreeDNSBase
1637
- ];
2092
+ var makeRegistrarActionsResponseSchema = (valueLabel = "Registrar Actions Response") => import_v410.default.discriminatedUnion("responseCode", [
2093
+ makeRegistrarActionsResponseOkSchema(valueLabel),
2094
+ makeRegistrarActionsResponseErrorSchema(valueLabel)
2095
+ ]);
1638
2096
 
1639
- // src/shared/log-level.ts
1640
- var import_v46 = require("zod/v4");
1641
- var LogLevelSchema = import_v46.z.enum(["fatal", "error", "warn", "info", "debug", "trace", "silent"]);
2097
+ // src/api/shared/pagination/zod-schemas.ts
2098
+ var import_v411 = __toESM(require("zod/v4"), 1);
1642
2099
 
1643
- // src/shared/protocol-acceleration/interpret-record-values.ts
1644
- var import_viem10 = require("viem");
2100
+ // src/api/shared/pagination/request.ts
2101
+ var RECORDS_PER_PAGE_DEFAULT = 10;
2102
+ var RECORDS_PER_PAGE_MAX = 100;
1645
2103
 
1646
- // ../ens-referrals/src/referrer.ts
2104
+ // ../ens-referrals/src/address.ts
1647
2105
  var import_viem11 = require("viem");
2106
+
2107
+ // ../ens-referrals/src/encoding.ts
2108
+ var import_viem12 = require("viem");
1648
2109
  var ENCODED_REFERRER_BYTE_OFFSET = 12;
1649
2110
  var ENCODED_REFERRER_BYTE_LENGTH = 32;
1650
- var encodedReferrerPadding = (0, import_viem11.pad)("0x", {
2111
+ var EXPECTED_ENCODED_REFERRER_PADDING = (0, import_viem12.pad)("0x", {
1651
2112
  size: ENCODED_REFERRER_BYTE_OFFSET,
1652
2113
  dir: "left"
1653
2114
  });
1654
- var zeroEncodedReferrer = (0, import_viem11.pad)("0x", {
2115
+ var ZERO_ENCODED_REFERRER = (0, import_viem12.pad)("0x", {
1655
2116
  size: ENCODED_REFERRER_BYTE_LENGTH,
1656
2117
  dir: "left"
1657
2118
  });
1658
2119
  function decodeEncodedReferrer(encodedReferrer) {
1659
- if ((0, import_viem11.size)(encodedReferrer) !== ENCODED_REFERRER_BYTE_LENGTH) {
2120
+ if ((0, import_viem12.size)(encodedReferrer) !== ENCODED_REFERRER_BYTE_LENGTH) {
1660
2121
  throw new Error(
1661
2122
  `Encoded referrer value must be represented by ${ENCODED_REFERRER_BYTE_LENGTH} bytes.`
1662
2123
  );
1663
2124
  }
1664
- const padding = (0, import_viem11.slice)(encodedReferrer, 0, ENCODED_REFERRER_BYTE_OFFSET);
1665
- if (padding !== encodedReferrerPadding) {
1666
- return import_viem11.zeroAddress;
2125
+ const padding = (0, import_viem12.slice)(encodedReferrer, 0, ENCODED_REFERRER_BYTE_OFFSET);
2126
+ if (padding !== EXPECTED_ENCODED_REFERRER_PADDING) {
2127
+ return import_viem12.zeroAddress;
1667
2128
  }
1668
- const decodedReferrer = (0, import_viem11.slice)(encodedReferrer, ENCODED_REFERRER_BYTE_OFFSET);
2129
+ const decodedReferrer = (0, import_viem12.slice)(encodedReferrer, ENCODED_REFERRER_BYTE_OFFSET);
1669
2130
  try {
1670
- return (0, import_viem11.getAddress)(decodedReferrer);
2131
+ return (0, import_viem12.getAddress)(decodedReferrer);
1671
2132
  } catch {
1672
2133
  throw new Error(`Decoded referrer value must be a valid EVM address.`);
1673
2134
  }
1674
2135
  }
1675
2136
 
2137
+ // ../ens-referrals/src/leaderboard-page.ts
2138
+ var REFERRERS_PER_LEADERBOARD_PAGE_MAX = 100;
2139
+
2140
+ // ../ens-referrals/src/link.ts
2141
+ var import_viem13 = require("viem");
2142
+
2143
+ // ../ens-referrals/src/referrer-detail.ts
2144
+ var ReferrerDetailTypeIds = {
2145
+ /**
2146
+ * Represents a referrer who is ranked on the leaderboard.
2147
+ */
2148
+ Ranked: "ranked",
2149
+ /**
2150
+ * Represents a referrer who is not ranked on the leaderboard.
2151
+ */
2152
+ Unranked: "unranked"
2153
+ };
2154
+
1676
2155
  // src/registrars/zod-schemas.ts
1677
- var import_v47 = __toESM(require("zod/v4"), 1);
2156
+ var import_v412 = __toESM(require("zod/v4"), 1);
1678
2157
 
1679
2158
  // src/registrars/subregistry.ts
1680
2159
  function serializeSubregistry(subregistry) {
@@ -1732,11 +2211,11 @@ function serializeRegistrarAction(registrarAction) {
1732
2211
  }
1733
2212
 
1734
2213
  // src/registrars/zod-schemas.ts
1735
- var makeSubregistrySchema = (valueLabel = "Subregistry") => import_v47.default.object({
2214
+ var makeSubregistrySchema = (valueLabel = "Subregistry") => import_v412.default.object({
1736
2215
  subregistryId: makeSerializedAccountIdSchema(`${valueLabel} Subregistry ID`),
1737
2216
  node: makeNodeSchema(`${valueLabel} Node`)
1738
2217
  });
1739
- var makeRegistrationLifecycleSchema = (valueLabel = "Registration Lifecycle") => import_v47.default.object({
2218
+ var makeRegistrationLifecycleSchema = (valueLabel = "Registration Lifecycle") => import_v412.default.object({
1740
2219
  subregistry: makeSubregistrySchema(`${valueLabel} Subregistry`),
1741
2220
  node: makeNodeSchema(`${valueLabel} Node`),
1742
2221
  expiresAt: makeUnixTimestampSchema(`${valueLabel} Expires at`)
@@ -1752,18 +2231,18 @@ function invariant_registrarActionPricingTotalIsSumOfBaseCostAndPremium(ctx) {
1752
2231
  });
1753
2232
  }
1754
2233
  }
1755
- var makeRegistrarActionPricingSchema = (valueLabel = "Registrar Action Pricing") => import_v47.default.union([
2234
+ var makeRegistrarActionPricingSchema = (valueLabel = "Registrar Action Pricing") => import_v412.default.union([
1756
2235
  // pricing available
1757
- import_v47.default.object({
2236
+ import_v412.default.object({
1758
2237
  baseCost: makePriceEthSchema(`${valueLabel} Base Cost`),
1759
2238
  premium: makePriceEthSchema(`${valueLabel} Premium`),
1760
2239
  total: makePriceEthSchema(`${valueLabel} Total`)
1761
2240
  }).check(invariant_registrarActionPricingTotalIsSumOfBaseCostAndPremium).transform((v) => v),
1762
2241
  // pricing unknown
1763
- import_v47.default.object({
1764
- baseCost: import_v47.default.null(),
1765
- premium: import_v47.default.null(),
1766
- total: import_v47.default.null()
2242
+ import_v412.default.object({
2243
+ baseCost: import_v412.default.null(),
2244
+ premium: import_v412.default.null(),
2245
+ total: import_v412.default.null()
1767
2246
  }).transform((v) => v)
1768
2247
  ]);
1769
2248
  function invariant_registrarActionDecodedReferrerBasedOnRawReferrer(ctx) {
@@ -1786,9 +2265,9 @@ function invariant_registrarActionDecodedReferrerBasedOnRawReferrer(ctx) {
1786
2265
  });
1787
2266
  }
1788
2267
  }
1789
- var makeRegistrarActionReferralSchema = (valueLabel = "Registrar Action Referral") => import_v47.default.union([
2268
+ var makeRegistrarActionReferralSchema = (valueLabel = "Registrar Action Referral") => import_v412.default.union([
1790
2269
  // referral available
1791
- import_v47.default.object({
2270
+ import_v412.default.object({
1792
2271
  encodedReferrer: makeHexStringSchema(
1793
2272
  { bytesCount: ENCODED_REFERRER_BYTE_LENGTH },
1794
2273
  `${valueLabel} Encoded Referrer`
@@ -1796,9 +2275,9 @@ var makeRegistrarActionReferralSchema = (valueLabel = "Registrar Action Referral
1796
2275
  decodedReferrer: makeLowercaseAddressSchema(`${valueLabel} Decoded Referrer`)
1797
2276
  }).check(invariant_registrarActionDecodedReferrerBasedOnRawReferrer),
1798
2277
  // referral not applicable
1799
- import_v47.default.object({
1800
- encodedReferrer: import_v47.default.null(),
1801
- decodedReferrer: import_v47.default.null()
2278
+ import_v412.default.object({
2279
+ encodedReferrer: import_v412.default.null(),
2280
+ decodedReferrer: import_v412.default.null()
1802
2281
  })
1803
2282
  ]);
1804
2283
  function invariant_eventIdsInitialElementIsTheActionId(ctx) {
@@ -1811,9 +2290,9 @@ function invariant_eventIdsInitialElementIsTheActionId(ctx) {
1811
2290
  });
1812
2291
  }
1813
2292
  }
1814
- var EventIdSchema = import_v47.default.string().nonempty();
1815
- var EventIdsSchema = import_v47.default.array(EventIdSchema).min(1).transform((v) => v);
1816
- var makeBaseRegistrarActionSchema = (valueLabel = "Base Registrar Action") => import_v47.default.object({
2293
+ var EventIdSchema = import_v412.default.string().nonempty();
2294
+ var EventIdsSchema = import_v412.default.array(EventIdSchema).min(1).transform((v) => v);
2295
+ var makeBaseRegistrarActionSchema = (valueLabel = "Base Registrar Action") => import_v412.default.object({
1817
2296
  id: EventIdSchema,
1818
2297
  incrementalDuration: makeDurationSchema(`${valueLabel} Incremental Duration`),
1819
2298
  registrant: makeLowercaseAddressSchema(`${valueLabel} Registrant`),
@@ -1827,380 +2306,188 @@ var makeBaseRegistrarActionSchema = (valueLabel = "Base Registrar Action") => im
1827
2306
  eventIds: EventIdsSchema
1828
2307
  }).check(invariant_eventIdsInitialElementIsTheActionId);
1829
2308
  var makeRegistrarActionRegistrationSchema = (valueLabel = "Registration ") => makeBaseRegistrarActionSchema(valueLabel).extend({
1830
- type: import_v47.default.literal(RegistrarActionTypes.Registration)
2309
+ type: import_v412.default.literal(RegistrarActionTypes.Registration)
1831
2310
  });
1832
2311
  var makeRegistrarActionRenewalSchema = (valueLabel = "Renewal") => makeBaseRegistrarActionSchema(valueLabel).extend({
1833
- type: import_v47.default.literal(RegistrarActionTypes.Renewal)
2312
+ type: import_v412.default.literal(RegistrarActionTypes.Renewal)
1834
2313
  });
1835
- var makeRegistrarActionSchema = (valueLabel = "Registrar Action") => import_v47.default.discriminatedUnion("type", [
2314
+ var makeRegistrarActionSchema = (valueLabel = "Registrar Action") => import_v412.default.discriminatedUnion("type", [
1836
2315
  makeRegistrarActionRegistrationSchema(`${valueLabel} Registration`),
1837
2316
  makeRegistrarActionRenewalSchema(`${valueLabel} Renewal`)
1838
2317
  ]);
1839
2318
 
1840
- // src/api/types.ts
1841
- var IndexingStatusResponseCodes = {
1842
- /**
1843
- * Represents that the indexing status is available.
1844
- */
1845
- Ok: "ok",
1846
- /**
1847
- * Represents that the indexing status is unavailable.
1848
- */
1849
- Error: "error"
1850
- };
1851
- var RegistrarActionsFilterTypes = {
1852
- BySubregistryNode: "bySubregistryNode",
1853
- WithEncodedReferral: "withEncodedReferral"
1854
- };
1855
- var RegistrarActionsOrders = {
1856
- LatestRegistrarActions: "orderBy[timestamp]=desc"
1857
- };
1858
- var RegistrarActionsResponseCodes = {
1859
- /**
1860
- * Represents that Registrar Actions are available.
1861
- */
1862
- Ok: "ok",
1863
- /**
1864
- * Represents that Registrar Actions are unavailable.
1865
- */
1866
- Error: "error"
1867
- };
2319
+ // src/shared/config/build-rpc-urls.ts
2320
+ var import_chains = require("viem/chains");
1868
2321
 
1869
- // src/api/zod-schemas.ts
1870
- var ErrorResponseSchema = import_v48.default.object({
1871
- message: import_v48.default.string(),
1872
- details: import_v48.default.optional(import_v48.default.unknown())
1873
- });
1874
- var makeIndexingStatusResponseOkSchema = (valueLabel = "Indexing Status Response OK") => import_v48.default.strictObject({
1875
- responseCode: import_v48.default.literal(IndexingStatusResponseCodes.Ok),
1876
- realtimeProjection: makeRealtimeIndexingStatusProjectionSchema(valueLabel)
1877
- });
1878
- var makeIndexingStatusResponseErrorSchema = (_valueLabel = "Indexing Status Response Error") => import_v48.default.strictObject({
1879
- responseCode: import_v48.default.literal(IndexingStatusResponseCodes.Error)
1880
- });
1881
- var makeIndexingStatusResponseSchema = (valueLabel = "Indexing Status Response") => import_v48.default.discriminatedUnion("responseCode", [
1882
- makeIndexingStatusResponseOkSchema(valueLabel),
1883
- makeIndexingStatusResponseErrorSchema(valueLabel)
1884
- ]);
1885
- function invariant_registrationLifecycleNodeMatchesName(ctx) {
1886
- const { name, action } = ctx.value;
1887
- const expectedNode = action.registrationLifecycle.node;
1888
- const actualNode = (0, import_viem12.namehash)(name);
1889
- if (actualNode !== expectedNode) {
2322
+ // src/shared/config/rpc-configs-from-env.ts
2323
+ var import_datasources4 = require("@ensnode/datasources");
2324
+
2325
+ // src/shared/config/validatons.ts
2326
+ var import_datasources5 = require("@ensnode/datasources");
2327
+ function invariant_rpcEndpointConfigIncludesAtLeastOneHTTPProtocolURL(ctx) {
2328
+ const endpoints = ctx.value;
2329
+ const httpEndpoints = endpoints.filter(isHttpProtocol);
2330
+ if (httpEndpoints.length < 1) {
1890
2331
  ctx.issues.push({
1891
2332
  code: "custom",
1892
- input: ctx.value,
1893
- message: `The 'action.registrationLifecycle.node' must match namehash of 'name'`
2333
+ input: endpoints,
2334
+ message: `RPC endpoint configuration for a chain must include at least one http/https protocol URL.`
1894
2335
  });
1895
2336
  }
1896
2337
  }
1897
- var makeNamedRegistrarActionSchema = (valueLabel = "Named Registrar Action") => import_v48.default.object({
1898
- action: makeRegistrarActionSchema(valueLabel),
1899
- name: makeReinterpretedNameSchema(valueLabel)
1900
- }).check(invariant_registrationLifecycleNodeMatchesName);
1901
- var makeRegistrarActionsResponseOkSchema = (valueLabel = "Registrar Actions Response OK") => import_v48.default.strictObject({
1902
- responseCode: import_v48.default.literal(RegistrarActionsResponseCodes.Ok),
1903
- registrarActions: import_v48.default.array(makeNamedRegistrarActionSchema(valueLabel))
2338
+ function invariant_rpcEndpointConfigIncludesAtMostOneWebSocketsProtocolURL(ctx) {
2339
+ const endpoints = ctx.value;
2340
+ const wsEndpoints = endpoints.filter(isWebSocketProtocol);
2341
+ if (wsEndpoints.length > 1) {
2342
+ ctx.issues.push({
2343
+ code: "custom",
2344
+ input: endpoints,
2345
+ message: `RPC endpoint configuration for a chain must include at most one websocket (ws/wss) protocol URL.`
2346
+ });
2347
+ }
2348
+ }
2349
+
2350
+ // src/shared/config/zod-schemas.ts
2351
+ var import_v413 = require("zod/v4");
2352
+ var import_datasources6 = require("@ensnode/datasources");
2353
+ var DatabaseSchemaNameSchema = import_v413.z.string({
2354
+ error: "DATABASE_SCHEMA is required."
2355
+ }).trim().min(1, {
2356
+ error: "DATABASE_SCHEMA is required and cannot be an empty string."
2357
+ });
2358
+ var RpcConfigSchema = import_v413.z.string().transform((val) => val.split(",")).pipe(import_v413.z.array(makeUrlSchema("RPC URL"))).check(invariant_rpcEndpointConfigIncludesAtLeastOneHTTPProtocolURL).check(invariant_rpcEndpointConfigIncludesAtMostOneWebSocketsProtocolURL);
2359
+ var RpcConfigsSchema = import_v413.z.record(makeChainIdStringSchema("RPC URL"), RpcConfigSchema, {
2360
+ error: "Chains configuration must be an object mapping valid chain IDs to their configs."
2361
+ }).transform((records) => {
2362
+ const rpcConfigs = /* @__PURE__ */ new Map();
2363
+ for (const [chainIdString, rpcConfig] of Object.entries(records)) {
2364
+ const httpRPCs = rpcConfig.filter(isHttpProtocol);
2365
+ const websocketRPC = rpcConfig.find(isWebSocketProtocol);
2366
+ rpcConfigs.set(deserializeChainId(chainIdString), {
2367
+ httpRPCs,
2368
+ websocketRPC
2369
+ });
2370
+ }
2371
+ return rpcConfigs;
2372
+ });
2373
+ var EnsIndexerUrlSchema = makeUrlSchema("ENSINDEXER_URL");
2374
+ var ENSNamespaceSchema = import_v413.z.enum(import_datasources6.ENSNamespaceIds, {
2375
+ error: ({ input }) => `Invalid NAMESPACE. Got '${input}', but supported ENS namespaces are: ${Object.keys(import_datasources6.ENSNamespaceIds).join(", ")}`
2376
+ });
2377
+ var PortSchema = import_v413.z.coerce.number({ error: "PORT must be a number." }).min(1, { error: "PORT must be greater than 1." }).max(65535, { error: "PORT must be less than 65535" }).optional();
2378
+ var TheGraphApiKeySchema = import_v413.z.string().optional();
2379
+
2380
+ // src/shared/datasources-with-resolvers.ts
2381
+ var import_datasources7 = require("@ensnode/datasources");
2382
+ var DATASOURCE_NAMES_WITH_RESOLVERS = [
2383
+ import_datasources7.DatasourceNames.ENSRoot,
2384
+ import_datasources7.DatasourceNames.Basenames,
2385
+ import_datasources7.DatasourceNames.Lineanames,
2386
+ import_datasources7.DatasourceNames.ThreeDNSOptimism,
2387
+ import_datasources7.DatasourceNames.ThreeDNSBase
2388
+ ];
2389
+
2390
+ // src/shared/log-level.ts
2391
+ var import_v414 = require("zod/v4");
2392
+ var LogLevelSchema = import_v414.z.enum(["fatal", "error", "warn", "info", "debug", "trace", "silent"]);
2393
+
2394
+ // src/shared/protocol-acceleration/interpret-record-values.ts
2395
+ var import_viem14 = require("viem");
2396
+
2397
+ // src/api/indexing-status/response.ts
2398
+ var IndexingStatusResponseCodes = {
2399
+ /**
2400
+ * Represents that the indexing status is available.
2401
+ */
2402
+ Ok: "ok",
2403
+ /**
2404
+ * Represents that the indexing status is unavailable.
2405
+ */
2406
+ Error: "error"
2407
+ };
2408
+
2409
+ // src/api/indexing-status/zod-schemas.ts
2410
+ var makeIndexingStatusResponseOkSchema = (valueLabel = "Indexing Status Response OK") => import_v415.default.strictObject({
2411
+ responseCode: import_v415.default.literal(IndexingStatusResponseCodes.Ok),
2412
+ realtimeProjection: makeRealtimeIndexingStatusProjectionSchema(valueLabel)
1904
2413
  });
1905
- var makeRegistrarActionsResponseErrorSchema = (_valueLabel = "Registrar Actions Response Error") => import_v48.default.strictObject({
1906
- responseCode: import_v48.default.literal(RegistrarActionsResponseCodes.Error),
1907
- error: ErrorResponseSchema
2414
+ var makeIndexingStatusResponseErrorSchema = (_valueLabel = "Indexing Status Response Error") => import_v415.default.strictObject({
2415
+ responseCode: import_v415.default.literal(IndexingStatusResponseCodes.Error)
1908
2416
  });
1909
- var makeRegistrarActionsResponseSchema = (valueLabel = "Registrar Actions Response") => import_v48.default.discriminatedUnion("responseCode", [
1910
- makeRegistrarActionsResponseOkSchema(valueLabel),
1911
- makeRegistrarActionsResponseErrorSchema(valueLabel)
2417
+ var makeIndexingStatusResponseSchema = (valueLabel = "Indexing Status Response") => import_v415.default.discriminatedUnion("responseCode", [
2418
+ makeIndexingStatusResponseOkSchema(valueLabel),
2419
+ makeIndexingStatusResponseErrorSchema(valueLabel)
1912
2420
  ]);
1913
2421
 
1914
- // src/api/deserialize.ts
1915
- function deserializeErrorResponse(maybeErrorResponse) {
1916
- const parsed = ErrorResponseSchema.safeParse(maybeErrorResponse);
1917
- if (parsed.error) {
1918
- throw new Error(`Cannot deserialize ErrorResponse:
1919
- ${(0, import_v49.prettifyError)(parsed.error)}
1920
- `);
1921
- }
1922
- return parsed.data;
1923
- }
2422
+ // src/api/indexing-status/deserialize.ts
1924
2423
  function deserializeIndexingStatusResponse(maybeResponse) {
1925
2424
  const parsed = makeIndexingStatusResponseSchema().safeParse(maybeResponse);
1926
2425
  if (parsed.error) {
1927
2426
  throw new Error(`Cannot deserialize IndexingStatusResponse:
1928
- ${(0, import_v49.prettifyError)(parsed.error)}
1929
- `);
1930
- }
1931
- return parsed.data;
1932
- }
1933
- function deserializeRegistrarActionsResponse(maybeResponse) {
1934
- const parsed = makeRegistrarActionsResponseSchema().safeParse(maybeResponse);
1935
- if (parsed.error) {
1936
- throw new Error(
1937
- `Cannot deserialize RegistrarActionsResponse:
1938
- ${(0, import_v49.prettifyError)(parsed.error)}
1939
- `
1940
- );
1941
- }
1942
- return parsed.data;
1943
- }
1944
-
1945
- // src/api/registrar-actions/filters.ts
1946
- function byParentNode(parentNode) {
1947
- if (typeof parentNode === "undefined") {
1948
- return void 0;
1949
- }
1950
- return {
1951
- filterType: RegistrarActionsFilterTypes.BySubregistryNode,
1952
- value: parentNode
1953
- };
1954
- }
1955
- function withReferral(withReferral2) {
1956
- if (!withReferral2) {
1957
- return void 0;
1958
- }
1959
- return {
1960
- filterType: RegistrarActionsFilterTypes.WithEncodedReferral
1961
- };
1962
- }
1963
- var registrarActionsFilter = {
1964
- byParentNode,
1965
- withReferral
1966
- };
1967
-
1968
- // src/ensindexer/config/deserialize.ts
1969
- var import_v410 = require("zod/v4");
1970
- function deserializeENSIndexerPublicConfig(maybeConfig, valueLabel) {
1971
- const schema = makeENSIndexerPublicConfigSchema(valueLabel);
1972
- const parsed = schema.safeParse(maybeConfig);
1973
- if (parsed.error) {
1974
- throw new Error(`Cannot deserialize ENSIndexerPublicConfig:
1975
- ${(0, import_v410.prettifyError)(parsed.error)}
2427
+ ${(0, import_v416.prettifyError)(parsed.error)}
1976
2428
  `);
1977
2429
  }
1978
2430
  return parsed.data;
1979
2431
  }
1980
2432
 
1981
- // src/ensindexer/config/label-utils.ts
1982
- var import_viem13 = require("viem");
1983
- function labelHashToBytes(labelHash) {
1984
- try {
1985
- if (labelHash.length !== 66) {
1986
- throw new Error(`Invalid labelHash length ${labelHash.length} characters (expected 66)`);
1987
- }
1988
- if (labelHash !== labelHash.toLowerCase()) {
1989
- throw new Error("Labelhash must be in lowercase");
1990
- }
1991
- if (!labelHash.startsWith("0x")) {
1992
- throw new Error("Labelhash must be 0x-prefixed");
1993
- }
1994
- const bytes = (0, import_viem13.hexToBytes)(labelHash);
1995
- if (bytes.length !== 32) {
1996
- throw new Error(`Invalid labelHash length ${bytes.length} bytes (expected 32)`);
1997
- }
1998
- return bytes;
1999
- } catch (e) {
2000
- if (e instanceof Error) {
2001
- throw e;
2002
- }
2003
- throw new Error("Invalid hex format");
2004
- }
2005
- }
2006
-
2007
- // src/ensindexer/config/labelset-utils.ts
2008
- function buildLabelSetId(maybeLabelSetId) {
2009
- return makeLabelSetIdSchema("LabelSetId").parse(maybeLabelSetId);
2010
- }
2011
- function buildLabelSetVersion(maybeLabelSetVersion) {
2012
- return makeLabelSetVersionSchema("LabelSetVersion").parse(maybeLabelSetVersion);
2013
- }
2014
- function buildEnsRainbowClientLabelSet(labelSetId, labelSetVersion) {
2015
- if (labelSetVersion !== void 0 && labelSetId === void 0) {
2016
- throw new Error("When a labelSetVersion is defined, labelSetId must also be defined.");
2017
- }
2018
- return { labelSetId, labelSetVersion };
2019
- }
2020
- function validateSupportedLabelSetAndVersion(serverSet, clientSet) {
2021
- if (clientSet.labelSetId === void 0) {
2022
- return;
2023
- }
2024
- if (serverSet.labelSetId !== clientSet.labelSetId) {
2025
- throw new Error(
2026
- `Server label set ID "${serverSet.labelSetId}" does not match client's requested label set ID "${clientSet.labelSetId}".`
2027
- );
2028
- }
2029
- if (clientSet.labelSetVersion !== void 0 && serverSet.highestLabelSetVersion < clientSet.labelSetVersion) {
2030
- throw new Error(
2031
- `Server highest label set version ${serverSet.highestLabelSetVersion} is less than client's requested version ${clientSet.labelSetVersion} for label set ID "${clientSet.labelSetId}".`
2032
- );
2033
- }
2034
- }
2035
-
2036
- // src/ensindexer/config/parsing.ts
2037
- function parseNonNegativeInteger(maybeNumber) {
2038
- const trimmed = maybeNumber.trim();
2039
- if (!trimmed) {
2040
- throw new Error("Input cannot be empty");
2041
- }
2042
- if (trimmed === "-0") {
2043
- throw new Error("Negative zero is not a valid non-negative integer");
2044
- }
2045
- const num = Number(maybeNumber);
2046
- if (Number.isNaN(num)) {
2047
- throw new Error(`"${maybeNumber}" is not a valid number`);
2048
- }
2049
- if (!Number.isFinite(num)) {
2050
- throw new Error(`"${maybeNumber}" is not a finite number`);
2051
- }
2052
- if (!Number.isInteger(num)) {
2053
- throw new Error(`"${maybeNumber}" is not an integer`);
2054
- }
2055
- if (num < 0) {
2056
- throw new Error(`"${maybeNumber}" is not a non-negative integer`);
2433
+ // src/api/indexing-status/serialize.ts
2434
+ function serializeIndexingStatusResponse(response) {
2435
+ switch (response.responseCode) {
2436
+ case IndexingStatusResponseCodes.Ok:
2437
+ return {
2438
+ responseCode: response.responseCode,
2439
+ realtimeProjection: serializeRealtimeIndexingStatusProjection(response.realtimeProjection)
2440
+ };
2441
+ case IndexingStatusResponseCodes.Error:
2442
+ return response;
2057
2443
  }
2058
- return num;
2059
- }
2060
-
2061
- // src/ensindexer/config/serialize.ts
2062
- function serializeIndexedChainIds(indexedChainIds) {
2063
- return Array.from(indexedChainIds);
2064
- }
2065
- function serializeENSIndexerPublicConfig(config) {
2066
- const {
2067
- labelSet,
2068
- indexedChainIds,
2069
- databaseSchemaName,
2070
- isSubgraphCompatible: isSubgraphCompatible2,
2071
- namespace,
2072
- plugins,
2073
- versionInfo
2074
- } = config;
2075
- return {
2076
- labelSet,
2077
- indexedChainIds: serializeIndexedChainIds(indexedChainIds),
2078
- databaseSchemaName,
2079
- isSubgraphCompatible: isSubgraphCompatible2,
2080
- namespace,
2081
- plugins,
2082
- versionInfo
2083
- };
2084
2444
  }
2085
2445
 
2086
- // src/ensindexer/indexing-status/deserialize.ts
2087
- var import_v411 = require("zod/v4");
2088
- function deserializeChainIndexingStatusSnapshot(maybeSnapshot, valueLabel) {
2089
- const schema = makeChainIndexingStatusSnapshotSchema(valueLabel);
2090
- const parsed = schema.safeParse(maybeSnapshot);
2091
- if (parsed.error) {
2092
- throw new Error(
2093
- `Cannot deserialize into ChainIndexingStatusSnapshot:
2094
- ${(0, import_v411.prettifyError)(parsed.error)}
2095
- `
2096
- );
2097
- }
2098
- return parsed.data;
2099
- }
2100
- function deserializeOmnichainIndexingStatusSnapshot(maybeSnapshot, valueLabel) {
2101
- const schema = makeOmnichainIndexingStatusSnapshotSchema(valueLabel);
2102
- const parsed = schema.safeParse(maybeSnapshot);
2103
- if (parsed.error) {
2104
- throw new Error(
2105
- `Cannot deserialize into OmnichainIndexingStatusSnapshot:
2106
- ${(0, import_v411.prettifyError)(parsed.error)}
2107
- `
2108
- );
2109
- }
2110
- return parsed.data;
2111
- }
2112
- function deserializeCrossChainIndexingStatusSnapshot(maybeSnapshot, valueLabel) {
2113
- const schema = makeCrossChainIndexingStatusSnapshotSchema(valueLabel);
2114
- const parsed = schema.safeParse(maybeSnapshot);
2115
- if (parsed.error) {
2116
- throw new Error(
2117
- `Cannot deserialize into CrossChainIndexingStatusSnapshot:
2118
- ${(0, import_v411.prettifyError)(parsed.error)}
2119
- `
2120
- );
2121
- }
2122
- return parsed.data;
2123
- }
2124
- function deserializeRealtimeIndexingStatusProjection(maybeProjection, valueLabel) {
2125
- const schema = makeRealtimeIndexingStatusProjectionSchema(valueLabel);
2126
- const parsed = schema.safeParse(maybeProjection);
2446
+ // src/api/registrar-actions/deserialize.ts
2447
+ var import_v417 = require("zod/v4");
2448
+ function deserializeRegistrarActionsResponse(maybeResponse) {
2449
+ const parsed = makeRegistrarActionsResponseSchema().safeParse(maybeResponse);
2127
2450
  if (parsed.error) {
2128
2451
  throw new Error(
2129
- `Cannot deserialize into RealtimeIndexingStatusProjection:
2130
- ${(0, import_v411.prettifyError)(parsed.error)}
2452
+ `Cannot deserialize RegistrarActionsResponse:
2453
+ ${(0, import_v417.prettifyError)(parsed.error)}
2131
2454
  `
2132
2455
  );
2133
2456
  }
2134
2457
  return parsed.data;
2135
2458
  }
2136
2459
 
2137
- // src/ensindexer/indexing-status/projection.ts
2138
- function createRealtimeIndexingStatusProjection(snapshot, now) {
2139
- const projectedAt = Math.max(now, snapshot.snapshotTime);
2140
- return {
2141
- projectedAt,
2142
- worstCaseDistance: projectedAt - snapshot.slowestChainIndexingCursor,
2143
- snapshot
2144
- };
2145
- }
2460
+ // src/api/registrar-actions/request.ts
2461
+ var RegistrarActionsFilterTypes = {
2462
+ BySubregistryNode: "bySubregistryNode",
2463
+ WithEncodedReferral: "withEncodedReferral"
2464
+ };
2465
+ var RegistrarActionsOrders = {
2466
+ LatestRegistrarActions: "orderBy[timestamp]=desc"
2467
+ };
2146
2468
 
2147
- // src/ensindexer/indexing-status/serialize.ts
2148
- function serializeCrossChainIndexingStatusSnapshotOmnichain({
2149
- strategy,
2150
- slowestChainIndexingCursor,
2151
- snapshotTime,
2152
- omnichainSnapshot
2153
- }) {
2154
- return {
2155
- strategy,
2156
- slowestChainIndexingCursor,
2157
- snapshotTime,
2158
- omnichainSnapshot: serializeOmnichainIndexingStatusSnapshot(omnichainSnapshot)
2159
- };
2160
- }
2161
- function serializeRealtimeIndexingStatusProjection(indexingProjection) {
2162
- return {
2163
- projectedAt: indexingProjection.projectedAt,
2164
- worstCaseDistance: indexingProjection.worstCaseDistance,
2165
- snapshot: serializeCrossChainIndexingStatusSnapshotOmnichain(indexingProjection.snapshot)
2166
- };
2167
- }
2168
- function serializeChainIndexingSnapshots(chains) {
2169
- const serializedSnapshots = {};
2170
- for (const [chainId, snapshot] of chains.entries()) {
2171
- serializedSnapshots[serializeChainId(chainId)] = snapshot;
2469
+ // src/api/registrar-actions/filters.ts
2470
+ function byParentNode(parentNode) {
2471
+ if (typeof parentNode === "undefined") {
2472
+ return void 0;
2172
2473
  }
2173
- return serializedSnapshots;
2474
+ return {
2475
+ filterType: RegistrarActionsFilterTypes.BySubregistryNode,
2476
+ value: parentNode
2477
+ };
2174
2478
  }
2175
- function serializeOmnichainIndexingStatusSnapshot(indexingStatus) {
2176
- switch (indexingStatus.omnichainStatus) {
2177
- case OmnichainIndexingStatusIds.Unstarted:
2178
- return {
2179
- omnichainStatus: OmnichainIndexingStatusIds.Unstarted,
2180
- chains: serializeChainIndexingSnapshots(indexingStatus.chains),
2181
- omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
2182
- };
2183
- case OmnichainIndexingStatusIds.Backfill:
2184
- return {
2185
- omnichainStatus: OmnichainIndexingStatusIds.Backfill,
2186
- chains: serializeChainIndexingSnapshots(indexingStatus.chains),
2187
- omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
2188
- };
2189
- case OmnichainIndexingStatusIds.Completed: {
2190
- return {
2191
- omnichainStatus: OmnichainIndexingStatusIds.Completed,
2192
- chains: serializeChainIndexingSnapshots(indexingStatus.chains),
2193
- omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
2194
- };
2195
- }
2196
- case OmnichainIndexingStatusIds.Following:
2197
- return {
2198
- omnichainStatus: OmnichainIndexingStatusIds.Following,
2199
- chains: serializeChainIndexingSnapshots(indexingStatus.chains),
2200
- omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
2201
- };
2479
+ function withReferral(withReferral2) {
2480
+ if (!withReferral2) {
2481
+ return void 0;
2202
2482
  }
2483
+ return {
2484
+ filterType: RegistrarActionsFilterTypes.WithEncodedReferral
2485
+ };
2203
2486
  }
2487
+ var registrarActionsFilter = {
2488
+ byParentNode,
2489
+ withReferral
2490
+ };
2204
2491
 
2205
2492
  // src/api/registrar-actions/prerequisites.ts
2206
2493
  var registrarActionsPrerequisites = Object.freeze({
@@ -2269,18 +2556,7 @@ function getEthnamesSubregistryId(namespace) {
2269
2556
  };
2270
2557
  }
2271
2558
 
2272
- // src/api/serialize.ts
2273
- function serializeIndexingStatusResponse(response) {
2274
- switch (response.responseCode) {
2275
- case IndexingStatusResponseCodes.Ok:
2276
- return {
2277
- responseCode: response.responseCode,
2278
- realtimeProjection: serializeRealtimeIndexingStatusProjection(response.realtimeProjection)
2279
- };
2280
- case IndexingStatusResponseCodes.Error:
2281
- return response;
2282
- }
2283
- }
2559
+ // src/api/registrar-actions/serialize.ts
2284
2560
  function serializeNamedRegistrarAction({
2285
2561
  action,
2286
2562
  name
@@ -2302,6 +2578,18 @@ function serializeRegistrarActionsResponse(response) {
2302
2578
  }
2303
2579
  }
2304
2580
 
2581
+ // src/api/shared/errors/deserialize.ts
2582
+ var import_v418 = require("zod/v4");
2583
+ function deserializeErrorResponse(maybeErrorResponse) {
2584
+ const parsed = ErrorResponseSchema.safeParse(maybeErrorResponse);
2585
+ if (parsed.error) {
2586
+ throw new Error(`Cannot deserialize ErrorResponse:
2587
+ ${(0, import_v418.prettifyError)(parsed.error)}
2588
+ `);
2589
+ }
2590
+ return parsed.data;
2591
+ }
2592
+
2305
2593
  // src/client-error.ts
2306
2594
  var ClientError = class _ClientError extends Error {
2307
2595
  details;
@@ -2316,160 +2604,195 @@ var ClientError = class _ClientError extends Error {
2316
2604
  };
2317
2605
 
2318
2606
  // src/ensanalytics/deserialize.ts
2319
- var import_v413 = require("zod/v4");
2607
+ var import_v420 = require("zod/v4");
2320
2608
 
2321
2609
  // src/ensanalytics/zod-schemas.ts
2322
- var import_v412 = __toESM(require("zod/v4"), 1);
2610
+ var import_v419 = __toESM(require("zod/v4"), 1);
2323
2611
 
2324
2612
  // src/ensanalytics/types.ts
2325
- var ITEMS_PER_PAGE_DEFAULT = 25;
2326
- var ITEMS_PER_PAGE_MAX = 100;
2327
- var PaginatedAggregatedReferrersResponseCodes = {
2613
+ var ReferrerLeaderboardPageResponseCodes = {
2614
+ /**
2615
+ * Represents that the requested referrer leaderboard page is available.
2616
+ */
2617
+ Ok: "ok",
2618
+ /**
2619
+ * Represents that the referrer leaderboard data is not available.
2620
+ */
2621
+ Error: "error"
2622
+ };
2623
+ var ReferrerDetailResponseCodes = {
2328
2624
  /**
2329
- * Represents that the aggregated referrers data is available.
2330
- * @note The response may contain an empty array for the first page if there are no qualified referrers.
2331
- * When the array is empty, total will be 0, page will be 1, and both hasNext and hasPrev will be false.
2625
+ * Represents that the referrer detail data is available.
2332
2626
  */
2333
2627
  Ok: "ok",
2334
2628
  /**
2335
- * Represents that the aggregated referrers data is not available.
2629
+ * Represents that an error occurred while fetching the data.
2336
2630
  */
2337
2631
  Error: "error"
2338
2632
  };
2339
2633
 
2340
2634
  // src/ensanalytics/zod-schemas.ts
2341
- var makeAggregatedReferrerMetricsSchema = (valueLabel = "AggregatedReferrerMetrics") => import_v412.default.object({
2635
+ var makeReferralProgramRulesSchema = (valueLabel = "ReferralProgramRules") => import_v419.default.object({
2636
+ totalAwardPoolValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.totalAwardPoolValue`),
2637
+ maxQualifiedReferrers: makeNonNegativeIntegerSchema(`${valueLabel}.maxQualifiedReferrers`),
2638
+ startTime: makeUnixTimestampSchema(`${valueLabel}.startTime`),
2639
+ endTime: makeUnixTimestampSchema(`${valueLabel}.endTime`),
2640
+ subregistryId: makeAccountIdSchema(`${valueLabel}.subregistryId`)
2641
+ });
2642
+ var makeAwardedReferrerMetricsSchema = (valueLabel = "AwardedReferrerMetrics") => import_v419.default.object({
2342
2643
  referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`),
2343
- totalReferrals: makePositiveIntegerSchema(`${valueLabel}.totalReferrals`),
2344
- totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`)
2644
+ totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`),
2645
+ totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`),
2646
+ score: makeFiniteNonNegativeNumberSchema(`${valueLabel}.score`),
2647
+ rank: makePositiveIntegerSchema(`${valueLabel}.rank`),
2648
+ isQualified: import_v419.default.boolean(),
2649
+ finalScoreBoost: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScoreBoost`).max(
2650
+ 1,
2651
+ `${valueLabel}.finalScoreBoost must be <= 1`
2652
+ ),
2653
+ finalScore: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScore`),
2654
+ awardPoolShare: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolShare`).max(
2655
+ 1,
2656
+ `${valueLabel}.awardPoolShare must be <= 1`
2657
+ ),
2658
+ awardPoolApproxValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolApproxValue`)
2345
2659
  });
2346
- var makeAggregatedReferrerMetricsContributionSchema = (valueLabel = "AggregatedReferrerMetricsContribution") => makeAggregatedReferrerMetricsSchema(valueLabel).extend({
2347
- totalReferralsContribution: import_v412.default.number({
2348
- error: `${valueLabel}.totalReferralsContribution must be a number`
2349
- }).min(0, `${valueLabel}.totalReferralsContribution must be >= 0`).max(1, `${valueLabel}.totalReferralsContribution must be <= 1`),
2350
- totalIncrementalDurationContribution: import_v412.default.number({
2351
- error: `${valueLabel}.totalIncrementalDurationContribution must be a number`
2352
- }).min(0, `${valueLabel}.totalIncrementalDurationContribution must be >= 0`).max(1, `${valueLabel}.totalIncrementalDurationContribution must be <= 1`)
2660
+ var makeUnrankedReferrerMetricsSchema = (valueLabel = "UnrankedReferrerMetrics") => import_v419.default.object({
2661
+ referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`),
2662
+ totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`),
2663
+ totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`),
2664
+ score: makeFiniteNonNegativeNumberSchema(`${valueLabel}.score`),
2665
+ rank: import_v419.default.null(),
2666
+ isQualified: import_v419.default.literal(false),
2667
+ finalScoreBoost: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScoreBoost`).max(
2668
+ 1,
2669
+ `${valueLabel}.finalScoreBoost must be <= 1`
2670
+ ),
2671
+ finalScore: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScore`),
2672
+ awardPoolShare: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolShare`).max(
2673
+ 1,
2674
+ `${valueLabel}.awardPoolShare must be <= 1`
2675
+ ),
2676
+ awardPoolApproxValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolApproxValue`)
2353
2677
  });
2354
- var makePaginationParamsSchema = (valueLabel = "PaginationParams") => import_v412.default.object({
2355
- page: makePositiveIntegerSchema(`${valueLabel}.page`).default(1),
2356
- itemsPerPage: makePositiveIntegerSchema(`${valueLabel}.itemsPerPage`).max(ITEMS_PER_PAGE_MAX, `${valueLabel}.itemsPerPage must not exceed ${ITEMS_PER_PAGE_MAX}`).default(ITEMS_PER_PAGE_DEFAULT)
2678
+ var makeAggregatedReferrerMetricsSchema = (valueLabel = "AggregatedReferrerMetrics") => import_v419.default.object({
2679
+ grandTotalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.grandTotalReferrals`),
2680
+ grandTotalIncrementalDuration: makeDurationSchema(
2681
+ `${valueLabel}.grandTotalIncrementalDuration`
2682
+ ),
2683
+ grandTotalQualifiedReferrersFinalScore: makeFiniteNonNegativeNumberSchema(
2684
+ `${valueLabel}.grandTotalQualifiedReferrersFinalScore`
2685
+ ),
2686
+ minFinalScoreToQualify: makeFiniteNonNegativeNumberSchema(
2687
+ `${valueLabel}.minFinalScoreToQualify`
2688
+ )
2357
2689
  });
2358
- var makePaginatedAggregatedReferrersSchema = (valueLabel = "PaginatedAggregatedReferrers") => import_v412.default.object({
2359
- referrers: import_v412.default.array(
2360
- makeAggregatedReferrerMetricsContributionSchema(`${valueLabel}.referrers[item]`)
2690
+ var makeReferrerLeaderboardPageContextSchema = (valueLabel = "ReferrerLeaderboardPageContext") => import_v419.default.object({
2691
+ page: makePositiveIntegerSchema(`${valueLabel}.page`),
2692
+ itemsPerPage: makePositiveIntegerSchema(`${valueLabel}.itemsPerPage`).max(
2693
+ REFERRERS_PER_LEADERBOARD_PAGE_MAX,
2694
+ `${valueLabel}.itemsPerPage must not exceed ${REFERRERS_PER_LEADERBOARD_PAGE_MAX}`
2361
2695
  ),
2362
- total: makeNonNegativeIntegerSchema(`${valueLabel}.total`),
2363
- paginationParams: makePaginationParamsSchema(`${valueLabel}.paginationParams`),
2364
- hasNext: import_v412.default.boolean(),
2365
- hasPrev: import_v412.default.boolean(),
2366
- updatedAt: makeUnixTimestampSchema(`${valueLabel}.updatedAt`)
2367
- }).check((ctx) => {
2368
- const { paginationParams, hasNext, hasPrev, total } = ctx.value;
2369
- const expectedHasPrev = paginationParams.page > 1;
2370
- if (hasPrev !== expectedHasPrev) {
2371
- ctx.issues.push({
2372
- code: "custom",
2373
- message: `${valueLabel}.hasPrev must be ${expectedHasPrev} when page is ${paginationParams.page}`,
2374
- input: ctx.value
2375
- });
2376
- }
2377
- const endIndex = paginationParams.page * paginationParams.itemsPerPage;
2378
- const expectedHasNext = endIndex < total;
2379
- if (hasNext !== expectedHasNext) {
2380
- ctx.issues.push({
2381
- code: "custom",
2382
- message: `${valueLabel}.hasNext must be ${expectedHasNext} when page=${paginationParams.page}, itemsPerPage=${paginationParams.itemsPerPage}, total=${total}`,
2383
- input: ctx.value
2384
- });
2385
- }
2696
+ totalRecords: makeNonNegativeIntegerSchema(`${valueLabel}.totalRecords`),
2697
+ totalPages: makePositiveIntegerSchema(`${valueLabel}.totalPages`),
2698
+ hasNext: import_v419.default.boolean(),
2699
+ hasPrev: import_v419.default.boolean(),
2700
+ startIndex: import_v419.default.optional(makeNonNegativeIntegerSchema(`${valueLabel}.startIndex`)),
2701
+ endIndex: import_v419.default.optional(makeNonNegativeIntegerSchema(`${valueLabel}.endIndex`))
2702
+ });
2703
+ var makeReferrerLeaderboardPageSchema = (valueLabel = "ReferrerLeaderboardPage") => import_v419.default.object({
2704
+ rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),
2705
+ referrers: import_v419.default.array(makeAwardedReferrerMetricsSchema(`${valueLabel}.referrers[item]`)),
2706
+ aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),
2707
+ paginationContext: makeReferrerLeaderboardPageContextSchema(`${valueLabel}.paginationContext`),
2708
+ accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`)
2709
+ });
2710
+ var makeReferrerLeaderboardPageResponseOkSchema = (valueLabel = "ReferrerLeaderboardPageResponseOk") => import_v419.default.object({
2711
+ responseCode: import_v419.default.literal(ReferrerLeaderboardPageResponseCodes.Ok),
2712
+ data: makeReferrerLeaderboardPageSchema(`${valueLabel}.data`)
2713
+ });
2714
+ var makeReferrerLeaderboardPageResponseErrorSchema = (_valueLabel = "ReferrerLeaderboardPageResponseError") => import_v419.default.object({
2715
+ responseCode: import_v419.default.literal(ReferrerLeaderboardPageResponseCodes.Error),
2716
+ error: import_v419.default.string(),
2717
+ errorMessage: import_v419.default.string()
2718
+ });
2719
+ var makeReferrerLeaderboardPageResponseSchema = (valueLabel = "ReferrerLeaderboardPageResponse") => import_v419.default.union([
2720
+ makeReferrerLeaderboardPageResponseOkSchema(valueLabel),
2721
+ makeReferrerLeaderboardPageResponseErrorSchema(valueLabel)
2722
+ ]);
2723
+ var makeReferrerDetailRankedSchema = (valueLabel = "ReferrerDetailRanked") => import_v419.default.object({
2724
+ type: import_v419.default.literal(ReferrerDetailTypeIds.Ranked),
2725
+ rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),
2726
+ referrer: makeAwardedReferrerMetricsSchema(`${valueLabel}.referrer`),
2727
+ aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),
2728
+ accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`)
2729
+ });
2730
+ var makeReferrerDetailUnrankedSchema = (valueLabel = "ReferrerDetailUnranked") => import_v419.default.object({
2731
+ type: import_v419.default.literal(ReferrerDetailTypeIds.Unranked),
2732
+ rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),
2733
+ referrer: makeUnrankedReferrerMetricsSchema(`${valueLabel}.referrer`),
2734
+ aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),
2735
+ accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`)
2386
2736
  });
2387
- var makePaginatedAggregatedReferrersResponseOkSchema = (valueLabel = "PaginatedAggregatedReferrersResponse") => import_v412.default.object({
2388
- responseCode: import_v412.default.literal(PaginatedAggregatedReferrersResponseCodes.Ok),
2389
- data: makePaginatedAggregatedReferrersSchema(`${valueLabel}.data`)
2737
+ var makeReferrerDetailResponseOkSchema = (valueLabel = "ReferrerDetailResponse") => import_v419.default.object({
2738
+ responseCode: import_v419.default.literal(ReferrerDetailResponseCodes.Ok),
2739
+ data: import_v419.default.union([
2740
+ makeReferrerDetailRankedSchema(`${valueLabel}.data`),
2741
+ makeReferrerDetailUnrankedSchema(`${valueLabel}.data`)
2742
+ ])
2390
2743
  });
2391
- var makePaginatedAggregatedReferrersResponseErrorSchema = (_valueLabel = "PaginatedAggregatedReferrersResponse") => import_v412.default.object({
2392
- responseCode: import_v412.default.literal(PaginatedAggregatedReferrersResponseCodes.Error),
2393
- error: import_v412.default.string(),
2394
- errorMessage: import_v412.default.string()
2744
+ var makeReferrerDetailResponseErrorSchema = (_valueLabel = "ReferrerDetailResponse") => import_v419.default.object({
2745
+ responseCode: import_v419.default.literal(ReferrerDetailResponseCodes.Error),
2746
+ error: import_v419.default.string(),
2747
+ errorMessage: import_v419.default.string()
2395
2748
  });
2396
- var makePaginatedAggregatedReferrersResponseSchema = (valueLabel = "PaginatedAggregatedReferrersResponse") => import_v412.default.union([
2397
- makePaginatedAggregatedReferrersResponseOkSchema(valueLabel),
2398
- makePaginatedAggregatedReferrersResponseErrorSchema(valueLabel)
2749
+ var makeReferrerDetailResponseSchema = (valueLabel = "ReferrerDetailResponse") => import_v419.default.union([
2750
+ makeReferrerDetailResponseOkSchema(valueLabel),
2751
+ makeReferrerDetailResponseErrorSchema(valueLabel)
2399
2752
  ]);
2400
2753
 
2401
2754
  // src/ensanalytics/deserialize.ts
2402
- function deserializePaginatedAggregatedReferrersResponse(maybeResponse, valueLabel) {
2403
- const schema = makePaginatedAggregatedReferrersResponseSchema(valueLabel);
2755
+ function deserializeReferrerLeaderboardPageResponse(maybeResponse, valueLabel) {
2756
+ const schema = makeReferrerLeaderboardPageResponseSchema(valueLabel);
2404
2757
  const parsed = schema.safeParse(maybeResponse);
2405
2758
  if (parsed.error) {
2406
2759
  throw new Error(
2407
- `Cannot deserialize PaginatedAggregatedReferrersResponse:
2408
- ${(0, import_v413.prettifyError)(parsed.error)}
2760
+ `Cannot deserialize SerializedReferrerLeaderboardPageResponse:
2761
+ ${(0, import_v420.prettifyError)(parsed.error)}
2409
2762
  `
2410
2763
  );
2411
2764
  }
2412
2765
  return parsed.data;
2413
2766
  }
2767
+ function deserializeReferrerDetailResponse(maybeResponse, valueLabel) {
2768
+ const schema = makeReferrerDetailResponseSchema(valueLabel);
2769
+ const parsed = schema.safeParse(maybeResponse);
2770
+ if (parsed.error) {
2771
+ throw new Error(`Cannot deserialize ReferrerDetailResponse:
2772
+ ${(0, import_v420.prettifyError)(parsed.error)}
2773
+ `);
2774
+ }
2775
+ return parsed.data;
2776
+ }
2414
2777
 
2415
2778
  // src/ensanalytics/serialize.ts
2416
- function serializePaginatedAggregatedReferrersResponse(response) {
2779
+ function serializeReferrerLeaderboardPageResponse(response) {
2417
2780
  switch (response.responseCode) {
2418
- case PaginatedAggregatedReferrersResponseCodes.Ok:
2781
+ case ReferrerLeaderboardPageResponseCodes.Ok:
2419
2782
  return response;
2420
- case PaginatedAggregatedReferrersResponseCodes.Error:
2783
+ case ReferrerLeaderboardPageResponseCodes.Error:
2421
2784
  return response;
2422
2785
  }
2423
2786
  }
2424
-
2425
- // src/ensapi/config/deserialize.ts
2426
- var import_v415 = require("zod/v4");
2427
-
2428
- // src/ensapi/config/zod-schemas.ts
2429
- var import_v414 = require("zod/v4");
2430
- var TheGraphCannotFallbackReasonSchema = import_v414.z.enum({
2431
- NotSubgraphCompatible: "not-subgraph-compatible",
2432
- NoApiKey: "no-api-key",
2433
- NoSubgraphUrl: "no-subgraph-url"
2434
- });
2435
- var TheGraphFallbackSchema = import_v414.z.strictObject({
2436
- canFallback: import_v414.z.boolean(),
2437
- reason: TheGraphCannotFallbackReasonSchema.nullable()
2438
- });
2439
- function makeENSApiPublicConfigSchema(valueLabel) {
2440
- const label = valueLabel ?? "ENSApiPublicConfig";
2441
- return import_v414.z.strictObject({
2442
- version: import_v414.z.string().min(1, `${label}.version must be a non-empty string`),
2443
- theGraphFallback: TheGraphFallbackSchema,
2444
- ensIndexerPublicConfig: makeENSIndexerPublicConfigSchema(`${label}.ensIndexerPublicConfig`)
2445
- });
2446
- }
2447
-
2448
- // src/ensapi/config/deserialize.ts
2449
- function deserializeENSApiPublicConfig(maybeConfig, valueLabel) {
2450
- const schema = makeENSApiPublicConfigSchema(valueLabel);
2451
- try {
2452
- return schema.parse(maybeConfig);
2453
- } catch (error) {
2454
- if (error instanceof import_v415.ZodError) {
2455
- throw new Error(`Cannot deserialize ENSApiPublicConfig:
2456
- ${(0, import_v415.prettifyError)(error)}
2457
- `);
2458
- }
2459
- throw error;
2787
+ function serializeReferrerDetailResponse(response) {
2788
+ switch (response.responseCode) {
2789
+ case ReferrerDetailResponseCodes.Ok:
2790
+ return response;
2791
+ case ReferrerDetailResponseCodes.Error:
2792
+ return response;
2460
2793
  }
2461
2794
  }
2462
2795
 
2463
- // src/ensapi/config/serialize.ts
2464
- function serializeENSApiPublicConfig(config) {
2465
- const { version, theGraphFallback, ensIndexerPublicConfig } = config;
2466
- return {
2467
- version,
2468
- theGraphFallback,
2469
- ensIndexerPublicConfig: serializeENSIndexerPublicConfig(ensIndexerPublicConfig)
2470
- };
2471
- }
2472
-
2473
2796
  // src/client.ts
2474
2797
  var DEFAULT_ENSNODE_API_URL = "https://api.alpha.ensnode.io";
2475
2798
  var ENSNodeClient = class _ENSNodeClient {
@@ -2673,7 +2996,7 @@ var ENSNodeClient = class _ENSNodeClient {
2673
2996
  const errorResponse = deserializeErrorResponse(responseData);
2674
2997
  throw new Error(`Fetching ENSNode Config Failed: ${errorResponse.message}`);
2675
2998
  }
2676
- return deserializeENSApiPublicConfig(responseData);
2999
+ return deserializeConfigResponse(responseData);
2677
3000
  }
2678
3001
  /**
2679
3002
  * Fetch ENSNode Indexing Status
@@ -2707,15 +3030,15 @@ var ENSNodeClient = class _ENSNodeClient {
2707
3030
  return deserializeIndexingStatusResponse(responseData);
2708
3031
  }
2709
3032
  /**
2710
- * Fetch Paginated Aggregated Referrers
3033
+ * Fetch Referrer Leaderboard Page
2711
3034
  *
2712
- * Retrieves a paginated list of aggregated referrer metrics with contribution percentages.
3035
+ * Retrieves a paginated list of referrer leaderboard metrics with contribution percentages.
2713
3036
  * Each referrer's contribution is calculated as a percentage of the grand totals across all referrers.
2714
3037
  *
2715
3038
  * @param request - Pagination parameters
2716
3039
  * @param request.page - The page number to retrieve (1-indexed, default: 1)
2717
3040
  * @param request.itemsPerPage - Number of items per page (default: 25, max: 100)
2718
- * @returns {PaginatedAggregatedReferrersResponse}
3041
+ * @returns {ReferrerLeaderboardPageResponse}
2719
3042
  *
2720
3043
  * @throws if the ENSNode request fails
2721
3044
  * @throws if the ENSNode API returns an error response
@@ -2724,21 +3047,42 @@ var ENSNodeClient = class _ENSNodeClient {
2724
3047
  * @example
2725
3048
  * ```typescript
2726
3049
  * // Get first page with default page size (25 items)
2727
- * const response = await client.getAggregatedReferrers();
2728
- * if (response.responseCode === 'ok') {
2729
- * console.log(response.data.referrers);
2730
- * console.log(`Page ${response.data.paginationParams.page} of ${Math.ceil(response.data.total / response.data.paginationParams.itemsPerPage)}`);
3050
+ * const response = await client.getReferrerLeaderboardPage();
3051
+ * if (response.responseCode === ReferrerLeaderboardPageResponseCodes.Ok) {
3052
+ * const {
3053
+ * aggregatedMetrics,
3054
+ * referrers,
3055
+ * rules,
3056
+ * paginationContext,
3057
+ * updatedAt
3058
+ * } = response.data;
3059
+ * console.log(aggregatedMetrics);
3060
+ * console.log(referrers);
3061
+ * console.log(rules);
3062
+ * console.log(updatedAt);
3063
+ * console.log(`Page ${paginationContext.page} of ${paginationContext.totalPages}`);
2731
3064
  * }
2732
3065
  * ```
2733
3066
  *
2734
3067
  * @example
2735
3068
  * ```typescript
2736
3069
  * // Get second page with 50 items per page
2737
- * const response = await client.getAggregatedReferrers({ page: 2, itemsPerPage: 50 });
3070
+ * const response = await client.getReferrerLeaderboardPage({ page: 2, itemsPerPage: 50 });
3071
+ * ```
3072
+ *
3073
+ * @example
3074
+ * ```typescript
3075
+ * // Handle error response, ie. when Referrer Leaderboard is not currently available.
3076
+ * const response = await client.getReferrerLeaderboardPage();
3077
+ *
3078
+ * if (response.responseCode === ReferrerLeaderboardPageResponseCodes.Error) {
3079
+ * console.error(response.error);
3080
+ * console.error(response.errorMessage);
3081
+ * }
2738
3082
  * ```
2739
3083
  */
2740
- async getAggregatedReferrers(request) {
2741
- const url = new URL(`/ensanalytics/aggregated-referrers`, this.options.url);
3084
+ async getReferrerLeaderboardPage(request) {
3085
+ const url = new URL(`/ensanalytics/referrers`, this.options.url);
2742
3086
  if (request?.page) url.searchParams.set("page", request.page.toString());
2743
3087
  if (request?.itemsPerPage)
2744
3088
  url.searchParams.set("itemsPerPage", request.itemsPerPage.toString());
@@ -2749,10 +3093,100 @@ var ENSNodeClient = class _ENSNodeClient {
2749
3093
  } catch {
2750
3094
  throw new Error("Malformed response data: invalid JSON");
2751
3095
  }
2752
- return deserializePaginatedAggregatedReferrersResponse(
3096
+ return deserializeReferrerLeaderboardPageResponse(
2753
3097
  responseData
2754
3098
  );
2755
3099
  }
3100
+ /**
3101
+ * Fetch Referrer Detail
3102
+ *
3103
+ * Retrieves detailed information about a specific referrer, whether they are on the
3104
+ * leaderboard or not.
3105
+ *
3106
+ * The response data is a discriminated union type with a `type` field:
3107
+ *
3108
+ * **For referrers on the leaderboard** (`ReferrerDetailRanked`):
3109
+ * - `type`: {@link ReferrerDetailTypeIds.Ranked}
3110
+ * - `referrer`: The `AwardedReferrerMetrics` from @namehash/ens-referrals
3111
+ * - `rules`: The referral program rules
3112
+ * - `aggregatedMetrics`: Aggregated metrics for all referrers on the leaderboard
3113
+ * - `accurateAsOf`: Unix timestamp indicating when the data was last updated
3114
+ *
3115
+ * **For referrers NOT on the leaderboard** (`ReferrerDetailUnranked`):
3116
+ * - `type`: {@link ReferrerDetailTypeIds.Unranked}
3117
+ * - `referrer`: The `UnrankedReferrerMetrics` from @namehash/ens-referrals
3118
+ * - `rules`: The referral program rules
3119
+ * - `aggregatedMetrics`: Aggregated metrics for all referrers on the leaderboard
3120
+ * - `accurateAsOf`: Unix timestamp indicating when the data was last updated
3121
+ *
3122
+ * @see {@link https://www.npmjs.com/package/@namehash/ens-referrals|@namehash/ens-referrals} for calculation details
3123
+ *
3124
+ * @param request The referrer address to query
3125
+ * @returns {ReferrerDetailResponse} Returns the referrer detail response
3126
+ *
3127
+ * @throws if the ENSNode request fails
3128
+ * @throws if the response data is malformed
3129
+ *
3130
+ * @example
3131
+ * ```typescript
3132
+ * // Get referrer detail for a specific address
3133
+ * const response = await client.getReferrerDetail({
3134
+ * referrer: "0x1234567890123456789012345678901234567890"
3135
+ * });
3136
+ * if (response.responseCode === ReferrerDetailResponseCodes.Ok) {
3137
+ * const { type, referrer, rules, aggregatedMetrics, accurateAsOf } = response.data;
3138
+ * console.log(type); // ReferrerDetailTypeIds.Ranked or ReferrerDetailTypeIds.Unranked
3139
+ * console.log(referrer);
3140
+ * console.log(accurateAsOf);
3141
+ * }
3142
+ * ```
3143
+ *
3144
+ * @example
3145
+ * ```typescript
3146
+ * // Use discriminated union to check if referrer is ranked
3147
+ * const response = await client.getReferrerDetail({
3148
+ * referrer: "0x1234567890123456789012345678901234567890"
3149
+ * });
3150
+ * if (response.responseCode === ReferrerDetailResponseCodes.Ok) {
3151
+ * if (response.data.type === ReferrerDetailTypeIds.Ranked) {
3152
+ * // TypeScript knows this is ReferrerDetailRanked
3153
+ * console.log(`Rank: ${response.data.referrer.rank}`);
3154
+ * console.log(`Qualified: ${response.data.referrer.isQualified}`);
3155
+ * console.log(`Award Pool Share: ${response.data.referrer.awardPoolShare * 100}%`);
3156
+ * } else {
3157
+ * // TypeScript knows this is ReferrerDetailUnranked
3158
+ * console.log("Referrer is not on the leaderboard (no referrals yet)");
3159
+ * }
3160
+ * }
3161
+ * ```
3162
+ *
3163
+ * @example
3164
+ * ```typescript
3165
+ * // Handle error response, ie. when Referrer Detail is not currently available.
3166
+ * const response = await client.getReferrerDetail({
3167
+ * referrer: "0x1234567890123456789012345678901234567890"
3168
+ * });
3169
+ *
3170
+ * if (response.responseCode === ReferrerDetailResponseCodes.Error) {
3171
+ * console.error(response.error);
3172
+ * console.error(response.errorMessage);
3173
+ * }
3174
+ * ```
3175
+ */
3176
+ async getReferrerDetail(request) {
3177
+ const url = new URL(
3178
+ `/api/ensanalytics/referrers/${encodeURIComponent(request.referrer)}`,
3179
+ this.options.url
3180
+ );
3181
+ const response = await fetch(url);
3182
+ let responseData;
3183
+ try {
3184
+ responseData = await response.json();
3185
+ } catch {
3186
+ throw new Error("Malformed response data: invalid JSON");
3187
+ }
3188
+ return deserializeReferrerDetailResponse(responseData);
3189
+ }
2756
3190
  /**
2757
3191
  * Fetch ENSNode Registrar Actions
2758
3192
  *
@@ -2916,6 +3350,231 @@ var translateDefaultableChainIdToChainId = (chainId, namespaceId) => {
2916
3350
  // src/resolution/resolver-records-selection.ts
2917
3351
  var isSelectionEmpty = (selection) => !selection.name && !selection.addresses?.length && !selection.texts?.length;
2918
3352
 
3353
+ // src/tokenscope/assets.ts
3354
+ var import_caip3 = require("caip");
3355
+ var import_viem15 = require("viem");
3356
+ var AssetNamespaces = {
3357
+ ERC721: "erc721",
3358
+ ERC1155: "erc1155"
3359
+ };
3360
+ function serializeAssetId(assetId) {
3361
+ const { assetNamespace, contract, tokenId } = assetId;
3362
+ return import_caip3.AssetId.format({
3363
+ chainId: { namespace: "eip155", reference: contract.chainId.toString() },
3364
+ assetName: { namespace: assetNamespace, reference: contract.address },
3365
+ tokenId: uint256ToHex32(tokenId)
3366
+ }).toLowerCase();
3367
+ }
3368
+ var buildAssetId = (contract, tokenId, assetNamespace) => {
3369
+ return {
3370
+ assetNamespace,
3371
+ contract,
3372
+ tokenId
3373
+ };
3374
+ };
3375
+ var NFTMintStatuses = {
3376
+ Minted: "minted",
3377
+ Burned: "burned"
3378
+ };
3379
+ var formatNFTTransferEventMetadata = (metadata) => {
3380
+ const serializedAssetId = serializeAssetId(metadata.nft);
3381
+ return [
3382
+ `Event: ${metadata.eventHandlerName}`,
3383
+ `Chain ID: ${metadata.chainId}`,
3384
+ `Block Number: ${metadata.blockNumber}`,
3385
+ `Transaction Hash: ${metadata.transactionHash}`,
3386
+ `NFT: ${serializedAssetId}`
3387
+ ].map((line) => ` - ${line}`).join("\n");
3388
+ };
3389
+ var NFTTransferTypes = {
3390
+ /**
3391
+ * Initial transfer from zeroAddress to a non-zeroAddress
3392
+ * Can happen at most once to a NFT AssetId
3393
+ *
3394
+ * Invariants:
3395
+ * - NFT is not indexed and therefore has no previous mint status or owner
3396
+ * - new NFT mint status is `minted`
3397
+ * - new NFT owner is a non-zeroAddress
3398
+ */
3399
+ Mint: "mint",
3400
+ /**
3401
+ * Subsequent transfer from zeroAddress to a non-zeroAddress
3402
+ * Can happen any number of times to a NFT AssetId as it passes in a cycle from
3403
+ * mint -> burn -> remint -> burn -> remint -> ...
3404
+ *
3405
+ * Invariants:
3406
+ * - NFT is indexed
3407
+ * - previous NFT mint status was `burned`
3408
+ * - previous NFT owner is the zeroAddress
3409
+ * - new NFT mint status is `minted`
3410
+ * - new NFT owner is a non-zeroAddress
3411
+ */
3412
+ Remint: "remint",
3413
+ /**
3414
+ * Special transfer type for improperly implemented NFT contracts that allow a NFT
3415
+ * that is currently minted to be reminted before an intermediate burn.
3416
+ *
3417
+ * Transfer from zeroAddress to non-zeroAddress for an indexed NFT where the
3418
+ * previously indexed nft had status `minted` with a non-zeroAddress owner.
3419
+ *
3420
+ * Invariants:
3421
+ * - NFT is indexed
3422
+ * - previous NFT mint status was `minted`
3423
+ * - previous NFT owner was a non-zeroAddress
3424
+ * - new NFT mint status is `minted`
3425
+ * - new NFT owner is a non-zeroAddress
3426
+ */
3427
+ MintedRemint: "minted-remint",
3428
+ /**
3429
+ * Transfer from a non-zeroAddress to zeroAddress
3430
+ *
3431
+ * Invariants:
3432
+ * - NFT is indexed
3433
+ * - previous NFT mint status was `minted`
3434
+ * - previous NFT owner is a non-zeroAddress
3435
+ * - new NFT mint status is `burned`
3436
+ * - new NFT owner is the zeroAddress
3437
+ */
3438
+ Burn: "burn",
3439
+ /**
3440
+ * Transfer from a non-zeroAddress to a distinct non-zeroAddress
3441
+ *
3442
+ * Invariants:
3443
+ * - NFT is indexed
3444
+ * - previous and new NFT mint status is `minted`
3445
+ * - previous and new NFT owner are distinct non-zeroAddress
3446
+ */
3447
+ Transfer: "transfer",
3448
+ /**
3449
+ * Transfer from a non-zeroAddress to the same non-zeroAddress
3450
+ *
3451
+ * Invariants:
3452
+ * - NFT is indexed
3453
+ * - previous and new NFT mint status is `minted`
3454
+ * - previous and new NFT owner are equivalent non-zeroAddress
3455
+ */
3456
+ SelfTransfer: "self-transfer",
3457
+ /**
3458
+ * Transfer from zeroAddress to zeroAddress for an indexed NFT
3459
+ *
3460
+ * Invariants:
3461
+ * - NFT is indexed
3462
+ * - previous and new NFT mint status is `burned`
3463
+ * - previous and new NFT owner are zeroAddress
3464
+ */
3465
+ RemintBurn: "remint-burn",
3466
+ /**
3467
+ * Special transfer type for improperly implemented NFT contracts that allow a NFT
3468
+ * that is currently minted to be reminted again before an intermediate burn.
3469
+ *
3470
+ * Transfer from zeroAddress to zeroAddress for an indexed NFT where the
3471
+ * previously indexed nft had status `minted` with a non-zeroAddress owner.
3472
+ *
3473
+ * Invariants:
3474
+ * - NFT is indexed
3475
+ * - previous NFT mint status was `minted`
3476
+ * - previous NFT owner was a non-zeroAddress
3477
+ * - new NFT mint status is `burned`
3478
+ * - new NFT owner is the zeroAddress
3479
+ */
3480
+ MintedRemintBurn: "minted-remint-burn",
3481
+ /**
3482
+ * Transfer from zeroAddress to zeroAddress for an unindexed NFT
3483
+ *
3484
+ * Invariants:
3485
+ * - NFT is not indexed and therefore has no previous mint status or owner
3486
+ * - NFT should remain unindexed and without any mint status or owner
3487
+ */
3488
+ MintBurn: "mint-burn"
3489
+ };
3490
+ var getNFTTransferType = (from, to, allowMintedRemint, metadata, currentlyIndexedOwner) => {
3491
+ const isIndexed = currentlyIndexedOwner !== void 0;
3492
+ const isIndexedAsMinted = isIndexed && !(0, import_viem15.isAddressEqual)(currentlyIndexedOwner, import_viem15.zeroAddress);
3493
+ const isMint = (0, import_viem15.isAddressEqual)(from, import_viem15.zeroAddress);
3494
+ const isBurn = (0, import_viem15.isAddressEqual)(to, import_viem15.zeroAddress);
3495
+ const isSelfTransfer = (0, import_viem15.isAddressEqual)(from, to);
3496
+ if (isIndexed && !(0, import_viem15.isAddressEqual)(currentlyIndexedOwner, from)) {
3497
+ if (isMint && allowMintedRemint) {
3498
+ } else {
3499
+ throw new Error(
3500
+ `Error: Sending from ${from} conflicts with currently indexed owner ${currentlyIndexedOwner}.
3501
+ ${formatNFTTransferEventMetadata(metadata)}`
3502
+ );
3503
+ }
3504
+ }
3505
+ if (isSelfTransfer) {
3506
+ if (isMint) {
3507
+ if (!isIndexed) {
3508
+ return NFTTransferTypes.MintBurn;
3509
+ } else if (!isIndexedAsMinted) {
3510
+ return NFTTransferTypes.RemintBurn;
3511
+ } else if (allowMintedRemint) {
3512
+ return NFTTransferTypes.MintedRemintBurn;
3513
+ } else {
3514
+ throw new Error(
3515
+ `Error: Invalid state transition from minted -> remint-burn
3516
+ ${formatNFTTransferEventMetadata(metadata)}`
3517
+ );
3518
+ }
3519
+ } else {
3520
+ if (!isIndexed) {
3521
+ throw new Error(
3522
+ `Error: Invalid state transition from unindexed -> self-transfer
3523
+ ${formatNFTTransferEventMetadata(metadata)}`
3524
+ );
3525
+ } else if (!isIndexedAsMinted) {
3526
+ throw new Error(
3527
+ `Error: invalid state transition from burned -> self-transfer
3528
+ ${formatNFTTransferEventMetadata(metadata)}`
3529
+ );
3530
+ } else {
3531
+ return NFTTransferTypes.SelfTransfer;
3532
+ }
3533
+ }
3534
+ } else if (isMint) {
3535
+ if (!isIndexed) {
3536
+ return NFTTransferTypes.Mint;
3537
+ } else if (!isIndexedAsMinted) {
3538
+ return NFTTransferTypes.Remint;
3539
+ } else if (allowMintedRemint) {
3540
+ return NFTTransferTypes.MintedRemint;
3541
+ } else {
3542
+ throw new Error(
3543
+ `Error: Invalid state transition from minted -> mint
3544
+ ${formatNFTTransferEventMetadata(metadata)}`
3545
+ );
3546
+ }
3547
+ } else if (isBurn) {
3548
+ if (!isIndexed) {
3549
+ throw new Error(
3550
+ `Error: Invalid state transition from unindexed -> burn
3551
+ ${formatNFTTransferEventMetadata(metadata)}`
3552
+ );
3553
+ } else if (!isIndexedAsMinted) {
3554
+ throw new Error(
3555
+ `Error: Invalid state transition from burned -> burn
3556
+ ${formatNFTTransferEventMetadata(metadata)}`
3557
+ );
3558
+ } else {
3559
+ return NFTTransferTypes.Burn;
3560
+ }
3561
+ } else {
3562
+ if (!isIndexed) {
3563
+ throw new Error(
3564
+ `Error: Invalid state transition from unindexed -> transfer
3565
+ ${formatNFTTransferEventMetadata(metadata)}`
3566
+ );
3567
+ } else if (!isIndexedAsMinted) {
3568
+ throw new Error(
3569
+ `Error: Invalid state transition from burned -> transfer
3570
+ ${formatNFTTransferEventMetadata(metadata)}`
3571
+ );
3572
+ } else {
3573
+ return NFTTransferTypes.Transfer;
3574
+ }
3575
+ }
3576
+ };
3577
+
2919
3578
  // src/tracing/index.ts
2920
3579
  var TraceableENSProtocol = /* @__PURE__ */ ((TraceableENSProtocol2) => {
2921
3580
  TraceableENSProtocol2["ForwardResolution"] = "forward-resolution";