@ensnode/ensnode-sdk 0.31.0 → 0.33.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.js CHANGED
@@ -1,19 +1,133 @@
1
- // src/utils/constants.ts
1
+ // src/ens/constants.ts
2
2
  import { namehash } from "viem";
3
3
  var ROOT_NODE = namehash("");
4
4
  var REVERSE_ROOT_NODES = /* @__PURE__ */ new Set([namehash("addr.reverse")]);
5
- var ETH_COIN_TYPE = 60n;
6
5
 
7
- // src/utils/types.ts
8
- var PluginName = /* @__PURE__ */ ((PluginName2) => {
9
- PluginName2["Subgraph"] = "subgraph";
10
- PluginName2["Basenames"] = "basenames";
11
- PluginName2["Lineanames"] = "lineanames";
12
- PluginName2["ThreeDNS"] = "threedns";
13
- return PluginName2;
14
- })(PluginName || {});
6
+ // src/ens/subname-helpers.ts
7
+ import { concat, isAddress, isHash, keccak256, toHex } from "viem";
8
+ import { labelhash } from "viem/ens";
9
+
10
+ // src/ens/coin-type.ts
11
+ import {
12
+ coinTypeToEvmChainId as _coinTypeToEvmChainId,
13
+ evmChainIdToCoinType as _evmChainIdToCoinType
14
+ } from "@ensdomains/address-encoder/utils";
15
+ var ETH_COIN_TYPE = 60;
16
+ var DEFAULT_EVM_CHAIN_ID = 0;
17
+ var DEFAULT_EVM_COIN_TYPE = 2147483648;
18
+ var coinTypeToEvmChainId = (coinType) => {
19
+ if (coinType === ETH_COIN_TYPE) return 1;
20
+ return _coinTypeToEvmChainId(coinType);
21
+ };
22
+ var evmChainIdToCoinType = (chainId) => {
23
+ if (chainId === 1) return ETH_COIN_TYPE;
24
+ return _evmChainIdToCoinType(chainId);
25
+ };
26
+ var bigintToCoinType = (value) => {
27
+ if (value > BigInt(Number.MAX_SAFE_INTEGER)) {
28
+ throw new Error(`'${value}' cannot represent as CoinType, it is too large.`);
29
+ }
30
+ return Number(value);
31
+ };
32
+
33
+ // src/ens/reverse-name.ts
34
+ var addrReverseLabel = (address) => address.slice(2).toLowerCase();
35
+ var coinTypeReverseLabel = (coinType) => coinType.toString(16);
36
+ function reverseName(address, coinType) {
37
+ const label = addrReverseLabel(address);
38
+ const middle = (() => {
39
+ switch (coinType) {
40
+ case ETH_COIN_TYPE:
41
+ return "addr";
42
+ case DEFAULT_EVM_COIN_TYPE:
43
+ return "default";
44
+ default:
45
+ return coinTypeReverseLabel(coinType);
46
+ }
47
+ })();
48
+ return `${label}.${middle}.reverse`;
49
+ }
50
+
51
+ // src/ens/subname-helpers.ts
52
+ var makeSubdomainNode = (labelHash, node) => keccak256(concat([node, labelHash]));
53
+ var maybeHealLabelByReverseAddress = ({
54
+ maybeReverseAddress,
55
+ labelHash
56
+ }) => {
57
+ if (!isAddress(maybeReverseAddress)) {
58
+ throw new Error(
59
+ `Invalid reverse address: '${maybeReverseAddress}'. Must be a valid EVM Address.`
60
+ );
61
+ }
62
+ if (!isHash(labelHash)) {
63
+ throw new Error(
64
+ `Invalid labelHash: '${labelHash}'. Must start with '0x' and represent 32 bytes.`
65
+ );
66
+ }
67
+ const assumedLabel = addrReverseLabel(maybeReverseAddress);
68
+ if (labelhash(assumedLabel) === labelHash) return assumedLabel;
69
+ return null;
70
+ };
71
+ var uint256ToHex32 = (num) => toHex(num, { size: 32 });
72
+ var UNINDEXABLE_LABEL_CHARACTERS = [
73
+ "\0",
74
+ // null byte: PostgreSQL does not allow storing this character in text fields.
75
+ ".",
76
+ // conflicts with ENS label separator logic.
77
+ "[",
78
+ // conflicts with "unknown label" representations.
79
+ "]"
80
+ // conflicts with "unknown label" representations.
81
+ ];
82
+ var UNINDEXABLE_LABEL_CHARACTER_CODES = new Set(
83
+ UNINDEXABLE_LABEL_CHARACTERS.map((char) => char.charCodeAt(0))
84
+ );
85
+ var isLabelIndexable = (label) => {
86
+ if (!label) return false;
87
+ for (let i = 0; i < label.length; i++) {
88
+ if (UNINDEXABLE_LABEL_CHARACTER_CODES.has(label.charCodeAt(i))) return false;
89
+ }
90
+ return true;
91
+ };
92
+
93
+ // src/ens/names.ts
94
+ var getNameHierarchy = (name) => name.split(".").map((_, i, labels) => labels.slice(i).join("."));
95
+
96
+ // src/ens/types.ts
97
+ import { ENSNamespaceIds } from "@ensnode/datasources";
15
98
 
16
- // src/utils/cache.ts
99
+ // src/ens/parse-reverse-name.ts
100
+ import { getAddress, hexToBigInt } from "viem";
101
+ var REVERSE_NAME_REGEX = /^([0-9a-fA-F]+)\.([0-9a-f]{1,64}|addr|default)\.reverse$/;
102
+ var parseAddressLabel = (addressLabel) => getAddress(`0x${addressLabel}`);
103
+ var parseCoinTypeLabel = (coinTypeLabel) => {
104
+ if (coinTypeLabel === "default") return DEFAULT_EVM_COIN_TYPE;
105
+ if (coinTypeLabel === "addr") return ETH_COIN_TYPE;
106
+ return bigintToCoinType(hexToBigInt(`0x${coinTypeLabel}`));
107
+ };
108
+ function parseReverseName(name) {
109
+ const match = name.match(REVERSE_NAME_REGEX);
110
+ if (!match) return null;
111
+ try {
112
+ const [, addressLabel, coinTypeLabel] = match;
113
+ if (!addressLabel) return null;
114
+ if (!coinTypeLabel) return null;
115
+ return {
116
+ address: parseAddressLabel(addressLabel),
117
+ coinType: parseCoinTypeLabel(coinTypeLabel)
118
+ };
119
+ } catch {
120
+ return null;
121
+ }
122
+ }
123
+
124
+ // src/ensindexer/config/deserialize.ts
125
+ import { prettifyError as prettifyError2 } from "zod/v4";
126
+
127
+ // src/ensindexer/config/zod-schemas.ts
128
+ import z2 from "zod/v4";
129
+
130
+ // src/shared/cache.ts
17
131
  var LruCache = class {
18
132
  _cache = /* @__PURE__ */ new Map();
19
133
  _capacity;
@@ -62,59 +176,960 @@ var LruCache = class {
62
176
  }
63
177
  };
64
178
 
65
- // src/utils/subname-helpers.ts
66
- import { concat, isAddress, isHash, keccak256, toHex } from "viem";
67
- import { labelhash } from "viem/ens";
68
- var makeSubdomainNode = (labelHash, node) => keccak256(concat([node, labelHash]));
69
- var addrReverseLabel = (address) => address.slice(2).toLowerCase();
70
- var maybeHealLabelByReverseAddress = ({
71
- maybeReverseAddress,
72
- labelHash
73
- }) => {
74
- if (!isAddress(maybeReverseAddress)) {
179
+ // src/shared/collections.ts
180
+ var uniq = (arr) => [...new Set(arr)];
181
+
182
+ // src/shared/serialize.ts
183
+ function serializeChainId(chainId) {
184
+ return chainId.toString();
185
+ }
186
+ function serializeDatetime(datetime) {
187
+ return datetime.toISOString();
188
+ }
189
+ function serializeUrl(url) {
190
+ return url.toString();
191
+ }
192
+
193
+ // src/shared/deserialize.ts
194
+ import { prettifyError } from "zod/v4";
195
+
196
+ // src/shared/zod-schemas.ts
197
+ import z from "zod/v4";
198
+ var makeIntegerSchema = (valueLabel = "Value") => z.int({
199
+ error: `${valueLabel} must be an integer.`
200
+ });
201
+ var makePositiveIntegerSchema = (valueLabel = "Value") => makeIntegerSchema(valueLabel).positive({
202
+ error: `${valueLabel} must be a positive integer (>0).`
203
+ });
204
+ var makeNonNegativeIntegerSchema = (valueLabel = "Value") => makeIntegerSchema(valueLabel).nonnegative({
205
+ error: `${valueLabel} must be a non-negative integer (>=0).`
206
+ });
207
+ var makeDurationSchema = (valueLabel = "Value") => z.coerce.number({
208
+ error: `${valueLabel} must be a number.`
209
+ }).pipe(makeNonNegativeIntegerSchema(valueLabel));
210
+ var makeChainIdSchema = (valueLabel = "Chain ID") => makePositiveIntegerSchema(valueLabel);
211
+ var makeChainIdStringSchema = (valueLabel = "Chain ID String") => z.string({ error: `${valueLabel} must be a string representing a chain ID.` }).pipe(z.coerce.number({ error: `${valueLabel} must represent a positive integer (>0).` })).pipe(makeChainIdSchema(`The numeric value represented by ${valueLabel}`));
212
+ var makeDatetimeSchema = (valueLabel = "Datetime string") => z.iso.datetime({ error: `${valueLabel} must be a string in ISO 8601 format.` }).transform((v) => new Date(v));
213
+ var makeUnixTimestampSchema = (valueLabel = "Timestamp") => makeIntegerSchema(valueLabel);
214
+ var makeUrlSchema = (valueLabel = "Value") => z.url({
215
+ error: `${valueLabel} must be a valid URL string (e.g., http://localhost:8080 or https://example.com).`
216
+ }).transform((v) => new URL(v));
217
+ var makeBlockNumberSchema = (valueLabel = "Block number") => makeNonNegativeIntegerSchema(valueLabel);
218
+ var makeBlockrangeSchema = (valueLabel = "Value") => z.strictObject(
219
+ {
220
+ startBlock: makeBlockNumberSchema(`${valueLabel}.startBlock`).optional(),
221
+ endBlock: makeBlockNumberSchema(`${valueLabel}.endBlock`).optional()
222
+ },
223
+ {
224
+ error: `${valueLabel} must be a valid Blockrange object.`
225
+ }
226
+ ).refine(
227
+ (v) => {
228
+ if (v.startBlock && v.endBlock) {
229
+ return v.startBlock <= v.endBlock;
230
+ }
231
+ return true;
232
+ },
233
+ { error: `${valueLabel}: startBlock must be before or equal to endBlock` }
234
+ );
235
+ var makeBlockRefSchema = (valueLabel = "Value") => z.strictObject(
236
+ {
237
+ timestamp: makeUnixTimestampSchema(`${valueLabel}.timestamp`),
238
+ number: makeBlockNumberSchema(`${valueLabel}.number`)
239
+ },
240
+ {
241
+ error: `${valueLabel} must be a valid BlockRef object.`
242
+ }
243
+ );
244
+ var makeENSNamespaceIdSchema = (valueLabel = "ENSNamespaceId") => z.enum(ENSNamespaceIds, {
245
+ error() {
246
+ return `Invalid ${valueLabel}. Supported ENS namespace IDs are: ${Object.keys(ENSNamespaceIds).join(", ")}`;
247
+ }
248
+ });
249
+
250
+ // src/shared/deserialize.ts
251
+ function deserializeChainId(maybeChainId, valueLabel) {
252
+ const schema = makeChainIdStringSchema(valueLabel);
253
+ const parsed = schema.safeParse(maybeChainId);
254
+ if (parsed.error) {
255
+ throw new Error(`Cannot deserialize ChainId:
256
+ ${prettifyError(parsed.error)}
257
+ `);
258
+ }
259
+ return parsed.data;
260
+ }
261
+ function deserializeDatetime(maybeDatetime, valueLabel) {
262
+ const schema = makeDatetimeSchema(valueLabel);
263
+ const parsed = schema.safeParse(maybeDatetime);
264
+ if (parsed.error) {
265
+ throw new Error(`Cannot deserialize Datetime:
266
+ ${prettifyError(parsed.error)}
267
+ `);
268
+ }
269
+ return parsed.data;
270
+ }
271
+ function deserializeUrl(maybeUrl, valueLabel) {
272
+ const schema = makeUrlSchema(valueLabel);
273
+ const parsed = schema.safeParse(maybeUrl);
274
+ if (parsed.error) {
275
+ throw new Error(`Cannot deserialize URL:
276
+ ${prettifyError(parsed.error)}
277
+ `);
278
+ }
279
+ return parsed.data;
280
+ }
281
+ function deserializeBlockNumber(maybeBlockNumber, valueLabel) {
282
+ const schema = makeBlockNumberSchema(valueLabel);
283
+ const parsed = schema.safeParse(maybeBlockNumber);
284
+ if (parsed.error) {
285
+ throw new Error(`Cannot deserialize BlockNumber:
286
+ ${prettifyError(parsed.error)}
287
+ `);
288
+ }
289
+ return parsed.data;
290
+ }
291
+ function deserializeBlockrange(maybeBlockrange, valueLabel) {
292
+ const schema = makeBlockrangeSchema(valueLabel);
293
+ const parsed = schema.safeParse(maybeBlockrange);
294
+ if (parsed.error) {
295
+ throw new Error(`Cannot deserialize Blockrange:
296
+ ${prettifyError(parsed.error)}
297
+ `);
298
+ }
299
+ return parsed.data;
300
+ }
301
+ function deserializeBlockRef(maybeBlockRef, valueLabel) {
302
+ const schema = makeBlockRefSchema(valueLabel);
303
+ const parsed = schema.safeParse(maybeBlockRef);
304
+ if (parsed.error) {
305
+ throw new Error(`Cannot deserialize BlockRef:
306
+ ${prettifyError(parsed.error)}
307
+ `);
308
+ }
309
+ return parsed.data;
310
+ }
311
+ function deserializeDuration(maybeDuration, valueLabel) {
312
+ const schema = makeDurationSchema(valueLabel);
313
+ const parsed = schema.safeParse(maybeDuration);
314
+ if (parsed.error) {
315
+ throw new RangeError(`Cannot deserialize Duration:
316
+ ${prettifyError(parsed.error)}
317
+ `);
318
+ }
319
+ return parsed.data;
320
+ }
321
+
322
+ // src/shared/is-normalized.ts
323
+ import { normalize } from "viem/ens";
324
+ function isNormalized(name) {
325
+ try {
326
+ return name === normalize(name);
327
+ } catch {
328
+ return false;
329
+ }
330
+ }
331
+
332
+ // src/ensindexer/config/types.ts
333
+ var PluginName = /* @__PURE__ */ ((PluginName2) => {
334
+ PluginName2["Subgraph"] = "subgraph";
335
+ PluginName2["Basenames"] = "basenames";
336
+ PluginName2["Lineanames"] = "lineanames";
337
+ PluginName2["ThreeDNS"] = "threedns";
338
+ PluginName2["ReverseResolvers"] = "reverse-resolvers";
339
+ PluginName2["Referrals"] = "referrals";
340
+ return PluginName2;
341
+ })(PluginName || {});
342
+
343
+ // src/ensindexer/config/helpers.ts
344
+ function isSubgraphCompatible(config) {
345
+ const onlySubgraphPluginActivated = config.plugins.length === 1 && config.plugins[0] === "subgraph" /* Subgraph */;
346
+ const indexingBehaviorIsSubgraphCompatible = !config.healReverseAddresses && !config.indexAdditionalResolverRecords;
347
+ return onlySubgraphPluginActivated && indexingBehaviorIsSubgraphCompatible;
348
+ }
349
+
350
+ // src/ensindexer/config/zod-schemas.ts
351
+ var makeIndexedChainIdsSchema = (valueLabel = "Indexed Chain IDs") => z2.array(makeChainIdSchema(valueLabel), {
352
+ error: `${valueLabel} must be an array.`
353
+ }).min(1, { error: `${valueLabel} list must include at least one element.` }).transform((v) => new Set(v));
354
+ var makePluginsListSchema = (valueLabel = "Plugins") => z2.array(
355
+ z2.enum(PluginName, {
356
+ error: `${valueLabel} must be a list with at least one valid plugin name. Valid plugins are: ${Object.values(
357
+ PluginName
358
+ ).join(", ")}`
359
+ })
360
+ ).min(1, {
361
+ error: `${valueLabel} must be a list with at least one valid plugin name. Valid plugins are: ${Object.values(
362
+ PluginName
363
+ ).join(", ")}`
364
+ }).refine((arr) => arr.length === uniq(arr).length, {
365
+ error: `${valueLabel} cannot contain duplicate values.`
366
+ });
367
+ var makeDatabaseSchemaNameSchema = (valueLabel = "Database schema name") => z2.string({ error: `${valueLabel} must be a string` }).trim().nonempty({
368
+ error: `${valueLabel} is required and must be a non-empty string.`
369
+ });
370
+ var makeNonEmptyStringSchema = (valueLabel = "Value") => z2.string().nonempty({ error: `${valueLabel} must be a non-empty string.` });
371
+ var makeDependencyInfoSchema = (valueLabel = "Value") => z2.strictObject(
372
+ {
373
+ nodejs: makeNonEmptyStringSchema(),
374
+ ponder: makeNonEmptyStringSchema(),
375
+ ensRainbow: makeNonEmptyStringSchema(),
376
+ ensRainbowSchema: makePositiveIntegerSchema()
377
+ },
378
+ {
379
+ error: `${valueLabel} must be a valid DependencyInfo object.`
380
+ }
381
+ );
382
+ function invariant_reverseResolversPluginNeedsResolverRecords(ctx) {
383
+ const { value: config } = ctx;
384
+ const reverseResolversPluginActive = config.plugins.includes("reverse-resolvers" /* ReverseResolvers */);
385
+ if (reverseResolversPluginActive && !config.indexAdditionalResolverRecords) {
386
+ ctx.issues.push({
387
+ code: "custom",
388
+ input: config,
389
+ message: `The '${"reverse-resolvers" /* ReverseResolvers */}' plugin requires 'indexAdditionalResolverRecords' to be 'true'.`
390
+ });
391
+ }
392
+ }
393
+ function invariant_isSubgraphCompatibleRequirements(ctx) {
394
+ const { value: config } = ctx;
395
+ if (config.isSubgraphCompatible !== isSubgraphCompatible(config)) {
396
+ const message = config.isSubgraphCompatible ? `'isSubgraphCompatible' requires only the '${"subgraph" /* Subgraph */}' plugin to be active. Also, both 'indexAdditionalResolverRecords' and 'healReverseAddresses' must be set to 'false'` : `Both 'indexAdditionalResolverRecords' and 'healReverseAddresses' were set to 'false', and the only active plugin was the '${"subgraph" /* Subgraph */}' plugin. The 'isSubgraphCompatible' must be set to 'true'`;
397
+ ctx.issues.push({
398
+ code: "custom",
399
+ input: config,
400
+ message
401
+ });
402
+ }
403
+ }
404
+ var makeENSIndexerPublicConfigSchema = (valueLabel = "ENSIndexerPublicConfig") => z2.object({
405
+ ensAdminUrl: makeUrlSchema(`${valueLabel}.ensAdminUrl`),
406
+ ensNodePublicUrl: makeUrlSchema(`${valueLabel}.ensNodePublicUrl`),
407
+ healReverseAddresses: z2.boolean({ error: `${valueLabel}.healReverseAddresses` }),
408
+ indexAdditionalResolverRecords: z2.boolean({
409
+ error: `${valueLabel}.indexAdditionalResolverRecords`
410
+ }),
411
+ indexedChainIds: makeIndexedChainIdsSchema(`${valueLabel}.indexedChainIds`),
412
+ isSubgraphCompatible: z2.boolean({ error: `${valueLabel}.isSubgraphCompatible` }),
413
+ namespace: makeENSNamespaceIdSchema(`${valueLabel}.namespace`),
414
+ plugins: makePluginsListSchema(`${valueLabel}.plugins`),
415
+ databaseSchemaName: makeDatabaseSchemaNameSchema(`${valueLabel}.databaseSchemaName`),
416
+ dependencyInfo: makeDependencyInfoSchema(`${valueLabel}.dependencyInfo`)
417
+ }).check(invariant_reverseResolversPluginNeedsResolverRecords).check(invariant_isSubgraphCompatibleRequirements);
418
+
419
+ // src/ensindexer/config/deserialize.ts
420
+ function deserializeENSIndexerPublicConfig(maybeConfig, valueLabel) {
421
+ const schema = makeENSIndexerPublicConfigSchema(valueLabel);
422
+ const parsed = schema.safeParse(maybeConfig);
423
+ if (parsed.error) {
424
+ throw new Error(`Cannot deserialize ENSIndexerPublicConfig:
425
+ ${prettifyError2(parsed.error)}
426
+ `);
427
+ }
428
+ return parsed.data;
429
+ }
430
+
431
+ // src/ensindexer/config/serialize.ts
432
+ function serializeIndexedChainIds(indexedChainIds) {
433
+ return Array.from(indexedChainIds);
434
+ }
435
+ function serializeENSIndexerPublicConfig(config) {
436
+ const {
437
+ ensAdminUrl,
438
+ ensNodePublicUrl,
439
+ indexedChainIds,
440
+ databaseSchemaName,
441
+ healReverseAddresses,
442
+ indexAdditionalResolverRecords,
443
+ isSubgraphCompatible: isSubgraphCompatible2,
444
+ namespace,
445
+ plugins,
446
+ dependencyInfo
447
+ } = config;
448
+ return {
449
+ ensAdminUrl: serializeUrl(ensAdminUrl),
450
+ ensNodePublicUrl: serializeUrl(ensNodePublicUrl),
451
+ indexedChainIds: serializeIndexedChainIds(indexedChainIds),
452
+ databaseSchemaName,
453
+ healReverseAddresses,
454
+ indexAdditionalResolverRecords,
455
+ isSubgraphCompatible: isSubgraphCompatible2,
456
+ namespace,
457
+ plugins,
458
+ dependencyInfo
459
+ };
460
+ }
461
+
462
+ // src/ensindexer/indexing-status/deserialize.ts
463
+ import { prettifyError as prettifyError3 } from "zod/v4";
464
+
465
+ // src/ensindexer/indexing-status/zod-schemas.ts
466
+ import z3 from "zod/v4";
467
+
468
+ // src/shared/block-ref.ts
469
+ function isBefore(blockA, blockB) {
470
+ return blockA.number < blockB.number && blockA.timestamp < blockB.timestamp;
471
+ }
472
+ function isEqualTo(blockA, blockB) {
473
+ return blockA.number === blockB.number && blockA.timestamp === blockB.timestamp;
474
+ }
475
+ function isBeforeOrEqualTo(blockA, blockB) {
476
+ return isBefore(blockA, blockB) || isEqualTo(blockA, blockB);
477
+ }
478
+
479
+ // src/ensindexer/indexing-status/types.ts
480
+ var ChainIndexingStatusIds = {
481
+ Unstarted: "unstarted",
482
+ Backfill: "backfill",
483
+ Following: "following",
484
+ Completed: "completed"
485
+ };
486
+ var OverallIndexingStatusIds = {
487
+ Unstarted: "unstarted",
488
+ Backfill: "backfill",
489
+ Following: "following",
490
+ Completed: "completed",
491
+ IndexerError: "indexer-error"
492
+ };
493
+ var ChainIndexingStrategyIds = {
494
+ Indefinite: "indefinite",
495
+ Definite: "definite"
496
+ };
497
+
498
+ // src/ensindexer/indexing-status/helpers.ts
499
+ function getOverallIndexingStatus(chains) {
500
+ const chainStatuses = chains.map((chain) => chain.status);
501
+ let overallStatus;
502
+ if (chainStatuses.some((chainStatus) => chainStatus === ChainIndexingStatusIds.Following)) {
503
+ overallStatus = OverallIndexingStatusIds.Following;
504
+ } else if (chainStatuses.some((chainStatus) => chainStatus === ChainIndexingStatusIds.Backfill)) {
505
+ overallStatus = OverallIndexingStatusIds.Backfill;
506
+ } else if (chainStatuses.some((chainStatus) => chainStatus === ChainIndexingStatusIds.Unstarted)) {
507
+ overallStatus = OverallIndexingStatusIds.Unstarted;
508
+ } else {
509
+ overallStatus = OverallIndexingStatusIds.Completed;
510
+ }
511
+ return overallStatus;
512
+ }
513
+ function getOverallApproxRealtimeDistance(chains) {
514
+ const chainApproxRealtimeDistances = chains.filter((chain) => chain.status === ChainIndexingStatusIds.Following).map((chain) => chain.approxRealtimeDistance);
515
+ if (chainApproxRealtimeDistances.length === 0) {
75
516
  throw new Error(
76
- `Invalid reverse address: '${maybeReverseAddress}'. Must be a valid EVM Address.`
517
+ `The overall approximate realtime distance value is undefined if no indexed chain is in the '${OverallIndexingStatusIds.Following}' status`
77
518
  );
78
519
  }
79
- if (!isHash(labelHash)) {
80
- throw new Error(
81
- `Invalid labelHash: '${labelHash}'. Must start with '0x' and represent 32 bytes.`
520
+ const approxRealtimeDistance = Math.max(...chainApproxRealtimeDistances);
521
+ return approxRealtimeDistance;
522
+ }
523
+ function getOmnichainIndexingCursor(chains) {
524
+ return Math.min(...chains.map((chain) => chain.latestIndexedBlock.timestamp));
525
+ }
526
+ function getActiveChains(chains) {
527
+ return chains.filter(
528
+ (chain) => chain.status === ChainIndexingStatusIds.Backfill || chain.status === ChainIndexingStatusIds.Following
529
+ );
530
+ }
531
+ function getStandbyChains(chains) {
532
+ return chains.filter(
533
+ (chain) => chain.status === ChainIndexingStatusIds.Unstarted || chain.status === ChainIndexingStatusIds.Completed
534
+ );
535
+ }
536
+ function createIndexingConfig(startBlock, endBlock) {
537
+ if (endBlock) {
538
+ return {
539
+ strategy: ChainIndexingStrategyIds.Definite,
540
+ startBlock,
541
+ endBlock
542
+ };
543
+ }
544
+ return {
545
+ strategy: ChainIndexingStrategyIds.Indefinite,
546
+ startBlock,
547
+ endBlock: null
548
+ };
549
+ }
550
+ function checkChainIndexingStatusesForUnstartedOverallStatus(chains) {
551
+ return chains.every((chain) => chain.status === ChainIndexingStatusIds.Unstarted);
552
+ }
553
+ function checkChainIndexingStatusesForBackfillOverallStatus(chains) {
554
+ const atLeastOneChainInTargetStatus = chains.some(
555
+ (chain) => chain.status === ChainIndexingStatusIds.Backfill
556
+ );
557
+ const otherChainsHaveValidStatuses = chains.every(
558
+ (chain) => chain.status === ChainIndexingStatusIds.Unstarted || chain.status === ChainIndexingStatusIds.Backfill || chain.status === ChainIndexingStatusIds.Completed
559
+ );
560
+ return atLeastOneChainInTargetStatus && otherChainsHaveValidStatuses;
561
+ }
562
+ function checkChainIndexingStatusesForCompletedOverallStatus(chains) {
563
+ const allChainsHaveValidStatuses = chains.every(
564
+ (chain) => chain.status === ChainIndexingStatusIds.Completed
565
+ );
566
+ return allChainsHaveValidStatuses;
567
+ }
568
+ function checkChainIndexingStatusesForFollowingOverallStatus(chains) {
569
+ const allChainsHaveValidStatuses = chains.some(
570
+ (chain) => chain.status === ChainIndexingStatusIds.Following
571
+ );
572
+ return allChainsHaveValidStatuses;
573
+ }
574
+
575
+ // src/ensindexer/indexing-status/zod-schemas.ts
576
+ var makeChainIndexingConfigSchema = (valueLabel = "Value") => z3.discriminatedUnion("strategy", [
577
+ z3.strictObject({
578
+ strategy: z3.literal(ChainIndexingStrategyIds.Indefinite),
579
+ startBlock: makeBlockRefSchema(valueLabel),
580
+ endBlock: z3.null()
581
+ }),
582
+ z3.strictObject({
583
+ strategy: z3.literal(ChainIndexingStrategyIds.Definite),
584
+ startBlock: makeBlockRefSchema(valueLabel),
585
+ endBlock: makeBlockRefSchema(valueLabel)
586
+ })
587
+ ]);
588
+ var makeChainIndexingUnstartedStatusSchema = (valueLabel = "Value") => z3.strictObject({
589
+ status: z3.literal(ChainIndexingStatusIds.Unstarted),
590
+ config: makeChainIndexingConfigSchema(valueLabel)
591
+ }).refine(
592
+ ({ config }) => config.endBlock === null || isBeforeOrEqualTo(config.startBlock, config.endBlock),
593
+ {
594
+ error: `config.startBlock must be before or same as config.endBlock.`
595
+ }
596
+ );
597
+ var makeChainIndexingBackfillStatusSchema = (valueLabel = "Value") => z3.strictObject({
598
+ status: z3.literal(ChainIndexingStatusIds.Backfill),
599
+ config: makeChainIndexingConfigSchema(valueLabel),
600
+ latestIndexedBlock: makeBlockRefSchema(valueLabel),
601
+ backfillEndBlock: makeBlockRefSchema(valueLabel)
602
+ }).refine(
603
+ ({ config, latestIndexedBlock }) => isBeforeOrEqualTo(config.startBlock, latestIndexedBlock),
604
+ {
605
+ error: `config.startBlock must be before or same as latestIndexedBlock.`
606
+ }
607
+ ).refine(
608
+ ({ latestIndexedBlock, backfillEndBlock }) => isBeforeOrEqualTo(latestIndexedBlock, backfillEndBlock),
609
+ {
610
+ error: `latestIndexedBlock must be before or same as backfillEndBlock.`
611
+ }
612
+ ).refine(
613
+ ({ config, backfillEndBlock }) => config.endBlock === null || isEqualTo(backfillEndBlock, config.endBlock),
614
+ {
615
+ error: `backfillEndBlock must be the same as config.endBlock.`
616
+ }
617
+ );
618
+ var makeChainIndexingFollowingStatusSchema = (valueLabel = "Value") => z3.strictObject({
619
+ status: z3.literal(ChainIndexingStatusIds.Following),
620
+ config: z3.strictObject({
621
+ strategy: z3.literal(ChainIndexingStrategyIds.Indefinite),
622
+ startBlock: makeBlockRefSchema(valueLabel)
623
+ }),
624
+ latestIndexedBlock: makeBlockRefSchema(valueLabel),
625
+ latestKnownBlock: makeBlockRefSchema(valueLabel),
626
+ approxRealtimeDistance: makeDurationSchema(valueLabel)
627
+ }).refine(
628
+ ({ config, latestIndexedBlock }) => isBeforeOrEqualTo(config.startBlock, latestIndexedBlock),
629
+ {
630
+ error: `config.startBlock must be before or same as latestIndexedBlock.`
631
+ }
632
+ ).refine(
633
+ ({ latestIndexedBlock, latestKnownBlock }) => isBeforeOrEqualTo(latestIndexedBlock, latestKnownBlock),
634
+ {
635
+ error: `latestIndexedBlock must be before or same as latestKnownBlock.`
636
+ }
637
+ );
638
+ var makeChainIndexingCompletedStatusSchema = (valueLabel = "Value") => z3.strictObject({
639
+ status: z3.literal(ChainIndexingStatusIds.Completed),
640
+ config: z3.strictObject({
641
+ strategy: z3.literal(ChainIndexingStrategyIds.Definite),
642
+ startBlock: makeBlockRefSchema(valueLabel),
643
+ endBlock: makeBlockRefSchema(valueLabel)
644
+ }),
645
+ latestIndexedBlock: makeBlockRefSchema(valueLabel)
646
+ }).refine(
647
+ ({ config, latestIndexedBlock }) => isBeforeOrEqualTo(config.startBlock, latestIndexedBlock),
648
+ {
649
+ error: `config.startBlock must be before or same as latestIndexedBlock.`
650
+ }
651
+ ).refine(
652
+ ({ config, latestIndexedBlock }) => isEqualTo(latestIndexedBlock, config.endBlock),
653
+ {
654
+ error: `latestIndexedBlock must be the same as config.endBlock.`
655
+ }
656
+ );
657
+ var makeChainIndexingStatusSchema = (valueLabel = "Value") => z3.discriminatedUnion("status", [
658
+ makeChainIndexingUnstartedStatusSchema(valueLabel),
659
+ makeChainIndexingBackfillStatusSchema(valueLabel),
660
+ makeChainIndexingFollowingStatusSchema(valueLabel),
661
+ makeChainIndexingCompletedStatusSchema(valueLabel)
662
+ ]);
663
+ var makeChainIndexingStatusesSchema = (valueLabel = "Value") => z3.record(makeChainIdStringSchema(), makeChainIndexingStatusSchema(valueLabel), {
664
+ error: "Chains configuration must be an object mapping valid chain IDs to their configs."
665
+ }).transform((serializedChainsIndexingStatus) => {
666
+ const chainsIndexingStatus = /* @__PURE__ */ new Map();
667
+ for (const [chainIdString, chainStatus] of Object.entries(serializedChainsIndexingStatus)) {
668
+ chainsIndexingStatus.set(deserializeChainId(chainIdString), chainStatus);
669
+ }
670
+ return chainsIndexingStatus;
671
+ });
672
+ var makeUnstartedOverallStatusSchema = (valueLabel) => z3.strictObject({
673
+ overallStatus: z3.literal(OverallIndexingStatusIds.Unstarted),
674
+ chains: makeChainIndexingStatusesSchema(valueLabel).refine(
675
+ (chains) => checkChainIndexingStatusesForUnstartedOverallStatus(Array.from(chains.values())),
676
+ {
677
+ error: `${valueLabel} at least one chain must be in "unstarted" status and
678
+ each chain has to have a status of either "unstarted", or "completed"`
679
+ }
680
+ ).transform((chains) => chains)
681
+ }).refine(
682
+ (indexingStatus) => {
683
+ const chains = Array.from(indexingStatus.chains.values());
684
+ return getOverallIndexingStatus(chains) === indexingStatus.overallStatus;
685
+ },
686
+ { error: `${valueLabel} is an invalid overallStatus.` }
687
+ );
688
+ var makeBackfillOverallStatusSchema = (valueLabel) => z3.strictObject({
689
+ overallStatus: z3.literal(OverallIndexingStatusIds.Backfill),
690
+ chains: makeChainIndexingStatusesSchema(valueLabel).refine(
691
+ (chains) => checkChainIndexingStatusesForBackfillOverallStatus(Array.from(chains.values())),
692
+ {
693
+ error: `${valueLabel} at least one chain must be in "backfill" status and
694
+ each chain has to have a status of either "unstarted", "backfill" or "completed"`
695
+ }
696
+ ).transform((chains) => chains),
697
+ omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
698
+ }).refine(
699
+ (indexingStatus) => {
700
+ const chains = Array.from(indexingStatus.chains.values());
701
+ return getOverallIndexingStatus(chains) === indexingStatus.overallStatus;
702
+ },
703
+ { error: `${valueLabel} is an invalid overallStatus.` }
704
+ ).refine(
705
+ (indexingStatus) => {
706
+ const chains = Array.from(indexingStatus.chains.values());
707
+ const standbyChainStartBlocks = getStandbyChains(chains).map(
708
+ (chain) => chain.config.startBlock.timestamp
82
709
  );
710
+ const standbyChainEarliestStartBlocks = Math.min(...standbyChainStartBlocks);
711
+ return indexingStatus.omnichainIndexingCursor <= standbyChainEarliestStartBlocks;
712
+ },
713
+ {
714
+ error: "omnichainIndexingCursor must be lower than or equal to the earliest config.startBlock across all standby chains"
83
715
  }
84
- const assumedLabel = addrReverseLabel(maybeReverseAddress);
85
- if (labelhash(assumedLabel) === labelHash) return assumedLabel;
86
- return null;
87
- };
88
- var uint256ToHex32 = (num) => toHex(num, { size: 32 });
89
- var UNINDEXABLE_LABEL_CHARACTERS = [
90
- "\0",
91
- // null byte: PostgreSQL does not allow storing this character in text fields.
92
- ".",
93
- // conflicts with ENS label separator logic.
94
- "[",
95
- // conflicts with "unknown label" representations.
96
- "]"
97
- // conflicts with "unknown label" representations.
98
- ];
99
- var UNINDEXABLE_LABEL_CHARACTER_CODES = new Set(
100
- UNINDEXABLE_LABEL_CHARACTERS.map((char) => char.charCodeAt(0))
101
716
  );
102
- var isLabelIndexable = (label) => {
103
- if (!label) return false;
104
- for (let i = 0; i < label.length; i++) {
105
- if (UNINDEXABLE_LABEL_CHARACTER_CODES.has(label.charCodeAt(i))) return false;
717
+ var makeCompletedOverallStatusSchema = (valueLabel) => z3.strictObject({
718
+ overallStatus: z3.literal(OverallIndexingStatusIds.Completed),
719
+ chains: makeChainIndexingStatusesSchema(valueLabel).refine(
720
+ (chains) => checkChainIndexingStatusesForCompletedOverallStatus(Array.from(chains.values())),
721
+ {
722
+ error: `${valueLabel} all chains must have "completed" status`
723
+ }
724
+ ).transform((chains) => chains)
725
+ }).refine(
726
+ (indexingStatus) => {
727
+ const chains = Array.from(indexingStatus.chains.values());
728
+ return getOverallIndexingStatus(chains) === indexingStatus.overallStatus;
729
+ },
730
+ { error: `${valueLabel} is an invalid overallStatus.` }
731
+ );
732
+ var makeFollowingOverallStatusSchema = (valueLabel) => z3.strictObject({
733
+ overallStatus: z3.literal(OverallIndexingStatusIds.Following),
734
+ chains: makeChainIndexingStatusesSchema(valueLabel),
735
+ overallApproxRealtimeDistance: makeDurationSchema(valueLabel),
736
+ omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
737
+ }).refine(
738
+ (indexingStatus) => {
739
+ const chains = Array.from(indexingStatus.chains.values());
740
+ return getOverallIndexingStatus(chains) === indexingStatus.overallStatus;
741
+ },
742
+ { error: `${valueLabel} is an invalid overallStatus.` }
743
+ ).refine(
744
+ (indexingStatus) => checkChainIndexingStatusesForFollowingOverallStatus(
745
+ Array.from(indexingStatus.chains.values())
746
+ ),
747
+ {
748
+ error: `${valueLabel} at least one chain must be in "following" status`
106
749
  }
107
- return true;
750
+ ).refine(
751
+ (indexingStatus) => {
752
+ const chains = Array.from(indexingStatus.chains.values());
753
+ return getOverallApproxRealtimeDistance(chains) === indexingStatus.overallApproxRealtimeDistance;
754
+ },
755
+ { error: `${valueLabel} is an invalid overallApproxRealtimeDistance.` }
756
+ ).refine(
757
+ (indexingStatus) => {
758
+ const chains = Array.from(indexingStatus.chains.values());
759
+ const standbyChainStartBlocks = getStandbyChains(chains).map(
760
+ (chain) => chain.config.startBlock.timestamp
761
+ );
762
+ const standbyChainEarliestStartBlocks = Math.min(...standbyChainStartBlocks);
763
+ return indexingStatus.omnichainIndexingCursor <= standbyChainEarliestStartBlocks;
764
+ },
765
+ {
766
+ error: "omnichainIndexingCursor must be lower than or equal to the earliest config.startBlock across all standby chains"
767
+ }
768
+ );
769
+ var makeErrorSchemaOverallStatusSchema = (valueLabel) => z3.strictObject({
770
+ overallStatus: z3.literal(OverallIndexingStatusIds.IndexerError)
771
+ });
772
+ var makeENSIndexerIndexingStatusSchema = (valueLabel = "ENSIndexerIndexingStatus") => z3.discriminatedUnion("overallStatus", [
773
+ makeUnstartedOverallStatusSchema(valueLabel),
774
+ makeBackfillOverallStatusSchema(valueLabel),
775
+ makeCompletedOverallStatusSchema(valueLabel),
776
+ makeFollowingOverallStatusSchema(valueLabel),
777
+ makeErrorSchemaOverallStatusSchema(valueLabel)
778
+ ]);
779
+
780
+ // src/ensindexer/indexing-status/deserialize.ts
781
+ function deserializeENSIndexerIndexingStatus(maybeStatus, valueLabel) {
782
+ const schema = makeENSIndexerIndexingStatusSchema(valueLabel);
783
+ const parsed = schema.safeParse(maybeStatus);
784
+ if (parsed.error) {
785
+ throw new Error(
786
+ `Cannot deserialize ENSIndexerIndexingStatus:
787
+ ${prettifyError3(parsed.error)}
788
+ `
789
+ );
790
+ }
791
+ return parsed.data;
792
+ }
793
+
794
+ // src/ensindexer/indexing-status/serialize.ts
795
+ function serializeChainIndexingStatuses(chainIndexingStatuses) {
796
+ const serializedChainsIndexingStatuses = {};
797
+ for (const [chainId, chainIndexingStatus] of chainIndexingStatuses.entries()) {
798
+ serializedChainsIndexingStatuses[serializeChainId(chainId)] = chainIndexingStatus;
799
+ }
800
+ return serializedChainsIndexingStatuses;
801
+ }
802
+ function serializeENSIndexerIndexingStatus(indexingStatus) {
803
+ switch (indexingStatus.overallStatus) {
804
+ case OverallIndexingStatusIds.IndexerError:
805
+ return {
806
+ overallStatus: OverallIndexingStatusIds.IndexerError
807
+ };
808
+ case OverallIndexingStatusIds.Unstarted:
809
+ return {
810
+ overallStatus: OverallIndexingStatusIds.Unstarted,
811
+ chains: serializeChainIndexingStatuses(indexingStatus.chains)
812
+ };
813
+ case OverallIndexingStatusIds.Backfill:
814
+ return {
815
+ overallStatus: OverallIndexingStatusIds.Backfill,
816
+ chains: serializeChainIndexingStatuses(indexingStatus.chains),
817
+ omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
818
+ };
819
+ case OverallIndexingStatusIds.Completed: {
820
+ return {
821
+ overallStatus: OverallIndexingStatusIds.Completed,
822
+ chains: serializeChainIndexingStatuses(indexingStatus.chains)
823
+ };
824
+ }
825
+ case OverallIndexingStatusIds.Following:
826
+ return {
827
+ overallStatus: OverallIndexingStatusIds.Following,
828
+ chains: serializeChainIndexingStatuses(indexingStatus.chains),
829
+ overallApproxRealtimeDistance: indexingStatus.overallApproxRealtimeDistance,
830
+ omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
831
+ };
832
+ }
833
+ }
834
+
835
+ // src/tracing/index.ts
836
+ var TraceableENSProtocol = /* @__PURE__ */ ((TraceableENSProtocol2) => {
837
+ TraceableENSProtocol2["ForwardResolution"] = "forward-resolution";
838
+ TraceableENSProtocol2["ReverseResolution"] = "reverse-resolution";
839
+ return TraceableENSProtocol2;
840
+ })(TraceableENSProtocol || {});
841
+ var ForwardResolutionProtocolStep = /* @__PURE__ */ ((ForwardResolutionProtocolStep2) => {
842
+ ForwardResolutionProtocolStep2["Operation"] = "operation";
843
+ ForwardResolutionProtocolStep2["FindResolver"] = "find-resolver";
844
+ ForwardResolutionProtocolStep2["ActiveResolverExists"] = "active-resolver-exists";
845
+ ForwardResolutionProtocolStep2["AccelerateENSIP19ReverseResolver"] = "accelerate-ensip-19-reverse-resolver";
846
+ ForwardResolutionProtocolStep2["AccelerateKnownOffchainLookupResolver"] = "accelerate-known-offchain-lookup-resolver";
847
+ ForwardResolutionProtocolStep2["AccelerateKnownOnchainStaticResolver"] = "accelerate-known-onchain-static-resolver";
848
+ ForwardResolutionProtocolStep2["RequireResolver"] = "require-resolver";
849
+ ForwardResolutionProtocolStep2["ExecuteResolveCalls"] = "execute-resolve-calls";
850
+ return ForwardResolutionProtocolStep2;
851
+ })(ForwardResolutionProtocolStep || {});
852
+ var ReverseResolutionProtocolStep = /* @__PURE__ */ ((ReverseResolutionProtocolStep2) => {
853
+ ReverseResolutionProtocolStep2["Operation"] = "operation";
854
+ ReverseResolutionProtocolStep2["ResolveReverseName"] = "resolve-reverse-name";
855
+ ReverseResolutionProtocolStep2["NameRecordExists"] = "name-record-exists-check";
856
+ ReverseResolutionProtocolStep2["ForwardResolveAddressRecord"] = "forward-resolve-address-record";
857
+ ReverseResolutionProtocolStep2["VerifyResolvedAddressMatchesAddress"] = "verify-resolved-address-matches-address";
858
+ return ReverseResolutionProtocolStep2;
859
+ })(ReverseResolutionProtocolStep || {});
860
+ var PROTOCOL_ATTRIBUTE_PREFIX = "ens";
861
+ var ATTR_PROTOCOL_NAME = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol`;
862
+ var ATTR_PROTOCOL_STEP = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol.step`;
863
+ var ATTR_PROTOCOL_STEP_RESULT = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol.step.result`;
864
+ function hrTimeToMicroseconds(time) {
865
+ return time[0] * 1e6 + time[1] / 1e3;
866
+ }
867
+ var readableSpanToProtocolSpan = (span) => ({
868
+ id: span.spanContext().spanId,
869
+ traceId: span.spanContext().traceId,
870
+ parentSpanContext: span.parentSpanContext,
871
+ name: span.name,
872
+ timestamp: hrTimeToMicroseconds(span.startTime),
873
+ duration: hrTimeToMicroseconds(span.duration),
874
+ // only export `ens.*` attributes to avoid leaking internal details
875
+ attributes: Object.fromEntries(
876
+ Object.entries(span.attributes).filter(
877
+ ([key]) => key.startsWith(`${PROTOCOL_ATTRIBUTE_PREFIX}.`)
878
+ )
879
+ ),
880
+ status: span.status,
881
+ events: span.events
882
+ });
883
+
884
+ // src/client.ts
885
+ var DEFAULT_ENSNODE_API_URL = "https://api.alpha.ensnode.io";
886
+ var ENSNodeClient = class _ENSNodeClient {
887
+ options;
888
+ static defaultOptions() {
889
+ return {
890
+ url: new URL(DEFAULT_ENSNODE_API_URL)
891
+ };
892
+ }
893
+ constructor(options = {}) {
894
+ this.options = {
895
+ ..._ENSNodeClient.defaultOptions(),
896
+ ...options
897
+ };
898
+ }
899
+ getOptions() {
900
+ return Object.freeze({
901
+ url: new URL(this.options.url.href)
902
+ });
903
+ }
904
+ /**
905
+ * Resolves records for an ENS name (Forward Resolution).
906
+ *
907
+ * @param name The ENS Name whose records to resolve
908
+ * @param selection selection of Resolver records
909
+ * @param options additional options
910
+ * @param options.accelerate whether to attempt Protocol Acceleration (default false)
911
+ * @param options.trace whether to include a trace in the response (default false)
912
+ * @returns ResolveRecordsResponse<SELECTION>
913
+ * @throws If the request fails or the ENSNode API returns an error response
914
+ *
915
+ * @example
916
+ * ```typescript
917
+ * const { records } = await client.resolveRecords("jesse.base.eth", {
918
+ * addresses: [60],
919
+ * texts: ["avatar", "com.twitter"]
920
+ * });
921
+ *
922
+ * console.log(records);
923
+ * // {
924
+ * // addresses: {
925
+ * // 60: "0xabcd..."
926
+ * // },
927
+ * // texts: {
928
+ * // avatar: "https://example.com/image.jpg",
929
+ * // "com.twitter": null, // if not set, for example
930
+ * // }
931
+ * // }
932
+ * ```
933
+ */
934
+ async resolveRecords(name, selection, options) {
935
+ const url = new URL(`/api/resolve/records/${encodeURIComponent(name)}`, this.options.url);
936
+ if (selection.name) {
937
+ url.searchParams.set("name", "true");
938
+ }
939
+ if (selection.addresses && selection.addresses.length > 0) {
940
+ url.searchParams.set("addresses", selection.addresses.join(","));
941
+ }
942
+ if (selection.texts && selection.texts.length > 0) {
943
+ url.searchParams.set("texts", selection.texts.join(","));
944
+ }
945
+ if (options?.trace) url.searchParams.set("trace", "true");
946
+ if (options?.accelerate) url.searchParams.set("accelerate", "true");
947
+ const response = await fetch(url);
948
+ if (!response.ok) {
949
+ const error = await response.json();
950
+ throw new Error(`Records Resolution Failed: ${error.message}`);
951
+ }
952
+ const data = await response.json();
953
+ return data;
954
+ }
955
+ /**
956
+ * Resolves the primary name of a specified address (Reverse Resolution) on a specific chain.
957
+ *
958
+ * If the `address` specifies a valid [ENSIP-19 Default Name](https://docs.ens.domains/ensip/19/#default-primary-name),
959
+ * the Default Name will be returned. You _may_ query the Default EVM Chain Id (`0`) in order to
960
+ * determine the `address`'s Default Name directly.
961
+ *
962
+ * @param address The Address whose Primary Name to resolve
963
+ * @param chainId The chain id within which to query the address' ENSIP-19 Multichain Primary Name
964
+ * @param options additional options
965
+ * @param options.accelerate whether to attempt Protocol Acceleration (default false)
966
+ * @param options.trace whether to include a trace in the response (default false)
967
+ * @returns ResolvePrimaryNameResponse
968
+ * @throws If the request fails or the ENSNode API returns an error response
969
+ *
970
+ * @example
971
+ * ```typescript
972
+ * // Resolve the address' Primary Name on Ethereum Mainnet
973
+ * const { name } = await client.resolvePrimaryName("0x179A862703a4adfb29896552DF9e307980D19285", 1);
974
+ * // name === 'gregskril.eth'
975
+ *
976
+ * // Resolve the address' Primary Name on Base
977
+ * const { name } = await client.resolvePrimaryName("0x179A862703a4adfb29896552DF9e307980D19285", 8453);
978
+ * // name === 'greg.base.eth'
979
+ *
980
+ * // Resolve the address' Default Primary Name
981
+ * const { name } = await client.resolvePrimaryName("0x179A862703a4adfb29896552DF9e307980D19285", 0);
982
+ * // name === 'gregskril.eth'
983
+ * ```
984
+ */
985
+ async resolvePrimaryName(address, chainId, options) {
986
+ const url = new URL(`/api/resolve/primary-name/${address}/${chainId}`, this.options.url);
987
+ if (options?.trace) url.searchParams.set("trace", "true");
988
+ if (options?.accelerate) url.searchParams.set("accelerate", "true");
989
+ const response = await fetch(url);
990
+ if (!response.ok) {
991
+ const error = await response.json();
992
+ throw new Error(`Primary Name Resolution Failed: ${error.message}`);
993
+ }
994
+ const data = await response.json();
995
+ return data;
996
+ }
997
+ /**
998
+ * Resolves the primary names of a specified address across multiple chains.
999
+ *
1000
+ * If the `address` specifies a valid [ENSIP-19 Default Name](https://docs.ens.domains/ensip/19/#default-primary-name),
1001
+ * the Default Name will be returned for all chainIds for which there is not a chain-specific
1002
+ * Primary Name. To avoid misuse, you _may not_ query the Default EVM Chain Id (`0`) directly, and
1003
+ * should rely on the aforementioned per-chain defaulting behavior.
1004
+ *
1005
+ * @param address The Address whose Primary Names to resolve
1006
+ * @param options additional options
1007
+ * @param options.chainIds The set of chain ids within which to query the address' ENSIP-19
1008
+ * Multichain Primary Name (default: all ENSIP-19 supported chains)
1009
+ * @param options.accelerate whether to attempt Protocol Acceleration (default: true)
1010
+ * @param options.trace whether to include a trace in the response (default: false)
1011
+ * @returns ResolvePrimaryNamesResponse
1012
+ * @throws If the request fails or the ENSNode API returns an error response
1013
+ *
1014
+ * @example
1015
+ * ```typescript
1016
+ * // Resolve the address' Primary Names on all ENSIP-19 supported chain ids
1017
+ * const { names } = await client.resolvePrimaryNames("0x179A862703a4adfb29896552DF9e307980D19285");
1018
+ *
1019
+ * console.log(names);
1020
+ * // {
1021
+ * // "1": "gregskril.eth",
1022
+ * // "10": "gregskril.eth",
1023
+ * // "8453": "greg.base.eth", // base-specific Primary Name!
1024
+ * // "42161": "gregskril.eth",
1025
+ * // "59144": "gregskril.eth",
1026
+ * // "534352": "gregskril.eth"
1027
+ * // }
1028
+ *
1029
+ * // Resolve the address' Primary Names on specific chain Ids
1030
+ * const { names } = await client.resolvePrimaryNames("0xabcd...", [1, 8453]);
1031
+ *
1032
+ * console.log(names);
1033
+ * // {
1034
+ * // "1": "gregskril.eth",
1035
+ * // "8453": "greg.base.eth", // base-specific Primary Name!
1036
+ * // }
1037
+ * ```
1038
+ */
1039
+ async resolvePrimaryNames(address, options) {
1040
+ const url = new URL(`/api/resolve/primary-names/${address}`, this.options.url);
1041
+ if (options?.chainIds) url.searchParams.set("chainIds", options.chainIds.join(","));
1042
+ if (options?.trace) url.searchParams.set("trace", "true");
1043
+ if (options?.accelerate) url.searchParams.set("accelerate", "true");
1044
+ const response = await fetch(url);
1045
+ if (!response.ok) {
1046
+ const error = await response.json();
1047
+ throw new Error(`Primary Names Resolution Failed: ${error.message}`);
1048
+ }
1049
+ const data = await response.json();
1050
+ return data;
1051
+ }
1052
+ };
1053
+
1054
+ // src/resolution/resolver-records-selection.ts
1055
+ var DEFAULT_RECORDS_SELECTION = {
1056
+ addresses: [ETH_COIN_TYPE],
1057
+ texts: [
1058
+ "url",
1059
+ "avatar",
1060
+ "header",
1061
+ "description",
1062
+ "email",
1063
+ "com.twitter",
1064
+ "com.farcaster",
1065
+ "com.github"
1066
+ ]
108
1067
  };
1068
+ var isSelectionEmpty = (selection) => !selection.name && !selection.addresses?.length && !selection.texts?.length;
109
1069
  export {
1070
+ ATTR_PROTOCOL_NAME,
1071
+ ATTR_PROTOCOL_STEP,
1072
+ ATTR_PROTOCOL_STEP_RESULT,
1073
+ ChainIndexingStatusIds,
1074
+ ChainIndexingStrategyIds,
1075
+ DEFAULT_ENSNODE_API_URL,
1076
+ DEFAULT_EVM_CHAIN_ID,
1077
+ DEFAULT_EVM_COIN_TYPE,
1078
+ DEFAULT_RECORDS_SELECTION,
1079
+ ENSNamespaceIds,
1080
+ ENSNodeClient,
110
1081
  ETH_COIN_TYPE,
1082
+ ForwardResolutionProtocolStep,
111
1083
  LruCache,
1084
+ OverallIndexingStatusIds,
112
1085
  PluginName,
113
1086
  REVERSE_ROOT_NODES,
114
1087
  ROOT_NODE,
1088
+ ReverseResolutionProtocolStep,
1089
+ TraceableENSProtocol,
1090
+ addrReverseLabel,
1091
+ bigintToCoinType,
1092
+ checkChainIndexingStatusesForBackfillOverallStatus,
1093
+ checkChainIndexingStatusesForCompletedOverallStatus,
1094
+ checkChainIndexingStatusesForFollowingOverallStatus,
1095
+ checkChainIndexingStatusesForUnstartedOverallStatus,
1096
+ coinTypeReverseLabel,
1097
+ coinTypeToEvmChainId,
1098
+ createIndexingConfig,
1099
+ deserializeBlockNumber,
1100
+ deserializeBlockRef,
1101
+ deserializeBlockrange,
1102
+ deserializeChainId,
1103
+ deserializeDatetime,
1104
+ deserializeDuration,
1105
+ deserializeENSIndexerIndexingStatus,
1106
+ deserializeENSIndexerPublicConfig,
1107
+ deserializeUrl,
1108
+ evmChainIdToCoinType,
1109
+ getActiveChains,
1110
+ getNameHierarchy,
1111
+ getOmnichainIndexingCursor,
1112
+ getOverallApproxRealtimeDistance,
1113
+ getOverallIndexingStatus,
1114
+ getStandbyChains,
1115
+ hrTimeToMicroseconds,
115
1116
  isLabelIndexable,
1117
+ isNormalized,
1118
+ isSelectionEmpty,
1119
+ isSubgraphCompatible,
116
1120
  makeSubdomainNode,
117
1121
  maybeHealLabelByReverseAddress,
118
- uint256ToHex32
1122
+ parseReverseName,
1123
+ readableSpanToProtocolSpan,
1124
+ reverseName,
1125
+ serializeChainId,
1126
+ serializeChainIndexingStatuses,
1127
+ serializeDatetime,
1128
+ serializeENSIndexerIndexingStatus,
1129
+ serializeENSIndexerPublicConfig,
1130
+ serializeIndexedChainIds,
1131
+ serializeUrl,
1132
+ uint256ToHex32,
1133
+ uniq
119
1134
  };
120
1135
  //# sourceMappingURL=index.js.map