@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/README.md +6 -0
- package/dist/index.d.ts +471 -46
- package/dist/index.js +413 -56
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
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/
|
|
323
|
-
import {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
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
|
-
|
|
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
|
|
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,
|
|
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: `
|
|
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 }) =>
|
|
835
|
+
({ config, latestIndexedBlock }) => isBeforeOrEqualTo(latestIndexedBlock, config.endBlock),
|
|
653
836
|
{
|
|
654
|
-
error: `latestIndexedBlock must be
|
|
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"] = "
|
|
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"] = "
|
|
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
|
-
|
|
865
|
-
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
1455
|
+
getTimestampForHighestOmnichainKnownBlock,
|
|
1456
|
+
getTimestampForLowestOmnichainStartBlock,
|
|
1457
|
+
interpretLiteralLabel,
|
|
1458
|
+
interpretLiteralName,
|
|
1459
|
+
invariant_isSubgraphCompatibleRequirements,
|
|
1460
|
+
invariant_reverseResolversPluginNeedsResolverRecords,
|
|
1116
1461
|
isLabelIndexable,
|
|
1117
|
-
|
|
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
|