@ensnode/ensnode-sdk 1.1.0 → 1.3.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,
@@ -44,16 +45,25 @@ __export(index_exports, {
44
45
  DEFAULT_EVM_COIN_TYPE: () => DEFAULT_EVM_COIN_TYPE,
45
46
  ENSNamespaceIds: () => import_datasources.ENSNamespaceIds,
46
47
  ENSNodeClient: () => ENSNodeClient,
48
+ ENS_ROOT: () => ENS_ROOT,
47
49
  ETH_COIN_TYPE: () => ETH_COIN_TYPE,
48
50
  ETH_NODE: () => ETH_NODE,
49
51
  ForwardResolutionProtocolStep: () => ForwardResolutionProtocolStep,
50
52
  IndexingStatusResponseCodes: () => IndexingStatusResponseCodes,
51
53
  LINEANAMES_NODE: () => LINEANAMES_NODE,
52
54
  LruCache: () => LruCache,
55
+ NFTMintStatuses: () => NFTMintStatuses,
56
+ NFTTransferTypes: () => NFTTransferTypes,
57
+ NameTokenOwnershipTypes: () => NameTokenOwnershipTypes,
58
+ NameTokensResponseCodes: () => NameTokensResponseCodes,
59
+ NameTokensResponseErrorCodes: () => NameTokensResponseErrorCodes,
53
60
  OmnichainIndexingStatusIds: () => OmnichainIndexingStatusIds,
54
61
  PROTOCOL_ATTRIBUTE_PREFIX: () => PROTOCOL_ATTRIBUTE_PREFIX,
55
62
  PluginName: () => PluginName,
63
+ RECORDS_PER_PAGE_DEFAULT: () => RECORDS_PER_PAGE_DEFAULT,
64
+ RECORDS_PER_PAGE_MAX: () => RECORDS_PER_PAGE_MAX,
56
65
  ROOT_NODE: () => ROOT_NODE,
66
+ ReferrerDetailResponseCodes: () => ReferrerDetailResponseCodes,
57
67
  ReferrerLeaderboardPageResponseCodes: () => ReferrerLeaderboardPageResponseCodes,
58
68
  RegistrarActionTypes: () => RegistrarActionTypes,
59
69
  RegistrarActionsFilterTypes: () => RegistrarActionsFilterTypes,
@@ -75,9 +85,11 @@ __export(index_exports, {
75
85
  beautifyName: () => beautifyName,
76
86
  bigIntToNumber: () => bigIntToNumber,
77
87
  bigintToCoinType: () => bigintToCoinType,
88
+ buildAssetId: () => buildAssetId,
78
89
  buildEnsRainbowClientLabelSet: () => buildEnsRainbowClientLabelSet,
79
90
  buildLabelSetId: () => buildLabelSetId,
80
91
  buildLabelSetVersion: () => buildLabelSetVersion,
92
+ buildPageContext: () => buildPageContext,
81
93
  buildUnresolvedIdentity: () => buildUnresolvedIdentity,
82
94
  checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill: () => checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill,
83
95
  checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted: () => checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted,
@@ -90,12 +102,13 @@ __export(index_exports, {
90
102
  decodeDNSEncodedLiteralName: () => decodeDNSEncodedLiteralName,
91
103
  decodeDNSEncodedName: () => decodeDNSEncodedName,
92
104
  decodeEncodedReferrer: () => decodeEncodedReferrer,
93
- deserializeAccountId: () => deserializeAccountId,
105
+ deserializeAssetId: () => deserializeAssetId,
94
106
  deserializeBlockNumber: () => deserializeBlockNumber,
95
107
  deserializeBlockRef: () => deserializeBlockRef,
96
108
  deserializeBlockrange: () => deserializeBlockrange,
97
109
  deserializeChainId: () => deserializeChainId,
98
110
  deserializeChainIndexingStatusSnapshot: () => deserializeChainIndexingStatusSnapshot,
111
+ deserializeConfigResponse: () => deserializeConfigResponse,
99
112
  deserializeCrossChainIndexingStatusSnapshot: () => deserializeCrossChainIndexingStatusSnapshot,
100
113
  deserializeDatetime: () => deserializeDatetime,
101
114
  deserializeDuration: () => deserializeDuration,
@@ -105,20 +118,35 @@ __export(index_exports, {
105
118
  deserializeIndexingStatusResponse: () => deserializeIndexingStatusResponse,
106
119
  deserializeOmnichainIndexingStatusSnapshot: () => deserializeOmnichainIndexingStatusSnapshot,
107
120
  deserializeRealtimeIndexingStatusProjection: () => deserializeRealtimeIndexingStatusProjection,
121
+ deserializeReferrerDetailResponse: () => deserializeReferrerDetailResponse,
108
122
  deserializeReferrerLeaderboardPageResponse: () => deserializeReferrerLeaderboardPageResponse,
109
123
  deserializeRegistrarActionsResponse: () => deserializeRegistrarActionsResponse,
110
124
  deserializeUnixTimestamp: () => deserializeUnixTimestamp,
111
125
  deserializeUrl: () => deserializeUrl,
126
+ deserializedNameTokensResponse: () => deserializedNameTokensResponse,
112
127
  durationBetween: () => durationBetween,
113
128
  encodeLabelHash: () => encodeLabelHash,
114
129
  evmChainIdToCoinType: () => evmChainIdToCoinType,
130
+ formatAccountId: () => formatAccountId,
131
+ formatAssetId: () => formatAssetId,
132
+ formatNFTTransferEventMetadata: () => formatNFTTransferEventMetadata,
133
+ getBasenamesSubregistryId: () => getBasenamesSubregistryId,
134
+ getBasenamesSubregistryManagedName: () => getBasenamesSubregistryManagedName,
115
135
  getCurrencyInfo: () => getCurrencyInfo,
136
+ getDatasourceContract: () => getDatasourceContract,
116
137
  getENSRootChainId: () => import_datasources2.getENSRootChainId,
117
138
  getEthnamesSubregistryId: () => getEthnamesSubregistryId,
139
+ getEthnamesSubregistryManagedName: () => getEthnamesSubregistryManagedName,
118
140
  getLatestIndexedBlockRef: () => getLatestIndexedBlockRef,
141
+ getLineanamesSubregistryId: () => getLineanamesSubregistryId,
142
+ getLineanamesSubregistryManagedName: () => getLineanamesSubregistryManagedName,
143
+ getNFTTransferType: () => getNFTTransferType,
119
144
  getNameHierarchy: () => getNameHierarchy,
145
+ getNameTokenOwnership: () => getNameTokenOwnership,
146
+ getNameWrapperAccounts: () => getNameWrapperAccounts,
120
147
  getOmnichainIndexingCursor: () => getOmnichainIndexingCursor,
121
148
  getOmnichainIndexingStatus: () => getOmnichainIndexingStatus,
149
+ getParentNameFQDN: () => getParentNameFQDN,
122
150
  getResolvePrimaryNameChainIdParam: () => getResolvePrimaryNameChainIdParam,
123
151
  getTimestampForHighestOmnichainKnownBlock: () => getTimestampForHighestOmnichainKnownBlock,
124
152
  getTimestampForLowestOmnichainStartBlock: () => getTimestampForLowestOmnichainStartBlock,
@@ -144,6 +172,10 @@ __export(index_exports, {
144
172
  literalLabelsToLiteralName: () => literalLabelsToLiteralName,
145
173
  makeENSApiPublicConfigSchema: () => makeENSApiPublicConfigSchema,
146
174
  makeSubdomainNode: () => makeSubdomainNode,
175
+ maybeGetDatasourceContract: () => maybeGetDatasourceContract,
176
+ nameTokensPrerequisites: () => nameTokensPrerequisites,
177
+ parseAccountId: () => parseAccountId,
178
+ parseAssetId: () => parseAssetId,
147
179
  parseNonNegativeInteger: () => parseNonNegativeInteger,
148
180
  parseReverseName: () => parseReverseName,
149
181
  priceDai: () => priceDai,
@@ -152,26 +184,30 @@ __export(index_exports, {
152
184
  registrarActionsFilter: () => registrarActionsFilter,
153
185
  registrarActionsPrerequisites: () => registrarActionsPrerequisites,
154
186
  reverseName: () => reverseName,
155
- serializeAccountId: () => serializeAccountId,
187
+ serializeAssetId: () => serializeAssetId,
156
188
  serializeChainId: () => serializeChainId,
157
189
  serializeChainIndexingSnapshots: () => serializeChainIndexingSnapshots,
190
+ serializeConfigResponse: () => serializeConfigResponse,
158
191
  serializeCrossChainIndexingStatusSnapshotOmnichain: () => serializeCrossChainIndexingStatusSnapshotOmnichain,
159
192
  serializeDatetime: () => serializeDatetime,
193
+ serializeDomainAssetId: () => serializeDomainAssetId,
160
194
  serializeENSApiPublicConfig: () => serializeENSApiPublicConfig,
161
195
  serializeENSIndexerPublicConfig: () => serializeENSIndexerPublicConfig,
162
196
  serializeIndexedChainIds: () => serializeIndexedChainIds,
163
197
  serializeIndexingStatusResponse: () => serializeIndexingStatusResponse,
198
+ serializeNameToken: () => serializeNameToken,
199
+ serializeNameTokensResponse: () => serializeNameTokensResponse,
164
200
  serializeNamedRegistrarAction: () => serializeNamedRegistrarAction,
165
201
  serializeOmnichainIndexingStatusSnapshot: () => serializeOmnichainIndexingStatusSnapshot,
166
202
  serializePrice: () => serializePrice,
167
203
  serializePriceEth: () => serializePriceEth,
168
204
  serializeRealtimeIndexingStatusProjection: () => serializeRealtimeIndexingStatusProjection,
205
+ serializeReferrerDetailResponse: () => serializeReferrerDetailResponse,
169
206
  serializeReferrerLeaderboardPageResponse: () => serializeReferrerLeaderboardPageResponse,
207
+ serializeRegisteredNameTokens: () => serializeRegisteredNameTokens,
170
208
  serializeRegistrarAction: () => serializeRegistrarAction,
171
209
  serializeRegistrarActionPricing: () => serializeRegistrarActionPricing,
172
210
  serializeRegistrarActionsResponse: () => serializeRegistrarActionsResponse,
173
- serializeRegistrationLifecycle: () => serializeRegistrationLifecycle,
174
- serializeSubregistry: () => serializeSubregistry,
175
211
  serializeUrl: () => serializeUrl,
176
212
  sortChainStatusesByStartBlockAsc: () => sortChainStatusesByStartBlockAsc,
177
213
  stripNullBytes: () => stripNullBytes,
@@ -182,35 +218,15 @@ __export(index_exports, {
182
218
  });
183
219
  module.exports = __toCommonJS(index_exports);
184
220
 
185
- // src/api/deserialize.ts
186
- var import_v49 = require("zod/v4");
221
+ // src/ensapi/config/deserialize.ts
222
+ var import_v45 = require("zod/v4");
187
223
 
188
- // src/api/zod-schemas.ts
189
- var import_viem14 = require("viem");
190
- var import_v48 = __toESM(require("zod/v4"), 1);
224
+ // src/ensapi/config/zod-schemas.ts
225
+ var import_v44 = require("zod/v4");
191
226
 
192
- // src/ensindexer/indexing-status/zod-schemas.ts
227
+ // src/ensindexer/config/zod-schemas.ts
193
228
  var import_v43 = __toESM(require("zod/v4"), 1);
194
229
 
195
- // src/ens/is-normalized.ts
196
- var import_ens = require("viem/ens");
197
- function isNormalizedName(name) {
198
- try {
199
- return name === (0, import_ens.normalize)(name);
200
- } catch {
201
- return false;
202
- }
203
- }
204
- function isNormalizedLabel(label) {
205
- if (label === "") return false;
206
- if (label.includes(".")) return false;
207
- try {
208
- return label === (0, import_ens.normalize)(label);
209
- } catch {
210
- return false;
211
- }
212
- }
213
-
214
230
  // src/shared/account-id.ts
215
231
  var import_viem = require("viem");
216
232
  var accountIdEqual = (a, b) => {
@@ -361,9 +377,39 @@ function isEncodedLabelHash(maybeEncodedLabelHash) {
361
377
  return expectedFormatting && includesLabelHash;
362
378
  }
363
379
 
380
+ // src/ens/is-normalized.ts
381
+ var import_ens = require("viem/ens");
382
+ function isNormalizedName(name) {
383
+ try {
384
+ return name === (0, import_ens.normalize)(name);
385
+ } catch {
386
+ return false;
387
+ }
388
+ }
389
+ function isNormalizedLabel(label) {
390
+ if (label === "") return false;
391
+ if (label.includes(".")) return false;
392
+ try {
393
+ return label === (0, import_ens.normalize)(label);
394
+ } catch {
395
+ return false;
396
+ }
397
+ }
398
+
364
399
  // src/ens/names.ts
365
400
  var import_ens_normalize = require("@adraffy/ens-normalize");
401
+ var ENS_ROOT = "";
366
402
  var getNameHierarchy = (name) => name.split(".").map((_, i, labels) => labels.slice(i).join("."));
403
+ var getParentNameFQDN = (name) => {
404
+ if (name === ENS_ROOT) {
405
+ throw new Error("There is no parent name for ENS Root.");
406
+ }
407
+ const labels = name.split(".");
408
+ if (labels.length === 1) {
409
+ return ENS_ROOT;
410
+ }
411
+ return labels.slice(1).join(".");
412
+ };
367
413
  var beautifyName = (name) => {
368
414
  const beautifiedLabels = name.split(".").map((label) => {
369
415
  if (isNormalizedLabel(label)) {
@@ -606,7 +652,7 @@ var makeAccountIdSchema = (valueLabel = "AccountId") => import_v4.default.strict
606
652
  chainId: makeChainIdSchema(`${valueLabel} chain ID`),
607
653
  address: makeLowercaseAddressSchema(`${valueLabel} address`)
608
654
  });
609
- var makeSerializedAccountIdSchema = (valueLabel = "Account ID") => import_v4.default.coerce.string().transform((v) => {
655
+ var makeAccountIdStringSchema = (valueLabel = "Account ID String") => import_v4.default.coerce.string().transform((v) => {
610
656
  const result = new import_caip.AccountId(v);
611
657
  return {
612
658
  chainId: Number(result.chainId.reference),
@@ -618,7 +664,7 @@ var makeHexStringSchema = (options, valueLabel = "String representation of bytes
618
664
  ctx.issues.push({
619
665
  code: "custom",
620
666
  input: ctx.value,
621
- message: `${valueLabel} must start with '0x'.`
667
+ message: `${valueLabel} must be a hexadecimal value which starts with '0x'.`
622
668
  });
623
669
  }
624
670
  }).transform((v) => v).check(function invariant_encodesRequiredBytesCount(ctx) {
@@ -728,8 +774,8 @@ ${(0, import_v42.prettifyError)(parsed.error)}
728
774
  }
729
775
  return parsed.data;
730
776
  }
731
- function deserializeAccountId(maybeAccountId, valueLabel) {
732
- const schema = makeSerializedAccountIdSchema(valueLabel);
777
+ function parseAccountId(maybeAccountId, valueLabel) {
778
+ const schema = makeAccountIdStringSchema(valueLabel);
733
779
  const parsed = schema.safeParse(maybeAccountId);
734
780
  if (parsed.error) {
735
781
  throw new RangeError(`Cannot deserialize AccountId:
@@ -992,6 +1038,28 @@ var TtlCache = class {
992
1038
  // src/shared/collections.ts
993
1039
  var uniq = (arr) => [...new Set(arr)];
994
1040
 
1041
+ // src/shared/datasource-contract.ts
1042
+ var import_datasources3 = require("@ensnode/datasources");
1043
+ var maybeGetDatasourceContract = (namespaceId, datasourceName, contractName) => {
1044
+ const datasource = (0, import_datasources3.maybeGetDatasource)(namespaceId, datasourceName);
1045
+ if (!datasource) return void 0;
1046
+ const address = datasource.contracts[contractName]?.address;
1047
+ if (address === void 0 || Array.isArray(address)) return void 0;
1048
+ return {
1049
+ chainId: datasource.chain.id,
1050
+ address
1051
+ };
1052
+ };
1053
+ var getDatasourceContract = (namespaceId, datasourceName, contractName) => {
1054
+ const contract = maybeGetDatasourceContract(namespaceId, datasourceName, contractName);
1055
+ if (!contract) {
1056
+ throw new Error(
1057
+ `Expected contract not found for ${namespaceId} ${datasourceName} ${contractName}`
1058
+ );
1059
+ }
1060
+ return contract;
1061
+ };
1062
+
995
1063
  // src/shared/labelhash.ts
996
1064
  var import_viem9 = require("viem");
997
1065
  var labelhashLiteralLabel = (label) => (0, import_viem9.keccak256)((0, import_viem9.stringToBytes)(label));
@@ -1050,7 +1118,7 @@ function serializePrice(price) {
1050
1118
  function serializePriceEth(price) {
1051
1119
  return serializePrice(price);
1052
1120
  }
1053
- function serializeAccountId(accountId) {
1121
+ function formatAccountId(accountId) {
1054
1122
  return import_caip2.AccountId.format({
1055
1123
  chainId: { namespace: "eip155", reference: accountId.chainId.toString() },
1056
1124
  address: accountId.address
@@ -1065,776 +1133,1670 @@ function isWebSocketProtocol(url) {
1065
1133
  return ["ws:", "wss:"].includes(url.protocol);
1066
1134
  }
1067
1135
 
1068
- // src/ensindexer/indexing-status/types.ts
1069
- var ChainIndexingConfigTypeIds = {
1070
- /**
1071
- * Represents that indexing of the chain should be performed for an indefinite range.
1072
- */
1073
- Indefinite: "indefinite",
1074
- /**
1075
- * Represents that indexing of the chain should be performed for a definite range.
1076
- */
1077
- Definite: "definite"
1078
- };
1079
- var ChainIndexingStatusIds = {
1080
- /**
1081
- * Represents that indexing of the chain is not ready to begin yet because:
1082
- * - ENSIndexer is in its initialization phase and the data to build a
1083
- * "true" {@link ChainIndexingSnapshot} for the chain is still being loaded; or
1084
- * - ENSIndexer is using an omnichain indexing strategy and the
1085
- * `omnichainIndexingCursor` is <= `config.startBlock.timestamp` for the chain's
1086
- * {@link ChainIndexingSnapshot}.
1087
- */
1088
- Queued: "chain-queued",
1089
- /**
1090
- * Represents that indexing of the chain is in progress and under a special
1091
- * "backfill" phase that optimizes for accelerated indexing until reaching the
1092
- * "fixed target" `backfillEndBlock`.
1093
- */
1094
- Backfill: "chain-backfill",
1095
- /**
1096
- * Represents that the "backfill" phase of indexing the chain is completed
1097
- * and that the chain is configured to be indexed for an indefinite range.
1098
- * Therefore, indexing of the chain remains indefinitely in progress where
1099
- * ENSIndexer will continuously work to discover and index new blocks as they
1100
- * are added to the chain across time.
1101
- */
1102
- Following: "chain-following",
1103
- /**
1104
- * Represents that indexing of the chain is completed as the chain is configured
1105
- * to be indexed for a definite range and the indexing of all blocks through
1106
- * that definite range is completed.
1107
- */
1108
- Completed: "chain-completed"
1109
- };
1110
- var OmnichainIndexingStatusIds = {
1111
- /**
1112
- * Represents that omnichain indexing is not ready to begin yet because
1113
- * ENSIndexer is in its initialization phase and the data to build a "true"
1114
- * {@link OmnichainIndexingStatusSnapshot} is still being loaded.
1115
- */
1116
- Unstarted: "omnichain-unstarted",
1117
- /**
1118
- * Represents that omnichain indexing is in an overall "backfill" status because
1119
- * - At least one indexed chain has a `chainStatus` of
1120
- * {@link ChainIndexingStatusIds.Backfill}; and
1121
- * - No indexed chain has a `chainStatus` of {@link ChainIndexingStatusIds.Following}.
1122
- */
1123
- Backfill: "omnichain-backfill",
1124
- /**
1125
- * Represents that omnichain indexing is in an overall "following" status because
1126
- * at least one indexed chain has a `chainStatus` of
1127
- * {@link ChainIndexingStatusIds.Following}.
1128
- */
1129
- Following: "omnichain-following",
1130
- /**
1131
- * Represents that omnichain indexing has completed because all indexed chains have
1132
- * a `chainStatus` of {@link ChainIndexingStatusIds.Completed}.
1133
- */
1134
- Completed: "omnichain-completed"
1135
- };
1136
- var CrossChainIndexingStrategyIds = {
1137
- /**
1138
- * Represents that the indexing of events across all indexed chains will
1139
- * proceed in a deterministic "omnichain" ordering by block timestamp, chain ID,
1140
- * and block number.
1141
- *
1142
- * This strategy is "deterministic" in that the order of processing cross-chain indexed
1143
- * events and each resulting indexed data state transition recorded in ENSDb is always
1144
- * the same for each ENSIndexer instance operating with an equivalent
1145
- * `ENSIndexerConfig` and ENSIndexer version. However it also has the drawbacks of:
1146
- * - increased indexing latency that must wait for the slowest indexed chain to
1147
- * add new blocks or to discover new blocks through the configured RPCs.
1148
- * - if any indexed chain gets "stuck" due to chain or RPC failures, all indexed chains
1149
- * will be affected.
1150
- */
1151
- Omnichain: "omnichain"
1152
- };
1136
+ // src/ensindexer/config/is-subgraph-compatible.ts
1137
+ var import_datasources4 = require("@ensnode/datasources");
1153
1138
 
1154
- // src/shared/block-ref.ts
1155
- function isBefore(blockA, blockB) {
1156
- return blockA.number < blockB.number && blockA.timestamp < blockB.timestamp;
1157
- }
1158
- function isEqualTo(blockA, blockB) {
1159
- return blockA.number === blockB.number && blockA.timestamp === blockB.timestamp;
1160
- }
1161
- function isBeforeOrEqualTo(blockA, blockB) {
1162
- return isBefore(blockA, blockB) || isEqualTo(blockA, blockB);
1139
+ // src/ensindexer/config/types.ts
1140
+ var PluginName = /* @__PURE__ */ ((PluginName2) => {
1141
+ PluginName2["Subgraph"] = "subgraph";
1142
+ PluginName2["Basenames"] = "basenames";
1143
+ PluginName2["Lineanames"] = "lineanames";
1144
+ PluginName2["ThreeDNS"] = "threedns";
1145
+ PluginName2["ProtocolAcceleration"] = "protocol-acceleration";
1146
+ PluginName2["Registrars"] = "registrars";
1147
+ PluginName2["TokenScope"] = "tokenscope";
1148
+ return PluginName2;
1149
+ })(PluginName || {});
1150
+
1151
+ // src/ensindexer/config/is-subgraph-compatible.ts
1152
+ function isSubgraphCompatible(config) {
1153
+ const onlySubgraphPluginActivated = config.plugins.length === 1 && config.plugins[0] === "subgraph" /* Subgraph */;
1154
+ const isSubgraphLabelSet = config.labelSet.labelSetId === "subgraph" && config.labelSet.labelSetVersion === 0;
1155
+ const isEnsTestEnvLabelSet = config.labelSet.labelSetId === "ens-test-env" && config.labelSet.labelSetVersion === 0;
1156
+ const labelSetIsSubgraphCompatible = isSubgraphLabelSet || config.namespace === import_datasources4.ENSNamespaceIds.EnsTestEnv && isEnsTestEnvLabelSet;
1157
+ return onlySubgraphPluginActivated && labelSetIsSubgraphCompatible;
1163
1158
  }
1164
1159
 
1165
- // src/ensindexer/indexing-status/helpers.ts
1166
- function getOmnichainIndexingStatus(chains) {
1167
- if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing(chains)) {
1168
- return OmnichainIndexingStatusIds.Following;
1160
+ // src/ensindexer/config/validations.ts
1161
+ function invariant_ensDbVersionIsSameAsEnsIndexerVersion(ctx) {
1162
+ const versionInfo = ctx.value;
1163
+ if (versionInfo.ensDb !== versionInfo.ensIndexer) {
1164
+ ctx.issues.push({
1165
+ code: "custom",
1166
+ input: versionInfo,
1167
+ message: "`ensDb` version must be same as `ensIndexer` version"
1168
+ });
1169
1169
  }
1170
- if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill(chains)) {
1171
- return OmnichainIndexingStatusIds.Backfill;
1170
+ }
1171
+
1172
+ // src/ensindexer/config/zod-schemas.ts
1173
+ var makeIndexedChainIdsSchema = (valueLabel = "Indexed Chain IDs") => import_v43.default.array(makeChainIdSchema(valueLabel), {
1174
+ error: `${valueLabel} must be an array.`
1175
+ }).min(1, { error: `${valueLabel} list must include at least one element.` }).transform((v) => new Set(v));
1176
+ var makePluginsListSchema = (valueLabel = "Plugins") => import_v43.default.array(import_v43.default.string(), {
1177
+ error: `${valueLabel} must be a list of strings.`
1178
+ }).min(1, {
1179
+ error: `${valueLabel} must be a list of strings with at least one string value`
1180
+ }).refine((arr) => arr.length === uniq(arr).length, {
1181
+ error: `${valueLabel} cannot contain duplicate values.`
1182
+ });
1183
+ var makeDatabaseSchemaNameSchema = (valueLabel = "Database schema name") => import_v43.default.string({ error: `${valueLabel} must be a string` }).trim().nonempty({
1184
+ error: `${valueLabel} is required and must be a non-empty string.`
1185
+ });
1186
+ var makeLabelSetIdSchema = (valueLabel) => {
1187
+ 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-]+$/, {
1188
+ error: `${valueLabel} can only contain lowercase letters (a-z) and hyphens (-)`
1189
+ });
1190
+ };
1191
+ var makeLabelSetVersionSchema = (valueLabel) => {
1192
+ return import_v43.default.coerce.number({ error: `${valueLabel} must be an integer.` }).pipe(makeNonNegativeIntegerSchema(valueLabel));
1193
+ };
1194
+ var makeFullyPinnedLabelSetSchema = (valueLabel = "Label set") => {
1195
+ let valueLabelLabelSetId = valueLabel;
1196
+ let valueLabelLabelSetVersion = valueLabel;
1197
+ if (valueLabel === "LABEL_SET") {
1198
+ valueLabelLabelSetId = "LABEL_SET_ID";
1199
+ valueLabelLabelSetVersion = "LABEL_SET_VERSION";
1200
+ } else {
1201
+ valueLabelLabelSetId = `${valueLabel}.labelSetId`;
1202
+ valueLabelLabelSetVersion = `${valueLabel}.labelSetVersion`;
1172
1203
  }
1173
- if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted(chains)) {
1174
- return OmnichainIndexingStatusIds.Unstarted;
1204
+ return import_v43.default.object({
1205
+ labelSetId: makeLabelSetIdSchema(valueLabelLabelSetId),
1206
+ labelSetVersion: makeLabelSetVersionSchema(valueLabelLabelSetVersion)
1207
+ });
1208
+ };
1209
+ var makeNonEmptyStringSchema = (valueLabel = "Value") => import_v43.default.string().nonempty({ error: `${valueLabel} must be a non-empty string.` });
1210
+ var makeENSIndexerVersionInfoSchema = (valueLabel = "Value") => import_v43.default.strictObject(
1211
+ {
1212
+ nodejs: makeNonEmptyStringSchema(),
1213
+ ponder: makeNonEmptyStringSchema(),
1214
+ ensDb: makeNonEmptyStringSchema(),
1215
+ ensIndexer: makeNonEmptyStringSchema(),
1216
+ ensNormalize: makeNonEmptyStringSchema(),
1217
+ ensRainbow: makeNonEmptyStringSchema(),
1218
+ ensRainbowSchema: makePositiveIntegerSchema()
1219
+ },
1220
+ {
1221
+ error: `${valueLabel} must be a valid ENSIndexerVersionInfo object.`
1175
1222
  }
1176
- if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted(chains)) {
1177
- return OmnichainIndexingStatusIds.Completed;
1223
+ ).check(invariant_ensDbVersionIsSameAsEnsIndexerVersion);
1224
+ function invariant_isSubgraphCompatibleRequirements(ctx) {
1225
+ const { value: config } = ctx;
1226
+ if (config.isSubgraphCompatible && !isSubgraphCompatible(config)) {
1227
+ ctx.issues.push({
1228
+ code: "custom",
1229
+ input: config,
1230
+ message: `'isSubgraphCompatible' requires only the '${"subgraph" /* Subgraph */}' plugin to be active and labelSet must be {labelSetId: "subgraph", labelSetVersion: 0}`
1231
+ });
1178
1232
  }
1179
- throw new Error(`Unable to determine omnichain indexing status for provided chains.`);
1180
- }
1181
- function getTimestampForLowestOmnichainStartBlock(chains) {
1182
- const earliestKnownBlockTimestamps = chains.map(
1183
- (chain) => chain.config.startBlock.timestamp
1184
- );
1185
- return Math.min(...earliestKnownBlockTimestamps);
1186
1233
  }
1187
- function getTimestampForHighestOmnichainKnownBlock(chains) {
1188
- const latestKnownBlockTimestamps = [];
1189
- for (const chain of chains) {
1190
- switch (chain.chainStatus) {
1191
- case ChainIndexingStatusIds.Queued:
1192
- if (chain.config.configType === ChainIndexingConfigTypeIds.Definite && chain.config.endBlock) {
1193
- latestKnownBlockTimestamps.push(chain.config.endBlock.timestamp);
1194
- }
1195
- break;
1196
- case ChainIndexingStatusIds.Backfill:
1197
- latestKnownBlockTimestamps.push(chain.backfillEndBlock.timestamp);
1198
- break;
1199
- case ChainIndexingStatusIds.Completed:
1200
- latestKnownBlockTimestamps.push(chain.latestIndexedBlock.timestamp);
1201
- break;
1202
- case ChainIndexingStatusIds.Following:
1203
- latestKnownBlockTimestamps.push(chain.latestKnownBlock.timestamp);
1204
- break;
1234
+ var makeENSIndexerPublicConfigSchema = (valueLabel = "ENSIndexerPublicConfig") => import_v43.default.object({
1235
+ labelSet: makeFullyPinnedLabelSetSchema(`${valueLabel}.labelSet`),
1236
+ indexedChainIds: makeIndexedChainIdsSchema(`${valueLabel}.indexedChainIds`),
1237
+ isSubgraphCompatible: import_v43.default.boolean({ error: `${valueLabel}.isSubgraphCompatible` }),
1238
+ namespace: makeENSNamespaceIdSchema(`${valueLabel}.namespace`),
1239
+ plugins: makePluginsListSchema(`${valueLabel}.plugins`),
1240
+ databaseSchemaName: makeDatabaseSchemaNameSchema(`${valueLabel}.databaseSchemaName`),
1241
+ versionInfo: makeENSIndexerVersionInfoSchema(`${valueLabel}.versionInfo`)
1242
+ }).check(invariant_isSubgraphCompatibleRequirements);
1243
+
1244
+ // src/ensapi/config/zod-schemas.ts
1245
+ var TheGraphCannotFallbackReasonSchema = import_v44.z.enum({
1246
+ NotSubgraphCompatible: "not-subgraph-compatible",
1247
+ NoApiKey: "no-api-key",
1248
+ NoSubgraphUrl: "no-subgraph-url"
1249
+ });
1250
+ var TheGraphFallbackSchema = import_v44.z.strictObject({
1251
+ canFallback: import_v44.z.boolean(),
1252
+ reason: TheGraphCannotFallbackReasonSchema.nullable()
1253
+ });
1254
+ function makeENSApiPublicConfigSchema(valueLabel) {
1255
+ const label = valueLabel ?? "ENSApiPublicConfig";
1256
+ return import_v44.z.strictObject({
1257
+ version: import_v44.z.string().min(1, `${label}.version must be a non-empty string`),
1258
+ theGraphFallback: TheGraphFallbackSchema,
1259
+ ensIndexerPublicConfig: makeENSIndexerPublicConfigSchema(`${label}.ensIndexerPublicConfig`)
1260
+ });
1261
+ }
1262
+
1263
+ // src/ensapi/config/deserialize.ts
1264
+ function deserializeENSApiPublicConfig(maybeConfig, valueLabel) {
1265
+ const schema = makeENSApiPublicConfigSchema(valueLabel);
1266
+ try {
1267
+ return schema.parse(maybeConfig);
1268
+ } catch (error) {
1269
+ if (error instanceof import_v45.ZodError) {
1270
+ throw new Error(`Cannot deserialize ENSApiPublicConfig:
1271
+ ${(0, import_v45.prettifyError)(error)}
1272
+ `);
1273
+ }
1274
+ throw error;
1275
+ }
1276
+ }
1277
+
1278
+ // src/ensindexer/config/deserialize.ts
1279
+ var import_v46 = require("zod/v4");
1280
+ function deserializeENSIndexerPublicConfig(maybeConfig, valueLabel) {
1281
+ const schema = makeENSIndexerPublicConfigSchema(valueLabel);
1282
+ const parsed = schema.safeParse(maybeConfig);
1283
+ if (parsed.error) {
1284
+ throw new Error(`Cannot deserialize ENSIndexerPublicConfig:
1285
+ ${(0, import_v46.prettifyError)(parsed.error)}
1286
+ `);
1287
+ }
1288
+ return parsed.data;
1289
+ }
1290
+
1291
+ // src/ensindexer/config/label-utils.ts
1292
+ var import_viem10 = require("viem");
1293
+ function labelHashToBytes(labelHash) {
1294
+ try {
1295
+ if (labelHash.length !== 66) {
1296
+ throw new Error(`Invalid labelHash length ${labelHash.length} characters (expected 66)`);
1297
+ }
1298
+ if (labelHash !== labelHash.toLowerCase()) {
1299
+ throw new Error("Labelhash must be in lowercase");
1300
+ }
1301
+ if (!labelHash.startsWith("0x")) {
1302
+ throw new Error("Labelhash must be 0x-prefixed");
1303
+ }
1304
+ const bytes = (0, import_viem10.hexToBytes)(labelHash);
1305
+ if (bytes.length !== 32) {
1306
+ throw new Error(`Invalid labelHash length ${bytes.length} bytes (expected 32)`);
1307
+ }
1308
+ return bytes;
1309
+ } catch (e) {
1310
+ if (e instanceof Error) {
1311
+ throw e;
1205
1312
  }
1313
+ throw new Error("Invalid hex format");
1314
+ }
1315
+ }
1316
+
1317
+ // src/ensindexer/config/labelset-utils.ts
1318
+ function buildLabelSetId(maybeLabelSetId) {
1319
+ return makeLabelSetIdSchema("LabelSetId").parse(maybeLabelSetId);
1320
+ }
1321
+ function buildLabelSetVersion(maybeLabelSetVersion) {
1322
+ return makeLabelSetVersionSchema("LabelSetVersion").parse(maybeLabelSetVersion);
1323
+ }
1324
+ function buildEnsRainbowClientLabelSet(labelSetId, labelSetVersion) {
1325
+ if (labelSetVersion !== void 0 && labelSetId === void 0) {
1326
+ throw new Error("When a labelSetVersion is defined, labelSetId must also be defined.");
1327
+ }
1328
+ return { labelSetId, labelSetVersion };
1329
+ }
1330
+ function validateSupportedLabelSetAndVersion(serverSet, clientSet) {
1331
+ if (clientSet.labelSetId === void 0) {
1332
+ return;
1333
+ }
1334
+ if (serverSet.labelSetId !== clientSet.labelSetId) {
1335
+ throw new Error(
1336
+ `Server label set ID "${serverSet.labelSetId}" does not match client's requested label set ID "${clientSet.labelSetId}".`
1337
+ );
1338
+ }
1339
+ if (clientSet.labelSetVersion !== void 0 && serverSet.highestLabelSetVersion < clientSet.labelSetVersion) {
1340
+ throw new Error(
1341
+ `Server highest label set version ${serverSet.highestLabelSetVersion} is less than client's requested version ${clientSet.labelSetVersion} for label set ID "${clientSet.labelSetId}".`
1342
+ );
1343
+ }
1344
+ }
1345
+
1346
+ // src/ensindexer/config/parsing.ts
1347
+ function parseNonNegativeInteger(maybeNumber) {
1348
+ const trimmed = maybeNumber.trim();
1349
+ if (!trimmed) {
1350
+ throw new Error("Input cannot be empty");
1351
+ }
1352
+ if (trimmed === "-0") {
1353
+ throw new Error("Negative zero is not a valid non-negative integer");
1354
+ }
1355
+ const num = Number(maybeNumber);
1356
+ if (Number.isNaN(num)) {
1357
+ throw new Error(`"${maybeNumber}" is not a valid number`);
1358
+ }
1359
+ if (!Number.isFinite(num)) {
1360
+ throw new Error(`"${maybeNumber}" is not a finite number`);
1361
+ }
1362
+ if (!Number.isInteger(num)) {
1363
+ throw new Error(`"${maybeNumber}" is not an integer`);
1364
+ }
1365
+ if (num < 0) {
1366
+ throw new Error(`"${maybeNumber}" is not a non-negative integer`);
1367
+ }
1368
+ return num;
1369
+ }
1370
+
1371
+ // src/ensindexer/config/serialize.ts
1372
+ function serializeIndexedChainIds(indexedChainIds) {
1373
+ return Array.from(indexedChainIds);
1374
+ }
1375
+ function serializeENSIndexerPublicConfig(config) {
1376
+ const {
1377
+ labelSet,
1378
+ indexedChainIds,
1379
+ databaseSchemaName,
1380
+ isSubgraphCompatible: isSubgraphCompatible2,
1381
+ namespace,
1382
+ plugins,
1383
+ versionInfo
1384
+ } = config;
1385
+ return {
1386
+ labelSet,
1387
+ indexedChainIds: serializeIndexedChainIds(indexedChainIds),
1388
+ databaseSchemaName,
1389
+ isSubgraphCompatible: isSubgraphCompatible2,
1390
+ namespace,
1391
+ plugins,
1392
+ versionInfo
1393
+ };
1394
+ }
1395
+
1396
+ // src/ensindexer/indexing-status/deserialize.ts
1397
+ var import_v48 = require("zod/v4");
1398
+
1399
+ // src/ensindexer/indexing-status/zod-schemas.ts
1400
+ var import_v47 = __toESM(require("zod/v4"), 1);
1401
+
1402
+ // src/ensindexer/indexing-status/types.ts
1403
+ var ChainIndexingConfigTypeIds = {
1404
+ /**
1405
+ * Represents that indexing of the chain should be performed for an indefinite range.
1406
+ */
1407
+ Indefinite: "indefinite",
1408
+ /**
1409
+ * Represents that indexing of the chain should be performed for a definite range.
1410
+ */
1411
+ Definite: "definite"
1412
+ };
1413
+ var ChainIndexingStatusIds = {
1414
+ /**
1415
+ * Represents that indexing of the chain is not ready to begin yet because:
1416
+ * - ENSIndexer is in its initialization phase and the data to build a
1417
+ * "true" {@link ChainIndexingSnapshot} for the chain is still being loaded; or
1418
+ * - ENSIndexer is using an omnichain indexing strategy and the
1419
+ * `omnichainIndexingCursor` is <= `config.startBlock.timestamp` for the chain's
1420
+ * {@link ChainIndexingSnapshot}.
1421
+ */
1422
+ Queued: "chain-queued",
1423
+ /**
1424
+ * Represents that indexing of the chain is in progress and under a special
1425
+ * "backfill" phase that optimizes for accelerated indexing until reaching the
1426
+ * "fixed target" `backfillEndBlock`.
1427
+ */
1428
+ Backfill: "chain-backfill",
1429
+ /**
1430
+ * Represents that the "backfill" phase of indexing the chain is completed
1431
+ * and that the chain is configured to be indexed for an indefinite range.
1432
+ * Therefore, indexing of the chain remains indefinitely in progress where
1433
+ * ENSIndexer will continuously work to discover and index new blocks as they
1434
+ * are added to the chain across time.
1435
+ */
1436
+ Following: "chain-following",
1437
+ /**
1438
+ * Represents that indexing of the chain is completed as the chain is configured
1439
+ * to be indexed for a definite range and the indexing of all blocks through
1440
+ * that definite range is completed.
1441
+ */
1442
+ Completed: "chain-completed"
1443
+ };
1444
+ var OmnichainIndexingStatusIds = {
1445
+ /**
1446
+ * Represents that omnichain indexing is not ready to begin yet because
1447
+ * ENSIndexer is in its initialization phase and the data to build a "true"
1448
+ * {@link OmnichainIndexingStatusSnapshot} is still being loaded.
1449
+ */
1450
+ Unstarted: "omnichain-unstarted",
1451
+ /**
1452
+ * Represents that omnichain indexing is in an overall "backfill" status because
1453
+ * - At least one indexed chain has a `chainStatus` of
1454
+ * {@link ChainIndexingStatusIds.Backfill}; and
1455
+ * - No indexed chain has a `chainStatus` of {@link ChainIndexingStatusIds.Following}.
1456
+ */
1457
+ Backfill: "omnichain-backfill",
1458
+ /**
1459
+ * Represents that omnichain indexing is in an overall "following" status because
1460
+ * at least one indexed chain has a `chainStatus` of
1461
+ * {@link ChainIndexingStatusIds.Following}.
1462
+ */
1463
+ Following: "omnichain-following",
1464
+ /**
1465
+ * Represents that omnichain indexing has completed because all indexed chains have
1466
+ * a `chainStatus` of {@link ChainIndexingStatusIds.Completed}.
1467
+ */
1468
+ Completed: "omnichain-completed"
1469
+ };
1470
+ var CrossChainIndexingStrategyIds = {
1471
+ /**
1472
+ * Represents that the indexing of events across all indexed chains will
1473
+ * proceed in a deterministic "omnichain" ordering by block timestamp, chain ID,
1474
+ * and block number.
1475
+ *
1476
+ * This strategy is "deterministic" in that the order of processing cross-chain indexed
1477
+ * events and each resulting indexed data state transition recorded in ENSDb is always
1478
+ * the same for each ENSIndexer instance operating with an equivalent
1479
+ * `ENSIndexerConfig` and ENSIndexer version. However it also has the drawbacks of:
1480
+ * - increased indexing latency that must wait for the slowest indexed chain to
1481
+ * add new blocks or to discover new blocks through the configured RPCs.
1482
+ * - if any indexed chain gets "stuck" due to chain or RPC failures, all indexed chains
1483
+ * will be affected.
1484
+ */
1485
+ Omnichain: "omnichain"
1486
+ };
1487
+
1488
+ // src/shared/block-ref.ts
1489
+ function isBefore(blockA, blockB) {
1490
+ return blockA.number < blockB.number && blockA.timestamp < blockB.timestamp;
1491
+ }
1492
+ function isEqualTo(blockA, blockB) {
1493
+ return blockA.number === blockB.number && blockA.timestamp === blockB.timestamp;
1494
+ }
1495
+ function isBeforeOrEqualTo(blockA, blockB) {
1496
+ return isBefore(blockA, blockB) || isEqualTo(blockA, blockB);
1497
+ }
1498
+
1499
+ // src/ensindexer/indexing-status/helpers.ts
1500
+ function getOmnichainIndexingStatus(chains) {
1501
+ if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing(chains)) {
1502
+ return OmnichainIndexingStatusIds.Following;
1503
+ }
1504
+ if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill(chains)) {
1505
+ return OmnichainIndexingStatusIds.Backfill;
1506
+ }
1507
+ if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted(chains)) {
1508
+ return OmnichainIndexingStatusIds.Unstarted;
1509
+ }
1510
+ if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted(chains)) {
1511
+ return OmnichainIndexingStatusIds.Completed;
1512
+ }
1513
+ throw new Error(`Unable to determine omnichain indexing status for provided chains.`);
1514
+ }
1515
+ function getTimestampForLowestOmnichainStartBlock(chains) {
1516
+ const earliestKnownBlockTimestamps = chains.map(
1517
+ (chain) => chain.config.startBlock.timestamp
1518
+ );
1519
+ return Math.min(...earliestKnownBlockTimestamps);
1520
+ }
1521
+ function getTimestampForHighestOmnichainKnownBlock(chains) {
1522
+ const latestKnownBlockTimestamps = [];
1523
+ for (const chain of chains) {
1524
+ switch (chain.chainStatus) {
1525
+ case ChainIndexingStatusIds.Queued:
1526
+ if (chain.config.configType === ChainIndexingConfigTypeIds.Definite && chain.config.endBlock) {
1527
+ latestKnownBlockTimestamps.push(chain.config.endBlock.timestamp);
1528
+ }
1529
+ break;
1530
+ case ChainIndexingStatusIds.Backfill:
1531
+ latestKnownBlockTimestamps.push(chain.backfillEndBlock.timestamp);
1532
+ break;
1533
+ case ChainIndexingStatusIds.Completed:
1534
+ latestKnownBlockTimestamps.push(chain.latestIndexedBlock.timestamp);
1535
+ break;
1536
+ case ChainIndexingStatusIds.Following:
1537
+ latestKnownBlockTimestamps.push(chain.latestKnownBlock.timestamp);
1538
+ break;
1539
+ }
1540
+ }
1541
+ return Math.max(...latestKnownBlockTimestamps);
1542
+ }
1543
+ function getOmnichainIndexingCursor(chains) {
1544
+ if (chains.length === 0) {
1545
+ throw new Error(`Unable to determine omnichain indexing cursor when no chains were provided.`);
1546
+ }
1547
+ if (getOmnichainIndexingStatus(chains) === OmnichainIndexingStatusIds.Unstarted) {
1548
+ const earliestStartBlockTimestamps = chains.map((chain) => chain.config.startBlock.timestamp);
1549
+ return Math.min(...earliestStartBlockTimestamps) - 1;
1550
+ }
1551
+ const latestIndexedBlockTimestamps = chains.filter((chain) => chain.chainStatus !== ChainIndexingStatusIds.Queued).map((chain) => chain.latestIndexedBlock.timestamp);
1552
+ if (latestIndexedBlockTimestamps.length < 1) {
1553
+ throw new Error("latestIndexedBlockTimestamps array must include at least one element");
1554
+ }
1555
+ return Math.max(...latestIndexedBlockTimestamps);
1556
+ }
1557
+ function createIndexingConfig(startBlock, endBlock) {
1558
+ if (endBlock) {
1559
+ return {
1560
+ configType: ChainIndexingConfigTypeIds.Definite,
1561
+ startBlock,
1562
+ endBlock
1563
+ };
1564
+ }
1565
+ return {
1566
+ configType: ChainIndexingConfigTypeIds.Indefinite,
1567
+ startBlock
1568
+ };
1569
+ }
1570
+ function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted(chains) {
1571
+ return chains.every((chain) => chain.chainStatus === ChainIndexingStatusIds.Queued);
1572
+ }
1573
+ function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill(chains) {
1574
+ const atLeastOneChainInTargetStatus = chains.some(
1575
+ (chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill
1576
+ );
1577
+ const otherChainsHaveValidStatuses = chains.every(
1578
+ (chain) => chain.chainStatus === ChainIndexingStatusIds.Queued || chain.chainStatus === ChainIndexingStatusIds.Backfill || chain.chainStatus === ChainIndexingStatusIds.Completed
1579
+ );
1580
+ return atLeastOneChainInTargetStatus && otherChainsHaveValidStatuses;
1581
+ }
1582
+ function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted(chains) {
1583
+ const allChainsHaveValidStatuses = chains.every(
1584
+ (chain) => chain.chainStatus === ChainIndexingStatusIds.Completed
1585
+ );
1586
+ return allChainsHaveValidStatuses;
1587
+ }
1588
+ function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing(chains) {
1589
+ const allChainsHaveValidStatuses = chains.some(
1590
+ (chain) => chain.chainStatus === ChainIndexingStatusIds.Following
1591
+ );
1592
+ return allChainsHaveValidStatuses;
1593
+ }
1594
+ function sortChainStatusesByStartBlockAsc(chains) {
1595
+ chains.sort(
1596
+ ([, chainA], [, chainB]) => chainA.config.startBlock.timestamp - chainB.config.startBlock.timestamp
1597
+ );
1598
+ return chains;
1599
+ }
1600
+ function getLatestIndexedBlockRef(indexingStatus, chainId) {
1601
+ const chainIndexingStatus = indexingStatus.omnichainSnapshot.chains.get(chainId);
1602
+ if (chainIndexingStatus === void 0) {
1603
+ return null;
1604
+ }
1605
+ if (chainIndexingStatus.chainStatus === ChainIndexingStatusIds.Queued) {
1606
+ return null;
1607
+ }
1608
+ return chainIndexingStatus.latestIndexedBlock;
1609
+ }
1610
+
1611
+ // src/ensindexer/indexing-status/validations.ts
1612
+ function invariant_chainSnapshotQueuedBlocks(ctx) {
1613
+ const { config } = ctx.value;
1614
+ if (config.configType === ChainIndexingConfigTypeIds.Indefinite) {
1615
+ return;
1616
+ }
1617
+ if (config.endBlock && isBeforeOrEqualTo(config.startBlock, config.endBlock) === false) {
1618
+ ctx.issues.push({
1619
+ code: "custom",
1620
+ input: ctx.value,
1621
+ message: "`config.startBlock` must be before or same as `config.endBlock`."
1622
+ });
1623
+ }
1624
+ }
1625
+ function invariant_chainSnapshotBackfillBlocks(ctx) {
1626
+ const { config, latestIndexedBlock, backfillEndBlock } = ctx.value;
1627
+ if (isBeforeOrEqualTo(config.startBlock, latestIndexedBlock) === false) {
1628
+ ctx.issues.push({
1629
+ code: "custom",
1630
+ input: ctx.value,
1631
+ message: "`config.startBlock` must be before or same as `latestIndexedBlock`."
1632
+ });
1633
+ }
1634
+ if (isBeforeOrEqualTo(latestIndexedBlock, backfillEndBlock) === false) {
1635
+ ctx.issues.push({
1636
+ code: "custom",
1637
+ input: ctx.value,
1638
+ message: "`latestIndexedBlock` must be before or same as `backfillEndBlock`."
1639
+ });
1640
+ }
1641
+ if (config.configType === ChainIndexingConfigTypeIds.Indefinite) {
1642
+ return;
1643
+ }
1644
+ if (config.endBlock && isEqualTo(backfillEndBlock, config.endBlock) === false) {
1645
+ ctx.issues.push({
1646
+ code: "custom",
1647
+ input: ctx.value,
1648
+ message: "`backfillEndBlock` must be the same as `config.endBlock`."
1649
+ });
1650
+ }
1651
+ }
1652
+ function invariant_chainSnapshotCompletedBlocks(ctx) {
1653
+ const { config, latestIndexedBlock } = ctx.value;
1654
+ if (isBeforeOrEqualTo(config.startBlock, latestIndexedBlock) === false) {
1655
+ ctx.issues.push({
1656
+ code: "custom",
1657
+ input: ctx.value,
1658
+ message: "`config.startBlock` must be before or same as `latestIndexedBlock`."
1659
+ });
1660
+ }
1661
+ if (isBeforeOrEqualTo(latestIndexedBlock, config.endBlock) === false) {
1662
+ ctx.issues.push({
1663
+ code: "custom",
1664
+ input: ctx.value,
1665
+ message: "`latestIndexedBlock` must be before or same as `config.endBlock`."
1666
+ });
1667
+ }
1668
+ }
1669
+ function invariant_chainSnapshotFollowingBlocks(ctx) {
1670
+ const { config, latestIndexedBlock, latestKnownBlock } = ctx.value;
1671
+ if (isBeforeOrEqualTo(config.startBlock, latestIndexedBlock) === false) {
1672
+ ctx.issues.push({
1673
+ code: "custom",
1674
+ input: ctx.value,
1675
+ message: "`config.startBlock` must be before or same as `latestIndexedBlock`."
1676
+ });
1677
+ }
1678
+ if (isBeforeOrEqualTo(latestIndexedBlock, latestKnownBlock) === false) {
1679
+ ctx.issues.push({
1680
+ code: "custom",
1681
+ input: ctx.value,
1682
+ message: "`latestIndexedBlock` must be before or same as `latestKnownBlock`."
1683
+ });
1684
+ }
1685
+ }
1686
+ function invariant_omnichainSnapshotStatusIsConsistentWithChainSnapshot(ctx) {
1687
+ const snapshot = ctx.value;
1688
+ const chains = Array.from(snapshot.chains.values());
1689
+ const expectedOmnichainStatus = getOmnichainIndexingStatus(chains);
1690
+ const actualOmnichainStatus = snapshot.omnichainStatus;
1691
+ if (expectedOmnichainStatus !== actualOmnichainStatus) {
1692
+ ctx.issues.push({
1693
+ code: "custom",
1694
+ input: snapshot,
1695
+ message: `'${actualOmnichainStatus}' is an invalid omnichainStatus. Expected '${expectedOmnichainStatus}' based on the statuses of individual chains.`
1696
+ });
1697
+ }
1698
+ }
1699
+ function invariant_omnichainIndexingCursorLowerThanEarliestStartBlockAcrossQueuedChains(ctx) {
1700
+ const snapshot = ctx.value;
1701
+ const queuedChains = Array.from(snapshot.chains.values()).filter(
1702
+ (chain) => chain.chainStatus === ChainIndexingStatusIds.Queued
1703
+ );
1704
+ if (queuedChains.length === 0) {
1705
+ return;
1706
+ }
1707
+ const queuedChainStartBlocks = queuedChains.map((chain) => chain.config.startBlock.timestamp);
1708
+ const queuedChainEarliestStartBlock = Math.min(...queuedChainStartBlocks);
1709
+ if (snapshot.omnichainIndexingCursor >= queuedChainEarliestStartBlock) {
1710
+ ctx.issues.push({
1711
+ code: "custom",
1712
+ input: snapshot,
1713
+ message: "`omnichainIndexingCursor` must be lower than the earliest start block across all queued chains."
1714
+ });
1715
+ }
1716
+ }
1717
+ function invariant_omnichainIndexingCursorLowerThanOrEqualToLatestBackfillEndBlockAcrossBackfillChains(ctx) {
1718
+ const snapshot = ctx.value;
1719
+ const backfillChains = Array.from(snapshot.chains.values()).filter(
1720
+ (chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill
1721
+ );
1722
+ if (backfillChains.length === 0) {
1723
+ return;
1724
+ }
1725
+ const backfillEndBlocks = backfillChains.map((chain) => chain.backfillEndBlock.timestamp);
1726
+ const highestBackfillEndBlock = Math.max(...backfillEndBlocks);
1727
+ if (snapshot.omnichainIndexingCursor > highestBackfillEndBlock) {
1728
+ ctx.issues.push({
1729
+ code: "custom",
1730
+ input: snapshot,
1731
+ message: "`omnichainIndexingCursor` must be lower than or equal to the highest `backfillEndBlock` across all backfill chains."
1732
+ });
1733
+ }
1734
+ }
1735
+ function invariant_omnichainIndexingCursorIsEqualToHighestLatestIndexedBlockAcrossIndexedChain(ctx) {
1736
+ const snapshot = ctx.value;
1737
+ const indexedChains = Array.from(snapshot.chains.values()).filter(
1738
+ (chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill || chain.chainStatus === ChainIndexingStatusIds.Completed || chain.chainStatus === ChainIndexingStatusIds.Following
1739
+ );
1740
+ if (indexedChains.length === 0) {
1741
+ return;
1742
+ }
1743
+ const indexedChainLatestIndexedBlocks = indexedChains.map(
1744
+ (chain) => chain.latestIndexedBlock.timestamp
1745
+ );
1746
+ const indexedChainHighestLatestIndexedBlock = Math.max(...indexedChainLatestIndexedBlocks);
1747
+ if (snapshot.omnichainIndexingCursor !== indexedChainHighestLatestIndexedBlock) {
1748
+ ctx.issues.push({
1749
+ code: "custom",
1750
+ input: snapshot,
1751
+ message: "`omnichainIndexingCursor` must be same as the highest `latestIndexedBlock` across all indexed chains."
1752
+ });
1753
+ }
1754
+ }
1755
+ function invariant_omnichainSnapshotUnstartedHasValidChains(ctx) {
1756
+ const chains = ctx.value;
1757
+ const hasValidChains = checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted(
1758
+ Array.from(chains.values())
1759
+ );
1760
+ if (hasValidChains === false) {
1761
+ ctx.issues.push({
1762
+ code: "custom",
1763
+ input: chains,
1764
+ message: `For omnichain status snapshot 'unstarted', all chains must have "queued" status.`
1765
+ });
1766
+ }
1767
+ }
1768
+ function invariant_omnichainStatusSnapshotBackfillHasValidChains(ctx) {
1769
+ const chains = ctx.value;
1770
+ const hasValidChains = checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill(
1771
+ Array.from(chains.values())
1772
+ );
1773
+ if (hasValidChains === false) {
1774
+ ctx.issues.push({
1775
+ code: "custom",
1776
+ input: chains,
1777
+ message: `For omnichain status snapshot 'backfill', at least one chain must be in "backfill" status and each chain has to have a status of either "queued", "backfill" or "completed".`
1778
+ });
1779
+ }
1780
+ }
1781
+ function invariant_omnichainStatusSnapshotCompletedHasValidChains(ctx) {
1782
+ const chains = ctx.value;
1783
+ const hasValidChains = checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted(
1784
+ Array.from(chains.values())
1785
+ );
1786
+ if (hasValidChains === false) {
1787
+ ctx.issues.push({
1788
+ code: "custom",
1789
+ input: chains,
1790
+ message: `For omnichain status snapshot 'completed', all chains must have "completed" status.`
1791
+ });
1792
+ }
1793
+ }
1794
+ function invariant_slowestChainEqualsToOmnichainSnapshotTime(ctx) {
1795
+ const { slowestChainIndexingCursor, omnichainSnapshot } = ctx.value;
1796
+ const { omnichainIndexingCursor } = omnichainSnapshot;
1797
+ if (slowestChainIndexingCursor !== omnichainIndexingCursor) {
1798
+ console.log("invariant_slowestChainEqualsToOmnichainSnapshotTime", {
1799
+ slowestChainIndexingCursor,
1800
+ omnichainIndexingCursor
1801
+ });
1802
+ ctx.issues.push({
1803
+ code: "custom",
1804
+ input: ctx.value,
1805
+ message: `'slowestChainIndexingCursor' must be equal to 'omnichainSnapshot.omnichainIndexingCursor'`
1806
+ });
1807
+ }
1808
+ }
1809
+ function invariant_snapshotTimeIsTheHighestKnownBlockTimestamp(ctx) {
1810
+ const { snapshotTime, omnichainSnapshot } = ctx.value;
1811
+ const chains = Array.from(omnichainSnapshot.chains.values());
1812
+ const startBlockTimestamps = chains.map((chain) => chain.config.startBlock.timestamp);
1813
+ const endBlockTimestamps = chains.map((chain) => chain.config).filter((chainConfig) => chainConfig.configType === ChainIndexingConfigTypeIds.Definite).map((chainConfig) => chainConfig.endBlock.timestamp);
1814
+ const backfillEndBlockTimestamps = chains.filter((chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill).map((chain) => chain.backfillEndBlock.timestamp);
1815
+ const latestKnownBlockTimestamps = chains.filter((chain) => chain.chainStatus === ChainIndexingStatusIds.Following).map((chain) => chain.latestKnownBlock.timestamp);
1816
+ const highestKnownBlockTimestamp = Math.max(
1817
+ ...startBlockTimestamps,
1818
+ ...endBlockTimestamps,
1819
+ ...backfillEndBlockTimestamps,
1820
+ ...latestKnownBlockTimestamps
1821
+ );
1822
+ if (snapshotTime < highestKnownBlockTimestamp) {
1823
+ ctx.issues.push({
1824
+ code: "custom",
1825
+ input: ctx.value,
1826
+ message: `'snapshotTime' must be greater than or equal to the "highest known block timestamp" (${highestKnownBlockTimestamp})`
1827
+ });
1828
+ }
1829
+ }
1830
+ function invariant_realtimeIndexingStatusProjectionProjectedAtIsAfterOrEqualToSnapshotTime(ctx) {
1831
+ const projection = ctx.value;
1832
+ const { snapshot, projectedAt } = projection;
1833
+ if (snapshot.snapshotTime > projectedAt) {
1834
+ ctx.issues.push({
1835
+ code: "custom",
1836
+ input: projection,
1837
+ message: "`projectedAt` must be after or same as `snapshot.snapshotTime`."
1838
+ });
1839
+ }
1840
+ }
1841
+ function invariant_realtimeIndexingStatusProjectionWorstCaseDistanceIsCorrect(ctx) {
1842
+ const projection = ctx.value;
1843
+ const { projectedAt, snapshot, worstCaseDistance } = projection;
1844
+ const { omnichainSnapshot } = snapshot;
1845
+ const expectedWorstCaseDistance = projectedAt - omnichainSnapshot.omnichainIndexingCursor;
1846
+ if (worstCaseDistance !== expectedWorstCaseDistance) {
1847
+ ctx.issues.push({
1848
+ code: "custom",
1849
+ input: projection,
1850
+ message: "`worstCaseDistance` must be the exact difference between `projectedAt` and `snapshot.omnichainIndexingCursor`."
1851
+ });
1852
+ }
1853
+ }
1854
+
1855
+ // src/ensindexer/indexing-status/zod-schemas.ts
1856
+ var makeChainIndexingConfigSchema = (valueLabel = "Value") => import_v47.default.discriminatedUnion("configType", [
1857
+ import_v47.default.strictObject({
1858
+ configType: import_v47.default.literal(ChainIndexingConfigTypeIds.Indefinite),
1859
+ startBlock: makeBlockRefSchema(valueLabel)
1860
+ }),
1861
+ import_v47.default.strictObject({
1862
+ configType: import_v47.default.literal(ChainIndexingConfigTypeIds.Definite),
1863
+ startBlock: makeBlockRefSchema(valueLabel),
1864
+ endBlock: makeBlockRefSchema(valueLabel)
1865
+ })
1866
+ ]);
1867
+ var makeChainIndexingStatusSnapshotQueuedSchema = (valueLabel = "Value") => import_v47.default.strictObject({
1868
+ chainStatus: import_v47.default.literal(ChainIndexingStatusIds.Queued),
1869
+ config: makeChainIndexingConfigSchema(valueLabel)
1870
+ }).check(invariant_chainSnapshotQueuedBlocks);
1871
+ var makeChainIndexingStatusSnapshotBackfillSchema = (valueLabel = "Value") => import_v47.default.strictObject({
1872
+ chainStatus: import_v47.default.literal(ChainIndexingStatusIds.Backfill),
1873
+ config: makeChainIndexingConfigSchema(valueLabel),
1874
+ latestIndexedBlock: makeBlockRefSchema(valueLabel),
1875
+ backfillEndBlock: makeBlockRefSchema(valueLabel)
1876
+ }).check(invariant_chainSnapshotBackfillBlocks);
1877
+ var makeChainIndexingStatusSnapshotCompletedSchema = (valueLabel = "Value") => import_v47.default.strictObject({
1878
+ chainStatus: import_v47.default.literal(ChainIndexingStatusIds.Completed),
1879
+ config: import_v47.default.strictObject({
1880
+ configType: import_v47.default.literal(ChainIndexingConfigTypeIds.Definite),
1881
+ startBlock: makeBlockRefSchema(valueLabel),
1882
+ endBlock: makeBlockRefSchema(valueLabel)
1883
+ }),
1884
+ latestIndexedBlock: makeBlockRefSchema(valueLabel)
1885
+ }).check(invariant_chainSnapshotCompletedBlocks);
1886
+ var makeChainIndexingStatusSnapshotFollowingSchema = (valueLabel = "Value") => import_v47.default.strictObject({
1887
+ chainStatus: import_v47.default.literal(ChainIndexingStatusIds.Following),
1888
+ config: import_v47.default.strictObject({
1889
+ configType: import_v47.default.literal(ChainIndexingConfigTypeIds.Indefinite),
1890
+ startBlock: makeBlockRefSchema(valueLabel)
1891
+ }),
1892
+ latestIndexedBlock: makeBlockRefSchema(valueLabel),
1893
+ latestKnownBlock: makeBlockRefSchema(valueLabel)
1894
+ }).check(invariant_chainSnapshotFollowingBlocks);
1895
+ var makeChainIndexingStatusSnapshotSchema = (valueLabel = "Value") => import_v47.default.discriminatedUnion("chainStatus", [
1896
+ makeChainIndexingStatusSnapshotQueuedSchema(valueLabel),
1897
+ makeChainIndexingStatusSnapshotBackfillSchema(valueLabel),
1898
+ makeChainIndexingStatusSnapshotCompletedSchema(valueLabel),
1899
+ makeChainIndexingStatusSnapshotFollowingSchema(valueLabel)
1900
+ ]);
1901
+ var makeChainIndexingStatusesSchema = (valueLabel = "Value") => import_v47.default.record(makeChainIdStringSchema(), makeChainIndexingStatusSnapshotSchema(valueLabel), {
1902
+ error: "Chains indexing statuses must be an object mapping valid chain IDs to their indexing status snapshots."
1903
+ }).transform((serializedChainsIndexingStatus) => {
1904
+ const chainsIndexingStatus = /* @__PURE__ */ new Map();
1905
+ for (const [chainIdString, chainStatus] of Object.entries(serializedChainsIndexingStatus)) {
1906
+ chainsIndexingStatus.set(deserializeChainId(chainIdString), chainStatus);
1206
1907
  }
1207
- return Math.max(...latestKnownBlockTimestamps);
1908
+ return chainsIndexingStatus;
1909
+ });
1910
+ var makeOmnichainIndexingStatusSnapshotUnstartedSchema = (valueLabel) => import_v47.default.strictObject({
1911
+ omnichainStatus: import_v47.default.literal(OmnichainIndexingStatusIds.Unstarted),
1912
+ chains: makeChainIndexingStatusesSchema(valueLabel).check(invariant_omnichainSnapshotUnstartedHasValidChains).transform((chains) => chains),
1913
+ omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
1914
+ });
1915
+ var makeOmnichainIndexingStatusSnapshotBackfillSchema = (valueLabel) => import_v47.default.strictObject({
1916
+ omnichainStatus: import_v47.default.literal(OmnichainIndexingStatusIds.Backfill),
1917
+ chains: makeChainIndexingStatusesSchema(valueLabel).check(invariant_omnichainStatusSnapshotBackfillHasValidChains).transform(
1918
+ (chains) => chains
1919
+ ),
1920
+ omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
1921
+ });
1922
+ var makeOmnichainIndexingStatusSnapshotCompletedSchema = (valueLabel) => import_v47.default.strictObject({
1923
+ omnichainStatus: import_v47.default.literal(OmnichainIndexingStatusIds.Completed),
1924
+ chains: makeChainIndexingStatusesSchema(valueLabel).check(invariant_omnichainStatusSnapshotCompletedHasValidChains).transform((chains) => chains),
1925
+ omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
1926
+ });
1927
+ var makeOmnichainIndexingStatusSnapshotFollowingSchema = (valueLabel) => import_v47.default.strictObject({
1928
+ omnichainStatus: import_v47.default.literal(OmnichainIndexingStatusIds.Following),
1929
+ chains: makeChainIndexingStatusesSchema(valueLabel),
1930
+ omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
1931
+ });
1932
+ var makeOmnichainIndexingStatusSnapshotSchema = (valueLabel = "Omnichain Indexing Snapshot") => import_v47.default.discriminatedUnion("omnichainStatus", [
1933
+ makeOmnichainIndexingStatusSnapshotUnstartedSchema(valueLabel),
1934
+ makeOmnichainIndexingStatusSnapshotBackfillSchema(valueLabel),
1935
+ makeOmnichainIndexingStatusSnapshotCompletedSchema(valueLabel),
1936
+ makeOmnichainIndexingStatusSnapshotFollowingSchema(valueLabel)
1937
+ ]).check(invariant_omnichainSnapshotStatusIsConsistentWithChainSnapshot).check(invariant_omnichainIndexingCursorLowerThanEarliestStartBlockAcrossQueuedChains).check(
1938
+ invariant_omnichainIndexingCursorLowerThanOrEqualToLatestBackfillEndBlockAcrossBackfillChains
1939
+ ).check(invariant_omnichainIndexingCursorIsEqualToHighestLatestIndexedBlockAcrossIndexedChain);
1940
+ var makeCrossChainIndexingStatusSnapshotOmnichainSchema = (valueLabel = "Cross-chain Indexing Status Snapshot Omnichain") => import_v47.default.strictObject({
1941
+ strategy: import_v47.default.literal(CrossChainIndexingStrategyIds.Omnichain),
1942
+ slowestChainIndexingCursor: makeUnixTimestampSchema(valueLabel),
1943
+ snapshotTime: makeUnixTimestampSchema(valueLabel),
1944
+ omnichainSnapshot: makeOmnichainIndexingStatusSnapshotSchema(valueLabel)
1945
+ }).check(invariant_slowestChainEqualsToOmnichainSnapshotTime).check(invariant_snapshotTimeIsTheHighestKnownBlockTimestamp);
1946
+ var makeCrossChainIndexingStatusSnapshotSchema = (valueLabel = "Cross-chain Indexing Status Snapshot") => import_v47.default.discriminatedUnion("strategy", [
1947
+ makeCrossChainIndexingStatusSnapshotOmnichainSchema(valueLabel)
1948
+ ]);
1949
+ var makeRealtimeIndexingStatusProjectionSchema = (valueLabel = "Realtime Indexing Status Projection") => import_v47.default.strictObject({
1950
+ projectedAt: makeUnixTimestampSchema(valueLabel),
1951
+ worstCaseDistance: makeDurationSchema(valueLabel),
1952
+ snapshot: makeCrossChainIndexingStatusSnapshotSchema(valueLabel)
1953
+ }).check(invariant_realtimeIndexingStatusProjectionProjectedAtIsAfterOrEqualToSnapshotTime).check(invariant_realtimeIndexingStatusProjectionWorstCaseDistanceIsCorrect);
1954
+
1955
+ // src/ensindexer/indexing-status/deserialize.ts
1956
+ function deserializeChainIndexingStatusSnapshot(maybeSnapshot, valueLabel) {
1957
+ const schema = makeChainIndexingStatusSnapshotSchema(valueLabel);
1958
+ const parsed = schema.safeParse(maybeSnapshot);
1959
+ if (parsed.error) {
1960
+ throw new Error(
1961
+ `Cannot deserialize into ChainIndexingStatusSnapshot:
1962
+ ${(0, import_v48.prettifyError)(parsed.error)}
1963
+ `
1964
+ );
1965
+ }
1966
+ return parsed.data;
1208
1967
  }
1209
- function getOmnichainIndexingCursor(chains) {
1210
- if (chains.length === 0) {
1211
- throw new Error(`Unable to determine omnichain indexing cursor when no chains were provided.`);
1968
+ function deserializeOmnichainIndexingStatusSnapshot(maybeSnapshot, valueLabel) {
1969
+ const schema = makeOmnichainIndexingStatusSnapshotSchema(valueLabel);
1970
+ const parsed = schema.safeParse(maybeSnapshot);
1971
+ if (parsed.error) {
1972
+ throw new Error(
1973
+ `Cannot deserialize into OmnichainIndexingStatusSnapshot:
1974
+ ${(0, import_v48.prettifyError)(parsed.error)}
1975
+ `
1976
+ );
1212
1977
  }
1213
- if (getOmnichainIndexingStatus(chains) === OmnichainIndexingStatusIds.Unstarted) {
1214
- const earliestStartBlockTimestamps = chains.map((chain) => chain.config.startBlock.timestamp);
1215
- return Math.min(...earliestStartBlockTimestamps) - 1;
1978
+ return parsed.data;
1979
+ }
1980
+ function deserializeCrossChainIndexingStatusSnapshot(maybeSnapshot, valueLabel) {
1981
+ const schema = makeCrossChainIndexingStatusSnapshotSchema(valueLabel);
1982
+ const parsed = schema.safeParse(maybeSnapshot);
1983
+ if (parsed.error) {
1984
+ throw new Error(
1985
+ `Cannot deserialize into CrossChainIndexingStatusSnapshot:
1986
+ ${(0, import_v48.prettifyError)(parsed.error)}
1987
+ `
1988
+ );
1216
1989
  }
1217
- const latestIndexedBlockTimestamps = chains.filter((chain) => chain.chainStatus !== ChainIndexingStatusIds.Queued).map((chain) => chain.latestIndexedBlock.timestamp);
1218
- if (latestIndexedBlockTimestamps.length < 1) {
1219
- throw new Error("latestIndexedBlockTimestamps array must include at least one element");
1990
+ return parsed.data;
1991
+ }
1992
+ function deserializeRealtimeIndexingStatusProjection(maybeProjection, valueLabel) {
1993
+ const schema = makeRealtimeIndexingStatusProjectionSchema(valueLabel);
1994
+ const parsed = schema.safeParse(maybeProjection);
1995
+ if (parsed.error) {
1996
+ throw new Error(
1997
+ `Cannot deserialize into RealtimeIndexingStatusProjection:
1998
+ ${(0, import_v48.prettifyError)(parsed.error)}
1999
+ `
2000
+ );
1220
2001
  }
1221
- return Math.max(...latestIndexedBlockTimestamps);
2002
+ return parsed.data;
1222
2003
  }
1223
- function createIndexingConfig(startBlock, endBlock) {
1224
- if (endBlock) {
1225
- return {
1226
- configType: ChainIndexingConfigTypeIds.Definite,
1227
- startBlock,
1228
- endBlock
1229
- };
2004
+
2005
+ // src/ensindexer/indexing-status/projection.ts
2006
+ function createRealtimeIndexingStatusProjection(snapshot, now) {
2007
+ const projectedAt = Math.max(now, snapshot.snapshotTime);
2008
+ return {
2009
+ projectedAt,
2010
+ worstCaseDistance: projectedAt - snapshot.slowestChainIndexingCursor,
2011
+ snapshot
2012
+ };
2013
+ }
2014
+
2015
+ // src/ensindexer/indexing-status/serialize.ts
2016
+ function serializeCrossChainIndexingStatusSnapshotOmnichain({
2017
+ strategy,
2018
+ slowestChainIndexingCursor,
2019
+ snapshotTime,
2020
+ omnichainSnapshot
2021
+ }) {
2022
+ return {
2023
+ strategy,
2024
+ slowestChainIndexingCursor,
2025
+ snapshotTime,
2026
+ omnichainSnapshot: serializeOmnichainIndexingStatusSnapshot(omnichainSnapshot)
2027
+ };
2028
+ }
2029
+ function serializeRealtimeIndexingStatusProjection(indexingProjection) {
2030
+ return {
2031
+ projectedAt: indexingProjection.projectedAt,
2032
+ worstCaseDistance: indexingProjection.worstCaseDistance,
2033
+ snapshot: serializeCrossChainIndexingStatusSnapshotOmnichain(indexingProjection.snapshot)
2034
+ };
2035
+ }
2036
+ function serializeChainIndexingSnapshots(chains) {
2037
+ const serializedSnapshots = {};
2038
+ for (const [chainId, snapshot] of chains.entries()) {
2039
+ serializedSnapshots[serializeChainId(chainId)] = snapshot;
2040
+ }
2041
+ return serializedSnapshots;
2042
+ }
2043
+ function serializeOmnichainIndexingStatusSnapshot(indexingStatus) {
2044
+ switch (indexingStatus.omnichainStatus) {
2045
+ case OmnichainIndexingStatusIds.Unstarted:
2046
+ return {
2047
+ omnichainStatus: OmnichainIndexingStatusIds.Unstarted,
2048
+ chains: serializeChainIndexingSnapshots(indexingStatus.chains),
2049
+ omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
2050
+ };
2051
+ case OmnichainIndexingStatusIds.Backfill:
2052
+ return {
2053
+ omnichainStatus: OmnichainIndexingStatusIds.Backfill,
2054
+ chains: serializeChainIndexingSnapshots(indexingStatus.chains),
2055
+ omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
2056
+ };
2057
+ case OmnichainIndexingStatusIds.Completed: {
2058
+ return {
2059
+ omnichainStatus: OmnichainIndexingStatusIds.Completed,
2060
+ chains: serializeChainIndexingSnapshots(indexingStatus.chains),
2061
+ omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
2062
+ };
2063
+ }
2064
+ case OmnichainIndexingStatusIds.Following:
2065
+ return {
2066
+ omnichainStatus: OmnichainIndexingStatusIds.Following,
2067
+ chains: serializeChainIndexingSnapshots(indexingStatus.chains),
2068
+ omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
2069
+ };
1230
2070
  }
2071
+ }
2072
+
2073
+ // src/ensapi/config/serialize.ts
2074
+ function serializeENSApiPublicConfig(config) {
2075
+ const { version, theGraphFallback, ensIndexerPublicConfig } = config;
1231
2076
  return {
1232
- configType: ChainIndexingConfigTypeIds.Indefinite,
1233
- startBlock
2077
+ version,
2078
+ theGraphFallback,
2079
+ ensIndexerPublicConfig: serializeENSIndexerPublicConfig(ensIndexerPublicConfig)
1234
2080
  };
1235
2081
  }
1236
- function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted(chains) {
1237
- return chains.every((chain) => chain.chainStatus === ChainIndexingStatusIds.Queued);
2082
+
2083
+ // src/api/config/deserialize.ts
2084
+ function deserializeConfigResponse(serializedResponse) {
2085
+ return deserializeENSApiPublicConfig(serializedResponse);
1238
2086
  }
1239
- function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill(chains) {
1240
- const atLeastOneChainInTargetStatus = chains.some(
1241
- (chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill
1242
- );
1243
- const otherChainsHaveValidStatuses = chains.every(
1244
- (chain) => chain.chainStatus === ChainIndexingStatusIds.Queued || chain.chainStatus === ChainIndexingStatusIds.Backfill || chain.chainStatus === ChainIndexingStatusIds.Completed
1245
- );
1246
- return atLeastOneChainInTargetStatus && otherChainsHaveValidStatuses;
2087
+
2088
+ // src/api/config/serialize.ts
2089
+ function serializeConfigResponse(response) {
2090
+ return serializeENSApiPublicConfig(response);
1247
2091
  }
1248
- function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted(chains) {
1249
- const allChainsHaveValidStatuses = chains.every(
1250
- (chain) => chain.chainStatus === ChainIndexingStatusIds.Completed
1251
- );
1252
- return allChainsHaveValidStatuses;
2092
+
2093
+ // src/api/indexing-status/deserialize.ts
2094
+ var import_v410 = require("zod/v4");
2095
+
2096
+ // src/api/indexing-status/zod-schemas.ts
2097
+ var import_v49 = __toESM(require("zod/v4"), 1);
2098
+
2099
+ // src/api/indexing-status/response.ts
2100
+ var IndexingStatusResponseCodes = {
2101
+ /**
2102
+ * Represents that the indexing status is available.
2103
+ */
2104
+ Ok: "ok",
2105
+ /**
2106
+ * Represents that the indexing status is unavailable.
2107
+ */
2108
+ Error: "error"
2109
+ };
2110
+
2111
+ // src/api/indexing-status/zod-schemas.ts
2112
+ var makeIndexingStatusResponseOkSchema = (valueLabel = "Indexing Status Response OK") => import_v49.default.strictObject({
2113
+ responseCode: import_v49.default.literal(IndexingStatusResponseCodes.Ok),
2114
+ realtimeProjection: makeRealtimeIndexingStatusProjectionSchema(valueLabel)
2115
+ });
2116
+ var makeIndexingStatusResponseErrorSchema = (_valueLabel = "Indexing Status Response Error") => import_v49.default.strictObject({
2117
+ responseCode: import_v49.default.literal(IndexingStatusResponseCodes.Error)
2118
+ });
2119
+ var makeIndexingStatusResponseSchema = (valueLabel = "Indexing Status Response") => import_v49.default.discriminatedUnion("responseCode", [
2120
+ makeIndexingStatusResponseOkSchema(valueLabel),
2121
+ makeIndexingStatusResponseErrorSchema(valueLabel)
2122
+ ]);
2123
+
2124
+ // src/api/indexing-status/deserialize.ts
2125
+ function deserializeIndexingStatusResponse(maybeResponse) {
2126
+ const parsed = makeIndexingStatusResponseSchema().safeParse(maybeResponse);
2127
+ if (parsed.error) {
2128
+ throw new Error(`Cannot deserialize IndexingStatusResponse:
2129
+ ${(0, import_v410.prettifyError)(parsed.error)}
2130
+ `);
2131
+ }
2132
+ return parsed.data;
2133
+ }
2134
+
2135
+ // src/api/indexing-status/serialize.ts
2136
+ function serializeIndexingStatusResponse(response) {
2137
+ switch (response.responseCode) {
2138
+ case IndexingStatusResponseCodes.Ok:
2139
+ return {
2140
+ responseCode: response.responseCode,
2141
+ realtimeProjection: serializeRealtimeIndexingStatusProjection(response.realtimeProjection)
2142
+ };
2143
+ case IndexingStatusResponseCodes.Error:
2144
+ return response;
2145
+ }
2146
+ }
2147
+
2148
+ // src/api/name-tokens/deserialize.ts
2149
+ var import_v415 = require("zod/v4");
2150
+
2151
+ // src/api/name-tokens/zod-schemas.ts
2152
+ var import_viem14 = require("viem");
2153
+ var import_v414 = __toESM(require("zod/v4"), 1);
2154
+
2155
+ // src/tokenscope/assets.ts
2156
+ var import_caip4 = require("caip");
2157
+ var import_viem13 = require("viem");
2158
+ var import_v412 = require("zod/v4");
2159
+
2160
+ // src/tokenscope/zod-schemas.ts
2161
+ var import_caip3 = require("caip");
2162
+ var import_viem12 = require("viem");
2163
+ var import_v411 = __toESM(require("zod/v4"), 1);
2164
+
2165
+ // src/tokenscope/name-token.ts
2166
+ var import_viem11 = require("viem");
2167
+ var import_datasources5 = require("@ensnode/datasources");
2168
+ var NameTokenOwnershipTypes = {
2169
+ /**
2170
+ * Name Token is owned by NameWrapper account.
2171
+ */
2172
+ NameWrapper: "namewrapper",
2173
+ /**
2174
+ * Name Token is owned fully onchain.
2175
+ *
2176
+ * This ownership type can only apply to direct subnames of `.eth`
2177
+ */
2178
+ FullyOnchain: "fully-onchain",
2179
+ /**
2180
+ * Name Token ownership has been transferred to the null address.
2181
+ */
2182
+ Burned: "burned",
2183
+ /**
2184
+ * Name Token ownership is unknown.
2185
+ */
2186
+ Unknown: "unknown"
2187
+ };
2188
+ function serializeNameToken(nameToken) {
2189
+ return {
2190
+ token: serializeAssetId(nameToken.token),
2191
+ ownership: nameToken.ownership,
2192
+ mintStatus: nameToken.mintStatus
2193
+ };
1253
2194
  }
1254
- function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing(chains) {
1255
- const allChainsHaveValidStatuses = chains.some(
1256
- (chain) => chain.chainStatus === ChainIndexingStatusIds.Following
2195
+ function getNameWrapperAccounts(namespaceId) {
2196
+ const ethnamesNameWrapperAccount = getDatasourceContract(
2197
+ namespaceId,
2198
+ import_datasources5.DatasourceNames.ENSRoot,
2199
+ "NameWrapper"
1257
2200
  );
1258
- return allChainsHaveValidStatuses;
1259
- }
1260
- function sortChainStatusesByStartBlockAsc(chains) {
1261
- chains.sort(
1262
- ([, chainA], [, chainB]) => chainA.config.startBlock.timestamp - chainB.config.startBlock.timestamp
2201
+ const lineanamesNameWrapperAccount = maybeGetDatasourceContract(
2202
+ namespaceId,
2203
+ import_datasources5.DatasourceNames.Lineanames,
2204
+ "NameWrapper"
1263
2205
  );
1264
- return chains;
1265
- }
1266
- function getLatestIndexedBlockRef(indexingStatus, chainId) {
1267
- const chainIndexingStatus = indexingStatus.omnichainSnapshot.chains.get(chainId);
1268
- if (chainIndexingStatus === void 0) {
1269
- return null;
1270
- }
1271
- if (chainIndexingStatus.chainStatus === ChainIndexingStatusIds.Queued) {
1272
- return null;
1273
- }
1274
- return chainIndexingStatus.latestIndexedBlock;
1275
- }
1276
-
1277
- // src/ensindexer/indexing-status/validations.ts
1278
- function invariant_chainSnapshotQueuedBlocks(ctx) {
1279
- const { config } = ctx.value;
1280
- if (config.configType === ChainIndexingConfigTypeIds.Indefinite) {
1281
- return;
1282
- }
1283
- if (config.endBlock && isBeforeOrEqualTo(config.startBlock, config.endBlock) === false) {
1284
- ctx.issues.push({
1285
- code: "custom",
1286
- input: ctx.value,
1287
- message: "`config.startBlock` must be before or same as `config.endBlock`."
1288
- });
1289
- }
2206
+ const nameWrapperAccounts = [
2207
+ // NameWrapper for direct subnames of .eth is defined for all ENS namespaces
2208
+ ethnamesNameWrapperAccount
2209
+ ];
2210
+ if (lineanamesNameWrapperAccount) {
2211
+ nameWrapperAccounts.push(lineanamesNameWrapperAccount);
2212
+ }
2213
+ return nameWrapperAccounts;
1290
2214
  }
1291
- function invariant_chainSnapshotBackfillBlocks(ctx) {
1292
- const { config, latestIndexedBlock, backfillEndBlock } = ctx.value;
1293
- if (isBeforeOrEqualTo(config.startBlock, latestIndexedBlock) === false) {
1294
- ctx.issues.push({
1295
- code: "custom",
1296
- input: ctx.value,
1297
- message: "`config.startBlock` must be before or same as `latestIndexedBlock`."
1298
- });
1299
- }
1300
- if (isBeforeOrEqualTo(latestIndexedBlock, backfillEndBlock) === false) {
1301
- ctx.issues.push({
1302
- code: "custom",
1303
- input: ctx.value,
1304
- message: "`latestIndexedBlock` must be before or same as `backfillEndBlock`."
1305
- });
2215
+ function getNameTokenOwnership(namespaceId, name, owner) {
2216
+ const nameWrapperAccounts = getNameWrapperAccounts(namespaceId);
2217
+ const hasNameWrapperOwnership = nameWrapperAccounts.some(
2218
+ (nameWrapperAccount) => accountIdEqual(owner, nameWrapperAccount)
2219
+ );
2220
+ if (hasNameWrapperOwnership) {
2221
+ return {
2222
+ ownershipType: NameTokenOwnershipTypes.NameWrapper,
2223
+ owner
2224
+ };
1306
2225
  }
1307
- if (config.configType === ChainIndexingConfigTypeIds.Indefinite) {
1308
- return;
2226
+ if ((0, import_viem11.isAddressEqual)(owner.address, import_viem11.zeroAddress)) {
2227
+ return {
2228
+ ownershipType: NameTokenOwnershipTypes.Burned,
2229
+ owner
2230
+ };
1309
2231
  }
1310
- if (config.endBlock && isEqualTo(backfillEndBlock, config.endBlock) === false) {
1311
- ctx.issues.push({
1312
- code: "custom",
1313
- input: ctx.value,
1314
- message: "`backfillEndBlock` must be the same as `config.endBlock`."
1315
- });
2232
+ const parentName = getParentNameFQDN(name);
2233
+ if (parentName === "eth") {
2234
+ return {
2235
+ ownershipType: NameTokenOwnershipTypes.FullyOnchain,
2236
+ owner
2237
+ };
1316
2238
  }
2239
+ return {
2240
+ ownershipType: NameTokenOwnershipTypes.Unknown,
2241
+ owner
2242
+ };
1317
2243
  }
1318
- function invariant_chainSnapshotCompletedBlocks(ctx) {
1319
- const { config, latestIndexedBlock } = ctx.value;
1320
- if (isBeforeOrEqualTo(config.startBlock, latestIndexedBlock) === false) {
1321
- ctx.issues.push({
1322
- code: "custom",
1323
- input: ctx.value,
1324
- message: "`config.startBlock` must be before or same as `latestIndexedBlock`."
1325
- });
2244
+
2245
+ // src/tokenscope/zod-schemas.ts
2246
+ var makeAssetIdSchema = (valueLabel = "Asset ID Schema") => import_v411.default.object({
2247
+ assetNamespace: import_v411.default.enum(AssetNamespaces),
2248
+ contract: makeAccountIdSchema(valueLabel),
2249
+ tokenId: import_v411.default.preprocess((v) => typeof v === "string" ? BigInt(v) : v, import_v411.default.bigint().positive())
2250
+ });
2251
+ var makeAssetIdStringSchema = (valueLabel = "Asset ID String Schema") => import_v411.default.preprocess((v) => {
2252
+ if (typeof v === "string") {
2253
+ const result = new import_caip3.AssetId(v);
2254
+ return {
2255
+ assetNamespace: result.assetName.namespace,
2256
+ contract: {
2257
+ chainId: Number(result.chainId.reference),
2258
+ address: result.assetName.reference
2259
+ },
2260
+ tokenId: result.tokenId
2261
+ };
1326
2262
  }
1327
- if (isBeforeOrEqualTo(latestIndexedBlock, config.endBlock) === false) {
2263
+ return v;
2264
+ }, makeAssetIdSchema(valueLabel));
2265
+ function invariant_nameTokenOwnershipHasNonZeroAddressOwner(ctx) {
2266
+ const ownership = ctx.value;
2267
+ if (ctx.value.owner.address === import_viem12.zeroAddress) {
1328
2268
  ctx.issues.push({
1329
2269
  code: "custom",
1330
2270
  input: ctx.value,
1331
- message: "`latestIndexedBlock` must be before or same as `config.endBlock`."
2271
+ message: `Name Token Ownership with '${ownership.ownershipType}' must have 'address' other than the zero address.`
1332
2272
  });
1333
2273
  }
1334
2274
  }
1335
- function invariant_chainSnapshotFollowingBlocks(ctx) {
1336
- const { config, latestIndexedBlock, latestKnownBlock } = ctx.value;
1337
- if (isBeforeOrEqualTo(config.startBlock, latestIndexedBlock) === false) {
1338
- ctx.issues.push({
1339
- code: "custom",
1340
- input: ctx.value,
1341
- message: "`config.startBlock` must be before or same as `latestIndexedBlock`."
1342
- });
1343
- }
1344
- if (isBeforeOrEqualTo(latestIndexedBlock, latestKnownBlock) === false) {
2275
+ var makeNameTokenOwnershipNameWrapperSchema = (valueLabel = "Name Token Ownership NameWrapper") => import_v411.default.object({
2276
+ ownershipType: import_v411.default.literal(NameTokenOwnershipTypes.NameWrapper),
2277
+ owner: makeAccountIdSchema(`${valueLabel}.owner`)
2278
+ }).check(invariant_nameTokenOwnershipHasNonZeroAddressOwner);
2279
+ var makeNameTokenOwnershipFullyOnchainSchema = (valueLabel = "Name Token Ownership Fully Onchain") => import_v411.default.object({
2280
+ ownershipType: import_v411.default.literal(NameTokenOwnershipTypes.FullyOnchain),
2281
+ owner: makeAccountIdSchema(`${valueLabel}.owner`)
2282
+ }).check(invariant_nameTokenOwnershipHasNonZeroAddressOwner);
2283
+ var makeNameTokenOwnershipBurnedSchema = (valueLabel = "Name Token Ownership Burned") => import_v411.default.object({
2284
+ ownershipType: import_v411.default.literal(NameTokenOwnershipTypes.Burned),
2285
+ owner: makeAccountIdSchema(`${valueLabel}.owner`)
2286
+ }).check(invariant_nameTokenOwnershipHasZeroAddressOwner);
2287
+ var makeNameTokenOwnershipUnknownSchema = (valueLabel = "Name Token Ownership Unknown") => import_v411.default.object({
2288
+ ownershipType: import_v411.default.literal(NameTokenOwnershipTypes.Unknown),
2289
+ owner: makeAccountIdSchema(`${valueLabel}.owner`)
2290
+ }).check(invariant_nameTokenOwnershipHasNonZeroAddressOwner);
2291
+ function invariant_nameTokenOwnershipHasZeroAddressOwner(ctx) {
2292
+ const ownership = ctx.value;
2293
+ if (ctx.value.owner.address !== import_viem12.zeroAddress) {
1345
2294
  ctx.issues.push({
1346
2295
  code: "custom",
1347
2296
  input: ctx.value,
1348
- message: "`latestIndexedBlock` must be before or same as `latestKnownBlock`."
2297
+ message: `Name Token Ownership with '${ownership.ownershipType}' must have 'address' set to the zero address.`
1349
2298
  });
1350
2299
  }
1351
2300
  }
1352
- function invariant_omnichainSnapshotStatusIsConsistentWithChainSnapshot(ctx) {
1353
- const snapshot = ctx.value;
1354
- const chains = Array.from(snapshot.chains.values());
1355
- const expectedOmnichainStatus = getOmnichainIndexingStatus(chains);
1356
- const actualOmnichainStatus = snapshot.omnichainStatus;
1357
- if (expectedOmnichainStatus !== actualOmnichainStatus) {
1358
- ctx.issues.push({
1359
- code: "custom",
1360
- input: snapshot,
1361
- message: `'${actualOmnichainStatus}' is an invalid omnichainStatus. Expected '${expectedOmnichainStatus}' based on the statuses of individual chains.`
1362
- });
1363
- }
2301
+ var makeNameTokenOwnershipSchema = (valueLabel = "Name Token Ownership") => import_v411.default.discriminatedUnion("ownershipType", [
2302
+ makeNameTokenOwnershipNameWrapperSchema(valueLabel),
2303
+ makeNameTokenOwnershipFullyOnchainSchema(valueLabel),
2304
+ makeNameTokenOwnershipBurnedSchema(valueLabel),
2305
+ makeNameTokenOwnershipUnknownSchema(valueLabel)
2306
+ ]);
2307
+ var makeNameTokenSchema = (valueLabel = "Name Token Schema") => import_v411.default.object({
2308
+ token: makeAssetIdSchema(`${valueLabel}.token`),
2309
+ ownership: makeNameTokenOwnershipSchema(`${valueLabel}.ownership`),
2310
+ mintStatus: import_v411.default.enum(NFTMintStatuses)
2311
+ });
2312
+
2313
+ // src/tokenscope/assets.ts
2314
+ var AssetNamespaces = {
2315
+ ERC721: "erc721",
2316
+ ERC1155: "erc1155"
2317
+ };
2318
+ function serializeAssetId(assetId) {
2319
+ return {
2320
+ assetNamespace: assetId.assetNamespace,
2321
+ contract: assetId.contract,
2322
+ tokenId: uint256ToHex32(assetId.tokenId)
2323
+ };
1364
2324
  }
1365
- function invariant_omnichainIndexingCursorLowerThanEarliestStartBlockAcrossQueuedChains(ctx) {
1366
- const snapshot = ctx.value;
1367
- const queuedChains = Array.from(snapshot.chains.values()).filter(
1368
- (chain) => chain.chainStatus === ChainIndexingStatusIds.Queued
1369
- );
1370
- if (queuedChains.length === 0) {
1371
- return;
1372
- }
1373
- const queuedChainStartBlocks = queuedChains.map((chain) => chain.config.startBlock.timestamp);
1374
- const queuedChainEarliestStartBlock = Math.min(...queuedChainStartBlocks);
1375
- if (snapshot.omnichainIndexingCursor >= queuedChainEarliestStartBlock) {
1376
- ctx.issues.push({
1377
- code: "custom",
1378
- input: snapshot,
1379
- message: "`omnichainIndexingCursor` must be lower than the earliest start block across all queued chains."
1380
- });
2325
+ function deserializeAssetId(maybeAssetId, valueLabel) {
2326
+ const schema = makeAssetIdSchema(valueLabel);
2327
+ const parsed = schema.safeParse(maybeAssetId);
2328
+ if (parsed.error) {
2329
+ throw new RangeError(`Cannot deserialize AssetId:
2330
+ ${(0, import_v412.prettifyError)(parsed.error)}
2331
+ `);
1381
2332
  }
2333
+ return parsed.data;
1382
2334
  }
1383
- function invariant_omnichainIndexingCursorLowerThanOrEqualToLatestBackfillEndBlockAcrossBackfillChains(ctx) {
1384
- const snapshot = ctx.value;
1385
- const backfillChains = Array.from(snapshot.chains.values()).filter(
1386
- (chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill
1387
- );
1388
- if (backfillChains.length === 0) {
1389
- return;
1390
- }
1391
- const backfillEndBlocks = backfillChains.map((chain) => chain.backfillEndBlock.timestamp);
1392
- const highestBackfillEndBlock = Math.max(...backfillEndBlocks);
1393
- if (snapshot.omnichainIndexingCursor > highestBackfillEndBlock) {
1394
- ctx.issues.push({
1395
- code: "custom",
1396
- input: snapshot,
1397
- message: "`omnichainIndexingCursor` must be lower than or equal to the highest `backfillEndBlock` across all backfill chains."
1398
- });
1399
- }
2335
+ function formatAssetId(assetId) {
2336
+ const { assetNamespace, contract, tokenId } = serializeAssetId(assetId);
2337
+ return import_caip4.AssetId.format({
2338
+ chainId: { namespace: "eip155", reference: contract.chainId.toString() },
2339
+ assetName: { namespace: assetNamespace, reference: contract.address },
2340
+ tokenId
2341
+ }).toLowerCase();
1400
2342
  }
1401
- function invariant_omnichainIndexingCursorIsEqualToHighestLatestIndexedBlockAcrossIndexedChain(ctx) {
1402
- const snapshot = ctx.value;
1403
- const indexedChains = Array.from(snapshot.chains.values()).filter(
1404
- (chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill || chain.chainStatus === ChainIndexingStatusIds.Completed || chain.chainStatus === ChainIndexingStatusIds.Following
1405
- );
1406
- if (indexedChains.length === 0) {
1407
- return;
1408
- }
1409
- const indexedChainLatestIndexedBlocks = indexedChains.map(
1410
- (chain) => chain.latestIndexedBlock.timestamp
1411
- );
1412
- const indexedChainHighestLatestIndexedBlock = Math.max(...indexedChainLatestIndexedBlocks);
1413
- if (snapshot.omnichainIndexingCursor !== indexedChainHighestLatestIndexedBlock) {
1414
- ctx.issues.push({
1415
- code: "custom",
1416
- input: snapshot,
1417
- message: "`omnichainIndexingCursor` must be same as the highest `latestIndexedBlock` across all indexed chains."
1418
- });
2343
+ function parseAssetId(maybeAssetId, valueLabel) {
2344
+ const schema = makeAssetIdStringSchema(valueLabel);
2345
+ const parsed = schema.safeParse(maybeAssetId);
2346
+ if (parsed.error) {
2347
+ throw new RangeError(`Cannot parse AssetId:
2348
+ ${(0, import_v412.prettifyError)(parsed.error)}
2349
+ `);
1419
2350
  }
2351
+ return parsed.data;
1420
2352
  }
1421
- function invariant_omnichainSnapshotUnstartedHasValidChains(ctx) {
1422
- const chains = ctx.value;
1423
- const hasValidChains = checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted(
1424
- Array.from(chains.values())
1425
- );
1426
- if (hasValidChains === false) {
1427
- ctx.issues.push({
1428
- code: "custom",
1429
- input: chains,
1430
- message: `For omnichain status snapshot 'unstarted', all chains must have "queued" status.`
1431
- });
1432
- }
2353
+ var buildAssetId = (contract, tokenId, assetNamespace) => {
2354
+ return {
2355
+ assetNamespace,
2356
+ contract,
2357
+ tokenId
2358
+ };
2359
+ };
2360
+ function serializeDomainAssetId(domainAsset) {
2361
+ return {
2362
+ ...serializeAssetId(domainAsset),
2363
+ domainId: domainAsset.domainId
2364
+ };
1433
2365
  }
1434
- function invariant_omnichainStatusSnapshotBackfillHasValidChains(ctx) {
1435
- const chains = ctx.value;
1436
- const hasValidChains = checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill(
1437
- Array.from(chains.values())
1438
- );
1439
- if (hasValidChains === false) {
1440
- ctx.issues.push({
1441
- code: "custom",
1442
- input: chains,
1443
- message: `For omnichain status snapshot 'backfill', at least one chain must be in "backfill" status and each chain has to have a status of either "queued", "backfill" or "completed".`
1444
- });
2366
+ var NFTMintStatuses = {
2367
+ Minted: "minted",
2368
+ Burned: "burned"
2369
+ };
2370
+ var formatNFTTransferEventMetadata = (metadata) => {
2371
+ const serializedAssetId = serializeAssetId(metadata.nft);
2372
+ return [
2373
+ `Event: ${metadata.eventHandlerName}`,
2374
+ `Chain ID: ${metadata.chainId}`,
2375
+ `Block Number: ${metadata.blockNumber}`,
2376
+ `Transaction Hash: ${metadata.transactionHash}`,
2377
+ `NFT: ${serializedAssetId}`
2378
+ ].map((line) => ` - ${line}`).join("\n");
2379
+ };
2380
+ var NFTTransferTypes = {
2381
+ /**
2382
+ * Initial transfer from zeroAddress to a non-zeroAddress
2383
+ * Can happen at most once to a NFT AssetId
2384
+ *
2385
+ * Invariants:
2386
+ * - NFT is not indexed and therefore has no previous mint status or owner
2387
+ * - new NFT mint status is `minted`
2388
+ * - new NFT owner is a non-zeroAddress
2389
+ */
2390
+ Mint: "mint",
2391
+ /**
2392
+ * Subsequent transfer from zeroAddress to a non-zeroAddress
2393
+ * Can happen any number of times to a NFT AssetId as it passes in a cycle from
2394
+ * mint -> burn -> remint -> burn -> remint -> ...
2395
+ *
2396
+ * Invariants:
2397
+ * - NFT is indexed
2398
+ * - previous NFT mint status was `burned`
2399
+ * - previous NFT owner is the zeroAddress
2400
+ * - new NFT mint status is `minted`
2401
+ * - new NFT owner is a non-zeroAddress
2402
+ */
2403
+ Remint: "remint",
2404
+ /**
2405
+ * Special transfer type for improperly implemented NFT contracts that allow a NFT
2406
+ * that is currently minted to be reminted before an intermediate burn.
2407
+ *
2408
+ * Transfer from zeroAddress to non-zeroAddress for an indexed NFT where the
2409
+ * previously indexed nft had status `minted` with a non-zeroAddress owner.
2410
+ *
2411
+ * Invariants:
2412
+ * - NFT is indexed
2413
+ * - previous NFT mint status was `minted`
2414
+ * - previous NFT owner was a non-zeroAddress
2415
+ * - new NFT mint status is `minted`
2416
+ * - new NFT owner is a non-zeroAddress
2417
+ */
2418
+ MintedRemint: "minted-remint",
2419
+ /**
2420
+ * Transfer from a non-zeroAddress to zeroAddress
2421
+ *
2422
+ * Invariants:
2423
+ * - NFT is indexed
2424
+ * - previous NFT mint status was `minted`
2425
+ * - previous NFT owner is a non-zeroAddress
2426
+ * - new NFT mint status is `burned`
2427
+ * - new NFT owner is the zeroAddress
2428
+ */
2429
+ Burn: "burn",
2430
+ /**
2431
+ * Transfer from a non-zeroAddress to a distinct non-zeroAddress
2432
+ *
2433
+ * Invariants:
2434
+ * - NFT is indexed
2435
+ * - previous and new NFT mint status is `minted`
2436
+ * - previous and new NFT owner are distinct non-zeroAddress
2437
+ */
2438
+ Transfer: "transfer",
2439
+ /**
2440
+ * Transfer from a non-zeroAddress to the same non-zeroAddress
2441
+ *
2442
+ * Invariants:
2443
+ * - NFT is indexed
2444
+ * - previous and new NFT mint status is `minted`
2445
+ * - previous and new NFT owner are equivalent non-zeroAddress
2446
+ */
2447
+ SelfTransfer: "self-transfer",
2448
+ /**
2449
+ * Transfer from zeroAddress to zeroAddress for an indexed NFT
2450
+ *
2451
+ * Invariants:
2452
+ * - NFT is indexed
2453
+ * - previous and new NFT mint status is `burned`
2454
+ * - previous and new NFT owner are zeroAddress
2455
+ */
2456
+ RemintBurn: "remint-burn",
2457
+ /**
2458
+ * Special transfer type for improperly implemented NFT contracts that allow a NFT
2459
+ * that is currently minted to be reminted again before an intermediate burn.
2460
+ *
2461
+ * Transfer from zeroAddress to zeroAddress for an indexed NFT where the
2462
+ * previously indexed nft had status `minted` with a non-zeroAddress owner.
2463
+ *
2464
+ * Invariants:
2465
+ * - NFT is indexed
2466
+ * - previous NFT mint status was `minted`
2467
+ * - previous NFT owner was a non-zeroAddress
2468
+ * - new NFT mint status is `burned`
2469
+ * - new NFT owner is the zeroAddress
2470
+ */
2471
+ MintedRemintBurn: "minted-remint-burn",
2472
+ /**
2473
+ * Transfer from zeroAddress to zeroAddress for an unindexed NFT
2474
+ *
2475
+ * Invariants:
2476
+ * - NFT is not indexed and therefore has no previous mint status or owner
2477
+ * - NFT should remain unindexed and without any mint status or owner
2478
+ */
2479
+ MintBurn: "mint-burn"
2480
+ };
2481
+ var getNFTTransferType = (from, to, allowMintedRemint, metadata, currentlyIndexedOwner) => {
2482
+ const isIndexed = currentlyIndexedOwner !== void 0;
2483
+ const isIndexedAsMinted = isIndexed && !(0, import_viem13.isAddressEqual)(currentlyIndexedOwner, import_viem13.zeroAddress);
2484
+ const isMint = (0, import_viem13.isAddressEqual)(from, import_viem13.zeroAddress);
2485
+ const isBurn = (0, import_viem13.isAddressEqual)(to, import_viem13.zeroAddress);
2486
+ const isSelfTransfer = (0, import_viem13.isAddressEqual)(from, to);
2487
+ if (isIndexed && !(0, import_viem13.isAddressEqual)(currentlyIndexedOwner, from)) {
2488
+ if (isMint && allowMintedRemint) {
2489
+ } else {
2490
+ throw new Error(
2491
+ `Error: Sending from ${from} conflicts with currently indexed owner ${currentlyIndexedOwner}.
2492
+ ${formatNFTTransferEventMetadata(metadata)}`
2493
+ );
2494
+ }
1445
2495
  }
1446
- }
1447
- function invariant_omnichainStatusSnapshotCompletedHasValidChains(ctx) {
1448
- const chains = ctx.value;
1449
- const hasValidChains = checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted(
1450
- Array.from(chains.values())
1451
- );
1452
- if (hasValidChains === false) {
1453
- ctx.issues.push({
1454
- code: "custom",
1455
- input: chains,
1456
- message: `For omnichain status snapshot 'completed', all chains must have "completed" status.`
1457
- });
2496
+ if (isSelfTransfer) {
2497
+ if (isMint) {
2498
+ if (!isIndexed) {
2499
+ return NFTTransferTypes.MintBurn;
2500
+ } else if (!isIndexedAsMinted) {
2501
+ return NFTTransferTypes.RemintBurn;
2502
+ } else if (allowMintedRemint) {
2503
+ return NFTTransferTypes.MintedRemintBurn;
2504
+ } else {
2505
+ throw new Error(
2506
+ `Error: Invalid state transition from minted -> remint-burn
2507
+ ${formatNFTTransferEventMetadata(metadata)}`
2508
+ );
2509
+ }
2510
+ } else {
2511
+ if (!isIndexed) {
2512
+ throw new Error(
2513
+ `Error: Invalid state transition from unindexed -> self-transfer
2514
+ ${formatNFTTransferEventMetadata(metadata)}`
2515
+ );
2516
+ } else if (!isIndexedAsMinted) {
2517
+ throw new Error(
2518
+ `Error: invalid state transition from burned -> self-transfer
2519
+ ${formatNFTTransferEventMetadata(metadata)}`
2520
+ );
2521
+ } else {
2522
+ return NFTTransferTypes.SelfTransfer;
2523
+ }
2524
+ }
2525
+ } else if (isMint) {
2526
+ if (!isIndexed) {
2527
+ return NFTTransferTypes.Mint;
2528
+ } else if (!isIndexedAsMinted) {
2529
+ return NFTTransferTypes.Remint;
2530
+ } else if (allowMintedRemint) {
2531
+ return NFTTransferTypes.MintedRemint;
2532
+ } else {
2533
+ throw new Error(
2534
+ `Error: Invalid state transition from minted -> mint
2535
+ ${formatNFTTransferEventMetadata(metadata)}`
2536
+ );
2537
+ }
2538
+ } else if (isBurn) {
2539
+ if (!isIndexed) {
2540
+ throw new Error(
2541
+ `Error: Invalid state transition from unindexed -> burn
2542
+ ${formatNFTTransferEventMetadata(metadata)}`
2543
+ );
2544
+ } else if (!isIndexedAsMinted) {
2545
+ throw new Error(
2546
+ `Error: Invalid state transition from burned -> burn
2547
+ ${formatNFTTransferEventMetadata(metadata)}`
2548
+ );
2549
+ } else {
2550
+ return NFTTransferTypes.Burn;
2551
+ }
2552
+ } else {
2553
+ if (!isIndexed) {
2554
+ throw new Error(
2555
+ `Error: Invalid state transition from unindexed -> transfer
2556
+ ${formatNFTTransferEventMetadata(metadata)}`
2557
+ );
2558
+ } else if (!isIndexedAsMinted) {
2559
+ throw new Error(
2560
+ `Error: Invalid state transition from burned -> transfer
2561
+ ${formatNFTTransferEventMetadata(metadata)}`
2562
+ );
2563
+ } else {
2564
+ return NFTTransferTypes.Transfer;
2565
+ }
1458
2566
  }
1459
- }
1460
- function invariant_slowestChainEqualsToOmnichainSnapshotTime(ctx) {
1461
- const { slowestChainIndexingCursor, omnichainSnapshot } = ctx.value;
1462
- const { omnichainIndexingCursor } = omnichainSnapshot;
1463
- if (slowestChainIndexingCursor !== omnichainIndexingCursor) {
1464
- console.log("invariant_slowestChainEqualsToOmnichainSnapshotTime", {
1465
- slowestChainIndexingCursor,
1466
- omnichainIndexingCursor
1467
- });
2567
+ };
2568
+
2569
+ // src/api/shared/errors/zod-schemas.ts
2570
+ var import_v413 = __toESM(require("zod/v4"), 1);
2571
+ var ErrorResponseSchema = import_v413.default.object({
2572
+ message: import_v413.default.string(),
2573
+ details: import_v413.default.optional(import_v413.default.unknown())
2574
+ });
2575
+
2576
+ // src/api/name-tokens/response.ts
2577
+ var NameTokensResponseCodes = {
2578
+ /**
2579
+ * Represents a response when Name Tokens API can respond with requested data.
2580
+ */
2581
+ Ok: "ok",
2582
+ /**
2583
+ * Represents a response when Name Tokens API could not respond with requested data.
2584
+ */
2585
+ Error: "error"
2586
+ };
2587
+ var NameTokensResponseErrorCodes = {
2588
+ /**
2589
+ * Name tokens not indexed
2590
+ *
2591
+ * Represents an error when tokens for the requested name are not indexed by
2592
+ * the ENSNode instance's configuration.
2593
+ */
2594
+ NameTokensNotIndexed: "name-tokens-not-indexed",
2595
+ /**
2596
+ * Unsupported ENSIndexer Config
2597
+ *
2598
+ * Represents a prerequisites error when connected ENSIndexer config lacks
2599
+ * params required to enable Name Tokens API.
2600
+ */
2601
+ EnsIndexerConfigUnsupported: "unsupported-ensindexer-config",
2602
+ /**
2603
+ * Unsupported Indexing Status
2604
+ *
2605
+ * Represents a prerequisites error when Indexing Status has not yet reached
2606
+ * status required to enable Name Tokens API.
2607
+ */
2608
+ IndexingStatusUnsupported: "unsupported-indexing-status"
2609
+ };
2610
+
2611
+ // src/api/name-tokens/zod-schemas.ts
2612
+ function invariant_nameIsAssociatedWithDomainId(ctx) {
2613
+ const { name, domainId } = ctx.value;
2614
+ if ((0, import_viem14.namehash)(name) !== domainId) {
1468
2615
  ctx.issues.push({
1469
2616
  code: "custom",
1470
2617
  input: ctx.value,
1471
- message: `'slowestChainIndexingCursor' must be equal to 'omnichainSnapshot.omnichainIndexingCursor'`
2618
+ message: `'name' must be associated with 'domainId': ${domainId}`
1472
2619
  });
1473
2620
  }
1474
2621
  }
1475
- function invariant_snapshotTimeIsTheHighestKnownBlockTimestamp(ctx) {
1476
- const { snapshotTime, omnichainSnapshot } = ctx.value;
1477
- const chains = Array.from(omnichainSnapshot.chains.values());
1478
- const startBlockTimestamps = chains.map((chain) => chain.config.startBlock.timestamp);
1479
- const endBlockTimestamps = chains.map((chain) => chain.config).filter((chainConfig) => chainConfig.configType === ChainIndexingConfigTypeIds.Definite).map((chainConfig) => chainConfig.endBlock.timestamp);
1480
- const backfillEndBlockTimestamps = chains.filter((chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill).map((chain) => chain.backfillEndBlock.timestamp);
1481
- const latestKnownBlockTimestamps = chains.filter((chain) => chain.chainStatus === ChainIndexingStatusIds.Following).map((chain) => chain.latestKnownBlock.timestamp);
1482
- const highestKnownBlockTimestamp = Math.max(
1483
- ...startBlockTimestamps,
1484
- ...endBlockTimestamps,
1485
- ...backfillEndBlockTimestamps,
1486
- ...latestKnownBlockTimestamps
2622
+ function invariant_nameTokensOwnershipTypeNameWrapperRequiresOwnershipTypeFullyOnchainOrUnknown(ctx) {
2623
+ const { tokens } = ctx.value;
2624
+ const containsOwnershipNameWrapper = tokens.some(
2625
+ (t) => t.ownership.ownershipType === NameTokenOwnershipTypes.NameWrapper
1487
2626
  );
1488
- if (snapshotTime < highestKnownBlockTimestamp) {
2627
+ const containsOwnershipFullyOnchainOrUnknown = tokens.some(
2628
+ (t) => t.ownership.ownershipType === NameTokenOwnershipTypes.FullyOnchain || t.ownership.ownershipType === NameTokenOwnershipTypes.Unknown
2629
+ );
2630
+ if (containsOwnershipNameWrapper && !containsOwnershipFullyOnchainOrUnknown) {
1489
2631
  ctx.issues.push({
1490
2632
  code: "custom",
1491
2633
  input: ctx.value,
1492
- message: `'snapshotTime' must be greater than or equal to the "highest known block timestamp" (${highestKnownBlockTimestamp})`
1493
- });
1494
- }
1495
- }
1496
- function invariant_realtimeIndexingStatusProjectionProjectedAtIsAfterOrEqualToSnapshotTime(ctx) {
1497
- const projection = ctx.value;
1498
- const { snapshot, projectedAt } = projection;
1499
- if (snapshot.snapshotTime > projectedAt) {
1500
- ctx.issues.push({
1501
- code: "custom",
1502
- input: projection,
1503
- message: "`projectedAt` must be after or same as `snapshot.snapshotTime`."
2634
+ message: `'tokens' must contain name token with ownership type 'fully-onchain' or 'unknown' when name token with ownership type 'namewrapper' in listed`
1504
2635
  });
1505
2636
  }
1506
2637
  }
1507
- function invariant_realtimeIndexingStatusProjectionWorstCaseDistanceIsCorrect(ctx) {
1508
- const projection = ctx.value;
1509
- const { projectedAt, snapshot, worstCaseDistance } = projection;
1510
- const { omnichainSnapshot } = snapshot;
1511
- const expectedWorstCaseDistance = projectedAt - omnichainSnapshot.omnichainIndexingCursor;
1512
- if (worstCaseDistance !== expectedWorstCaseDistance) {
2638
+ function invariant_nameTokensContainAtMostOneWithOwnershipTypeEffective(ctx) {
2639
+ const { tokens } = ctx.value;
2640
+ const tokensCountWithOwnershipFullyOnchain = tokens.filter(
2641
+ (t) => t.ownership.ownershipType === NameTokenOwnershipTypes.FullyOnchain
2642
+ ).length;
2643
+ if (tokensCountWithOwnershipFullyOnchain > 1) {
1513
2644
  ctx.issues.push({
1514
2645
  code: "custom",
1515
- input: projection,
1516
- message: "`worstCaseDistance` must be the exact difference between `projectedAt` and `snapshot.omnichainIndexingCursor`."
2646
+ input: ctx.value,
2647
+ message: `'tokens' must contain at most one name token with ownership type 'fully-onchain', current count: ${tokensCountWithOwnershipFullyOnchain}`
1517
2648
  });
1518
2649
  }
1519
2650
  }
1520
-
1521
- // src/ensindexer/indexing-status/zod-schemas.ts
1522
- var makeChainIndexingConfigSchema = (valueLabel = "Value") => import_v43.default.discriminatedUnion("configType", [
1523
- import_v43.default.strictObject({
1524
- configType: import_v43.default.literal(ChainIndexingConfigTypeIds.Indefinite),
1525
- startBlock: makeBlockRefSchema(valueLabel)
1526
- }),
1527
- import_v43.default.strictObject({
1528
- configType: import_v43.default.literal(ChainIndexingConfigTypeIds.Definite),
1529
- startBlock: makeBlockRefSchema(valueLabel),
1530
- endBlock: makeBlockRefSchema(valueLabel)
1531
- })
1532
- ]);
1533
- var makeChainIndexingStatusSnapshotQueuedSchema = (valueLabel = "Value") => import_v43.default.strictObject({
1534
- chainStatus: import_v43.default.literal(ChainIndexingStatusIds.Queued),
1535
- config: makeChainIndexingConfigSchema(valueLabel)
1536
- }).check(invariant_chainSnapshotQueuedBlocks);
1537
- var makeChainIndexingStatusSnapshotBackfillSchema = (valueLabel = "Value") => import_v43.default.strictObject({
1538
- chainStatus: import_v43.default.literal(ChainIndexingStatusIds.Backfill),
1539
- config: makeChainIndexingConfigSchema(valueLabel),
1540
- latestIndexedBlock: makeBlockRefSchema(valueLabel),
1541
- backfillEndBlock: makeBlockRefSchema(valueLabel)
1542
- }).check(invariant_chainSnapshotBackfillBlocks);
1543
- var makeChainIndexingStatusSnapshotCompletedSchema = (valueLabel = "Value") => import_v43.default.strictObject({
1544
- chainStatus: import_v43.default.literal(ChainIndexingStatusIds.Completed),
1545
- config: import_v43.default.strictObject({
1546
- configType: import_v43.default.literal(ChainIndexingConfigTypeIds.Definite),
1547
- startBlock: makeBlockRefSchema(valueLabel),
1548
- endBlock: makeBlockRefSchema(valueLabel)
1549
- }),
1550
- latestIndexedBlock: makeBlockRefSchema(valueLabel)
1551
- }).check(invariant_chainSnapshotCompletedBlocks);
1552
- var makeChainIndexingStatusSnapshotFollowingSchema = (valueLabel = "Value") => import_v43.default.strictObject({
1553
- chainStatus: import_v43.default.literal(ChainIndexingStatusIds.Following),
1554
- config: import_v43.default.strictObject({
1555
- configType: import_v43.default.literal(ChainIndexingConfigTypeIds.Indefinite),
1556
- startBlock: makeBlockRefSchema(valueLabel)
1557
- }),
1558
- latestIndexedBlock: makeBlockRefSchema(valueLabel),
1559
- latestKnownBlock: makeBlockRefSchema(valueLabel)
1560
- }).check(invariant_chainSnapshotFollowingBlocks);
1561
- var makeChainIndexingStatusSnapshotSchema = (valueLabel = "Value") => import_v43.default.discriminatedUnion("chainStatus", [
1562
- makeChainIndexingStatusSnapshotQueuedSchema(valueLabel),
1563
- makeChainIndexingStatusSnapshotBackfillSchema(valueLabel),
1564
- makeChainIndexingStatusSnapshotCompletedSchema(valueLabel),
1565
- makeChainIndexingStatusSnapshotFollowingSchema(valueLabel)
1566
- ]);
1567
- var makeChainIndexingStatusesSchema = (valueLabel = "Value") => import_v43.default.record(makeChainIdStringSchema(), makeChainIndexingStatusSnapshotSchema(valueLabel), {
1568
- error: "Chains indexing statuses must be an object mapping valid chain IDs to their indexing status snapshots."
1569
- }).transform((serializedChainsIndexingStatus) => {
1570
- const chainsIndexingStatus = /* @__PURE__ */ new Map();
1571
- for (const [chainIdString, chainStatus] of Object.entries(serializedChainsIndexingStatus)) {
1572
- chainsIndexingStatus.set(deserializeChainId(chainIdString), chainStatus);
1573
- }
1574
- return chainsIndexingStatus;
1575
- });
1576
- var makeOmnichainIndexingStatusSnapshotUnstartedSchema = (valueLabel) => import_v43.default.strictObject({
1577
- omnichainStatus: import_v43.default.literal(OmnichainIndexingStatusIds.Unstarted),
1578
- chains: makeChainIndexingStatusesSchema(valueLabel).check(invariant_omnichainSnapshotUnstartedHasValidChains).transform((chains) => chains),
1579
- omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
2651
+ var makeRegisteredNameTokenSchema = (valueLabel = "Registered Name Token") => import_v414.default.object({
2652
+ domainId: makeNodeSchema(`${valueLabel}.domainId`),
2653
+ name: makeReinterpretedNameSchema(valueLabel),
2654
+ tokens: import_v414.default.array(makeNameTokenSchema(`${valueLabel}.tokens`)).nonempty(),
2655
+ expiresAt: makeUnixTimestampSchema(`${valueLabel}.expiresAt`),
2656
+ accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`)
2657
+ }).check(invariant_nameIsAssociatedWithDomainId).check(invariant_nameTokensContainAtMostOneWithOwnershipTypeEffective).check(invariant_nameTokensOwnershipTypeNameWrapperRequiresOwnershipTypeFullyOnchainOrUnknown);
2658
+ var makeNameTokensResponseOkSchema = (valueLabel = "Name Tokens Response OK") => import_v414.default.strictObject({
2659
+ responseCode: import_v414.default.literal(NameTokensResponseCodes.Ok),
2660
+ registeredNameTokens: makeRegisteredNameTokenSchema(`${valueLabel}.nameTokens`)
1580
2661
  });
1581
- var makeOmnichainIndexingStatusSnapshotBackfillSchema = (valueLabel) => import_v43.default.strictObject({
1582
- omnichainStatus: import_v43.default.literal(OmnichainIndexingStatusIds.Backfill),
1583
- chains: makeChainIndexingStatusesSchema(valueLabel).check(invariant_omnichainStatusSnapshotBackfillHasValidChains).transform(
1584
- (chains) => chains
1585
- ),
1586
- omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
2662
+ var makeNameTokensResponseErrorNameTokensNotIndexedSchema = (_valueLabel = "Name Tokens Response Error Name Not Indexed") => import_v414.default.strictObject({
2663
+ responseCode: import_v414.default.literal(NameTokensResponseCodes.Error),
2664
+ errorCode: import_v414.default.literal(NameTokensResponseErrorCodes.NameTokensNotIndexed),
2665
+ error: ErrorResponseSchema
1587
2666
  });
1588
- var makeOmnichainIndexingStatusSnapshotCompletedSchema = (valueLabel) => import_v43.default.strictObject({
1589
- omnichainStatus: import_v43.default.literal(OmnichainIndexingStatusIds.Completed),
1590
- chains: makeChainIndexingStatusesSchema(valueLabel).check(invariant_omnichainStatusSnapshotCompletedHasValidChains).transform((chains) => chains),
1591
- omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
2667
+ var makeNameTokensResponseErrorEnsIndexerConfigUnsupported = (_valueLabel = "Name Tokens Response Error ENSIndexer Config Unsupported") => import_v414.default.strictObject({
2668
+ responseCode: import_v414.default.literal(NameTokensResponseCodes.Error),
2669
+ errorCode: import_v414.default.literal(NameTokensResponseErrorCodes.EnsIndexerConfigUnsupported),
2670
+ error: ErrorResponseSchema
1592
2671
  });
1593
- var makeOmnichainIndexingStatusSnapshotFollowingSchema = (valueLabel) => import_v43.default.strictObject({
1594
- omnichainStatus: import_v43.default.literal(OmnichainIndexingStatusIds.Following),
1595
- chains: makeChainIndexingStatusesSchema(valueLabel),
1596
- omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
2672
+ var makeNameTokensResponseErrorNameIndexingStatusUnsupported = (_valueLabel = "Name Tokens Response Error Indexing Status Unsupported") => import_v414.default.strictObject({
2673
+ responseCode: import_v414.default.literal(NameTokensResponseCodes.Error),
2674
+ errorCode: import_v414.default.literal(NameTokensResponseErrorCodes.IndexingStatusUnsupported),
2675
+ error: ErrorResponseSchema
1597
2676
  });
1598
- var makeOmnichainIndexingStatusSnapshotSchema = (valueLabel = "Omnichain Indexing Snapshot") => import_v43.default.discriminatedUnion("omnichainStatus", [
1599
- makeOmnichainIndexingStatusSnapshotUnstartedSchema(valueLabel),
1600
- makeOmnichainIndexingStatusSnapshotBackfillSchema(valueLabel),
1601
- makeOmnichainIndexingStatusSnapshotCompletedSchema(valueLabel),
1602
- makeOmnichainIndexingStatusSnapshotFollowingSchema(valueLabel)
1603
- ]).check(invariant_omnichainSnapshotStatusIsConsistentWithChainSnapshot).check(invariant_omnichainIndexingCursorLowerThanEarliestStartBlockAcrossQueuedChains).check(
1604
- invariant_omnichainIndexingCursorLowerThanOrEqualToLatestBackfillEndBlockAcrossBackfillChains
1605
- ).check(invariant_omnichainIndexingCursorIsEqualToHighestLatestIndexedBlockAcrossIndexedChain);
1606
- var makeCrossChainIndexingStatusSnapshotOmnichainSchema = (valueLabel = "Cross-chain Indexing Status Snapshot Omnichain") => import_v43.default.strictObject({
1607
- strategy: import_v43.default.literal(CrossChainIndexingStrategyIds.Omnichain),
1608
- slowestChainIndexingCursor: makeUnixTimestampSchema(valueLabel),
1609
- snapshotTime: makeUnixTimestampSchema(valueLabel),
1610
- omnichainSnapshot: makeOmnichainIndexingStatusSnapshotSchema(valueLabel)
1611
- }).check(invariant_slowestChainEqualsToOmnichainSnapshotTime).check(invariant_snapshotTimeIsTheHighestKnownBlockTimestamp);
1612
- var makeCrossChainIndexingStatusSnapshotSchema = (valueLabel = "Cross-chain Indexing Status Snapshot") => import_v43.default.discriminatedUnion("strategy", [
1613
- makeCrossChainIndexingStatusSnapshotOmnichainSchema(valueLabel)
2677
+ var makeNameTokensResponseErrorSchema = (valueLabel = "Name Tokens Response Error") => import_v414.default.discriminatedUnion("errorCode", [
2678
+ makeNameTokensResponseErrorNameTokensNotIndexedSchema(valueLabel),
2679
+ makeNameTokensResponseErrorEnsIndexerConfigUnsupported(valueLabel),
2680
+ makeNameTokensResponseErrorNameIndexingStatusUnsupported(valueLabel)
2681
+ ]);
2682
+ var makeNameTokensResponseSchema = (valueLabel = "Name Tokens Response") => import_v414.default.discriminatedUnion("responseCode", [
2683
+ makeNameTokensResponseOkSchema(valueLabel),
2684
+ makeNameTokensResponseErrorSchema(valueLabel)
1614
2685
  ]);
1615
- var makeRealtimeIndexingStatusProjectionSchema = (valueLabel = "Realtime Indexing Status Projection") => import_v43.default.strictObject({
1616
- projectedAt: makeUnixTimestampSchema(valueLabel),
1617
- worstCaseDistance: makeDurationSchema(valueLabel),
1618
- snapshot: makeCrossChainIndexingStatusSnapshotSchema(valueLabel)
1619
- }).check(invariant_realtimeIndexingStatusProjectionProjectedAtIsAfterOrEqualToSnapshotTime).check(invariant_realtimeIndexingStatusProjectionWorstCaseDistanceIsCorrect);
1620
-
1621
- // src/ensindexer/config/zod-schemas.ts
1622
- var import_v44 = __toESM(require("zod/v4"), 1);
1623
-
1624
- // src/ensindexer/config/is-subgraph-compatible.ts
1625
- var import_datasources3 = require("@ensnode/datasources");
1626
-
1627
- // src/ensindexer/config/types.ts
1628
- var PluginName = /* @__PURE__ */ ((PluginName2) => {
1629
- PluginName2["Subgraph"] = "subgraph";
1630
- PluginName2["Basenames"] = "basenames";
1631
- PluginName2["Lineanames"] = "lineanames";
1632
- PluginName2["ThreeDNS"] = "threedns";
1633
- PluginName2["ProtocolAcceleration"] = "protocol-acceleration";
1634
- PluginName2["Registrars"] = "registrars";
1635
- PluginName2["TokenScope"] = "tokenscope";
1636
- return PluginName2;
1637
- })(PluginName || {});
1638
-
1639
- // src/ensindexer/config/is-subgraph-compatible.ts
1640
- function isSubgraphCompatible(config) {
1641
- const onlySubgraphPluginActivated = config.plugins.length === 1 && config.plugins[0] === "subgraph" /* Subgraph */;
1642
- const isSubgraphLabelSet = config.labelSet.labelSetId === "subgraph" && config.labelSet.labelSetVersion === 0;
1643
- const isEnsTestEnvLabelSet = config.labelSet.labelSetId === "ens-test-env" && config.labelSet.labelSetVersion === 0;
1644
- const labelSetIsSubgraphCompatible = isSubgraphLabelSet || config.namespace === import_datasources3.ENSNamespaceIds.EnsTestEnv && isEnsTestEnvLabelSet;
1645
- return onlySubgraphPluginActivated && labelSetIsSubgraphCompatible;
1646
- }
1647
2686
 
1648
- // src/ensindexer/config/validations.ts
1649
- function invariant_ensDbVersionIsSameAsEnsIndexerVersion(ctx) {
1650
- const versionInfo = ctx.value;
1651
- if (versionInfo.ensDb !== versionInfo.ensIndexer) {
1652
- ctx.issues.push({
1653
- code: "custom",
1654
- input: versionInfo,
1655
- message: "`ensDb` version must be same as `ensIndexer` version"
1656
- });
2687
+ // src/api/name-tokens/deserialize.ts
2688
+ function deserializedNameTokensResponse(maybeResponse) {
2689
+ const parsed = makeNameTokensResponseSchema().safeParse(maybeResponse);
2690
+ if (parsed.error) {
2691
+ throw new Error(`Cannot deserialize NameTokensResponse:
2692
+ ${(0, import_v415.prettifyError)(parsed.error)}
2693
+ `);
1657
2694
  }
2695
+ return parsed.data;
1658
2696
  }
1659
2697
 
1660
- // src/ensindexer/config/zod-schemas.ts
1661
- var makeIndexedChainIdsSchema = (valueLabel = "Indexed Chain IDs") => import_v44.default.array(makeChainIdSchema(valueLabel), {
1662
- error: `${valueLabel} must be an array.`
1663
- }).min(1, { error: `${valueLabel} list must include at least one element.` }).transform((v) => new Set(v));
1664
- var makePluginsListSchema = (valueLabel = "Plugins") => import_v44.default.array(import_v44.default.string(), {
1665
- error: `${valueLabel} must be a list of strings.`
1666
- }).min(1, {
1667
- error: `${valueLabel} must be a list of strings with at least one string value`
1668
- }).refine((arr) => arr.length === uniq(arr).length, {
1669
- error: `${valueLabel} cannot contain duplicate values.`
1670
- });
1671
- var makeDatabaseSchemaNameSchema = (valueLabel = "Database schema name") => import_v44.default.string({ error: `${valueLabel} must be a string` }).trim().nonempty({
1672
- error: `${valueLabel} is required and must be a non-empty string.`
1673
- });
1674
- var makeLabelSetIdSchema = (valueLabel) => {
1675
- 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-]+$/, {
1676
- error: `${valueLabel} can only contain lowercase letters (a-z) and hyphens (-)`
1677
- });
1678
- };
1679
- var makeLabelSetVersionSchema = (valueLabel) => {
1680
- return import_v44.default.coerce.number({ error: `${valueLabel} must be an integer.` }).pipe(makeNonNegativeIntegerSchema(valueLabel));
1681
- };
1682
- var makeFullyPinnedLabelSetSchema = (valueLabel = "Label set") => {
1683
- let valueLabelLabelSetId = valueLabel;
1684
- let valueLabelLabelSetVersion = valueLabel;
1685
- if (valueLabel === "LABEL_SET") {
1686
- valueLabelLabelSetId = "LABEL_SET_ID";
1687
- valueLabelLabelSetVersion = "LABEL_SET_VERSION";
1688
- } else {
1689
- valueLabelLabelSetId = `${valueLabel}.labelSetId`;
1690
- valueLabelLabelSetVersion = `${valueLabel}.labelSetVersion`;
1691
- }
1692
- return import_v44.default.object({
1693
- labelSetId: makeLabelSetIdSchema(valueLabelLabelSetId),
1694
- labelSetVersion: makeLabelSetVersionSchema(valueLabelLabelSetVersion)
1695
- });
1696
- };
1697
- var makeNonEmptyStringSchema = (valueLabel = "Value") => import_v44.default.string().nonempty({ error: `${valueLabel} must be a non-empty string.` });
1698
- var makeENSIndexerVersionInfoSchema = (valueLabel = "Value") => import_v44.default.strictObject(
1699
- {
1700
- nodejs: makeNonEmptyStringSchema(),
1701
- ponder: makeNonEmptyStringSchema(),
1702
- ensDb: makeNonEmptyStringSchema(),
1703
- ensIndexer: makeNonEmptyStringSchema(),
1704
- ensNormalize: makeNonEmptyStringSchema(),
1705
- ensRainbow: makeNonEmptyStringSchema(),
1706
- ensRainbowSchema: makePositiveIntegerSchema()
2698
+ // src/api/name-tokens/prerequisites.ts
2699
+ var nameTokensPrerequisites = Object.freeze({
2700
+ /**
2701
+ * Required plugins to enable Name Tokens API routes.
2702
+ *
2703
+ * 1. `registrars` plugin is required so that data in the `registrationLifecycles`
2704
+ * table is populated.
2705
+ * 2. `tokenscope` plugin is required so that data in the `nameTokens`
2706
+ * table is populated.
2707
+ */
2708
+ requiredPlugins: ["registrars" /* Registrars */, "tokenscope" /* TokenScope */],
2709
+ /**
2710
+ * Check if provided ENSApiPublicConfig supports the Name Tokens API.
2711
+ */
2712
+ hasEnsIndexerConfigSupport(config) {
2713
+ return nameTokensPrerequisites.requiredPlugins.every(
2714
+ (plugin) => config.plugins.includes(plugin)
2715
+ );
1707
2716
  },
1708
- {
1709
- error: `${valueLabel} must be a valid ENSIndexerVersionInfo object.`
1710
- }
1711
- ).check(invariant_ensDbVersionIsSameAsEnsIndexerVersion);
1712
- function invariant_isSubgraphCompatibleRequirements(ctx) {
1713
- const { value: config } = ctx;
1714
- if (config.isSubgraphCompatible && !isSubgraphCompatible(config)) {
1715
- ctx.issues.push({
1716
- code: "custom",
1717
- input: config,
1718
- message: `'isSubgraphCompatible' requires only the '${"subgraph" /* Subgraph */}' plugin to be active and labelSet must be {labelSetId: "subgraph", labelSetVersion: 0}`
1719
- });
2717
+ /**
2718
+ * Required Indexing Status IDs
2719
+ *
2720
+ * Database indexes are created by the time the omnichain indexing status
2721
+ * is either `completed` or `following`.
2722
+ */
2723
+ supportedIndexingStatusIds: [
2724
+ OmnichainIndexingStatusIds.Completed,
2725
+ OmnichainIndexingStatusIds.Following
2726
+ ],
2727
+ /**
2728
+ * Check if provided indexing status supports the Name Tokens API.
2729
+ */
2730
+ hasIndexingStatusSupport(omnichainIndexingStatusId) {
2731
+ return nameTokensPrerequisites.supportedIndexingStatusIds.some(
2732
+ (supportedIndexingStatusId) => supportedIndexingStatusId === omnichainIndexingStatusId
2733
+ );
1720
2734
  }
1721
- }
1722
- var makeENSIndexerPublicConfigSchema = (valueLabel = "ENSIndexerPublicConfig") => import_v44.default.object({
1723
- labelSet: makeFullyPinnedLabelSetSchema(`${valueLabel}.labelSet`),
1724
- indexedChainIds: makeIndexedChainIdsSchema(`${valueLabel}.indexedChainIds`),
1725
- isSubgraphCompatible: import_v44.default.boolean({ error: `${valueLabel}.isSubgraphCompatible` }),
1726
- namespace: makeENSNamespaceIdSchema(`${valueLabel}.namespace`),
1727
- plugins: makePluginsListSchema(`${valueLabel}.plugins`),
1728
- databaseSchemaName: makeDatabaseSchemaNameSchema(`${valueLabel}.databaseSchemaName`),
1729
- versionInfo: makeENSIndexerVersionInfoSchema(`${valueLabel}.versionInfo`)
1730
- }).check(invariant_isSubgraphCompatibleRequirements);
1731
-
1732
- // src/shared/config/build-rpc-urls.ts
1733
- var import_chains = require("viem/chains");
1734
-
1735
- // src/shared/config/rpc-configs-from-env.ts
1736
- var import_datasources4 = require("@ensnode/datasources");
2735
+ });
1737
2736
 
1738
- // src/shared/config/validatons.ts
1739
- var import_datasources5 = require("@ensnode/datasources");
1740
- function invariant_rpcEndpointConfigIncludesAtLeastOneHTTPProtocolURL(ctx) {
1741
- const endpoints = ctx.value;
1742
- const httpEndpoints = endpoints.filter(isHttpProtocol);
1743
- if (httpEndpoints.length < 1) {
1744
- ctx.issues.push({
1745
- code: "custom",
1746
- input: endpoints,
1747
- message: `RPC endpoint configuration for a chain must include at least one http/https protocol URL.`
1748
- });
1749
- }
2737
+ // src/api/name-tokens/serialize.ts
2738
+ function serializeRegisteredNameTokens({
2739
+ domainId,
2740
+ name,
2741
+ tokens,
2742
+ expiresAt,
2743
+ accurateAsOf
2744
+ }) {
2745
+ return {
2746
+ domainId,
2747
+ name,
2748
+ tokens: tokens.map(serializeNameToken),
2749
+ expiresAt,
2750
+ accurateAsOf
2751
+ };
1750
2752
  }
1751
- function invariant_rpcEndpointConfigIncludesAtMostOneWebSocketsProtocolURL(ctx) {
1752
- const endpoints = ctx.value;
1753
- const wsEndpoints = endpoints.filter(isWebSocketProtocol);
1754
- if (wsEndpoints.length > 1) {
1755
- ctx.issues.push({
1756
- code: "custom",
1757
- input: endpoints,
1758
- message: `RPC endpoint configuration for a chain must include at most one websocket (ws/wss) protocol URL.`
1759
- });
2753
+ function serializeNameTokensResponse(response) {
2754
+ switch (response.responseCode) {
2755
+ case NameTokensResponseCodes.Ok:
2756
+ return {
2757
+ responseCode: response.responseCode,
2758
+ registeredNameTokens: serializeRegisteredNameTokens(response.registeredNameTokens)
2759
+ };
2760
+ case NameTokensResponseCodes.Error:
2761
+ return response;
1760
2762
  }
1761
2763
  }
1762
2764
 
1763
- // src/shared/config/zod-schemas.ts
1764
- var import_v45 = require("zod/v4");
1765
- var import_datasources6 = require("@ensnode/datasources");
1766
- var DatabaseSchemaNameSchema = import_v45.z.string({
1767
- error: "DATABASE_SCHEMA is required."
1768
- }).trim().min(1, {
1769
- error: "DATABASE_SCHEMA is required and cannot be an empty string."
1770
- });
1771
- var RpcConfigSchema = import_v45.z.string().transform((val) => val.split(",")).pipe(import_v45.z.array(makeUrlSchema("RPC URL"))).check(invariant_rpcEndpointConfigIncludesAtLeastOneHTTPProtocolURL).check(invariant_rpcEndpointConfigIncludesAtMostOneWebSocketsProtocolURL);
1772
- var RpcConfigsSchema = import_v45.z.record(makeChainIdStringSchema("RPC URL"), RpcConfigSchema, {
1773
- error: "Chains configuration must be an object mapping valid chain IDs to their configs."
1774
- }).transform((records) => {
1775
- const rpcConfigs = /* @__PURE__ */ new Map();
1776
- for (const [chainIdString, rpcConfig] of Object.entries(records)) {
1777
- const httpRPCs = rpcConfig.filter(isHttpProtocol);
1778
- const websocketRPC = rpcConfig.find(isWebSocketProtocol);
1779
- rpcConfigs.set(deserializeChainId(chainIdString), {
1780
- httpRPCs,
1781
- websocketRPC
1782
- });
1783
- }
1784
- return rpcConfigs;
1785
- });
1786
- var EnsIndexerUrlSchema = makeUrlSchema("ENSINDEXER_URL");
1787
- var ENSNamespaceSchema = import_v45.z.enum(import_datasources6.ENSNamespaceIds, {
1788
- error: ({ input }) => `Invalid NAMESPACE. Got '${input}', but supported ENS namespaces are: ${Object.keys(import_datasources6.ENSNamespaceIds).join(", ")}`
1789
- });
1790
- 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();
1791
- var TheGraphApiKeySchema = import_v45.z.string().optional();
1792
-
1793
- // src/shared/datasources-with-resolvers.ts
1794
- var import_datasources7 = require("@ensnode/datasources");
1795
- var DATASOURCE_NAMES_WITH_RESOLVERS = [
1796
- import_datasources7.DatasourceNames.ENSRoot,
1797
- import_datasources7.DatasourceNames.Basenames,
1798
- import_datasources7.DatasourceNames.Lineanames,
1799
- import_datasources7.DatasourceNames.ThreeDNSOptimism,
1800
- import_datasources7.DatasourceNames.ThreeDNSBase
1801
- ];
1802
-
1803
- // src/shared/log-level.ts
1804
- var import_v46 = require("zod/v4");
1805
- var LogLevelSchema = import_v46.z.enum(["fatal", "error", "warn", "info", "debug", "trace", "silent"]);
2765
+ // src/api/registrar-actions/deserialize.ts
2766
+ var import_v419 = require("zod/v4");
1806
2767
 
1807
- // src/shared/protocol-acceleration/interpret-record-values.ts
1808
- var import_viem10 = require("viem");
2768
+ // src/api/registrar-actions/zod-schemas.ts
2769
+ var import_ens7 = require("viem/ens");
2770
+ var import_v418 = __toESM(require("zod/v4"), 1);
1809
2771
 
1810
2772
  // ../ens-referrals/src/address.ts
1811
- var import_viem11 = require("viem");
2773
+ var import_viem15 = require("viem");
1812
2774
 
1813
2775
  // ../ens-referrals/src/encoding.ts
1814
- var import_viem12 = require("viem");
2776
+ var import_viem16 = require("viem");
1815
2777
  var ENCODED_REFERRER_BYTE_OFFSET = 12;
1816
2778
  var ENCODED_REFERRER_BYTE_LENGTH = 32;
1817
- var EXPECTED_ENCODED_REFERRER_PADDING = (0, import_viem12.pad)("0x", {
2779
+ var EXPECTED_ENCODED_REFERRER_PADDING = (0, import_viem16.pad)("0x", {
1818
2780
  size: ENCODED_REFERRER_BYTE_OFFSET,
1819
2781
  dir: "left"
1820
2782
  });
1821
- var ZERO_ENCODED_REFERRER = (0, import_viem12.pad)("0x", {
2783
+ var ZERO_ENCODED_REFERRER = (0, import_viem16.pad)("0x", {
1822
2784
  size: ENCODED_REFERRER_BYTE_LENGTH,
1823
2785
  dir: "left"
1824
2786
  });
1825
2787
  function decodeEncodedReferrer(encodedReferrer) {
1826
- if ((0, import_viem12.size)(encodedReferrer) !== ENCODED_REFERRER_BYTE_LENGTH) {
2788
+ if ((0, import_viem16.size)(encodedReferrer) !== ENCODED_REFERRER_BYTE_LENGTH) {
1827
2789
  throw new Error(
1828
2790
  `Encoded referrer value must be represented by ${ENCODED_REFERRER_BYTE_LENGTH} bytes.`
1829
2791
  );
1830
2792
  }
1831
- const padding = (0, import_viem12.slice)(encodedReferrer, 0, ENCODED_REFERRER_BYTE_OFFSET);
2793
+ const padding = (0, import_viem16.slice)(encodedReferrer, 0, ENCODED_REFERRER_BYTE_OFFSET);
1832
2794
  if (padding !== EXPECTED_ENCODED_REFERRER_PADDING) {
1833
- return import_viem12.zeroAddress;
2795
+ return import_viem16.zeroAddress;
1834
2796
  }
1835
- const decodedReferrer = (0, import_viem12.slice)(encodedReferrer, ENCODED_REFERRER_BYTE_OFFSET);
2797
+ const decodedReferrer = (0, import_viem16.slice)(encodedReferrer, ENCODED_REFERRER_BYTE_OFFSET);
1836
2798
  try {
1837
- return (0, import_viem12.getAddress)(decodedReferrer);
2799
+ return (0, import_viem16.getAddress)(decodedReferrer);
1838
2800
  } catch {
1839
2801
  throw new Error(`Decoded referrer value must be a valid EVM address.`);
1840
2802
  }
@@ -1844,27 +2806,22 @@ function decodeEncodedReferrer(encodedReferrer) {
1844
2806
  var REFERRERS_PER_LEADERBOARD_PAGE_MAX = 100;
1845
2807
 
1846
2808
  // ../ens-referrals/src/link.ts
1847
- var import_viem13 = require("viem");
1848
-
1849
- // src/registrars/zod-schemas.ts
1850
- var import_v47 = __toESM(require("zod/v4"), 1);
2809
+ var import_viem17 = require("viem");
1851
2810
 
1852
- // src/registrars/subregistry.ts
1853
- function serializeSubregistry(subregistry) {
1854
- return {
1855
- subregistryId: serializeAccountId(subregistry.subregistryId),
1856
- node: subregistry.node
1857
- };
1858
- }
2811
+ // ../ens-referrals/src/referrer-detail.ts
2812
+ var ReferrerDetailTypeIds = {
2813
+ /**
2814
+ * Represents a referrer who is ranked on the leaderboard.
2815
+ */
2816
+ Ranked: "ranked",
2817
+ /**
2818
+ * Represents a referrer who is not ranked on the leaderboard.
2819
+ */
2820
+ Unranked: "unranked"
2821
+ };
1859
2822
 
1860
- // src/registrars/registration-lifecycle.ts
1861
- function serializeRegistrationLifecycle(registrationLifecycle) {
1862
- return {
1863
- subregistry: serializeSubregistry(registrationLifecycle.subregistry),
1864
- node: registrationLifecycle.node,
1865
- expiresAt: registrationLifecycle.expiresAt
1866
- };
1867
- }
2823
+ // src/registrars/zod-schemas.ts
2824
+ var import_v416 = __toESM(require("zod/v4"), 1);
1868
2825
 
1869
2826
  // src/registrars/registrar-action.ts
1870
2827
  var RegistrarActionTypes = {
@@ -1895,7 +2852,7 @@ function serializeRegistrarAction(registrarAction) {
1895
2852
  type: registrarAction.type,
1896
2853
  incrementalDuration: registrarAction.incrementalDuration,
1897
2854
  registrant: registrarAction.registrant,
1898
- registrationLifecycle: serializeRegistrationLifecycle(registrarAction.registrationLifecycle),
2855
+ registrationLifecycle: registrarAction.registrationLifecycle,
1899
2856
  pricing: serializeRegistrarActionPricing(registrarAction.pricing),
1900
2857
  referral: registrarAction.referral,
1901
2858
  block: registrarAction.block,
@@ -1905,11 +2862,11 @@ function serializeRegistrarAction(registrarAction) {
1905
2862
  }
1906
2863
 
1907
2864
  // src/registrars/zod-schemas.ts
1908
- var makeSubregistrySchema = (valueLabel = "Subregistry") => import_v47.default.object({
1909
- subregistryId: makeSerializedAccountIdSchema(`${valueLabel} Subregistry ID`),
2865
+ var makeSubregistrySchema = (valueLabel = "Subregistry") => import_v416.default.object({
2866
+ subregistryId: makeAccountIdSchema(`${valueLabel} Subregistry ID`),
1910
2867
  node: makeNodeSchema(`${valueLabel} Node`)
1911
2868
  });
1912
- var makeRegistrationLifecycleSchema = (valueLabel = "Registration Lifecycle") => import_v47.default.object({
2869
+ var makeRegistrationLifecycleSchema = (valueLabel = "Registration Lifecycle") => import_v416.default.object({
1913
2870
  subregistry: makeSubregistrySchema(`${valueLabel} Subregistry`),
1914
2871
  node: makeNodeSchema(`${valueLabel} Node`),
1915
2872
  expiresAt: makeUnixTimestampSchema(`${valueLabel} Expires at`)
@@ -1925,18 +2882,18 @@ function invariant_registrarActionPricingTotalIsSumOfBaseCostAndPremium(ctx) {
1925
2882
  });
1926
2883
  }
1927
2884
  }
1928
- var makeRegistrarActionPricingSchema = (valueLabel = "Registrar Action Pricing") => import_v47.default.union([
2885
+ var makeRegistrarActionPricingSchema = (valueLabel = "Registrar Action Pricing") => import_v416.default.union([
1929
2886
  // pricing available
1930
- import_v47.default.object({
2887
+ import_v416.default.object({
1931
2888
  baseCost: makePriceEthSchema(`${valueLabel} Base Cost`),
1932
2889
  premium: makePriceEthSchema(`${valueLabel} Premium`),
1933
2890
  total: makePriceEthSchema(`${valueLabel} Total`)
1934
2891
  }).check(invariant_registrarActionPricingTotalIsSumOfBaseCostAndPremium).transform((v) => v),
1935
2892
  // pricing unknown
1936
- import_v47.default.object({
1937
- baseCost: import_v47.default.null(),
1938
- premium: import_v47.default.null(),
1939
- total: import_v47.default.null()
2893
+ import_v416.default.object({
2894
+ baseCost: import_v416.default.null(),
2895
+ premium: import_v416.default.null(),
2896
+ total: import_v416.default.null()
1940
2897
  }).transform((v) => v)
1941
2898
  ]);
1942
2899
  function invariant_registrarActionDecodedReferrerBasedOnRawReferrer(ctx) {
@@ -1956,424 +2913,227 @@ function invariant_registrarActionDecodedReferrerBasedOnRawReferrer(ctx) {
1956
2913
  code: "custom",
1957
2914
  input: ctx.value,
1958
2915
  message: errorMessage
1959
- });
1960
- }
1961
- }
1962
- var makeRegistrarActionReferralSchema = (valueLabel = "Registrar Action Referral") => import_v47.default.union([
1963
- // referral available
1964
- import_v47.default.object({
1965
- encodedReferrer: makeHexStringSchema(
1966
- { bytesCount: ENCODED_REFERRER_BYTE_LENGTH },
1967
- `${valueLabel} Encoded Referrer`
1968
- ),
1969
- decodedReferrer: makeLowercaseAddressSchema(`${valueLabel} Decoded Referrer`)
1970
- }).check(invariant_registrarActionDecodedReferrerBasedOnRawReferrer),
1971
- // referral not applicable
1972
- import_v47.default.object({
1973
- encodedReferrer: import_v47.default.null(),
1974
- decodedReferrer: import_v47.default.null()
1975
- })
1976
- ]);
1977
- function invariant_eventIdsInitialElementIsTheActionId(ctx) {
1978
- const { id, eventIds } = ctx.value;
1979
- if (eventIds[0] !== id) {
1980
- ctx.issues.push({
1981
- code: "custom",
1982
- input: ctx.value,
1983
- message: "The initial element of `eventIds` must be the `id` value"
1984
- });
1985
- }
1986
- }
1987
- var EventIdSchema = import_v47.default.string().nonempty();
1988
- var EventIdsSchema = import_v47.default.array(EventIdSchema).min(1).transform((v) => v);
1989
- var makeBaseRegistrarActionSchema = (valueLabel = "Base Registrar Action") => import_v47.default.object({
1990
- id: EventIdSchema,
1991
- incrementalDuration: makeDurationSchema(`${valueLabel} Incremental Duration`),
1992
- registrant: makeLowercaseAddressSchema(`${valueLabel} Registrant`),
1993
- registrationLifecycle: makeRegistrationLifecycleSchema(
1994
- `${valueLabel} Registration Lifecycle`
1995
- ),
1996
- pricing: makeRegistrarActionPricingSchema(`${valueLabel} Pricing`),
1997
- referral: makeRegistrarActionReferralSchema(`${valueLabel} Referral`),
1998
- block: makeBlockRefSchema(`${valueLabel} Block`),
1999
- transactionHash: makeTransactionHashSchema(`${valueLabel} Transaction Hash`),
2000
- eventIds: EventIdsSchema
2001
- }).check(invariant_eventIdsInitialElementIsTheActionId);
2002
- var makeRegistrarActionRegistrationSchema = (valueLabel = "Registration ") => makeBaseRegistrarActionSchema(valueLabel).extend({
2003
- type: import_v47.default.literal(RegistrarActionTypes.Registration)
2004
- });
2005
- var makeRegistrarActionRenewalSchema = (valueLabel = "Renewal") => makeBaseRegistrarActionSchema(valueLabel).extend({
2006
- type: import_v47.default.literal(RegistrarActionTypes.Renewal)
2007
- });
2008
- var makeRegistrarActionSchema = (valueLabel = "Registrar Action") => import_v47.default.discriminatedUnion("type", [
2009
- makeRegistrarActionRegistrationSchema(`${valueLabel} Registration`),
2010
- makeRegistrarActionRenewalSchema(`${valueLabel} Renewal`)
2011
- ]);
2012
-
2013
- // src/api/types.ts
2014
- var IndexingStatusResponseCodes = {
2015
- /**
2016
- * Represents that the indexing status is available.
2017
- */
2018
- Ok: "ok",
2019
- /**
2020
- * Represents that the indexing status is unavailable.
2021
- */
2022
- Error: "error"
2023
- };
2024
- var RegistrarActionsFilterTypes = {
2025
- BySubregistryNode: "bySubregistryNode",
2026
- WithEncodedReferral: "withEncodedReferral"
2027
- };
2028
- var RegistrarActionsOrders = {
2029
- LatestRegistrarActions: "orderBy[timestamp]=desc"
2030
- };
2031
- var RegistrarActionsResponseCodes = {
2032
- /**
2033
- * Represents that Registrar Actions are available.
2034
- */
2035
- Ok: "ok",
2036
- /**
2037
- * Represents that Registrar Actions are unavailable.
2038
- */
2039
- Error: "error"
2040
- };
2041
-
2042
- // src/api/zod-schemas.ts
2043
- var ErrorResponseSchema = import_v48.default.object({
2044
- message: import_v48.default.string(),
2045
- details: import_v48.default.optional(import_v48.default.unknown())
2046
- });
2047
- var makeIndexingStatusResponseOkSchema = (valueLabel = "Indexing Status Response OK") => import_v48.default.strictObject({
2048
- responseCode: import_v48.default.literal(IndexingStatusResponseCodes.Ok),
2049
- realtimeProjection: makeRealtimeIndexingStatusProjectionSchema(valueLabel)
2050
- });
2051
- var makeIndexingStatusResponseErrorSchema = (_valueLabel = "Indexing Status Response Error") => import_v48.default.strictObject({
2052
- responseCode: import_v48.default.literal(IndexingStatusResponseCodes.Error)
2053
- });
2054
- var makeIndexingStatusResponseSchema = (valueLabel = "Indexing Status Response") => import_v48.default.discriminatedUnion("responseCode", [
2055
- makeIndexingStatusResponseOkSchema(valueLabel),
2056
- makeIndexingStatusResponseErrorSchema(valueLabel)
2057
- ]);
2058
- function invariant_registrationLifecycleNodeMatchesName(ctx) {
2059
- const { name, action } = ctx.value;
2060
- const expectedNode = action.registrationLifecycle.node;
2061
- const actualNode = (0, import_viem14.namehash)(name);
2062
- if (actualNode !== expectedNode) {
2063
- ctx.issues.push({
2064
- code: "custom",
2065
- input: ctx.value,
2066
- message: `The 'action.registrationLifecycle.node' must match namehash of 'name'`
2067
- });
2068
- }
2069
- }
2070
- var makeNamedRegistrarActionSchema = (valueLabel = "Named Registrar Action") => import_v48.default.object({
2071
- action: makeRegistrarActionSchema(valueLabel),
2072
- name: makeReinterpretedNameSchema(valueLabel)
2073
- }).check(invariant_registrationLifecycleNodeMatchesName);
2074
- var makeRegistrarActionsResponseOkSchema = (valueLabel = "Registrar Actions Response OK") => import_v48.default.strictObject({
2075
- responseCode: import_v48.default.literal(RegistrarActionsResponseCodes.Ok),
2076
- registrarActions: import_v48.default.array(makeNamedRegistrarActionSchema(valueLabel))
2077
- });
2078
- var makeRegistrarActionsResponseErrorSchema = (_valueLabel = "Registrar Actions Response Error") => import_v48.default.strictObject({
2079
- responseCode: import_v48.default.literal(RegistrarActionsResponseCodes.Error),
2080
- error: ErrorResponseSchema
2081
- });
2082
- var makeRegistrarActionsResponseSchema = (valueLabel = "Registrar Actions Response") => import_v48.default.discriminatedUnion("responseCode", [
2083
- makeRegistrarActionsResponseOkSchema(valueLabel),
2084
- makeRegistrarActionsResponseErrorSchema(valueLabel)
2085
- ]);
2086
-
2087
- // src/api/deserialize.ts
2088
- function deserializeErrorResponse(maybeErrorResponse) {
2089
- const parsed = ErrorResponseSchema.safeParse(maybeErrorResponse);
2090
- if (parsed.error) {
2091
- throw new Error(`Cannot deserialize ErrorResponse:
2092
- ${(0, import_v49.prettifyError)(parsed.error)}
2093
- `);
2094
- }
2095
- return parsed.data;
2096
- }
2097
- function deserializeIndexingStatusResponse(maybeResponse) {
2098
- const parsed = makeIndexingStatusResponseSchema().safeParse(maybeResponse);
2099
- if (parsed.error) {
2100
- throw new Error(`Cannot deserialize IndexingStatusResponse:
2101
- ${(0, import_v49.prettifyError)(parsed.error)}
2102
- `);
2103
- }
2104
- return parsed.data;
2105
- }
2106
- function deserializeRegistrarActionsResponse(maybeResponse) {
2107
- const parsed = makeRegistrarActionsResponseSchema().safeParse(maybeResponse);
2108
- if (parsed.error) {
2109
- throw new Error(
2110
- `Cannot deserialize RegistrarActionsResponse:
2111
- ${(0, import_v49.prettifyError)(parsed.error)}
2112
- `
2113
- );
2114
- }
2115
- return parsed.data;
2116
- }
2117
-
2118
- // src/api/registrar-actions/filters.ts
2119
- function byParentNode(parentNode) {
2120
- if (typeof parentNode === "undefined") {
2121
- return void 0;
2122
- }
2123
- return {
2124
- filterType: RegistrarActionsFilterTypes.BySubregistryNode,
2125
- value: parentNode
2126
- };
2127
- }
2128
- function withReferral(withReferral2) {
2129
- if (!withReferral2) {
2130
- return void 0;
2131
- }
2132
- return {
2133
- filterType: RegistrarActionsFilterTypes.WithEncodedReferral
2134
- };
2135
- }
2136
- var registrarActionsFilter = {
2137
- byParentNode,
2138
- withReferral
2139
- };
2140
-
2141
- // src/ensindexer/config/deserialize.ts
2142
- var import_v410 = require("zod/v4");
2143
- function deserializeENSIndexerPublicConfig(maybeConfig, valueLabel) {
2144
- const schema = makeENSIndexerPublicConfigSchema(valueLabel);
2145
- const parsed = schema.safeParse(maybeConfig);
2146
- if (parsed.error) {
2147
- throw new Error(`Cannot deserialize ENSIndexerPublicConfig:
2148
- ${(0, import_v410.prettifyError)(parsed.error)}
2149
- `);
2150
- }
2151
- return parsed.data;
2152
- }
2153
-
2154
- // src/ensindexer/config/label-utils.ts
2155
- var import_viem15 = require("viem");
2156
- function labelHashToBytes(labelHash) {
2157
- try {
2158
- if (labelHash.length !== 66) {
2159
- throw new Error(`Invalid labelHash length ${labelHash.length} characters (expected 66)`);
2160
- }
2161
- if (labelHash !== labelHash.toLowerCase()) {
2162
- throw new Error("Labelhash must be in lowercase");
2163
- }
2164
- if (!labelHash.startsWith("0x")) {
2165
- throw new Error("Labelhash must be 0x-prefixed");
2166
- }
2167
- const bytes = (0, import_viem15.hexToBytes)(labelHash);
2168
- if (bytes.length !== 32) {
2169
- throw new Error(`Invalid labelHash length ${bytes.length} bytes (expected 32)`);
2170
- }
2171
- return bytes;
2172
- } catch (e) {
2173
- if (e instanceof Error) {
2174
- throw e;
2175
- }
2176
- throw new Error("Invalid hex format");
2177
- }
2178
- }
2179
-
2180
- // src/ensindexer/config/labelset-utils.ts
2181
- function buildLabelSetId(maybeLabelSetId) {
2182
- return makeLabelSetIdSchema("LabelSetId").parse(maybeLabelSetId);
2183
- }
2184
- function buildLabelSetVersion(maybeLabelSetVersion) {
2185
- return makeLabelSetVersionSchema("LabelSetVersion").parse(maybeLabelSetVersion);
2186
- }
2187
- function buildEnsRainbowClientLabelSet(labelSetId, labelSetVersion) {
2188
- if (labelSetVersion !== void 0 && labelSetId === void 0) {
2189
- throw new Error("When a labelSetVersion is defined, labelSetId must also be defined.");
2916
+ });
2190
2917
  }
2191
- return { labelSetId, labelSetVersion };
2192
2918
  }
2193
- function validateSupportedLabelSetAndVersion(serverSet, clientSet) {
2194
- if (clientSet.labelSetId === void 0) {
2195
- return;
2196
- }
2197
- if (serverSet.labelSetId !== clientSet.labelSetId) {
2198
- throw new Error(
2199
- `Server label set ID "${serverSet.labelSetId}" does not match client's requested label set ID "${clientSet.labelSetId}".`
2200
- );
2201
- }
2202
- if (clientSet.labelSetVersion !== void 0 && serverSet.highestLabelSetVersion < clientSet.labelSetVersion) {
2203
- throw new Error(
2204
- `Server highest label set version ${serverSet.highestLabelSetVersion} is less than client's requested version ${clientSet.labelSetVersion} for label set ID "${clientSet.labelSetId}".`
2205
- );
2919
+ var makeRegistrarActionReferralSchema = (valueLabel = "Registrar Action Referral") => import_v416.default.union([
2920
+ // referral available
2921
+ import_v416.default.object({
2922
+ encodedReferrer: makeHexStringSchema(
2923
+ { bytesCount: ENCODED_REFERRER_BYTE_LENGTH },
2924
+ `${valueLabel} Encoded Referrer`
2925
+ ),
2926
+ decodedReferrer: makeLowercaseAddressSchema(`${valueLabel} Decoded Referrer`)
2927
+ }).check(invariant_registrarActionDecodedReferrerBasedOnRawReferrer),
2928
+ // referral not applicable
2929
+ import_v416.default.object({
2930
+ encodedReferrer: import_v416.default.null(),
2931
+ decodedReferrer: import_v416.default.null()
2932
+ })
2933
+ ]);
2934
+ function invariant_eventIdsInitialElementIsTheActionId(ctx) {
2935
+ const { id, eventIds } = ctx.value;
2936
+ if (eventIds[0] !== id) {
2937
+ ctx.issues.push({
2938
+ code: "custom",
2939
+ input: ctx.value,
2940
+ message: "The initial element of `eventIds` must be the `id` value"
2941
+ });
2206
2942
  }
2207
2943
  }
2944
+ var EventIdSchema = import_v416.default.string().nonempty();
2945
+ var EventIdsSchema = import_v416.default.array(EventIdSchema).min(1).transform((v) => v);
2946
+ var makeBaseRegistrarActionSchema = (valueLabel = "Base Registrar Action") => import_v416.default.object({
2947
+ id: EventIdSchema,
2948
+ incrementalDuration: makeDurationSchema(`${valueLabel} Incremental Duration`),
2949
+ registrant: makeLowercaseAddressSchema(`${valueLabel} Registrant`),
2950
+ registrationLifecycle: makeRegistrationLifecycleSchema(
2951
+ `${valueLabel} Registration Lifecycle`
2952
+ ),
2953
+ pricing: makeRegistrarActionPricingSchema(`${valueLabel} Pricing`),
2954
+ referral: makeRegistrarActionReferralSchema(`${valueLabel} Referral`),
2955
+ block: makeBlockRefSchema(`${valueLabel} Block`),
2956
+ transactionHash: makeTransactionHashSchema(`${valueLabel} Transaction Hash`),
2957
+ eventIds: EventIdsSchema
2958
+ }).check(invariant_eventIdsInitialElementIsTheActionId);
2959
+ var makeRegistrarActionRegistrationSchema = (valueLabel = "Registration ") => makeBaseRegistrarActionSchema(valueLabel).extend({
2960
+ type: import_v416.default.literal(RegistrarActionTypes.Registration)
2961
+ });
2962
+ var makeRegistrarActionRenewalSchema = (valueLabel = "Renewal") => makeBaseRegistrarActionSchema(valueLabel).extend({
2963
+ type: import_v416.default.literal(RegistrarActionTypes.Renewal)
2964
+ });
2965
+ var makeRegistrarActionSchema = (valueLabel = "Registrar Action") => import_v416.default.discriminatedUnion("type", [
2966
+ makeRegistrarActionRegistrationSchema(`${valueLabel} Registration`),
2967
+ makeRegistrarActionRenewalSchema(`${valueLabel} Renewal`)
2968
+ ]);
2208
2969
 
2209
- // src/ensindexer/config/parsing.ts
2210
- function parseNonNegativeInteger(maybeNumber) {
2211
- const trimmed = maybeNumber.trim();
2212
- if (!trimmed) {
2213
- throw new Error("Input cannot be empty");
2214
- }
2215
- if (trimmed === "-0") {
2216
- throw new Error("Negative zero is not a valid non-negative integer");
2217
- }
2218
- const num = Number(maybeNumber);
2219
- if (Number.isNaN(num)) {
2220
- throw new Error(`"${maybeNumber}" is not a valid number`);
2970
+ // src/api/shared/pagination/zod-schemas.ts
2971
+ var import_v417 = __toESM(require("zod/v4"), 1);
2972
+
2973
+ // src/api/shared/pagination/request.ts
2974
+ var RECORDS_PER_PAGE_DEFAULT = 10;
2975
+ var RECORDS_PER_PAGE_MAX = 100;
2976
+
2977
+ // src/api/shared/pagination/zod-schemas.ts
2978
+ var makeRequestPageParamsSchema = (valueLabel = "RequestPageParams") => import_v417.default.object({
2979
+ page: makePositiveIntegerSchema(`${valueLabel}.page`),
2980
+ recordsPerPage: makePositiveIntegerSchema(`${valueLabel}.recordsPerPage`).max(
2981
+ RECORDS_PER_PAGE_MAX,
2982
+ `${valueLabel}.recordsPerPage must not exceed ${RECORDS_PER_PAGE_MAX}`
2983
+ )
2984
+ });
2985
+ var makeResponsePageContextSchemaWithNoRecords = (valueLabel = "ResponsePageContextWithNoRecords") => import_v417.default.object({
2986
+ totalRecords: import_v417.default.literal(0),
2987
+ totalPages: import_v417.default.literal(1),
2988
+ hasNext: import_v417.default.literal(false),
2989
+ hasPrev: import_v417.default.literal(false),
2990
+ startIndex: import_v417.default.undefined(),
2991
+ endIndex: import_v417.default.undefined()
2992
+ }).extend(makeRequestPageParamsSchema(valueLabel).shape);
2993
+ function invariant_responsePageWithRecordsIsCorrect(ctx) {
2994
+ const { hasNext, hasPrev, recordsPerPage, page, totalRecords, startIndex, endIndex } = ctx.value;
2995
+ const expectedHasNext = page * recordsPerPage < totalRecords;
2996
+ if (hasNext !== expectedHasNext) {
2997
+ ctx.issues.push({
2998
+ code: "custom",
2999
+ input: ctx.value,
3000
+ message: `hasNext must be equal to '${expectedHasNext ? "true" : "false"}'`
3001
+ });
2221
3002
  }
2222
- if (!Number.isFinite(num)) {
2223
- throw new Error(`"${maybeNumber}" is not a finite number`);
3003
+ const expectedHasPrev = page > 1;
3004
+ if (hasPrev !== expectedHasPrev) {
3005
+ ctx.issues.push({
3006
+ code: "custom",
3007
+ input: ctx.value,
3008
+ message: `hasPrev must be equal to '${expectedHasPrev ? "true" : "false"}'`
3009
+ });
2224
3010
  }
2225
- if (!Number.isInteger(num)) {
2226
- throw new Error(`"${maybeNumber}" is not an integer`);
3011
+ if (endIndex < startIndex) {
3012
+ ctx.issues.push({
3013
+ code: "custom",
3014
+ input: ctx.value,
3015
+ message: `endIndex must be greater than or equal to startIndex`
3016
+ });
2227
3017
  }
2228
- if (num < 0) {
2229
- throw new Error(`"${maybeNumber}" is not a non-negative integer`);
3018
+ if (endIndex >= totalRecords) {
3019
+ ctx.issues.push({
3020
+ code: "custom",
3021
+ input: ctx.value,
3022
+ message: `endIndex must be lower than totalRecords`
3023
+ });
2230
3024
  }
2231
- return num;
2232
3025
  }
3026
+ var makeResponsePageContextSchemaWithRecords = (valueLabel = "ResponsePageContextWithRecords") => import_v417.default.object({
3027
+ totalRecords: makePositiveIntegerSchema(`${valueLabel}.totalRecords`),
3028
+ totalPages: makePositiveIntegerSchema(`${valueLabel}.totalPages`),
3029
+ hasNext: import_v417.default.boolean(),
3030
+ hasPrev: import_v417.default.boolean(),
3031
+ startIndex: makeNonNegativeIntegerSchema(`${valueLabel}.startIndex`),
3032
+ endIndex: makeNonNegativeIntegerSchema(`${valueLabel}.endIndex`)
3033
+ }).extend(makeRequestPageParamsSchema(valueLabel).shape).check(invariant_responsePageWithRecordsIsCorrect);
3034
+ var makeResponsePageContextSchema = (valueLabel = "ResponsePageContext") => import_v417.default.union([
3035
+ makeResponsePageContextSchemaWithNoRecords(valueLabel),
3036
+ makeResponsePageContextSchemaWithRecords(valueLabel)
3037
+ ]);
2233
3038
 
2234
- // src/ensindexer/config/serialize.ts
2235
- function serializeIndexedChainIds(indexedChainIds) {
2236
- return Array.from(indexedChainIds);
2237
- }
2238
- function serializeENSIndexerPublicConfig(config) {
2239
- const {
2240
- labelSet,
2241
- indexedChainIds,
2242
- databaseSchemaName,
2243
- isSubgraphCompatible: isSubgraphCompatible2,
2244
- namespace,
2245
- plugins,
2246
- versionInfo
2247
- } = config;
2248
- return {
2249
- labelSet,
2250
- indexedChainIds: serializeIndexedChainIds(indexedChainIds),
2251
- databaseSchemaName,
2252
- isSubgraphCompatible: isSubgraphCompatible2,
2253
- namespace,
2254
- plugins,
2255
- versionInfo
2256
- };
2257
- }
3039
+ // src/api/registrar-actions/response.ts
3040
+ var RegistrarActionsResponseCodes = {
3041
+ /**
3042
+ * Represents that Registrar Actions are available.
3043
+ */
3044
+ Ok: "ok",
3045
+ /**
3046
+ * Represents that Registrar Actions are unavailable.
3047
+ */
3048
+ Error: "error"
3049
+ };
2258
3050
 
2259
- // src/ensindexer/indexing-status/deserialize.ts
2260
- var import_v411 = require("zod/v4");
2261
- function deserializeChainIndexingStatusSnapshot(maybeSnapshot, valueLabel) {
2262
- const schema = makeChainIndexingStatusSnapshotSchema(valueLabel);
2263
- const parsed = schema.safeParse(maybeSnapshot);
2264
- if (parsed.error) {
2265
- throw new Error(
2266
- `Cannot deserialize into ChainIndexingStatusSnapshot:
2267
- ${(0, import_v411.prettifyError)(parsed.error)}
2268
- `
2269
- );
2270
- }
2271
- return parsed.data;
2272
- }
2273
- function deserializeOmnichainIndexingStatusSnapshot(maybeSnapshot, valueLabel) {
2274
- const schema = makeOmnichainIndexingStatusSnapshotSchema(valueLabel);
2275
- const parsed = schema.safeParse(maybeSnapshot);
2276
- if (parsed.error) {
2277
- throw new Error(
2278
- `Cannot deserialize into OmnichainIndexingStatusSnapshot:
2279
- ${(0, import_v411.prettifyError)(parsed.error)}
2280
- `
2281
- );
2282
- }
2283
- return parsed.data;
2284
- }
2285
- function deserializeCrossChainIndexingStatusSnapshot(maybeSnapshot, valueLabel) {
2286
- const schema = makeCrossChainIndexingStatusSnapshotSchema(valueLabel);
2287
- const parsed = schema.safeParse(maybeSnapshot);
2288
- if (parsed.error) {
2289
- throw new Error(
2290
- `Cannot deserialize into CrossChainIndexingStatusSnapshot:
2291
- ${(0, import_v411.prettifyError)(parsed.error)}
2292
- `
2293
- );
3051
+ // src/api/registrar-actions/zod-schemas.ts
3052
+ function invariant_registrationLifecycleNodeMatchesName(ctx) {
3053
+ const { name, action } = ctx.value;
3054
+ const expectedNode = action.registrationLifecycle.node;
3055
+ const actualNode = (0, import_ens7.namehash)(name);
3056
+ if (actualNode !== expectedNode) {
3057
+ ctx.issues.push({
3058
+ code: "custom",
3059
+ input: ctx.value,
3060
+ message: `The 'action.registrationLifecycle.node' must match namehash of 'name'`
3061
+ });
2294
3062
  }
2295
- return parsed.data;
2296
3063
  }
2297
- function deserializeRealtimeIndexingStatusProjection(maybeProjection, valueLabel) {
2298
- const schema = makeRealtimeIndexingStatusProjectionSchema(valueLabel);
2299
- const parsed = schema.safeParse(maybeProjection);
3064
+ var makeNamedRegistrarActionSchema = (valueLabel = "Named Registrar Action") => import_v418.default.object({
3065
+ action: makeRegistrarActionSchema(valueLabel),
3066
+ name: makeReinterpretedNameSchema(valueLabel)
3067
+ }).check(invariant_registrationLifecycleNodeMatchesName);
3068
+ var makeRegistrarActionsResponseOkSchema = (valueLabel = "Registrar Actions Response OK") => import_v418.default.strictObject({
3069
+ responseCode: import_v418.default.literal(RegistrarActionsResponseCodes.Ok),
3070
+ registrarActions: import_v418.default.array(makeNamedRegistrarActionSchema(valueLabel)),
3071
+ pageContext: makeResponsePageContextSchema(`${valueLabel}.pageContext`)
3072
+ });
3073
+ var makeRegistrarActionsResponseErrorSchema = (_valueLabel = "Registrar Actions Response Error") => import_v418.default.strictObject({
3074
+ responseCode: import_v418.default.literal(RegistrarActionsResponseCodes.Error),
3075
+ error: ErrorResponseSchema
3076
+ });
3077
+ var makeRegistrarActionsResponseSchema = (valueLabel = "Registrar Actions Response") => import_v418.default.discriminatedUnion("responseCode", [
3078
+ makeRegistrarActionsResponseOkSchema(valueLabel),
3079
+ makeRegistrarActionsResponseErrorSchema(valueLabel)
3080
+ ]);
3081
+
3082
+ // src/api/registrar-actions/deserialize.ts
3083
+ function deserializeRegistrarActionsResponse(maybeResponse) {
3084
+ const parsed = makeRegistrarActionsResponseSchema().safeParse(maybeResponse);
2300
3085
  if (parsed.error) {
2301
3086
  throw new Error(
2302
- `Cannot deserialize into RealtimeIndexingStatusProjection:
2303
- ${(0, import_v411.prettifyError)(parsed.error)}
3087
+ `Cannot deserialize RegistrarActionsResponse:
3088
+ ${(0, import_v419.prettifyError)(parsed.error)}
2304
3089
  `
2305
3090
  );
2306
3091
  }
2307
3092
  return parsed.data;
2308
3093
  }
2309
3094
 
2310
- // src/ensindexer/indexing-status/projection.ts
2311
- function createRealtimeIndexingStatusProjection(snapshot, now) {
2312
- const projectedAt = Math.max(now, snapshot.snapshotTime);
2313
- return {
2314
- projectedAt,
2315
- worstCaseDistance: projectedAt - snapshot.slowestChainIndexingCursor,
2316
- snapshot
2317
- };
2318
- }
3095
+ // src/api/registrar-actions/request.ts
3096
+ var RegistrarActionsFilterTypes = {
3097
+ BySubregistryNode: "bySubregistryNode",
3098
+ WithEncodedReferral: "withEncodedReferral",
3099
+ ByDecodedReferrer: "byDecodedReferrer"
3100
+ };
3101
+ var RegistrarActionsOrders = {
3102
+ LatestRegistrarActions: "orderBy[timestamp]=desc"
3103
+ };
2319
3104
 
2320
- // src/ensindexer/indexing-status/serialize.ts
2321
- function serializeCrossChainIndexingStatusSnapshotOmnichain({
2322
- strategy,
2323
- slowestChainIndexingCursor,
2324
- snapshotTime,
2325
- omnichainSnapshot
2326
- }) {
2327
- return {
2328
- strategy,
2329
- slowestChainIndexingCursor,
2330
- snapshotTime,
2331
- omnichainSnapshot: serializeOmnichainIndexingStatusSnapshot(omnichainSnapshot)
2332
- };
2333
- }
2334
- function serializeRealtimeIndexingStatusProjection(indexingProjection) {
2335
- return {
2336
- projectedAt: indexingProjection.projectedAt,
2337
- worstCaseDistance: indexingProjection.worstCaseDistance,
2338
- snapshot: serializeCrossChainIndexingStatusSnapshotOmnichain(indexingProjection.snapshot)
2339
- };
2340
- }
2341
- function serializeChainIndexingSnapshots(chains) {
2342
- const serializedSnapshots = {};
2343
- for (const [chainId, snapshot] of chains.entries()) {
2344
- serializedSnapshots[serializeChainId(chainId)] = snapshot;
2345
- }
2346
- return serializedSnapshots;
2347
- }
2348
- function serializeOmnichainIndexingStatusSnapshot(indexingStatus) {
2349
- switch (indexingStatus.omnichainStatus) {
2350
- case OmnichainIndexingStatusIds.Unstarted:
2351
- return {
2352
- omnichainStatus: OmnichainIndexingStatusIds.Unstarted,
2353
- chains: serializeChainIndexingSnapshots(indexingStatus.chains),
2354
- omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
2355
- };
2356
- case OmnichainIndexingStatusIds.Backfill:
2357
- return {
2358
- omnichainStatus: OmnichainIndexingStatusIds.Backfill,
2359
- chains: serializeChainIndexingSnapshots(indexingStatus.chains),
2360
- omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
2361
- };
2362
- case OmnichainIndexingStatusIds.Completed: {
2363
- return {
2364
- omnichainStatus: OmnichainIndexingStatusIds.Completed,
2365
- chains: serializeChainIndexingSnapshots(indexingStatus.chains),
2366
- omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
2367
- };
2368
- }
2369
- case OmnichainIndexingStatusIds.Following:
2370
- return {
2371
- omnichainStatus: OmnichainIndexingStatusIds.Following,
2372
- chains: serializeChainIndexingSnapshots(indexingStatus.chains),
2373
- omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
2374
- };
3105
+ // src/api/registrar-actions/filters.ts
3106
+ function byParentNode(parentNode) {
3107
+ if (typeof parentNode === "undefined") {
3108
+ return void 0;
3109
+ }
3110
+ return {
3111
+ filterType: RegistrarActionsFilterTypes.BySubregistryNode,
3112
+ value: parentNode
3113
+ };
3114
+ }
3115
+ function withReferral(withReferral2) {
3116
+ if (!withReferral2) {
3117
+ return void 0;
3118
+ }
3119
+ return {
3120
+ filterType: RegistrarActionsFilterTypes.WithEncodedReferral
3121
+ };
3122
+ }
3123
+ function byDecodedReferrer(decodedReferrer) {
3124
+ if (typeof decodedReferrer === "undefined") {
3125
+ return void 0;
2375
3126
  }
3127
+ return {
3128
+ filterType: RegistrarActionsFilterTypes.ByDecodedReferrer,
3129
+ value: decodedReferrer
3130
+ };
2376
3131
  }
3132
+ var registrarActionsFilter = {
3133
+ byParentNode,
3134
+ withReferral,
3135
+ byDecodedReferrer
3136
+ };
2377
3137
 
2378
3138
  // src/api/registrar-actions/prerequisites.ts
2379
3139
  var registrarActionsPrerequisites = Object.freeze({
@@ -2425,12 +3185,42 @@ var registrarActionsPrerequisites = Object.freeze({
2425
3185
  }
2426
3186
  });
2427
3187
 
3188
+ // src/registrars/basenames-subregistry.ts
3189
+ var import_datasources6 = require("@ensnode/datasources");
3190
+ function getBasenamesSubregistryId(namespace) {
3191
+ const datasource = (0, import_datasources6.maybeGetDatasource)(namespace, import_datasources6.DatasourceNames.Basenames);
3192
+ if (!datasource) {
3193
+ throw new Error(`Datasource not found for ${namespace} ${import_datasources6.DatasourceNames.Basenames}`);
3194
+ }
3195
+ const address = datasource.contracts.BaseRegistrar?.address;
3196
+ if (address === void 0 || Array.isArray(address)) {
3197
+ throw new Error(`BaseRegistrar contract not found or has multiple addresses for ${namespace}`);
3198
+ }
3199
+ return {
3200
+ chainId: datasource.chain.id,
3201
+ address
3202
+ };
3203
+ }
3204
+ function getBasenamesSubregistryManagedName(namespaceId) {
3205
+ switch (namespaceId) {
3206
+ case import_datasources6.ENSNamespaceIds.Mainnet:
3207
+ return "base.eth";
3208
+ case import_datasources6.ENSNamespaceIds.Sepolia:
3209
+ return "basetest.eth";
3210
+ case import_datasources6.ENSNamespaceIds.Holesky:
3211
+ case import_datasources6.ENSNamespaceIds.EnsTestEnv:
3212
+ throw new Error(
3213
+ `No registrar managed name is known for the 'basenames' subregistry within the "${namespaceId}" namespace.`
3214
+ );
3215
+ }
3216
+ }
3217
+
2428
3218
  // src/registrars/ethnames-subregistry.ts
2429
- var import_datasources8 = require("@ensnode/datasources");
3219
+ var import_datasources7 = require("@ensnode/datasources");
2430
3220
  function getEthnamesSubregistryId(namespace) {
2431
- const datasource = (0, import_datasources8.maybeGetDatasource)(namespace, import_datasources8.DatasourceNames.ENSRoot);
3221
+ const datasource = (0, import_datasources7.maybeGetDatasource)(namespace, import_datasources7.DatasourceNames.ENSRoot);
2432
3222
  if (!datasource) {
2433
- throw new Error(`Datasource not found for ${namespace} ${import_datasources8.DatasourceNames.ENSRoot}`);
3223
+ throw new Error(`Datasource not found for ${namespace} ${import_datasources7.DatasourceNames.ENSRoot}`);
2434
3224
  }
2435
3225
  const address = datasource.contracts.BaseRegistrar?.address;
2436
3226
  if (address === void 0 || Array.isArray(address)) {
@@ -2441,19 +3231,47 @@ function getEthnamesSubregistryId(namespace) {
2441
3231
  address
2442
3232
  };
2443
3233
  }
3234
+ function getEthnamesSubregistryManagedName(namespaceId) {
3235
+ switch (namespaceId) {
3236
+ case import_datasources7.ENSNamespaceIds.Mainnet:
3237
+ case import_datasources7.ENSNamespaceIds.Sepolia:
3238
+ case import_datasources7.ENSNamespaceIds.Holesky:
3239
+ case import_datasources7.ENSNamespaceIds.EnsTestEnv:
3240
+ return "eth";
3241
+ }
3242
+ }
2444
3243
 
2445
- // src/api/serialize.ts
2446
- function serializeIndexingStatusResponse(response) {
2447
- switch (response.responseCode) {
2448
- case IndexingStatusResponseCodes.Ok:
2449
- return {
2450
- responseCode: response.responseCode,
2451
- realtimeProjection: serializeRealtimeIndexingStatusProjection(response.realtimeProjection)
2452
- };
2453
- case IndexingStatusResponseCodes.Error:
2454
- return response;
3244
+ // src/registrars/lineanames-subregistry.ts
3245
+ var import_datasources8 = require("@ensnode/datasources");
3246
+ function getLineanamesSubregistryId(namespace) {
3247
+ const datasource = (0, import_datasources8.maybeGetDatasource)(namespace, import_datasources8.DatasourceNames.Lineanames);
3248
+ if (!datasource) {
3249
+ throw new Error(`Datasource not found for ${namespace} ${import_datasources8.DatasourceNames.Lineanames}`);
3250
+ }
3251
+ const address = datasource.contracts.BaseRegistrar?.address;
3252
+ if (address === void 0 || Array.isArray(address)) {
3253
+ throw new Error(`BaseRegistrar contract not found or has multiple addresses for ${namespace}`);
3254
+ }
3255
+ return {
3256
+ chainId: datasource.chain.id,
3257
+ address
3258
+ };
3259
+ }
3260
+ function getLineanamesSubregistryManagedName(namespaceId) {
3261
+ switch (namespaceId) {
3262
+ case import_datasources8.ENSNamespaceIds.Mainnet:
3263
+ return "linea.eth";
3264
+ case import_datasources8.ENSNamespaceIds.Sepolia:
3265
+ return "linea-sepolia.eth";
3266
+ case import_datasources8.ENSNamespaceIds.Holesky:
3267
+ case import_datasources8.ENSNamespaceIds.EnsTestEnv:
3268
+ throw new Error(
3269
+ `No registrar managed name is known for the 'Lineanames' subregistry within the "${namespaceId}" namespace.`
3270
+ );
2455
3271
  }
2456
3272
  }
3273
+
3274
+ // src/api/registrar-actions/serialize.ts
2457
3275
  function serializeNamedRegistrarAction({
2458
3276
  action,
2459
3277
  name
@@ -2468,13 +3286,61 @@ function serializeRegistrarActionsResponse(response) {
2468
3286
  case RegistrarActionsResponseCodes.Ok:
2469
3287
  return {
2470
3288
  responseCode: response.responseCode,
2471
- registrarActions: response.registrarActions.map(serializeNamedRegistrarAction)
3289
+ registrarActions: response.registrarActions.map(serializeNamedRegistrarAction),
3290
+ pageContext: response.pageContext
2472
3291
  };
2473
3292
  case RegistrarActionsResponseCodes.Error:
2474
3293
  return response;
2475
3294
  }
2476
3295
  }
2477
3296
 
3297
+ // src/api/shared/errors/deserialize.ts
3298
+ var import_v420 = require("zod/v4");
3299
+ function deserializeErrorResponse(maybeErrorResponse) {
3300
+ const parsed = ErrorResponseSchema.safeParse(maybeErrorResponse);
3301
+ if (parsed.error) {
3302
+ throw new Error(`Cannot deserialize ErrorResponse:
3303
+ ${(0, import_v420.prettifyError)(parsed.error)}
3304
+ `);
3305
+ }
3306
+ return parsed.data;
3307
+ }
3308
+
3309
+ // src/api/shared/pagination/build-page-context.ts
3310
+ function buildPageContext(page, recordsPerPage, totalRecords) {
3311
+ const totalPages = Math.max(1, Math.ceil(totalRecords / recordsPerPage));
3312
+ if (page > totalPages) {
3313
+ throw new Error(`Invalid page: page ${page} exceeds total pages ${totalPages}.`);
3314
+ }
3315
+ if (totalRecords === 0) {
3316
+ return {
3317
+ page,
3318
+ recordsPerPage,
3319
+ totalRecords: 0,
3320
+ totalPages: 1,
3321
+ hasNext: false,
3322
+ hasPrev: false,
3323
+ startIndex: void 0,
3324
+ endIndex: void 0
3325
+ };
3326
+ }
3327
+ const startIndex = (page - 1) * recordsPerPage;
3328
+ const maxTheoreticalIndexOnPage = startIndex + (recordsPerPage - 1);
3329
+ const endIndex = Math.min(maxTheoreticalIndexOnPage, totalRecords - 1);
3330
+ const hasNext = maxTheoreticalIndexOnPage < totalRecords - 1;
3331
+ const hasPrev = page > 1;
3332
+ return {
3333
+ page,
3334
+ recordsPerPage,
3335
+ totalRecords,
3336
+ totalPages,
3337
+ hasNext,
3338
+ hasPrev,
3339
+ startIndex,
3340
+ endIndex
3341
+ };
3342
+ }
3343
+
2478
3344
  // src/client-error.ts
2479
3345
  var ClientError = class _ClientError extends Error {
2480
3346
  details;
@@ -2489,10 +3355,10 @@ var ClientError = class _ClientError extends Error {
2489
3355
  };
2490
3356
 
2491
3357
  // src/ensanalytics/deserialize.ts
2492
- var import_v413 = require("zod/v4");
3358
+ var import_v422 = require("zod/v4");
2493
3359
 
2494
3360
  // src/ensanalytics/zod-schemas.ts
2495
- var import_v412 = __toESM(require("zod/v4"), 1);
3361
+ var import_v421 = __toESM(require("zod/v4"), 1);
2496
3362
 
2497
3363
  // src/ensanalytics/types.ts
2498
3364
  var ReferrerLeaderboardPageResponseCodes = {
@@ -2505,22 +3371,50 @@ var ReferrerLeaderboardPageResponseCodes = {
2505
3371
  */
2506
3372
  Error: "error"
2507
3373
  };
3374
+ var ReferrerDetailResponseCodes = {
3375
+ /**
3376
+ * Represents that the referrer detail data is available.
3377
+ */
3378
+ Ok: "ok",
3379
+ /**
3380
+ * Represents that an error occurred while fetching the data.
3381
+ */
3382
+ Error: "error"
3383
+ };
2508
3384
 
2509
3385
  // src/ensanalytics/zod-schemas.ts
2510
- var makeReferralProgramRulesSchema = (valueLabel = "ReferralProgramRules") => import_v412.default.object({
3386
+ var makeReferralProgramRulesSchema = (valueLabel = "ReferralProgramRules") => import_v421.default.object({
2511
3387
  totalAwardPoolValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.totalAwardPoolValue`),
2512
3388
  maxQualifiedReferrers: makeNonNegativeIntegerSchema(`${valueLabel}.maxQualifiedReferrers`),
2513
3389
  startTime: makeUnixTimestampSchema(`${valueLabel}.startTime`),
2514
3390
  endTime: makeUnixTimestampSchema(`${valueLabel}.endTime`),
2515
3391
  subregistryId: makeAccountIdSchema(`${valueLabel}.subregistryId`)
2516
3392
  });
2517
- var makeAwardedReferrerMetricsSchema = (valueLabel = "AwardedReferrerMetrics") => import_v412.default.object({
3393
+ var makeAwardedReferrerMetricsSchema = (valueLabel = "AwardedReferrerMetrics") => import_v421.default.object({
2518
3394
  referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`),
2519
3395
  totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`),
2520
3396
  totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`),
2521
3397
  score: makeFiniteNonNegativeNumberSchema(`${valueLabel}.score`),
2522
3398
  rank: makePositiveIntegerSchema(`${valueLabel}.rank`),
2523
- isQualified: import_v412.default.boolean(),
3399
+ isQualified: import_v421.default.boolean(),
3400
+ finalScoreBoost: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScoreBoost`).max(
3401
+ 1,
3402
+ `${valueLabel}.finalScoreBoost must be <= 1`
3403
+ ),
3404
+ finalScore: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScore`),
3405
+ awardPoolShare: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolShare`).max(
3406
+ 1,
3407
+ `${valueLabel}.awardPoolShare must be <= 1`
3408
+ ),
3409
+ awardPoolApproxValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolApproxValue`)
3410
+ });
3411
+ var makeUnrankedReferrerMetricsSchema = (valueLabel = "UnrankedReferrerMetrics") => import_v421.default.object({
3412
+ referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`),
3413
+ totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`),
3414
+ totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`),
3415
+ score: makeFiniteNonNegativeNumberSchema(`${valueLabel}.score`),
3416
+ rank: import_v421.default.null(),
3417
+ isQualified: import_v421.default.literal(false),
2524
3418
  finalScoreBoost: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScoreBoost`).max(
2525
3419
  1,
2526
3420
  `${valueLabel}.finalScoreBoost must be <= 1`
@@ -2532,7 +3426,7 @@ var makeAwardedReferrerMetricsSchema = (valueLabel = "AwardedReferrerMetrics") =
2532
3426
  ),
2533
3427
  awardPoolApproxValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolApproxValue`)
2534
3428
  });
2535
- var makeAggregatedReferrerMetricsSchema = (valueLabel = "AggregatedReferrerMetrics") => import_v412.default.object({
3429
+ var makeAggregatedReferrerMetricsSchema = (valueLabel = "AggregatedReferrerMetrics") => import_v421.default.object({
2536
3430
  grandTotalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.grandTotalReferrals`),
2537
3431
  grandTotalIncrementalDuration: makeDurationSchema(
2538
3432
  `${valueLabel}.grandTotalIncrementalDuration`
@@ -2544,41 +3438,69 @@ var makeAggregatedReferrerMetricsSchema = (valueLabel = "AggregatedReferrerMetri
2544
3438
  `${valueLabel}.minFinalScoreToQualify`
2545
3439
  )
2546
3440
  });
2547
- var makeReferrerLeaderboardPaginationContextSchema = (valueLabel = "ReferrerLeaderboardPaginationContext") => import_v412.default.object({
3441
+ var makeReferrerLeaderboardPageContextSchema = (valueLabel = "ReferrerLeaderboardPageContext") => import_v421.default.object({
2548
3442
  page: makePositiveIntegerSchema(`${valueLabel}.page`),
2549
- itemsPerPage: makePositiveIntegerSchema(`${valueLabel}.itemsPerPage`).max(
3443
+ recordsPerPage: makePositiveIntegerSchema(`${valueLabel}.recordsPerPage`).max(
2550
3444
  REFERRERS_PER_LEADERBOARD_PAGE_MAX,
2551
- `${valueLabel}.itemsPerPage must not exceed ${REFERRERS_PER_LEADERBOARD_PAGE_MAX}`
3445
+ `${valueLabel}.recordsPerPage must not exceed ${REFERRERS_PER_LEADERBOARD_PAGE_MAX}`
2552
3446
  ),
2553
3447
  totalRecords: makeNonNegativeIntegerSchema(`${valueLabel}.totalRecords`),
2554
3448
  totalPages: makePositiveIntegerSchema(`${valueLabel}.totalPages`),
2555
- hasNext: import_v412.default.boolean(),
2556
- hasPrev: import_v412.default.boolean(),
2557
- startIndex: import_v412.default.optional(makeNonNegativeIntegerSchema(`${valueLabel}.startIndex`)),
2558
- endIndex: import_v412.default.optional(makeNonNegativeIntegerSchema(`${valueLabel}.endIndex`))
3449
+ hasNext: import_v421.default.boolean(),
3450
+ hasPrev: import_v421.default.boolean(),
3451
+ startIndex: import_v421.default.optional(makeNonNegativeIntegerSchema(`${valueLabel}.startIndex`)),
3452
+ endIndex: import_v421.default.optional(makeNonNegativeIntegerSchema(`${valueLabel}.endIndex`))
2559
3453
  });
2560
- var makeReferrerLeaderboardPageSchema = (valueLabel = "ReferrerLeaderboardPage") => import_v412.default.object({
3454
+ var makeReferrerLeaderboardPageSchema = (valueLabel = "ReferrerLeaderboardPage") => import_v421.default.object({
2561
3455
  rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),
2562
- referrers: import_v412.default.array(makeAwardedReferrerMetricsSchema(`${valueLabel}.referrers[item]`)),
3456
+ referrers: import_v421.default.array(makeAwardedReferrerMetricsSchema(`${valueLabel}.referrers[record]`)),
2563
3457
  aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),
2564
- paginationContext: makeReferrerLeaderboardPaginationContextSchema(
2565
- `${valueLabel}.paginationContext`
2566
- ),
3458
+ pageContext: makeReferrerLeaderboardPageContextSchema(`${valueLabel}.pageContext`),
2567
3459
  accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`)
2568
3460
  });
2569
- var makeReferrerLeaderboardPageResponseOkSchema = (valueLabel = "ReferrerLeaderboardPageResponseOk") => import_v412.default.object({
2570
- responseCode: import_v412.default.literal(ReferrerLeaderboardPageResponseCodes.Ok),
3461
+ var makeReferrerLeaderboardPageResponseOkSchema = (valueLabel = "ReferrerLeaderboardPageResponseOk") => import_v421.default.object({
3462
+ responseCode: import_v421.default.literal(ReferrerLeaderboardPageResponseCodes.Ok),
2571
3463
  data: makeReferrerLeaderboardPageSchema(`${valueLabel}.data`)
2572
3464
  });
2573
- var makeReferrerLeaderboardPageResponseErrorSchema = (_valueLabel = "ReferrerLeaderboardPageResponseError") => import_v412.default.object({
2574
- responseCode: import_v412.default.literal(ReferrerLeaderboardPageResponseCodes.Error),
2575
- error: import_v412.default.string(),
2576
- errorMessage: import_v412.default.string()
3465
+ var makeReferrerLeaderboardPageResponseErrorSchema = (_valueLabel = "ReferrerLeaderboardPageResponseError") => import_v421.default.object({
3466
+ responseCode: import_v421.default.literal(ReferrerLeaderboardPageResponseCodes.Error),
3467
+ error: import_v421.default.string(),
3468
+ errorMessage: import_v421.default.string()
2577
3469
  });
2578
- var makeReferrerLeaderboardPageResponseSchema = (valueLabel = "ReferrerLeaderboardPageResponse") => import_v412.default.union([
3470
+ var makeReferrerLeaderboardPageResponseSchema = (valueLabel = "ReferrerLeaderboardPageResponse") => import_v421.default.union([
2579
3471
  makeReferrerLeaderboardPageResponseOkSchema(valueLabel),
2580
3472
  makeReferrerLeaderboardPageResponseErrorSchema(valueLabel)
2581
3473
  ]);
3474
+ var makeReferrerDetailRankedSchema = (valueLabel = "ReferrerDetailRanked") => import_v421.default.object({
3475
+ type: import_v421.default.literal(ReferrerDetailTypeIds.Ranked),
3476
+ rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),
3477
+ referrer: makeAwardedReferrerMetricsSchema(`${valueLabel}.referrer`),
3478
+ aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),
3479
+ accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`)
3480
+ });
3481
+ var makeReferrerDetailUnrankedSchema = (valueLabel = "ReferrerDetailUnranked") => import_v421.default.object({
3482
+ type: import_v421.default.literal(ReferrerDetailTypeIds.Unranked),
3483
+ rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),
3484
+ referrer: makeUnrankedReferrerMetricsSchema(`${valueLabel}.referrer`),
3485
+ aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),
3486
+ accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`)
3487
+ });
3488
+ var makeReferrerDetailResponseOkSchema = (valueLabel = "ReferrerDetailResponse") => import_v421.default.object({
3489
+ responseCode: import_v421.default.literal(ReferrerDetailResponseCodes.Ok),
3490
+ data: import_v421.default.union([
3491
+ makeReferrerDetailRankedSchema(`${valueLabel}.data`),
3492
+ makeReferrerDetailUnrankedSchema(`${valueLabel}.data`)
3493
+ ])
3494
+ });
3495
+ var makeReferrerDetailResponseErrorSchema = (_valueLabel = "ReferrerDetailResponse") => import_v421.default.object({
3496
+ responseCode: import_v421.default.literal(ReferrerDetailResponseCodes.Error),
3497
+ error: import_v421.default.string(),
3498
+ errorMessage: import_v421.default.string()
3499
+ });
3500
+ var makeReferrerDetailResponseSchema = (valueLabel = "ReferrerDetailResponse") => import_v421.default.union([
3501
+ makeReferrerDetailResponseOkSchema(valueLabel),
3502
+ makeReferrerDetailResponseErrorSchema(valueLabel)
3503
+ ]);
2582
3504
 
2583
3505
  // src/ensanalytics/deserialize.ts
2584
3506
  function deserializeReferrerLeaderboardPageResponse(maybeResponse, valueLabel) {
@@ -2587,12 +3509,22 @@ function deserializeReferrerLeaderboardPageResponse(maybeResponse, valueLabel) {
2587
3509
  if (parsed.error) {
2588
3510
  throw new Error(
2589
3511
  `Cannot deserialize SerializedReferrerLeaderboardPageResponse:
2590
- ${(0, import_v413.prettifyError)(parsed.error)}
3512
+ ${(0, import_v422.prettifyError)(parsed.error)}
2591
3513
  `
2592
3514
  );
2593
3515
  }
2594
3516
  return parsed.data;
2595
3517
  }
3518
+ function deserializeReferrerDetailResponse(maybeResponse, valueLabel) {
3519
+ const schema = makeReferrerDetailResponseSchema(valueLabel);
3520
+ const parsed = schema.safeParse(maybeResponse);
3521
+ if (parsed.error) {
3522
+ throw new Error(`Cannot deserialize ReferrerDetailResponse:
3523
+ ${(0, import_v422.prettifyError)(parsed.error)}
3524
+ `);
3525
+ }
3526
+ return parsed.data;
3527
+ }
2596
3528
 
2597
3529
  // src/ensanalytics/serialize.ts
2598
3530
  function serializeReferrerLeaderboardPageResponse(response) {
@@ -2603,55 +3535,15 @@ function serializeReferrerLeaderboardPageResponse(response) {
2603
3535
  return response;
2604
3536
  }
2605
3537
  }
2606
-
2607
- // src/ensapi/config/deserialize.ts
2608
- var import_v415 = require("zod/v4");
2609
-
2610
- // src/ensapi/config/zod-schemas.ts
2611
- var import_v414 = require("zod/v4");
2612
- var TheGraphCannotFallbackReasonSchema = import_v414.z.enum({
2613
- NotSubgraphCompatible: "not-subgraph-compatible",
2614
- NoApiKey: "no-api-key",
2615
- NoSubgraphUrl: "no-subgraph-url"
2616
- });
2617
- var TheGraphFallbackSchema = import_v414.z.strictObject({
2618
- canFallback: import_v414.z.boolean(),
2619
- reason: TheGraphCannotFallbackReasonSchema.nullable()
2620
- });
2621
- function makeENSApiPublicConfigSchema(valueLabel) {
2622
- const label = valueLabel ?? "ENSApiPublicConfig";
2623
- return import_v414.z.strictObject({
2624
- version: import_v414.z.string().min(1, `${label}.version must be a non-empty string`),
2625
- theGraphFallback: TheGraphFallbackSchema,
2626
- ensIndexerPublicConfig: makeENSIndexerPublicConfigSchema(`${label}.ensIndexerPublicConfig`)
2627
- });
2628
- }
2629
-
2630
- // src/ensapi/config/deserialize.ts
2631
- function deserializeENSApiPublicConfig(maybeConfig, valueLabel) {
2632
- const schema = makeENSApiPublicConfigSchema(valueLabel);
2633
- try {
2634
- return schema.parse(maybeConfig);
2635
- } catch (error) {
2636
- if (error instanceof import_v415.ZodError) {
2637
- throw new Error(`Cannot deserialize ENSApiPublicConfig:
2638
- ${(0, import_v415.prettifyError)(error)}
2639
- `);
2640
- }
2641
- throw error;
3538
+ function serializeReferrerDetailResponse(response) {
3539
+ switch (response.responseCode) {
3540
+ case ReferrerDetailResponseCodes.Ok:
3541
+ return response;
3542
+ case ReferrerDetailResponseCodes.Error:
3543
+ return response;
2642
3544
  }
2643
3545
  }
2644
3546
 
2645
- // src/ensapi/config/serialize.ts
2646
- function serializeENSApiPublicConfig(config) {
2647
- const { version, theGraphFallback, ensIndexerPublicConfig } = config;
2648
- return {
2649
- version,
2650
- theGraphFallback,
2651
- ensIndexerPublicConfig: serializeENSIndexerPublicConfig(ensIndexerPublicConfig)
2652
- };
2653
- }
2654
-
2655
3547
  // src/client.ts
2656
3548
  var DEFAULT_ENSNODE_API_URL = "https://api.alpha.ensnode.io";
2657
3549
  var ENSNodeClient = class _ENSNodeClient {
@@ -2855,7 +3747,7 @@ var ENSNodeClient = class _ENSNodeClient {
2855
3747
  const errorResponse = deserializeErrorResponse(responseData);
2856
3748
  throw new Error(`Fetching ENSNode Config Failed: ${errorResponse.message}`);
2857
3749
  }
2858
- return deserializeENSApiPublicConfig(responseData);
3750
+ return deserializeConfigResponse(responseData);
2859
3751
  }
2860
3752
  /**
2861
3753
  * Fetch ENSNode Indexing Status
@@ -2896,7 +3788,7 @@ var ENSNodeClient = class _ENSNodeClient {
2896
3788
  *
2897
3789
  * @param request - Pagination parameters
2898
3790
  * @param request.page - The page number to retrieve (1-indexed, default: 1)
2899
- * @param request.itemsPerPage - Number of items per page (default: 25, max: 100)
3791
+ * @param request.recordsPerPage - Number of records per page (default: 25, max: 100)
2900
3792
  * @returns {ReferrerLeaderboardPageResponse}
2901
3793
  *
2902
3794
  * @throws if the ENSNode request fails
@@ -2905,34 +3797,34 @@ var ENSNodeClient = class _ENSNodeClient {
2905
3797
  *
2906
3798
  * @example
2907
3799
  * ```typescript
2908
- * // Get first page with default page size (25 items)
2909
- * const response = await client.getReferrerLeaderboard();
3800
+ * // Get first page with default page size (25 records)
3801
+ * const response = await client.getReferrerLeaderboardPage();
2910
3802
  * if (response.responseCode === ReferrerLeaderboardPageResponseCodes.Ok) {
2911
3803
  * const {
2912
3804
  * aggregatedMetrics,
2913
3805
  * referrers,
2914
3806
  * rules,
2915
- * paginationContext,
3807
+ * pageContext,
2916
3808
  * updatedAt
2917
3809
  * } = response.data;
2918
3810
  * console.log(aggregatedMetrics);
2919
3811
  * console.log(referrers);
2920
3812
  * console.log(rules);
2921
3813
  * console.log(updatedAt);
2922
- * console.log(`Page ${paginationContext.page} of ${paginationContext.totalPages}`);
3814
+ * console.log(`Page ${pageContext.page} of ${pageContext.totalPages}`);
2923
3815
  * }
2924
3816
  * ```
2925
3817
  *
2926
3818
  * @example
2927
3819
  * ```typescript
2928
- * // Get second page with 50 items per page
2929
- * const response = await client.getReferrerLeaderboard({ page: 2, itemsPerPage: 50 });
3820
+ * // Get second page with 50 records per page
3821
+ * const response = await client.getReferrerLeaderboardPage({ page: 2, recordsPerPage: 50 });
2930
3822
  * ```
2931
3823
  *
2932
3824
  * @example
2933
3825
  * ```typescript
2934
3826
  * // Handle error response, ie. when Referrer Leaderboard is not currently available.
2935
- * const response = await client.getReferrerLeaderboard();
3827
+ * const response = await client.getReferrerLeaderboardPage();
2936
3828
  *
2937
3829
  * if (response.responseCode === ReferrerLeaderboardPageResponseCodes.Error) {
2938
3830
  * console.error(response.error);
@@ -2940,11 +3832,11 @@ var ENSNodeClient = class _ENSNodeClient {
2940
3832
  * }
2941
3833
  * ```
2942
3834
  */
2943
- async getReferrerLeaderboard(request) {
3835
+ async getReferrerLeaderboardPage(request) {
2944
3836
  const url = new URL(`/ensanalytics/referrers`, this.options.url);
2945
3837
  if (request?.page) url.searchParams.set("page", request.page.toString());
2946
- if (request?.itemsPerPage)
2947
- url.searchParams.set("itemsPerPage", request.itemsPerPage.toString());
3838
+ if (request?.recordsPerPage)
3839
+ url.searchParams.set("recordsPerPage", request.recordsPerPage.toString());
2948
3840
  const response = await fetch(url);
2949
3841
  let responseData;
2950
3842
  try {
@@ -2956,14 +3848,106 @@ var ENSNodeClient = class _ENSNodeClient {
2956
3848
  responseData
2957
3849
  );
2958
3850
  }
3851
+ /**
3852
+ * Fetch Referrer Detail
3853
+ *
3854
+ * Retrieves detailed information about a specific referrer, whether they are on the
3855
+ * leaderboard or not.
3856
+ *
3857
+ * The response data is a discriminated union type with a `type` field:
3858
+ *
3859
+ * **For referrers on the leaderboard** (`ReferrerDetailRanked`):
3860
+ * - `type`: {@link ReferrerDetailTypeIds.Ranked}
3861
+ * - `referrer`: The `AwardedReferrerMetrics` from @namehash/ens-referrals
3862
+ * - `rules`: The referral program rules
3863
+ * - `aggregatedMetrics`: Aggregated metrics for all referrers on the leaderboard
3864
+ * - `accurateAsOf`: Unix timestamp indicating when the data was last updated
3865
+ *
3866
+ * **For referrers NOT on the leaderboard** (`ReferrerDetailUnranked`):
3867
+ * - `type`: {@link ReferrerDetailTypeIds.Unranked}
3868
+ * - `referrer`: The `UnrankedReferrerMetrics` from @namehash/ens-referrals
3869
+ * - `rules`: The referral program rules
3870
+ * - `aggregatedMetrics`: Aggregated metrics for all referrers on the leaderboard
3871
+ * - `accurateAsOf`: Unix timestamp indicating when the data was last updated
3872
+ *
3873
+ * @see {@link https://www.npmjs.com/package/@namehash/ens-referrals|@namehash/ens-referrals} for calculation details
3874
+ *
3875
+ * @param request The referrer address to query
3876
+ * @returns {ReferrerDetailResponse} Returns the referrer detail response
3877
+ *
3878
+ * @throws if the ENSNode request fails
3879
+ * @throws if the response data is malformed
3880
+ *
3881
+ * @example
3882
+ * ```typescript
3883
+ * // Get referrer detail for a specific address
3884
+ * const response = await client.getReferrerDetail({
3885
+ * referrer: "0x1234567890123456789012345678901234567890"
3886
+ * });
3887
+ * if (response.responseCode === ReferrerDetailResponseCodes.Ok) {
3888
+ * const { type, referrer, rules, aggregatedMetrics, accurateAsOf } = response.data;
3889
+ * console.log(type); // ReferrerDetailTypeIds.Ranked or ReferrerDetailTypeIds.Unranked
3890
+ * console.log(referrer);
3891
+ * console.log(accurateAsOf);
3892
+ * }
3893
+ * ```
3894
+ *
3895
+ * @example
3896
+ * ```typescript
3897
+ * // Use discriminated union to check if referrer is ranked
3898
+ * const response = await client.getReferrerDetail({
3899
+ * referrer: "0x1234567890123456789012345678901234567890"
3900
+ * });
3901
+ * if (response.responseCode === ReferrerDetailResponseCodes.Ok) {
3902
+ * if (response.data.type === ReferrerDetailTypeIds.Ranked) {
3903
+ * // TypeScript knows this is ReferrerDetailRanked
3904
+ * console.log(`Rank: ${response.data.referrer.rank}`);
3905
+ * console.log(`Qualified: ${response.data.referrer.isQualified}`);
3906
+ * console.log(`Award Pool Share: ${response.data.referrer.awardPoolShare * 100}%`);
3907
+ * } else {
3908
+ * // TypeScript knows this is ReferrerDetailUnranked
3909
+ * console.log("Referrer is not on the leaderboard (no referrals yet)");
3910
+ * }
3911
+ * }
3912
+ * ```
3913
+ *
3914
+ * @example
3915
+ * ```typescript
3916
+ * // Handle error response, ie. when Referrer Detail is not currently available.
3917
+ * const response = await client.getReferrerDetail({
3918
+ * referrer: "0x1234567890123456789012345678901234567890"
3919
+ * });
3920
+ *
3921
+ * if (response.responseCode === ReferrerDetailResponseCodes.Error) {
3922
+ * console.error(response.error);
3923
+ * console.error(response.errorMessage);
3924
+ * }
3925
+ * ```
3926
+ */
3927
+ async getReferrerDetail(request) {
3928
+ const url = new URL(
3929
+ `/api/ensanalytics/referrers/${encodeURIComponent(request.referrer)}`,
3930
+ this.options.url
3931
+ );
3932
+ const response = await fetch(url);
3933
+ let responseData;
3934
+ try {
3935
+ responseData = await response.json();
3936
+ } catch {
3937
+ throw new Error("Malformed response data: invalid JSON");
3938
+ }
3939
+ return deserializeReferrerDetailResponse(responseData);
3940
+ }
2959
3941
  /**
2960
3942
  * Fetch ENSNode Registrar Actions
2961
3943
  *
2962
- * @param {RegistrarActionsRequestFilter} request.filter is
2963
- * an optional request filter configuration.
2964
- * @param {number} request.limit sets the maximum count of results in the response.
2965
- * @param {RegistrarActionsRequestOrder} request.order sets the order of
2966
- * results in the response by field and direction.
3944
+ * Retrieves a paginated list of registrar actions with optional filters.
3945
+ *
3946
+ * @param request is a request configuration.
3947
+ * @param request.page sets the page number to retrieve (1-indexed, default: 1)
3948
+ * @param request.recordsPerPage sets the number of records per page (default: 10, max: 100)
3949
+ * @param request.filters is an optional request filter configuration.
3950
+ * @param request.order sets the order of results in the response by field and direction.
2967
3951
  * @returns {RegistrarActionsResponse}
2968
3952
  *
2969
3953
  * @throws if the ENSNode request fails
@@ -2973,23 +3957,25 @@ var ENSNodeClient = class _ENSNodeClient {
2973
3957
  * @example
2974
3958
  * ```ts
2975
3959
  * import {
2976
- * registrarActionsFilter,,
3960
+ * registrarActionsFilter,
2977
3961
  * ENSNodeClient,
2978
3962
  * } from "@ensnode/ensnode-sdk";
2979
3963
  * import { namehash } from "viem/ens";
2980
3964
  *
2981
3965
  * const client: ENSNodeClient;
2982
3966
  *
2983
- * // get latest registrar action records across all indexed subregistries
2984
- * // NOTE: when no `limit` value is passed,
2985
- * // the default RESPONSE_ITEMS_PER_PAGE_DEFAULT applies.
2986
- * const registrarActions = await client.registrarActions();
3967
+ * // Get first page with default page size (10 records)
3968
+ * const response = await client.registrarActions();
3969
+ * if (response.responseCode === RegistrarActionsResponseCodes.Ok) {
3970
+ * const { registrarActions, pageContext } = response;
3971
+ * console.log(registrarActions);
3972
+ * console.log(`Page ${pageContext.page} of ${pageContext.totalPages}`);
3973
+ * }
2987
3974
  *
2988
- * // get latest 5 registrar action records across all indexed subregistries
2989
- * // NOTE: when a `limit` value is passed, it must be lower than or equal to
2990
- * // the RESPONSE_ITEMS_PER_PAGE_MAX value.
2991
- * const registrarActions = await client.registrarActions({
2992
- * limit: 5,
3975
+ * // Get second page with 25 records per page
3976
+ * const response = await client.registrarActions({
3977
+ * page: 2,
3978
+ * recordsPerPage: 25,
2993
3979
  * });
2994
3980
  *
2995
3981
  * // get latest registrar action records associated with
@@ -3003,11 +3989,16 @@ var ENSNodeClient = class _ENSNodeClient {
3003
3989
  * filters: [registrarActionsFilter.withReferral(true)],
3004
3990
  * });
3005
3991
  *
3992
+ * // get latest registrar action records for a specific decoded referrer
3993
+ * await client.registrarActions({
3994
+ * filters: [registrarActionsFilter.byDecodedReferrer("0x1234567890123456789012345678901234567890")],
3995
+ * });
3996
+ *
3006
3997
  * // get latest 10 registrar action records associated with
3007
3998
  * // subregistry managing `base.eth` name
3008
3999
  * await client.registrarActions({
3009
4000
  * filters: [registrarActionsFilter.byParentNode(namehash('base.eth'))],
3010
- * limit: 10
4001
+ * recordsPerPage: 10
3011
4002
  * });
3012
4003
  * ```
3013
4004
  */
@@ -3024,6 +4015,12 @@ var ENSNodeClient = class _ENSNodeClient {
3024
4015
  );
3025
4016
  return withReferralFilter ? { key: "withReferral", value: "true" } : null;
3026
4017
  };
4018
+ const buildDecodedReferrerArg = (filters) => {
4019
+ const decodedReferrerFilter = filters?.find(
4020
+ (f) => f.filterType === RegistrarActionsFilterTypes.ByDecodedReferrer
4021
+ );
4022
+ return decodedReferrerFilter ? { key: "decodedReferrer", value: decodedReferrerFilter.value } : null;
4023
+ };
3027
4024
  const buildOrderArg = (order) => {
3028
4025
  switch (order) {
3029
4026
  case RegistrarActionsOrders.LatestRegistrarActions: {
@@ -3040,13 +4037,20 @@ var ENSNodeClient = class _ENSNodeClient {
3040
4037
  const orderArgs = buildOrderArg(request.order);
3041
4038
  url.searchParams.set(orderArgs.key, orderArgs.value);
3042
4039
  }
3043
- if (request.itemsPerPage) {
3044
- url.searchParams.set("itemsPerPage", request.itemsPerPage.toString());
4040
+ if (request.page) {
4041
+ url.searchParams.set("page", request.page.toString());
4042
+ }
4043
+ if (request.recordsPerPage) {
4044
+ url.searchParams.set("recordsPerPage", request.recordsPerPage.toString());
3045
4045
  }
3046
4046
  const referralArg = buildWithReferralArg(request.filters);
3047
4047
  if (referralArg) {
3048
4048
  url.searchParams.set(referralArg.key, referralArg.value);
3049
4049
  }
4050
+ const decodedReferrerArg = buildDecodedReferrerArg(request.filters);
4051
+ if (decodedReferrerArg) {
4052
+ url.searchParams.set(decodedReferrerArg.key, decodedReferrerArg.value);
4053
+ }
3050
4054
  const response = await fetch(url);
3051
4055
  let responseData;
3052
4056
  try {
@@ -3067,6 +4071,62 @@ var ENSNodeClient = class _ENSNodeClient {
3067
4071
  }
3068
4072
  return deserializeRegistrarActionsResponse(responseData);
3069
4073
  }
4074
+ /**
4075
+ * Fetch Name Tokens for requested name.
4076
+ *
4077
+ * @param request.name - Name for which Name Tokens will be fetched.
4078
+ * @returns {NameTokensResponse}
4079
+ *
4080
+ * @throws if the ENSNode request fails
4081
+ * @throws if the ENSNode API returns an error response
4082
+ * @throws if the ENSNode response breaks required invariants
4083
+ *
4084
+ * @example
4085
+ * ```ts
4086
+ * import {
4087
+ * ENSNodeClient,
4088
+ * } from "@ensnode/ensnode-sdk";
4089
+ * import { namehash } from "viem/ens";
4090
+ *
4091
+ * const client: ENSNodeClient;
4092
+ *
4093
+ * // get latest name token records from the indexed subregistry based on the requested name
4094
+ * const response = await client.nameTokens({
4095
+ * name: "vitalik.eth"
4096
+ * });
4097
+ *
4098
+ * const response = await client.nameTokens({
4099
+ * domainId: "0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835" // namehash('vitalik.eth')
4100
+ * })
4101
+ * ```
4102
+ */
4103
+ async nameTokens(request) {
4104
+ const url = new URL(`/api/name-tokens`, this.options.url);
4105
+ if (request.name !== void 0) {
4106
+ url.searchParams.set("name", request.name);
4107
+ } else {
4108
+ url.searchParams.set("domainId", request.domainId);
4109
+ }
4110
+ const response = await fetch(url);
4111
+ let responseData;
4112
+ try {
4113
+ responseData = await response.json();
4114
+ } catch {
4115
+ throw new Error("Malformed response data: invalid JSON");
4116
+ }
4117
+ if (!response.ok) {
4118
+ let errorResponse;
4119
+ try {
4120
+ errorResponse = deserializeErrorResponse(responseData);
4121
+ } catch {
4122
+ console.log("Name Tokens API: handling a known server error.");
4123
+ }
4124
+ if (typeof errorResponse !== "undefined") {
4125
+ throw new Error(`Fetching ENSNode Name Tokens Failed: ${errorResponse.message}`);
4126
+ }
4127
+ }
4128
+ return deserializedNameTokensResponse(responseData);
4129
+ }
3070
4130
  };
3071
4131
 
3072
4132
  // src/identity/identity.ts
@@ -3106,11 +4166,11 @@ function isResolvedIdentity(identity) {
3106
4166
  }
3107
4167
 
3108
4168
  // src/resolution/ensip19-chainid.ts
3109
- var import_chains2 = require("viem/chains");
4169
+ var import_chains = require("viem/chains");
3110
4170
  var import_datasources10 = require("@ensnode/datasources");
3111
4171
  var getResolvePrimaryNameChainIdParam = (chainId, namespaceId) => {
3112
4172
  const ensRootChainId = (0, import_datasources10.getENSRootChainId)(namespaceId);
3113
- return chainId === ensRootChainId ? import_chains2.mainnet.id : chainId;
4173
+ return chainId === ensRootChainId ? import_chains.mainnet.id : chainId;
3114
4174
  };
3115
4175
  var translateDefaultableChainIdToChainId = (chainId, namespaceId) => {
3116
4176
  return chainId === DEFAULT_EVM_CHAIN_ID ? (0, import_datasources10.getENSRootChainId)(namespaceId) : chainId;