@ensnode/ensnode-sdk 0.33.0 → 0.35.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,6 +1,9 @@
1
1
  // src/ens/constants.ts
2
2
  import { namehash } from "viem";
3
3
  var ROOT_NODE = namehash("");
4
+ var ETH_NODE = namehash("eth");
5
+ var BASENAMES_NODE = namehash("base.eth");
6
+ var LINEANAMES_NODE = namehash("linea.eth");
4
7
  var REVERSE_ROOT_NODES = /* @__PURE__ */ new Set([namehash("addr.reverse")]);
5
8
 
6
9
  // src/ens/subname-helpers.ts
@@ -121,6 +124,28 @@ function parseReverseName(name) {
121
124
  }
122
125
  }
123
126
 
127
+ // src/ens/is-normalized.ts
128
+ import { normalize } from "viem/ens";
129
+ function isNormalizedName(name) {
130
+ try {
131
+ return name === normalize(name);
132
+ } catch {
133
+ return false;
134
+ }
135
+ }
136
+ function isNormalizedLabel(label) {
137
+ if (label === "") return false;
138
+ if (label.includes(".")) return false;
139
+ try {
140
+ return label === normalize(label);
141
+ } catch {
142
+ return false;
143
+ }
144
+ }
145
+
146
+ // src/ens/encode-labelhash.ts
147
+ var encodeLabelHash = (labelHash) => `[${labelHash.slice(2)}]`;
148
+
124
149
  // src/ensindexer/config/deserialize.ts
125
150
  import { prettifyError as prettifyError2 } from "zod/v4";
126
151
 
@@ -319,14 +344,21 @@ ${prettifyError(parsed.error)}
319
344
  return parsed.data;
320
345
  }
321
346
 
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
- }
347
+ // src/shared/account-id.ts
348
+ import { isAddressEqual } from "viem";
349
+ var accountIdEqual = (a, b) => {
350
+ return a.chainId === b.chainId && isAddressEqual(a.address, b.address);
351
+ };
352
+
353
+ // src/shared/interpretation.ts
354
+ import { labelhash as labelhash2 } from "viem";
355
+ function interpretLiteralLabel(label) {
356
+ if (isNormalizedLabel(label)) return label;
357
+ return encodeLabelHash(labelhash2(label));
358
+ }
359
+ function interpretLiteralName(name) {
360
+ if (isNormalizedName(name)) return name;
361
+ return name.split(".").map(interpretLiteralLabel).join(".");
330
362
  }
331
363
 
332
364
  // src/ensindexer/config/types.ts
@@ -337,14 +369,16 @@ var PluginName = /* @__PURE__ */ ((PluginName2) => {
337
369
  PluginName2["ThreeDNS"] = "threedns";
338
370
  PluginName2["ReverseResolvers"] = "reverse-resolvers";
339
371
  PluginName2["Referrals"] = "referrals";
372
+ PluginName2["TokenScope"] = "tokenscope";
340
373
  return PluginName2;
341
374
  })(PluginName || {});
342
375
 
343
376
  // src/ensindexer/config/helpers.ts
344
377
  function isSubgraphCompatible(config) {
345
378
  const onlySubgraphPluginActivated = config.plugins.length === 1 && config.plugins[0] === "subgraph" /* Subgraph */;
346
- const indexingBehaviorIsSubgraphCompatible = !config.healReverseAddresses && !config.indexAdditionalResolverRecords;
347
- return onlySubgraphPluginActivated && indexingBehaviorIsSubgraphCompatible;
379
+ const indexingBehaviorIsSubgraphCompatible = !config.healReverseAddresses && !config.indexAdditionalResolverRecords && !config.replaceUnnormalized;
380
+ const labelSetIsSubgraphCompatible = config.labelSet.labelSetId === "subgraph" && config.labelSet.labelSetVersion === 0;
381
+ return onlySubgraphPluginActivated && indexingBehaviorIsSubgraphCompatible && labelSetIsSubgraphCompatible;
348
382
  }
349
383
 
350
384
  // src/ensindexer/config/zod-schemas.ts
@@ -367,6 +401,29 @@ var makePluginsListSchema = (valueLabel = "Plugins") => z2.array(
367
401
  var makeDatabaseSchemaNameSchema = (valueLabel = "Database schema name") => z2.string({ error: `${valueLabel} must be a string` }).trim().nonempty({
368
402
  error: `${valueLabel} is required and must be a non-empty string.`
369
403
  });
404
+ var makeLabelSetIdSchema = (valueLabel) => {
405
+ return z2.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-]+$/, {
406
+ error: `${valueLabel} can only contain lowercase letters (a-z) and hyphens (-)`
407
+ });
408
+ };
409
+ var makeLabelSetVersionSchema = (valueLabel) => {
410
+ return z2.coerce.number({ error: `${valueLabel} must be an integer.` }).pipe(makeNonNegativeIntegerSchema(valueLabel));
411
+ };
412
+ var makeFullyPinnedLabelSetSchema = (valueLabel = "Label set") => {
413
+ let valueLabelLabelSetId = valueLabel;
414
+ let valueLabelLabelSetVersion = valueLabel;
415
+ if (valueLabel == "LABEL_SET") {
416
+ valueLabelLabelSetId = "LABEL_SET_ID";
417
+ valueLabelLabelSetVersion = "LABEL_SET_VERSION";
418
+ } else {
419
+ valueLabelLabelSetId = valueLabel + ".labelSetId";
420
+ valueLabelLabelSetVersion = valueLabel + ".labelSetVersion";
421
+ }
422
+ return z2.object({
423
+ labelSetId: makeLabelSetIdSchema(valueLabelLabelSetId),
424
+ labelSetVersion: makeLabelSetVersionSchema(valueLabelLabelSetVersion)
425
+ });
426
+ };
370
427
  var makeNonEmptyStringSchema = (valueLabel = "Value") => z2.string().nonempty({ error: `${valueLabel} must be a non-empty string.` });
371
428
  var makeDependencyInfoSchema = (valueLabel = "Value") => z2.strictObject(
372
429
  {
@@ -393,7 +450,7 @@ function invariant_reverseResolversPluginNeedsResolverRecords(ctx) {
393
450
  function invariant_isSubgraphCompatibleRequirements(ctx) {
394
451
  const { value: config } = ctx;
395
452
  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'`;
453
+ const message = config.isSubgraphCompatible ? `'isSubgraphCompatible' requires only the '${"subgraph" /* Subgraph */}' plugin to be active, 'indexAdditionalResolverRecords', 'healReverseAddresses', and 'replaceUnnormalized' must be set to 'false', and labelSet must be {labelSetId: "subgraph", labelSetVersion: 0}` : `'indexAdditionalResolverRecords', 'healReverseAddresses', and 'replaceUnnormalized' were set to 'false', the only active plugin was the '${"subgraph" /* Subgraph */}' plugin, and labelSet was {labelSetId: "subgraph", labelSetVersion: 0}. The 'isSubgraphCompatible' must be set to 'true'`;
397
454
  ctx.issues.push({
398
455
  code: "custom",
399
456
  input: config,
@@ -404,10 +461,12 @@ function invariant_isSubgraphCompatibleRequirements(ctx) {
404
461
  var makeENSIndexerPublicConfigSchema = (valueLabel = "ENSIndexerPublicConfig") => z2.object({
405
462
  ensAdminUrl: makeUrlSchema(`${valueLabel}.ensAdminUrl`),
406
463
  ensNodePublicUrl: makeUrlSchema(`${valueLabel}.ensNodePublicUrl`),
464
+ labelSet: makeFullyPinnedLabelSetSchema(`${valueLabel}.labelSet`),
407
465
  healReverseAddresses: z2.boolean({ error: `${valueLabel}.healReverseAddresses` }),
408
466
  indexAdditionalResolverRecords: z2.boolean({
409
467
  error: `${valueLabel}.indexAdditionalResolverRecords`
410
468
  }),
469
+ replaceUnnormalized: z2.boolean({ error: `${valueLabel}.replaceUnnormalized` }),
411
470
  indexedChainIds: makeIndexedChainIdsSchema(`${valueLabel}.indexedChainIds`),
412
471
  isSubgraphCompatible: z2.boolean({ error: `${valueLabel}.isSubgraphCompatible` }),
413
472
  namespace: makeENSNamespaceIdSchema(`${valueLabel}.namespace`),
@@ -436,10 +495,12 @@ function serializeENSIndexerPublicConfig(config) {
436
495
  const {
437
496
  ensAdminUrl,
438
497
  ensNodePublicUrl,
498
+ labelSet,
439
499
  indexedChainIds,
440
500
  databaseSchemaName,
441
501
  healReverseAddresses,
442
502
  indexAdditionalResolverRecords,
503
+ replaceUnnormalized,
443
504
  isSubgraphCompatible: isSubgraphCompatible2,
444
505
  namespace,
445
506
  plugins,
@@ -448,10 +509,12 @@ function serializeENSIndexerPublicConfig(config) {
448
509
  return {
449
510
  ensAdminUrl: serializeUrl(ensAdminUrl),
450
511
  ensNodePublicUrl: serializeUrl(ensNodePublicUrl),
512
+ labelSet,
451
513
  indexedChainIds: serializeIndexedChainIds(indexedChainIds),
452
514
  databaseSchemaName,
453
515
  healReverseAddresses,
454
516
  indexAdditionalResolverRecords,
517
+ replaceUnnormalized,
455
518
  isSubgraphCompatible: isSubgraphCompatible2,
456
519
  namespace,
457
520
  plugins,
@@ -459,6 +522,86 @@ function serializeENSIndexerPublicConfig(config) {
459
522
  };
460
523
  }
461
524
 
525
+ // src/ensindexer/config/labelset-utils.ts
526
+ function buildLabelSetId(maybeLabelSetId) {
527
+ return makeLabelSetIdSchema("LabelSetId").parse(maybeLabelSetId);
528
+ }
529
+ function buildLabelSetVersion(maybeLabelSetVersion) {
530
+ return makeLabelSetVersionSchema("LabelSetVersion").parse(maybeLabelSetVersion);
531
+ }
532
+ function buildEnsRainbowClientLabelSet(labelSetId, labelSetVersion) {
533
+ if (labelSetVersion !== void 0 && labelSetId === void 0) {
534
+ throw new Error("When a labelSetVersion is defined, labelSetId must also be defined.");
535
+ }
536
+ return { labelSetId, labelSetVersion };
537
+ }
538
+ function validateSupportedLabelSetAndVersion(serverSet, clientSet) {
539
+ if (clientSet.labelSetId === void 0) {
540
+ return;
541
+ }
542
+ if (serverSet.labelSetId !== clientSet.labelSetId) {
543
+ throw new Error(
544
+ `Server label set ID "${serverSet.labelSetId}" does not match client's requested label set ID "${clientSet.labelSetId}".`
545
+ );
546
+ }
547
+ if (clientSet.labelSetVersion !== void 0 && serverSet.highestLabelSetVersion < clientSet.labelSetVersion) {
548
+ throw new Error(
549
+ `Server highest label set version ${serverSet.highestLabelSetVersion} is less than client's requested version ${clientSet.labelSetVersion} for label set ID "${clientSet.labelSetId}".`
550
+ );
551
+ }
552
+ }
553
+
554
+ // src/ensindexer/config/label-utils.ts
555
+ import { hexToBytes } from "viem";
556
+ function labelHashToBytes(labelHash) {
557
+ try {
558
+ if (labelHash.length !== 66) {
559
+ throw new Error(`Invalid labelHash length ${labelHash.length} characters (expected 66)`);
560
+ }
561
+ if (labelHash !== labelHash.toLowerCase()) {
562
+ throw new Error("Labelhash must be in lowercase");
563
+ }
564
+ if (!labelHash.startsWith("0x")) {
565
+ throw new Error("Labelhash must be 0x-prefixed");
566
+ }
567
+ const bytes = hexToBytes(labelHash);
568
+ if (bytes.length !== 32) {
569
+ throw new Error(`Invalid labelHash length ${bytes.length} bytes (expected 32)`);
570
+ }
571
+ return bytes;
572
+ } catch (e) {
573
+ if (e instanceof Error) {
574
+ throw e;
575
+ }
576
+ throw new Error("Invalid hex format");
577
+ }
578
+ }
579
+
580
+ // src/ensindexer/config/parsing.ts
581
+ function parseNonNegativeInteger(maybeNumber) {
582
+ const trimmed = maybeNumber.trim();
583
+ if (!trimmed) {
584
+ throw new Error("Input cannot be empty");
585
+ }
586
+ if (trimmed === "-0") {
587
+ throw new Error("Negative zero is not a valid non-negative integer");
588
+ }
589
+ const num = Number(maybeNumber);
590
+ if (Number.isNaN(num)) {
591
+ throw new Error(`"${maybeNumber}" is not a valid number`);
592
+ }
593
+ if (!Number.isFinite(num)) {
594
+ throw new Error(`"${maybeNumber}" is not a finite number`);
595
+ }
596
+ if (!Number.isInteger(num)) {
597
+ throw new Error(`"${maybeNumber}" is not an integer`);
598
+ }
599
+ if (num < 0) {
600
+ throw new Error(`"${maybeNumber}" is not a non-negative integer`);
601
+ }
602
+ return num;
603
+ }
604
+
462
605
  // src/ensindexer/indexing-status/deserialize.ts
463
606
  import { prettifyError as prettifyError3 } from "zod/v4";
464
607
 
@@ -520,6 +663,34 @@ function getOverallApproxRealtimeDistance(chains) {
520
663
  const approxRealtimeDistance = Math.max(...chainApproxRealtimeDistances);
521
664
  return approxRealtimeDistance;
522
665
  }
666
+ function getTimestampForLowestOmnichainStartBlock(chains) {
667
+ const earliestKnownBlockTimestamps = chains.map(
668
+ (chain) => chain.config.startBlock.timestamp
669
+ );
670
+ return Math.min(...earliestKnownBlockTimestamps);
671
+ }
672
+ function getTimestampForHighestOmnichainKnownBlock(chains) {
673
+ const latestKnownBlockTimestamps = [];
674
+ for (const chain of chains) {
675
+ switch (chain.status) {
676
+ case ChainIndexingStatusIds.Unstarted:
677
+ if (chain.config.endBlock) {
678
+ latestKnownBlockTimestamps.push(chain.config.endBlock.timestamp);
679
+ }
680
+ break;
681
+ case ChainIndexingStatusIds.Backfill:
682
+ latestKnownBlockTimestamps.push(chain.backfillEndBlock.timestamp);
683
+ break;
684
+ case ChainIndexingStatusIds.Completed:
685
+ latestKnownBlockTimestamps.push(chain.latestIndexedBlock.timestamp);
686
+ break;
687
+ case ChainIndexingStatusIds.Following:
688
+ latestKnownBlockTimestamps.push(chain.latestKnownBlock.timestamp);
689
+ break;
690
+ }
691
+ }
692
+ return Math.max(...latestKnownBlockTimestamps);
693
+ }
523
694
  function getOmnichainIndexingCursor(chains) {
524
695
  return Math.min(...chains.map((chain) => chain.latestIndexedBlock.timestamp));
525
696
  }
@@ -571,6 +742,12 @@ function checkChainIndexingStatusesForFollowingOverallStatus(chains) {
571
742
  );
572
743
  return allChainsHaveValidStatuses;
573
744
  }
745
+ function sortAscChainStatusesByStartBlock(chains) {
746
+ chains.sort(
747
+ ([, chainA], [, chainB]) => chainA.config.startBlock.timestamp - chainB.config.startBlock.timestamp
748
+ );
749
+ return chains;
750
+ }
574
751
 
575
752
  // src/ensindexer/indexing-status/zod-schemas.ts
576
753
  var makeChainIndexingConfigSchema = (valueLabel = "Value") => z3.discriminatedUnion("strategy", [
@@ -598,6 +775,7 @@ var makeChainIndexingBackfillStatusSchema = (valueLabel = "Value") => z3.strictO
598
775
  status: z3.literal(ChainIndexingStatusIds.Backfill),
599
776
  config: makeChainIndexingConfigSchema(valueLabel),
600
777
  latestIndexedBlock: makeBlockRefSchema(valueLabel),
778
+ latestSyncedBlock: makeBlockRefSchema(valueLabel),
601
779
  backfillEndBlock: makeBlockRefSchema(valueLabel)
602
780
  }).refine(
603
781
  ({ config, latestIndexedBlock }) => isBeforeOrEqualTo(config.startBlock, latestIndexedBlock),
@@ -605,9 +783,14 @@ var makeChainIndexingBackfillStatusSchema = (valueLabel = "Value") => z3.strictO
605
783
  error: `config.startBlock must be before or same as latestIndexedBlock.`
606
784
  }
607
785
  ).refine(
608
- ({ latestIndexedBlock, backfillEndBlock }) => isBeforeOrEqualTo(latestIndexedBlock, backfillEndBlock),
786
+ ({ latestIndexedBlock, latestSyncedBlock }) => isBeforeOrEqualTo(latestIndexedBlock, latestSyncedBlock),
787
+ {
788
+ error: `latestIndexedBlock must be before or same as latestSyncedBlock.`
789
+ }
790
+ ).refine(
791
+ ({ latestSyncedBlock, backfillEndBlock }) => isBeforeOrEqualTo(latestSyncedBlock, backfillEndBlock),
609
792
  {
610
- error: `latestIndexedBlock must be before or same as backfillEndBlock.`
793
+ error: `latestSyncedBlock must be before or same as backfillEndBlock.`
611
794
  }
612
795
  ).refine(
613
796
  ({ config, backfillEndBlock }) => config.endBlock === null || isEqualTo(backfillEndBlock, config.endBlock),
@@ -649,9 +832,9 @@ var makeChainIndexingCompletedStatusSchema = (valueLabel = "Value") => z3.strict
649
832
  error: `config.startBlock must be before or same as latestIndexedBlock.`
650
833
  }
651
834
  ).refine(
652
- ({ config, latestIndexedBlock }) => isEqualTo(latestIndexedBlock, config.endBlock),
835
+ ({ config, latestIndexedBlock }) => isBeforeOrEqualTo(latestIndexedBlock, config.endBlock),
653
836
  {
654
- error: `latestIndexedBlock must be the same as config.endBlock.`
837
+ error: `latestIndexedBlock must be before or same as config.endBlock.`
655
838
  }
656
839
  );
657
840
  var makeChainIndexingStatusSchema = (valueLabel = "Value") => z3.discriminatedUnion("status", [
@@ -839,7 +1022,7 @@ var TraceableENSProtocol = /* @__PURE__ */ ((TraceableENSProtocol2) => {
839
1022
  return TraceableENSProtocol2;
840
1023
  })(TraceableENSProtocol || {});
841
1024
  var ForwardResolutionProtocolStep = /* @__PURE__ */ ((ForwardResolutionProtocolStep2) => {
842
- ForwardResolutionProtocolStep2["Operation"] = "operation";
1025
+ ForwardResolutionProtocolStep2["Operation"] = "forward-resolution";
843
1026
  ForwardResolutionProtocolStep2["FindResolver"] = "find-resolver";
844
1027
  ForwardResolutionProtocolStep2["ActiveResolverExists"] = "active-resolver-exists";
845
1028
  ForwardResolutionProtocolStep2["AccelerateENSIP19ReverseResolver"] = "accelerate-ensip-19-reverse-resolver";
@@ -850,7 +1033,7 @@ var ForwardResolutionProtocolStep = /* @__PURE__ */ ((ForwardResolutionProtocolS
850
1033
  return ForwardResolutionProtocolStep2;
851
1034
  })(ForwardResolutionProtocolStep || {});
852
1035
  var ReverseResolutionProtocolStep = /* @__PURE__ */ ((ReverseResolutionProtocolStep2) => {
853
- ReverseResolutionProtocolStep2["Operation"] = "operation";
1036
+ ReverseResolutionProtocolStep2["Operation"] = "reverse-resolution";
854
1037
  ReverseResolutionProtocolStep2["ResolveReverseName"] = "resolve-reverse-name";
855
1038
  ReverseResolutionProtocolStep2["NameRecordExists"] = "name-record-exists-check";
856
1039
  ReverseResolutionProtocolStep2["ForwardResolveAddressRecord"] = "forward-resolve-address-record";
@@ -861,26 +1044,47 @@ var PROTOCOL_ATTRIBUTE_PREFIX = "ens";
861
1044
  var ATTR_PROTOCOL_NAME = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol`;
862
1045
  var ATTR_PROTOCOL_STEP = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol.step`;
863
1046
  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
1047
+
1048
+ // src/api/helpers.ts
1049
+ import { prettifyError as prettifyError4 } from "zod/v4";
1050
+
1051
+ // src/api/zod-schemas.ts
1052
+ import z4 from "zod/v4";
1053
+ var ErrorResponseSchema = z4.object({
1054
+ message: z4.string(),
1055
+ details: z4.optional(z4.unknown())
882
1056
  });
883
1057
 
1058
+ // src/api/helpers.ts
1059
+ function deserializeErrorResponse(maybeErrorResponse) {
1060
+ const parsed = ErrorResponseSchema.safeParse(maybeErrorResponse);
1061
+ if (parsed.error) {
1062
+ throw new Error(`Cannot deserialize ErrorResponse:
1063
+ ${prettifyError4(parsed.error)}
1064
+ `);
1065
+ }
1066
+ return parsed.data;
1067
+ }
1068
+
1069
+ // src/api/types.ts
1070
+ var IndexingStatusResponseCodes = {
1071
+ IndexerError: 512,
1072
+ RequestedDistanceNotAchievedError: 513
1073
+ };
1074
+
1075
+ // src/client-error.ts
1076
+ var ClientError = class _ClientError extends Error {
1077
+ details;
1078
+ constructor(message, details) {
1079
+ super(message);
1080
+ this.name = "ClientError";
1081
+ this.details = details;
1082
+ }
1083
+ static fromErrorResponse({ message, details }) {
1084
+ return new _ClientError(message, details);
1085
+ }
1086
+ };
1087
+
884
1088
  // src/client.ts
885
1089
  var DEFAULT_ENSNODE_API_URL = "https://api.alpha.ensnode.io";
886
1090
  var ENSNodeClient = class _ENSNodeClient {
@@ -904,6 +1108,9 @@ var ENSNodeClient = class _ENSNodeClient {
904
1108
  /**
905
1109
  * Resolves records for an ENS name (Forward Resolution).
906
1110
  *
1111
+ * The returned `name` field, if set, is guaranteed to be a [Normalized Name](https://ensnode.io/docs/reference/terminology#normalized-name).
1112
+ * If the name record returned by the resolver is not normalized, `null` is returned as if no name record was set.
1113
+ *
907
1114
  * @param name The ENS Name whose records to resolve
908
1115
  * @param selection selection of Resolver records
909
1116
  * @param options additional options
@@ -947,7 +1154,7 @@ var ENSNodeClient = class _ENSNodeClient {
947
1154
  const response = await fetch(url);
948
1155
  if (!response.ok) {
949
1156
  const error = await response.json();
950
- throw new Error(`Records Resolution Failed: ${error.message}`);
1157
+ throw ClientError.fromErrorResponse(error);
951
1158
  }
952
1159
  const data = await response.json();
953
1160
  return data;
@@ -959,6 +1166,9 @@ var ENSNodeClient = class _ENSNodeClient {
959
1166
  * the Default Name will be returned. You _may_ query the Default EVM Chain Id (`0`) in order to
960
1167
  * determine the `address`'s Default Name directly.
961
1168
  *
1169
+ * The returned Primary Name, if set, is guaranteed to be a [Normalized Name](https://ensnode.io/docs/reference/terminology#normalized-name).
1170
+ * If the primary name set for the address is not normalized, `null` is returned as if no primary name was set.
1171
+ *
962
1172
  * @param address The Address whose Primary Name to resolve
963
1173
  * @param chainId The chain id within which to query the address' ENSIP-19 Multichain Primary Name
964
1174
  * @param options additional options
@@ -989,7 +1199,7 @@ var ENSNodeClient = class _ENSNodeClient {
989
1199
  const response = await fetch(url);
990
1200
  if (!response.ok) {
991
1201
  const error = await response.json();
992
- throw new Error(`Primary Name Resolution Failed: ${error.message}`);
1202
+ throw ClientError.fromErrorResponse(error);
993
1203
  }
994
1204
  const data = await response.json();
995
1205
  return data;
@@ -1002,6 +1212,9 @@ var ENSNodeClient = class _ENSNodeClient {
1002
1212
  * Primary Name. To avoid misuse, you _may not_ query the Default EVM Chain Id (`0`) directly, and
1003
1213
  * should rely on the aforementioned per-chain defaulting behavior.
1004
1214
  *
1215
+ * Each returned Primary Name, if set, is guaranteed to be a [Normalized Name](https://ensnode.io/docs/reference/terminology#normalized-name).
1216
+ * If the primary name set for the address on any chain is not normalized, `null` is returned for that chain as if no primary name was set.
1217
+ *
1005
1218
  * @param address The Address whose Primary Names to resolve
1006
1219
  * @param options additional options
1007
1220
  * @param options.chainIds The set of chain ids within which to query the address' ENSIP-19
@@ -1044,51 +1257,176 @@ var ENSNodeClient = class _ENSNodeClient {
1044
1257
  const response = await fetch(url);
1045
1258
  if (!response.ok) {
1046
1259
  const error = await response.json();
1047
- throw new Error(`Primary Names Resolution Failed: ${error.message}`);
1260
+ throw ClientError.fromErrorResponse(error);
1048
1261
  }
1049
1262
  const data = await response.json();
1050
1263
  return data;
1051
1264
  }
1265
+ /**
1266
+ * Fetch ENSNode Config
1267
+ *
1268
+ * Fetch the ENSNode's configuration.
1269
+ *
1270
+ * @returns {ConfigResponse}
1271
+ *
1272
+ * @throws if the ENSNode request fails
1273
+ * @throws if the ENSNode API returns an error response
1274
+ * @throws if the ENSNode response breaks required invariants
1275
+ */
1276
+ async config() {
1277
+ const url = new URL(`/api/config`, this.options.url);
1278
+ const response = await fetch(url);
1279
+ let responseData;
1280
+ try {
1281
+ responseData = await response.json();
1282
+ } catch {
1283
+ throw new Error("Malformed response data: invalid JSON");
1284
+ }
1285
+ if (!response.ok) {
1286
+ const errorResponse = deserializeErrorResponse(responseData);
1287
+ throw new Error(`Fetching ENSNode Config Failed: ${errorResponse.message}`);
1288
+ }
1289
+ return deserializeENSIndexerPublicConfig(responseData);
1290
+ }
1291
+ /**
1292
+ * Fetch ENSNode Indexing Status
1293
+ *
1294
+ * Fetch the ENSNode's multichain indexing status.
1295
+ *
1296
+ * @param options additional options
1297
+ * @param options.maxRealtimeDistance the max allowed distance between the
1298
+ * latest indexed block of each chain and the "tip" of all indexed chains.
1299
+ * Setting this parameter influences the HTTP response code as follows:
1300
+ * - Success (200 OK): The latest indexed block of each chain is within the
1301
+ * requested distance from realtime.
1302
+ * - Service Unavailable (503): The latest indexed block of each chain is NOT
1303
+ * within the requested distance from realtime.
1304
+ *
1305
+ * @returns {IndexingStatusResponse}
1306
+ *
1307
+ * @throws if the ENSNode request fails
1308
+ * @throws if the ENSNode API returns an error response
1309
+ * @throws if the ENSNode response breaks required invariants
1310
+ */
1311
+ async indexingStatus(options) {
1312
+ const url = new URL(`/api/indexing-status`, this.options.url);
1313
+ if (typeof options?.maxRealtimeDistance !== "undefined") {
1314
+ url.searchParams.set("maxRealtimeDistance", `${options.maxRealtimeDistance}`);
1315
+ }
1316
+ const response = await fetch(url);
1317
+ let responseData;
1318
+ try {
1319
+ responseData = await response.json();
1320
+ } catch {
1321
+ throw new Error("Malformed response data: invalid JSON");
1322
+ }
1323
+ if (!response.ok) {
1324
+ switch (response.status) {
1325
+ case IndexingStatusResponseCodes.IndexerError: {
1326
+ console.error("Indexing Status API: indexer error");
1327
+ return deserializeENSIndexerIndexingStatus(
1328
+ responseData
1329
+ );
1330
+ }
1331
+ case IndexingStatusResponseCodes.RequestedDistanceNotAchievedError: {
1332
+ console.error(
1333
+ "Indexing Status API: Requested realtime indexing distance not achieved error"
1334
+ );
1335
+ return deserializeENSIndexerIndexingStatus(
1336
+ responseData
1337
+ );
1338
+ }
1339
+ default: {
1340
+ const errorResponse = deserializeErrorResponse(responseData);
1341
+ throw new Error(`Fetching ENSNode Indexing Status Failed: ${errorResponse.message}`);
1342
+ }
1343
+ }
1344
+ }
1345
+ return deserializeENSIndexerIndexingStatus(
1346
+ responseData
1347
+ );
1348
+ }
1052
1349
  };
1053
1350
 
1054
1351
  // 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
- ]
1067
- };
1068
1352
  var isSelectionEmpty = (selection) => !selection.name && !selection.addresses?.length && !selection.texts?.length;
1353
+
1354
+ // src/resolution/default-records-selection.ts
1355
+ import {
1356
+ DatasourceNames,
1357
+ ENSNamespaceIds as ENSNamespaceIds2,
1358
+ maybeGetDatasource
1359
+ } from "@ensnode/datasources";
1360
+ var getENSIP19SupportedCoinTypes = (namespace) => uniq(
1361
+ [
1362
+ maybeGetDatasource(namespace, DatasourceNames.ReverseResolverBase),
1363
+ maybeGetDatasource(namespace, DatasourceNames.ReverseResolverLinea),
1364
+ maybeGetDatasource(namespace, DatasourceNames.ReverseResolverOptimism),
1365
+ maybeGetDatasource(namespace, DatasourceNames.ReverseResolverArbitrum),
1366
+ maybeGetDatasource(namespace, DatasourceNames.ReverseResolverScroll)
1367
+ ].filter((ds) => ds !== void 0).map((ds) => ds.chain.id)
1368
+ ).map(evmChainIdToCoinType);
1369
+ var TEXTS = [
1370
+ "url",
1371
+ "avatar",
1372
+ "header",
1373
+ "description",
1374
+ "email",
1375
+ "com.twitter",
1376
+ "com.farcaster",
1377
+ "com.github"
1378
+ ];
1379
+ var DefaultRecordsSelection = {
1380
+ [ENSNamespaceIds2.Mainnet]: {
1381
+ addresses: [ETH_COIN_TYPE, ...getENSIP19SupportedCoinTypes(ENSNamespaceIds2.Mainnet)],
1382
+ texts: TEXTS
1383
+ },
1384
+ [ENSNamespaceIds2.Sepolia]: {
1385
+ addresses: [ETH_COIN_TYPE, ...getENSIP19SupportedCoinTypes(ENSNamespaceIds2.Sepolia)],
1386
+ texts: TEXTS
1387
+ },
1388
+ [ENSNamespaceIds2.Holesky]: {
1389
+ addresses: [ETH_COIN_TYPE, ...getENSIP19SupportedCoinTypes(ENSNamespaceIds2.Holesky)],
1390
+ texts: TEXTS
1391
+ },
1392
+ [ENSNamespaceIds2.EnsTestEnv]: {
1393
+ addresses: [ETH_COIN_TYPE, ...getENSIP19SupportedCoinTypes(ENSNamespaceIds2.EnsTestEnv)],
1394
+ texts: TEXTS
1395
+ }
1396
+ };
1069
1397
  export {
1070
1398
  ATTR_PROTOCOL_NAME,
1071
1399
  ATTR_PROTOCOL_STEP,
1072
1400
  ATTR_PROTOCOL_STEP_RESULT,
1401
+ BASENAMES_NODE,
1073
1402
  ChainIndexingStatusIds,
1074
1403
  ChainIndexingStrategyIds,
1404
+ ClientError,
1075
1405
  DEFAULT_ENSNODE_API_URL,
1076
1406
  DEFAULT_EVM_CHAIN_ID,
1077
1407
  DEFAULT_EVM_COIN_TYPE,
1078
- DEFAULT_RECORDS_SELECTION,
1408
+ DefaultRecordsSelection,
1079
1409
  ENSNamespaceIds,
1080
1410
  ENSNodeClient,
1081
1411
  ETH_COIN_TYPE,
1412
+ ETH_NODE,
1082
1413
  ForwardResolutionProtocolStep,
1414
+ IndexingStatusResponseCodes,
1415
+ LINEANAMES_NODE,
1083
1416
  LruCache,
1084
1417
  OverallIndexingStatusIds,
1418
+ PROTOCOL_ATTRIBUTE_PREFIX,
1085
1419
  PluginName,
1086
1420
  REVERSE_ROOT_NODES,
1087
1421
  ROOT_NODE,
1088
1422
  ReverseResolutionProtocolStep,
1089
1423
  TraceableENSProtocol,
1424
+ accountIdEqual,
1090
1425
  addrReverseLabel,
1091
1426
  bigintToCoinType,
1427
+ buildEnsRainbowClientLabelSet,
1428
+ buildLabelSetId,
1429
+ buildLabelSetVersion,
1092
1430
  checkChainIndexingStatusesForBackfillOverallStatus,
1093
1431
  checkChainIndexingStatusesForCompletedOverallStatus,
1094
1432
  checkChainIndexingStatusesForFollowingOverallStatus,
@@ -1104,7 +1442,9 @@ export {
1104
1442
  deserializeDuration,
1105
1443
  deserializeENSIndexerIndexingStatus,
1106
1444
  deserializeENSIndexerPublicConfig,
1445
+ deserializeErrorResponse,
1107
1446
  deserializeUrl,
1447
+ encodeLabelHash,
1108
1448
  evmChainIdToCoinType,
1109
1449
  getActiveChains,
1110
1450
  getNameHierarchy,
@@ -1112,15 +1452,30 @@ export {
1112
1452
  getOverallApproxRealtimeDistance,
1113
1453
  getOverallIndexingStatus,
1114
1454
  getStandbyChains,
1115
- hrTimeToMicroseconds,
1455
+ getTimestampForHighestOmnichainKnownBlock,
1456
+ getTimestampForLowestOmnichainStartBlock,
1457
+ interpretLiteralLabel,
1458
+ interpretLiteralName,
1459
+ invariant_isSubgraphCompatibleRequirements,
1460
+ invariant_reverseResolversPluginNeedsResolverRecords,
1116
1461
  isLabelIndexable,
1117
- isNormalized,
1462
+ isNormalizedLabel,
1463
+ isNormalizedName,
1118
1464
  isSelectionEmpty,
1119
1465
  isSubgraphCompatible,
1466
+ labelHashToBytes,
1467
+ makeDatabaseSchemaNameSchema,
1468
+ makeDependencyInfoSchema,
1469
+ makeENSIndexerPublicConfigSchema,
1470
+ makeFullyPinnedLabelSetSchema,
1471
+ makeIndexedChainIdsSchema,
1472
+ makeLabelSetIdSchema,
1473
+ makeLabelSetVersionSchema,
1474
+ makePluginsListSchema,
1120
1475
  makeSubdomainNode,
1121
1476
  maybeHealLabelByReverseAddress,
1477
+ parseNonNegativeInteger,
1122
1478
  parseReverseName,
1123
- readableSpanToProtocolSpan,
1124
1479
  reverseName,
1125
1480
  serializeChainId,
1126
1481
  serializeChainIndexingStatuses,
@@ -1129,7 +1484,9 @@ export {
1129
1484
  serializeENSIndexerPublicConfig,
1130
1485
  serializeIndexedChainIds,
1131
1486
  serializeUrl,
1487
+ sortAscChainStatusesByStartBlock,
1132
1488
  uint256ToHex32,
1133
- uniq
1489
+ uniq,
1490
+ validateSupportedLabelSetAndVersion
1134
1491
  };
1135
1492
  //# sourceMappingURL=index.js.map