@ensnode/ensnode-sdk 0.34.0 → 0.36.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 +55 -10
- package/dist/index.d.ts +1250 -570
- package/dist/index.js +899 -508
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
package/dist/index.js
CHANGED
|
@@ -4,11 +4,12 @@ var ROOT_NODE = namehash("");
|
|
|
4
4
|
var ETH_NODE = namehash("eth");
|
|
5
5
|
var BASENAMES_NODE = namehash("base.eth");
|
|
6
6
|
var LINEANAMES_NODE = namehash("linea.eth");
|
|
7
|
-
var
|
|
7
|
+
var ADDR_REVERSE_NODE = namehash("addr.reverse");
|
|
8
8
|
|
|
9
9
|
// src/ens/subname-helpers.ts
|
|
10
|
-
import { concat,
|
|
11
|
-
|
|
10
|
+
import { concat, keccak256, toHex } from "viem";
|
|
11
|
+
var makeSubdomainNode = (labelHash, node) => keccak256(concat([node, labelHash]));
|
|
12
|
+
var uint256ToHex32 = (num) => toHex(num, { size: 32 });
|
|
12
13
|
|
|
13
14
|
// src/ens/coin-type.ts
|
|
14
15
|
import {
|
|
@@ -33,8 +34,43 @@ var bigintToCoinType = (value) => {
|
|
|
33
34
|
return Number(value);
|
|
34
35
|
};
|
|
35
36
|
|
|
37
|
+
// src/ens/names.ts
|
|
38
|
+
import { ens_beautify } from "@adraffy/ens-normalize";
|
|
39
|
+
|
|
40
|
+
// src/ens/is-normalized.ts
|
|
41
|
+
import { normalize } from "viem/ens";
|
|
42
|
+
function isNormalizedName(name) {
|
|
43
|
+
try {
|
|
44
|
+
return name === normalize(name);
|
|
45
|
+
} catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function isNormalizedLabel(label) {
|
|
50
|
+
if (label === "") return false;
|
|
51
|
+
if (label.includes(".")) return false;
|
|
52
|
+
try {
|
|
53
|
+
return label === normalize(label);
|
|
54
|
+
} catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// src/ens/names.ts
|
|
60
|
+
var getNameHierarchy = (name) => name.split(".").map((_, i, labels) => labels.slice(i).join("."));
|
|
61
|
+
var beautifyName = (name) => {
|
|
62
|
+
const beautifiedLabels = name.split(".").map((label) => {
|
|
63
|
+
if (isNormalizedLabel(label)) {
|
|
64
|
+
return ens_beautify(label);
|
|
65
|
+
} else {
|
|
66
|
+
return label;
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
return beautifiedLabels.join(".");
|
|
70
|
+
};
|
|
71
|
+
|
|
36
72
|
// src/ens/reverse-name.ts
|
|
37
|
-
var addrReverseLabel = (address) => address.slice(2)
|
|
73
|
+
var addrReverseLabel = (address) => address.slice(2);
|
|
38
74
|
var coinTypeReverseLabel = (coinType) => coinType.toString(16);
|
|
39
75
|
function reverseName(address, coinType) {
|
|
40
76
|
const label = addrReverseLabel(address);
|
|
@@ -51,84 +87,16 @@ function reverseName(address, coinType) {
|
|
|
51
87
|
return `${label}.${middle}.reverse`;
|
|
52
88
|
}
|
|
53
89
|
|
|
54
|
-
// src/ens/subname-helpers.ts
|
|
55
|
-
var makeSubdomainNode = (labelHash, node) => keccak256(concat([node, labelHash]));
|
|
56
|
-
var maybeHealLabelByReverseAddress = ({
|
|
57
|
-
maybeReverseAddress,
|
|
58
|
-
labelHash
|
|
59
|
-
}) => {
|
|
60
|
-
if (!isAddress(maybeReverseAddress)) {
|
|
61
|
-
throw new Error(
|
|
62
|
-
`Invalid reverse address: '${maybeReverseAddress}'. Must be a valid EVM Address.`
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
if (!isHash(labelHash)) {
|
|
66
|
-
throw new Error(
|
|
67
|
-
`Invalid labelHash: '${labelHash}'. Must start with '0x' and represent 32 bytes.`
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
const assumedLabel = addrReverseLabel(maybeReverseAddress);
|
|
71
|
-
if (labelhash(assumedLabel) === labelHash) return assumedLabel;
|
|
72
|
-
return null;
|
|
73
|
-
};
|
|
74
|
-
var uint256ToHex32 = (num) => toHex(num, { size: 32 });
|
|
75
|
-
var UNINDEXABLE_LABEL_CHARACTERS = [
|
|
76
|
-
"\0",
|
|
77
|
-
// null byte: PostgreSQL does not allow storing this character in text fields.
|
|
78
|
-
".",
|
|
79
|
-
// conflicts with ENS label separator logic.
|
|
80
|
-
"[",
|
|
81
|
-
// conflicts with "unknown label" representations.
|
|
82
|
-
"]"
|
|
83
|
-
// conflicts with "unknown label" representations.
|
|
84
|
-
];
|
|
85
|
-
var UNINDEXABLE_LABEL_CHARACTER_CODES = new Set(
|
|
86
|
-
UNINDEXABLE_LABEL_CHARACTERS.map((char) => char.charCodeAt(0))
|
|
87
|
-
);
|
|
88
|
-
var isLabelIndexable = (label) => {
|
|
89
|
-
if (!label) return false;
|
|
90
|
-
for (let i = 0; i < label.length; i++) {
|
|
91
|
-
if (UNINDEXABLE_LABEL_CHARACTER_CODES.has(label.charCodeAt(i))) return false;
|
|
92
|
-
}
|
|
93
|
-
return true;
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
// src/ens/names.ts
|
|
97
|
-
var getNameHierarchy = (name) => name.split(".").map((_, i, labels) => labels.slice(i).join("."));
|
|
98
|
-
|
|
99
90
|
// src/ens/types.ts
|
|
100
91
|
import { ENSNamespaceIds } from "@ensnode/datasources";
|
|
101
92
|
|
|
102
93
|
// src/ens/parse-reverse-name.ts
|
|
103
|
-
import {
|
|
104
|
-
var REVERSE_NAME_REGEX = /^([0-9a-fA-F]+)\.([0-9a-f]{1,64}|addr|default)\.reverse$/;
|
|
105
|
-
var parseAddressLabel = (addressLabel) => getAddress(`0x${addressLabel}`);
|
|
106
|
-
var parseCoinTypeLabel = (coinTypeLabel) => {
|
|
107
|
-
if (coinTypeLabel === "default") return DEFAULT_EVM_COIN_TYPE;
|
|
108
|
-
if (coinTypeLabel === "addr") return ETH_COIN_TYPE;
|
|
109
|
-
return bigintToCoinType(hexToBigInt(`0x${coinTypeLabel}`));
|
|
110
|
-
};
|
|
111
|
-
function parseReverseName(name) {
|
|
112
|
-
const match = name.match(REVERSE_NAME_REGEX);
|
|
113
|
-
if (!match) return null;
|
|
114
|
-
try {
|
|
115
|
-
const [, addressLabel, coinTypeLabel] = match;
|
|
116
|
-
if (!addressLabel) return null;
|
|
117
|
-
if (!coinTypeLabel) return null;
|
|
118
|
-
return {
|
|
119
|
-
address: parseAddressLabel(addressLabel),
|
|
120
|
-
coinType: parseCoinTypeLabel(coinTypeLabel)
|
|
121
|
-
};
|
|
122
|
-
} catch {
|
|
123
|
-
return null;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// src/ensindexer/config/deserialize.ts
|
|
128
|
-
import { prettifyError as prettifyError2 } from "zod/v4";
|
|
94
|
+
import { hexToBigInt, isAddress as isAddress2 } from "viem";
|
|
129
95
|
|
|
130
|
-
// src/
|
|
131
|
-
|
|
96
|
+
// src/shared/address.ts
|
|
97
|
+
function asLowerCaseAddress(address) {
|
|
98
|
+
return address.toLowerCase();
|
|
99
|
+
}
|
|
132
100
|
|
|
133
101
|
// src/shared/cache.ts
|
|
134
102
|
var LruCache = class {
|
|
@@ -197,6 +165,7 @@ function serializeUrl(url) {
|
|
|
197
165
|
import { prettifyError } from "zod/v4";
|
|
198
166
|
|
|
199
167
|
// src/shared/zod-schemas.ts
|
|
168
|
+
import { isAddress } from "viem";
|
|
200
169
|
import z from "zod/v4";
|
|
201
170
|
var makeIntegerSchema = (valueLabel = "Value") => z.int({
|
|
202
171
|
error: `${valueLabel} must be an integer.`
|
|
@@ -210,7 +179,7 @@ var makeNonNegativeIntegerSchema = (valueLabel = "Value") => makeIntegerSchema(v
|
|
|
210
179
|
var makeDurationSchema = (valueLabel = "Value") => z.coerce.number({
|
|
211
180
|
error: `${valueLabel} must be a number.`
|
|
212
181
|
}).pipe(makeNonNegativeIntegerSchema(valueLabel));
|
|
213
|
-
var makeChainIdSchema = (valueLabel = "Chain ID") => makePositiveIntegerSchema(valueLabel);
|
|
182
|
+
var makeChainIdSchema = (valueLabel = "Chain ID") => makePositiveIntegerSchema(valueLabel).transform((val) => val);
|
|
214
183
|
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}`));
|
|
215
184
|
var makeDatetimeSchema = (valueLabel = "Datetime string") => z.iso.datetime({ error: `${valueLabel} must be a string in ISO 8601 format.` }).transform((v) => new Date(v));
|
|
216
185
|
var makeUnixTimestampSchema = (valueLabel = "Timestamp") => makeIntegerSchema(valueLabel);
|
|
@@ -271,6 +240,16 @@ ${prettifyError(parsed.error)}
|
|
|
271
240
|
}
|
|
272
241
|
return parsed.data;
|
|
273
242
|
}
|
|
243
|
+
function deserializeUnixTimestamp(maybeTimestamp, valueLabel) {
|
|
244
|
+
const schema = makeUnixTimestampSchema(valueLabel);
|
|
245
|
+
const parsed = schema.safeParse(maybeTimestamp);
|
|
246
|
+
if (parsed.error) {
|
|
247
|
+
throw new Error(`Cannot deserialize Unix Timestamp:
|
|
248
|
+
${prettifyError(parsed.error)}
|
|
249
|
+
`);
|
|
250
|
+
}
|
|
251
|
+
return parsed.data;
|
|
252
|
+
}
|
|
274
253
|
function deserializeUrl(maybeUrl, valueLabel) {
|
|
275
254
|
const schema = makeUrlSchema(valueLabel);
|
|
276
255
|
const parsed = schema.safeParse(maybeUrl);
|
|
@@ -322,29 +301,121 @@ ${prettifyError(parsed.error)}
|
|
|
322
301
|
return parsed.data;
|
|
323
302
|
}
|
|
324
303
|
|
|
325
|
-
// src/shared/is-normalized.ts
|
|
326
|
-
import { normalize } from "viem/ens";
|
|
327
|
-
function isNormalized(name) {
|
|
328
|
-
try {
|
|
329
|
-
return name === normalize(name);
|
|
330
|
-
} catch {
|
|
331
|
-
return false;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
304
|
// src/shared/account-id.ts
|
|
336
305
|
import { isAddressEqual } from "viem";
|
|
337
306
|
var accountIdEqual = (a, b) => {
|
|
338
307
|
return a.chainId === b.chainId && isAddressEqual(a.address, b.address);
|
|
339
308
|
};
|
|
340
309
|
|
|
310
|
+
// src/shared/labelhash.ts
|
|
311
|
+
import { keccak256 as keccak2562, stringToBytes } from "viem";
|
|
312
|
+
var labelhashLiteralLabel = (label) => keccak2562(stringToBytes(label));
|
|
313
|
+
|
|
314
|
+
// src/shared/interpretation.ts
|
|
315
|
+
function literalLabelToInterpretedLabel(label) {
|
|
316
|
+
if (isNormalizedLabel(label)) return label;
|
|
317
|
+
return encodeLabelHash(labelhashLiteralLabel(label));
|
|
318
|
+
}
|
|
319
|
+
function literalLabelsToInterpretedName(labels) {
|
|
320
|
+
return labels.map(literalLabelToInterpretedLabel).join(".");
|
|
321
|
+
}
|
|
322
|
+
function interpretedLabelsToInterpretedName(labels) {
|
|
323
|
+
return labels.join(".");
|
|
324
|
+
}
|
|
325
|
+
function literalLabelsToLiteralName(labels) {
|
|
326
|
+
return labels.join(".");
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// src/shared/url.ts
|
|
330
|
+
function isHttpProtocol(url) {
|
|
331
|
+
return ["http:", "https:"].includes(url.protocol);
|
|
332
|
+
}
|
|
333
|
+
function isWebSocketProtocol(url) {
|
|
334
|
+
return ["ws:", "wss:"].includes(url.protocol);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// src/ens/parse-reverse-name.ts
|
|
338
|
+
var REVERSE_NAME_REGEX = /^([0-9a-fA-F]+)\.([0-9a-f]{1,64}|addr|default)\.reverse$/;
|
|
339
|
+
var parseAddressLabel = (addressLabel) => {
|
|
340
|
+
const maybeAddress = `0x${addressLabel}`;
|
|
341
|
+
if (!isAddress2(maybeAddress)) {
|
|
342
|
+
throw new Error(`Invalid EVM address "${maybeAddress}"`);
|
|
343
|
+
}
|
|
344
|
+
return asLowerCaseAddress(maybeAddress);
|
|
345
|
+
};
|
|
346
|
+
var parseCoinTypeLabel = (coinTypeLabel) => {
|
|
347
|
+
if (coinTypeLabel === "default") return DEFAULT_EVM_COIN_TYPE;
|
|
348
|
+
if (coinTypeLabel === "addr") return ETH_COIN_TYPE;
|
|
349
|
+
return bigintToCoinType(hexToBigInt(`0x${coinTypeLabel}`));
|
|
350
|
+
};
|
|
351
|
+
function parseReverseName(name) {
|
|
352
|
+
const match = name.match(REVERSE_NAME_REGEX);
|
|
353
|
+
if (!match) return null;
|
|
354
|
+
try {
|
|
355
|
+
const [, addressLabel, coinTypeLabel] = match;
|
|
356
|
+
if (!addressLabel) return null;
|
|
357
|
+
if (!coinTypeLabel) return null;
|
|
358
|
+
return {
|
|
359
|
+
address: parseAddressLabel(addressLabel),
|
|
360
|
+
coinType: parseCoinTypeLabel(coinTypeLabel)
|
|
361
|
+
};
|
|
362
|
+
} catch {
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// src/ens/encode-labelhash.ts
|
|
368
|
+
var encodeLabelHash = (labelHash) => `[${labelHash.slice(2)}]`;
|
|
369
|
+
|
|
370
|
+
// src/ens/dns-encoded-name.ts
|
|
371
|
+
import { bytesToString, hexToBytes } from "viem";
|
|
372
|
+
function decodeDNSEncodedLiteralName(packet) {
|
|
373
|
+
return decodeDNSEncodedName(packet);
|
|
374
|
+
}
|
|
375
|
+
function decodeDNSEncodedName(packet) {
|
|
376
|
+
const segments = [];
|
|
377
|
+
const bytes = hexToBytes(packet);
|
|
378
|
+
if (bytes.length === 0) throw new Error(`Packet is empty.`);
|
|
379
|
+
let offset = 0;
|
|
380
|
+
while (offset < bytes.length) {
|
|
381
|
+
const len = bytes[offset];
|
|
382
|
+
if (len === void 0) {
|
|
383
|
+
throw new Error(`Invariant: bytes[offset] is undefined after offset < bytes.length check.`);
|
|
384
|
+
}
|
|
385
|
+
if (len < 0 || len > 255) {
|
|
386
|
+
throw new Error(
|
|
387
|
+
`Invariant: this should be literally impossible, but an unsigned byte was less than zero or greater than 255. The value in question is ${len}`
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
if (len === 0) break;
|
|
391
|
+
const segment = bytesToString(bytes.subarray(offset + 1, offset + len + 1));
|
|
392
|
+
segments.push(segment);
|
|
393
|
+
offset += len + 1;
|
|
394
|
+
}
|
|
395
|
+
if (offset >= bytes.length) throw new Error(`Overflow, offset >= bytes.length`);
|
|
396
|
+
if (offset !== bytes.length - 1) throw new Error(`Junk at end of name`);
|
|
397
|
+
return segments;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// src/ens/index.ts
|
|
401
|
+
import { getENSRootChainId } from "@ensnode/datasources";
|
|
402
|
+
|
|
403
|
+
// src/ensindexer/config/deserialize.ts
|
|
404
|
+
import { prettifyError as prettifyError2 } from "zod/v4";
|
|
405
|
+
|
|
406
|
+
// src/ensindexer/config/zod-schemas.ts
|
|
407
|
+
import z2 from "zod/v4";
|
|
408
|
+
|
|
409
|
+
// src/ensindexer/config/helpers.ts
|
|
410
|
+
import { ENSNamespaceIds as ENSNamespaceIds2 } from "@ensnode/datasources";
|
|
411
|
+
|
|
341
412
|
// src/ensindexer/config/types.ts
|
|
342
413
|
var PluginName = /* @__PURE__ */ ((PluginName2) => {
|
|
343
414
|
PluginName2["Subgraph"] = "subgraph";
|
|
344
415
|
PluginName2["Basenames"] = "basenames";
|
|
345
416
|
PluginName2["Lineanames"] = "lineanames";
|
|
346
417
|
PluginName2["ThreeDNS"] = "threedns";
|
|
347
|
-
PluginName2["
|
|
418
|
+
PluginName2["ProtocolAcceleration"] = "protocol-acceleration";
|
|
348
419
|
PluginName2["Referrals"] = "referrals";
|
|
349
420
|
PluginName2["TokenScope"] = "tokenscope";
|
|
350
421
|
return PluginName2;
|
|
@@ -353,25 +424,32 @@ var PluginName = /* @__PURE__ */ ((PluginName2) => {
|
|
|
353
424
|
// src/ensindexer/config/helpers.ts
|
|
354
425
|
function isSubgraphCompatible(config) {
|
|
355
426
|
const onlySubgraphPluginActivated = config.plugins.length === 1 && config.plugins[0] === "subgraph" /* Subgraph */;
|
|
356
|
-
const
|
|
357
|
-
const
|
|
358
|
-
|
|
427
|
+
const isSubgraphLabelSet = config.labelSet.labelSetId === "subgraph" && config.labelSet.labelSetVersion === 0;
|
|
428
|
+
const isEnsTestEnvLabelSet = config.labelSet.labelSetId === "ens-test-env" && config.labelSet.labelSetVersion === 0;
|
|
429
|
+
const labelSetIsSubgraphCompatible = isSubgraphLabelSet || config.namespace === ENSNamespaceIds2.EnsTestEnv && isEnsTestEnvLabelSet;
|
|
430
|
+
return onlySubgraphPluginActivated && labelSetIsSubgraphCompatible;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// src/ensindexer/config/validations.ts
|
|
434
|
+
function invariant_ensDbVersionIsSameAsEnsIndexerVersion(ctx) {
|
|
435
|
+
const versionInfo = ctx.value;
|
|
436
|
+
if (versionInfo.ensDb !== versionInfo.ensIndexer) {
|
|
437
|
+
ctx.issues.push({
|
|
438
|
+
code: "custom",
|
|
439
|
+
input: versionInfo,
|
|
440
|
+
message: "`ensDb` version must be same as `ensIndexer` version"
|
|
441
|
+
});
|
|
442
|
+
}
|
|
359
443
|
}
|
|
360
444
|
|
|
361
445
|
// src/ensindexer/config/zod-schemas.ts
|
|
362
446
|
var makeIndexedChainIdsSchema = (valueLabel = "Indexed Chain IDs") => z2.array(makeChainIdSchema(valueLabel), {
|
|
363
447
|
error: `${valueLabel} must be an array.`
|
|
364
448
|
}).min(1, { error: `${valueLabel} list must include at least one element.` }).transform((v) => new Set(v));
|
|
365
|
-
var makePluginsListSchema = (valueLabel = "Plugins") => z2.array(
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
).join(", ")}`
|
|
370
|
-
})
|
|
371
|
-
).min(1, {
|
|
372
|
-
error: `${valueLabel} must be a list with at least one valid plugin name. Valid plugins are: ${Object.values(
|
|
373
|
-
PluginName
|
|
374
|
-
).join(", ")}`
|
|
449
|
+
var makePluginsListSchema = (valueLabel = "Plugins") => z2.array(z2.string(), {
|
|
450
|
+
error: `${valueLabel} must be a list of strings.`
|
|
451
|
+
}).min(1, {
|
|
452
|
+
error: `${valueLabel} must be a list of strings with at least one string value`
|
|
375
453
|
}).refine((arr) => arr.length === uniq(arr).length, {
|
|
376
454
|
error: `${valueLabel} cannot contain duplicate values.`
|
|
377
455
|
});
|
|
@@ -402,54 +480,39 @@ var makeFullyPinnedLabelSetSchema = (valueLabel = "Label set") => {
|
|
|
402
480
|
});
|
|
403
481
|
};
|
|
404
482
|
var makeNonEmptyStringSchema = (valueLabel = "Value") => z2.string().nonempty({ error: `${valueLabel} must be a non-empty string.` });
|
|
405
|
-
var
|
|
483
|
+
var makeENSIndexerVersionInfoSchema = (valueLabel = "Value") => z2.strictObject(
|
|
406
484
|
{
|
|
407
485
|
nodejs: makeNonEmptyStringSchema(),
|
|
408
486
|
ponder: makeNonEmptyStringSchema(),
|
|
487
|
+
ensDb: makeNonEmptyStringSchema(),
|
|
488
|
+
ensIndexer: makeNonEmptyStringSchema(),
|
|
489
|
+
ensNormalize: makeNonEmptyStringSchema(),
|
|
409
490
|
ensRainbow: makeNonEmptyStringSchema(),
|
|
410
491
|
ensRainbowSchema: makePositiveIntegerSchema()
|
|
411
492
|
},
|
|
412
493
|
{
|
|
413
|
-
error: `${valueLabel} must be a valid
|
|
494
|
+
error: `${valueLabel} must be a valid ENSIndexerVersionInfo object.`
|
|
414
495
|
}
|
|
415
|
-
);
|
|
416
|
-
function invariant_reverseResolversPluginNeedsResolverRecords(ctx) {
|
|
417
|
-
const { value: config } = ctx;
|
|
418
|
-
const reverseResolversPluginActive = config.plugins.includes("reverse-resolvers" /* ReverseResolvers */);
|
|
419
|
-
if (reverseResolversPluginActive && !config.indexAdditionalResolverRecords) {
|
|
420
|
-
ctx.issues.push({
|
|
421
|
-
code: "custom",
|
|
422
|
-
input: config,
|
|
423
|
-
message: `The '${"reverse-resolvers" /* ReverseResolvers */}' plugin requires 'indexAdditionalResolverRecords' to be 'true'.`
|
|
424
|
-
});
|
|
425
|
-
}
|
|
426
|
-
}
|
|
496
|
+
).check(invariant_ensDbVersionIsSameAsEnsIndexerVersion);
|
|
427
497
|
function invariant_isSubgraphCompatibleRequirements(ctx) {
|
|
428
498
|
const { value: config } = ctx;
|
|
429
|
-
if (config.isSubgraphCompatible
|
|
430
|
-
const message = config.isSubgraphCompatible ? `'isSubgraphCompatible' requires only the '${"subgraph" /* Subgraph */}' plugin to be active, both 'indexAdditionalResolverRecords' and 'healReverseAddresses' must be set to 'false', and labelSet must be {labelSetId: "subgraph", labelSetVersion: 0}` : `Both 'indexAdditionalResolverRecords' and 'healReverseAddresses' 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'`;
|
|
499
|
+
if (config.isSubgraphCompatible && !isSubgraphCompatible(config)) {
|
|
431
500
|
ctx.issues.push({
|
|
432
501
|
code: "custom",
|
|
433
502
|
input: config,
|
|
434
|
-
message
|
|
503
|
+
message: `'isSubgraphCompatible' requires only the '${"subgraph" /* Subgraph */}' plugin to be active and labelSet must be {labelSetId: "subgraph", labelSetVersion: 0}`
|
|
435
504
|
});
|
|
436
505
|
}
|
|
437
506
|
}
|
|
438
507
|
var makeENSIndexerPublicConfigSchema = (valueLabel = "ENSIndexerPublicConfig") => z2.object({
|
|
439
|
-
ensAdminUrl: makeUrlSchema(`${valueLabel}.ensAdminUrl`),
|
|
440
|
-
ensNodePublicUrl: makeUrlSchema(`${valueLabel}.ensNodePublicUrl`),
|
|
441
508
|
labelSet: makeFullyPinnedLabelSetSchema(`${valueLabel}.labelSet`),
|
|
442
|
-
healReverseAddresses: z2.boolean({ error: `${valueLabel}.healReverseAddresses` }),
|
|
443
|
-
indexAdditionalResolverRecords: z2.boolean({
|
|
444
|
-
error: `${valueLabel}.indexAdditionalResolverRecords`
|
|
445
|
-
}),
|
|
446
509
|
indexedChainIds: makeIndexedChainIdsSchema(`${valueLabel}.indexedChainIds`),
|
|
447
510
|
isSubgraphCompatible: z2.boolean({ error: `${valueLabel}.isSubgraphCompatible` }),
|
|
448
511
|
namespace: makeENSNamespaceIdSchema(`${valueLabel}.namespace`),
|
|
449
512
|
plugins: makePluginsListSchema(`${valueLabel}.plugins`),
|
|
450
513
|
databaseSchemaName: makeDatabaseSchemaNameSchema(`${valueLabel}.databaseSchemaName`),
|
|
451
|
-
|
|
452
|
-
}).check(
|
|
514
|
+
versionInfo: makeENSIndexerVersionInfoSchema(`${valueLabel}.versionInfo`)
|
|
515
|
+
}).check(invariant_isSubgraphCompatibleRequirements);
|
|
453
516
|
|
|
454
517
|
// src/ensindexer/config/deserialize.ts
|
|
455
518
|
function deserializeENSIndexerPublicConfig(maybeConfig, valueLabel) {
|
|
@@ -469,30 +532,22 @@ function serializeIndexedChainIds(indexedChainIds) {
|
|
|
469
532
|
}
|
|
470
533
|
function serializeENSIndexerPublicConfig(config) {
|
|
471
534
|
const {
|
|
472
|
-
ensAdminUrl,
|
|
473
|
-
ensNodePublicUrl,
|
|
474
535
|
labelSet,
|
|
475
536
|
indexedChainIds,
|
|
476
537
|
databaseSchemaName,
|
|
477
|
-
healReverseAddresses,
|
|
478
|
-
indexAdditionalResolverRecords,
|
|
479
538
|
isSubgraphCompatible: isSubgraphCompatible2,
|
|
480
539
|
namespace,
|
|
481
540
|
plugins,
|
|
482
|
-
|
|
541
|
+
versionInfo
|
|
483
542
|
} = config;
|
|
484
543
|
return {
|
|
485
|
-
ensAdminUrl: serializeUrl(ensAdminUrl),
|
|
486
|
-
ensNodePublicUrl: serializeUrl(ensNodePublicUrl),
|
|
487
544
|
labelSet,
|
|
488
545
|
indexedChainIds: serializeIndexedChainIds(indexedChainIds),
|
|
489
546
|
databaseSchemaName,
|
|
490
|
-
healReverseAddresses,
|
|
491
|
-
indexAdditionalResolverRecords,
|
|
492
547
|
isSubgraphCompatible: isSubgraphCompatible2,
|
|
493
548
|
namespace,
|
|
494
549
|
plugins,
|
|
495
|
-
|
|
550
|
+
versionInfo
|
|
496
551
|
};
|
|
497
552
|
}
|
|
498
553
|
|
|
@@ -526,7 +581,7 @@ function validateSupportedLabelSetAndVersion(serverSet, clientSet) {
|
|
|
526
581
|
}
|
|
527
582
|
|
|
528
583
|
// src/ensindexer/config/label-utils.ts
|
|
529
|
-
import { hexToBytes } from "viem";
|
|
584
|
+
import { hexToBytes as hexToBytes2 } from "viem";
|
|
530
585
|
function labelHashToBytes(labelHash) {
|
|
531
586
|
try {
|
|
532
587
|
if (labelHash.length !== 66) {
|
|
@@ -538,7 +593,7 @@ function labelHashToBytes(labelHash) {
|
|
|
538
593
|
if (!labelHash.startsWith("0x")) {
|
|
539
594
|
throw new Error("Labelhash must be 0x-prefixed");
|
|
540
595
|
}
|
|
541
|
-
const bytes =
|
|
596
|
+
const bytes = hexToBytes2(labelHash);
|
|
542
597
|
if (bytes.length !== 32) {
|
|
543
598
|
throw new Error(`Invalid labelHash length ${bytes.length} bytes (expected 32)`);
|
|
544
599
|
}
|
|
@@ -582,6 +637,92 @@ import { prettifyError as prettifyError3 } from "zod/v4";
|
|
|
582
637
|
// src/ensindexer/indexing-status/zod-schemas.ts
|
|
583
638
|
import z3 from "zod/v4";
|
|
584
639
|
|
|
640
|
+
// src/ensindexer/indexing-status/types.ts
|
|
641
|
+
var ChainIndexingConfigTypeIds = {
|
|
642
|
+
/**
|
|
643
|
+
* Represents that indexing of the chain should be performed for an indefinite range.
|
|
644
|
+
*/
|
|
645
|
+
Indefinite: "indefinite",
|
|
646
|
+
/**
|
|
647
|
+
* Represents that indexing of the chain should be performed for a definite range.
|
|
648
|
+
*/
|
|
649
|
+
Definite: "definite"
|
|
650
|
+
};
|
|
651
|
+
var ChainIndexingStatusIds = {
|
|
652
|
+
/**
|
|
653
|
+
* Represents that indexing of the chain is not ready to begin yet because:
|
|
654
|
+
* - ENSIndexer is in its initialization phase and the data to build a
|
|
655
|
+
* "true" {@link ChainIndexingSnapshot} for the chain is still being loaded; or
|
|
656
|
+
* - ENSIndexer is using an omnichain indexing strategy and the
|
|
657
|
+
* `omnichainIndexingCursor` is <= `config.startBlock.timestamp` for the chain's
|
|
658
|
+
* {@link ChainIndexingSnapshot}.
|
|
659
|
+
*/
|
|
660
|
+
Queued: "chain-queued",
|
|
661
|
+
/**
|
|
662
|
+
* Represents that indexing of the chain is in progress and under a special
|
|
663
|
+
* "backfill" phase that optimizes for accelerated indexing until reaching the
|
|
664
|
+
* "fixed target" `backfillEndBlock`.
|
|
665
|
+
*/
|
|
666
|
+
Backfill: "chain-backfill",
|
|
667
|
+
/**
|
|
668
|
+
* Represents that the "backfill" phase of indexing the chain is completed
|
|
669
|
+
* and that the chain is configured to be indexed for an indefinite range.
|
|
670
|
+
* Therefore, indexing of the chain remains indefinitely in progress where
|
|
671
|
+
* ENSIndexer will continuously work to discover and index new blocks as they
|
|
672
|
+
* are added to the chain across time.
|
|
673
|
+
*/
|
|
674
|
+
Following: "chain-following",
|
|
675
|
+
/**
|
|
676
|
+
* Represents that indexing of the chain is completed as the chain is configured
|
|
677
|
+
* to be indexed for a definite range and the indexing of all blocks through
|
|
678
|
+
* that definite range is completed.
|
|
679
|
+
*/
|
|
680
|
+
Completed: "chain-completed"
|
|
681
|
+
};
|
|
682
|
+
var OmnichainIndexingStatusIds = {
|
|
683
|
+
/**
|
|
684
|
+
* Represents that omnichain indexing is not ready to begin yet because
|
|
685
|
+
* ENSIndexer is in its initialization phase and the data to build a "true"
|
|
686
|
+
* {@link OmnichainIndexingStatusSnapshot} is still being loaded.
|
|
687
|
+
*/
|
|
688
|
+
Unstarted: "omnichain-unstarted",
|
|
689
|
+
/**
|
|
690
|
+
* Represents that omnichain indexing is in an overall "backfill" status because
|
|
691
|
+
* - At least one indexed chain has a `chainStatus` of
|
|
692
|
+
* {@link ChainIndexingStatusIds.Backfill}; and
|
|
693
|
+
* - No indexed chain has a `chainStatus` of {@link ChainIndexingStatusIds.Following}.
|
|
694
|
+
*/
|
|
695
|
+
Backfill: "omnichain-backfill",
|
|
696
|
+
/**
|
|
697
|
+
* Represents that omnichain indexing is in an overall "following" status because
|
|
698
|
+
* at least one indexed chain has a `chainStatus` of
|
|
699
|
+
* {@link ChainIndexingStatusIds.Following}.
|
|
700
|
+
*/
|
|
701
|
+
Following: "omnichain-following",
|
|
702
|
+
/**
|
|
703
|
+
* Represents that omnichain indexing has completed because all indexed chains have
|
|
704
|
+
* a `chainStatus` of {@link ChainIndexingStatusIds.Completed}.
|
|
705
|
+
*/
|
|
706
|
+
Completed: "omnichain-completed"
|
|
707
|
+
};
|
|
708
|
+
var CrossChainIndexingStrategyIds = {
|
|
709
|
+
/**
|
|
710
|
+
* Represents that the indexing of events across all indexed chains will
|
|
711
|
+
* proceed in a deterministic "omnichain" ordering by block timestamp, chain ID,
|
|
712
|
+
* and block number.
|
|
713
|
+
*
|
|
714
|
+
* This strategy is "deterministic" in that the order of processing cross-chain indexed
|
|
715
|
+
* events and each resulting indexed data state transition recorded in ENSDb is always
|
|
716
|
+
* the same for each ENSIndexer instance operating with an equivalent
|
|
717
|
+
* `ENSIndexerConfig` and ENSIndexer version. However it also has the drawbacks of:
|
|
718
|
+
* - increased indexing latency that must wait for the slowest indexed chain to
|
|
719
|
+
* add new blocks or to discover new blocks through the configured RPCs.
|
|
720
|
+
* - if any indexed chain gets "stuck" due to chain or RPC failures, all indexed chains
|
|
721
|
+
* will be affected.
|
|
722
|
+
*/
|
|
723
|
+
Omnichain: "omnichain"
|
|
724
|
+
};
|
|
725
|
+
|
|
585
726
|
// src/shared/block-ref.ts
|
|
586
727
|
function isBefore(blockA, blockB) {
|
|
587
728
|
return blockA.number < blockB.number && blockA.timestamp < blockB.timestamp;
|
|
@@ -593,49 +734,21 @@ function isBeforeOrEqualTo(blockA, blockB) {
|
|
|
593
734
|
return isBefore(blockA, blockB) || isEqualTo(blockA, blockB);
|
|
594
735
|
}
|
|
595
736
|
|
|
596
|
-
// src/ensindexer/indexing-status/types.ts
|
|
597
|
-
var ChainIndexingStatusIds = {
|
|
598
|
-
Unstarted: "unstarted",
|
|
599
|
-
Backfill: "backfill",
|
|
600
|
-
Following: "following",
|
|
601
|
-
Completed: "completed"
|
|
602
|
-
};
|
|
603
|
-
var OverallIndexingStatusIds = {
|
|
604
|
-
Unstarted: "unstarted",
|
|
605
|
-
Backfill: "backfill",
|
|
606
|
-
Following: "following",
|
|
607
|
-
Completed: "completed",
|
|
608
|
-
IndexerError: "indexer-error"
|
|
609
|
-
};
|
|
610
|
-
var ChainIndexingStrategyIds = {
|
|
611
|
-
Indefinite: "indefinite",
|
|
612
|
-
Definite: "definite"
|
|
613
|
-
};
|
|
614
|
-
|
|
615
737
|
// src/ensindexer/indexing-status/helpers.ts
|
|
616
|
-
function
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
if (chainStatuses.some((chainStatus) => chainStatus === ChainIndexingStatusIds.Following)) {
|
|
620
|
-
overallStatus = OverallIndexingStatusIds.Following;
|
|
621
|
-
} else if (chainStatuses.some((chainStatus) => chainStatus === ChainIndexingStatusIds.Backfill)) {
|
|
622
|
-
overallStatus = OverallIndexingStatusIds.Backfill;
|
|
623
|
-
} else if (chainStatuses.some((chainStatus) => chainStatus === ChainIndexingStatusIds.Unstarted)) {
|
|
624
|
-
overallStatus = OverallIndexingStatusIds.Unstarted;
|
|
625
|
-
} else {
|
|
626
|
-
overallStatus = OverallIndexingStatusIds.Completed;
|
|
738
|
+
function getOmnichainIndexingStatus(chains) {
|
|
739
|
+
if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing(chains)) {
|
|
740
|
+
return OmnichainIndexingStatusIds.Following;
|
|
627
741
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
throw new Error(
|
|
634
|
-
`The overall approximate realtime distance value is undefined if no indexed chain is in the '${OverallIndexingStatusIds.Following}' status`
|
|
635
|
-
);
|
|
742
|
+
if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill(chains)) {
|
|
743
|
+
return OmnichainIndexingStatusIds.Backfill;
|
|
744
|
+
}
|
|
745
|
+
if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted(chains)) {
|
|
746
|
+
return OmnichainIndexingStatusIds.Unstarted;
|
|
636
747
|
}
|
|
637
|
-
|
|
638
|
-
|
|
748
|
+
if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted(chains)) {
|
|
749
|
+
return OmnichainIndexingStatusIds.Completed;
|
|
750
|
+
}
|
|
751
|
+
throw new Error(`Unable to determine omnichain indexing status for provided chains.`);
|
|
639
752
|
}
|
|
640
753
|
function getTimestampForLowestOmnichainStartBlock(chains) {
|
|
641
754
|
const earliestKnownBlockTimestamps = chains.map(
|
|
@@ -646,8 +759,8 @@ function getTimestampForLowestOmnichainStartBlock(chains) {
|
|
|
646
759
|
function getTimestampForHighestOmnichainKnownBlock(chains) {
|
|
647
760
|
const latestKnownBlockTimestamps = [];
|
|
648
761
|
for (const chain of chains) {
|
|
649
|
-
switch (chain.
|
|
650
|
-
case ChainIndexingStatusIds.
|
|
762
|
+
switch (chain.chainStatus) {
|
|
763
|
+
case ChainIndexingStatusIds.Queued:
|
|
651
764
|
if (chain.config.endBlock) {
|
|
652
765
|
latestKnownBlockTimestamps.push(chain.config.endBlock.timestamp);
|
|
653
766
|
}
|
|
@@ -666,159 +779,349 @@ function getTimestampForHighestOmnichainKnownBlock(chains) {
|
|
|
666
779
|
return Math.max(...latestKnownBlockTimestamps);
|
|
667
780
|
}
|
|
668
781
|
function getOmnichainIndexingCursor(chains) {
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
(chain) => chain.
|
|
674
|
-
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
(
|
|
679
|
-
|
|
782
|
+
if (chains.length === 0) {
|
|
783
|
+
throw new Error(`Unable to determine omnichain indexing cursor when no chains were provided.`);
|
|
784
|
+
}
|
|
785
|
+
if (getOmnichainIndexingStatus(chains) === OmnichainIndexingStatusIds.Unstarted) {
|
|
786
|
+
const earliestStartBlockTimestamps = chains.map((chain) => chain.config.startBlock.timestamp);
|
|
787
|
+
return Math.min(...earliestStartBlockTimestamps) - 1;
|
|
788
|
+
}
|
|
789
|
+
const latestIndexedBlockTimestamps = chains.filter((chain) => chain.chainStatus !== ChainIndexingStatusIds.Queued).map((chain) => chain.latestIndexedBlock.timestamp);
|
|
790
|
+
if (latestIndexedBlockTimestamps.length < 1) {
|
|
791
|
+
throw new Error("latestIndexedBlockTimestamps array must include at least one element");
|
|
792
|
+
}
|
|
793
|
+
return Math.max(...latestIndexedBlockTimestamps);
|
|
680
794
|
}
|
|
681
795
|
function createIndexingConfig(startBlock, endBlock) {
|
|
682
796
|
if (endBlock) {
|
|
683
797
|
return {
|
|
684
|
-
|
|
798
|
+
configType: ChainIndexingConfigTypeIds.Definite,
|
|
685
799
|
startBlock,
|
|
686
800
|
endBlock
|
|
687
801
|
};
|
|
688
802
|
}
|
|
689
803
|
return {
|
|
690
|
-
|
|
691
|
-
startBlock
|
|
692
|
-
endBlock: null
|
|
804
|
+
configType: ChainIndexingConfigTypeIds.Indefinite,
|
|
805
|
+
startBlock
|
|
693
806
|
};
|
|
694
807
|
}
|
|
695
|
-
function
|
|
696
|
-
return chains.every((chain) => chain.
|
|
808
|
+
function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted(chains) {
|
|
809
|
+
return chains.every((chain) => chain.chainStatus === ChainIndexingStatusIds.Queued);
|
|
697
810
|
}
|
|
698
|
-
function
|
|
811
|
+
function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill(chains) {
|
|
699
812
|
const atLeastOneChainInTargetStatus = chains.some(
|
|
700
|
-
(chain) => chain.
|
|
813
|
+
(chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill
|
|
701
814
|
);
|
|
702
815
|
const otherChainsHaveValidStatuses = chains.every(
|
|
703
|
-
(chain) => chain.
|
|
816
|
+
(chain) => chain.chainStatus === ChainIndexingStatusIds.Queued || chain.chainStatus === ChainIndexingStatusIds.Backfill || chain.chainStatus === ChainIndexingStatusIds.Completed
|
|
704
817
|
);
|
|
705
818
|
return atLeastOneChainInTargetStatus && otherChainsHaveValidStatuses;
|
|
706
819
|
}
|
|
707
|
-
function
|
|
820
|
+
function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted(chains) {
|
|
708
821
|
const allChainsHaveValidStatuses = chains.every(
|
|
709
|
-
(chain) => chain.
|
|
822
|
+
(chain) => chain.chainStatus === ChainIndexingStatusIds.Completed
|
|
710
823
|
);
|
|
711
824
|
return allChainsHaveValidStatuses;
|
|
712
825
|
}
|
|
713
|
-
function
|
|
826
|
+
function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing(chains) {
|
|
714
827
|
const allChainsHaveValidStatuses = chains.some(
|
|
715
|
-
(chain) => chain.
|
|
828
|
+
(chain) => chain.chainStatus === ChainIndexingStatusIds.Following
|
|
716
829
|
);
|
|
717
830
|
return allChainsHaveValidStatuses;
|
|
718
831
|
}
|
|
719
|
-
function
|
|
832
|
+
function sortChainStatusesByStartBlockAsc(chains) {
|
|
720
833
|
chains.sort(
|
|
721
834
|
([, chainA], [, chainB]) => chainA.config.startBlock.timestamp - chainB.config.startBlock.timestamp
|
|
722
835
|
);
|
|
723
836
|
return chains;
|
|
724
837
|
}
|
|
725
838
|
|
|
839
|
+
// src/ensindexer/indexing-status/validations.ts
|
|
840
|
+
function invariant_chainSnapshotQueuedBlocks(ctx) {
|
|
841
|
+
const { config } = ctx.value;
|
|
842
|
+
if (config.endBlock && isBeforeOrEqualTo(config.startBlock, config.endBlock) === false) {
|
|
843
|
+
ctx.issues.push({
|
|
844
|
+
code: "custom",
|
|
845
|
+
input: ctx.value,
|
|
846
|
+
message: "`config.startBlock` must be before or same as `config.endBlock`."
|
|
847
|
+
});
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
function invariant_chainSnapshotBackfillBlocks(ctx) {
|
|
851
|
+
const { config, latestIndexedBlock, backfillEndBlock } = ctx.value;
|
|
852
|
+
if (isBeforeOrEqualTo(config.startBlock, latestIndexedBlock) === false) {
|
|
853
|
+
ctx.issues.push({
|
|
854
|
+
code: "custom",
|
|
855
|
+
input: ctx.value,
|
|
856
|
+
message: "`config.startBlock` must be before or same as `latestIndexedBlock`."
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
if (isBeforeOrEqualTo(latestIndexedBlock, backfillEndBlock) === false) {
|
|
860
|
+
ctx.issues.push({
|
|
861
|
+
code: "custom",
|
|
862
|
+
input: ctx.value,
|
|
863
|
+
message: "`latestIndexedBlock` must be before or same as `backfillEndBlock`."
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
if (config.endBlock && isEqualTo(backfillEndBlock, config.endBlock) === false) {
|
|
867
|
+
ctx.issues.push({
|
|
868
|
+
code: "custom",
|
|
869
|
+
input: ctx.value,
|
|
870
|
+
message: "`backfillEndBlock` must be the same as `config.endBlock`."
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
function invariant_chainSnapshotCompletedBlocks(ctx) {
|
|
875
|
+
const { config, latestIndexedBlock } = ctx.value;
|
|
876
|
+
if (isBeforeOrEqualTo(config.startBlock, latestIndexedBlock) === false) {
|
|
877
|
+
ctx.issues.push({
|
|
878
|
+
code: "custom",
|
|
879
|
+
input: ctx.value,
|
|
880
|
+
message: "`config.startBlock` must be before or same as `latestIndexedBlock`."
|
|
881
|
+
});
|
|
882
|
+
}
|
|
883
|
+
if (isBeforeOrEqualTo(latestIndexedBlock, config.endBlock) === false) {
|
|
884
|
+
ctx.issues.push({
|
|
885
|
+
code: "custom",
|
|
886
|
+
input: ctx.value,
|
|
887
|
+
message: "`latestIndexedBlock` must be before or same as `config.endBlock`."
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
function invariant_chainSnapshotFollowingBlocks(ctx) {
|
|
892
|
+
const { config, latestIndexedBlock, latestKnownBlock } = ctx.value;
|
|
893
|
+
if (isBeforeOrEqualTo(config.startBlock, latestIndexedBlock) === false) {
|
|
894
|
+
ctx.issues.push({
|
|
895
|
+
code: "custom",
|
|
896
|
+
input: ctx.value,
|
|
897
|
+
message: "`config.startBlock` must be before or same as `latestIndexedBlock`."
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
if (isBeforeOrEqualTo(latestIndexedBlock, latestKnownBlock) === false) {
|
|
901
|
+
ctx.issues.push({
|
|
902
|
+
code: "custom",
|
|
903
|
+
input: ctx.value,
|
|
904
|
+
message: "`latestIndexedBlock` must be before or same as `latestKnownBlock`."
|
|
905
|
+
});
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
function invariant_omnichainSnapshotStatusIsConsistentWithChainSnapshot(ctx) {
|
|
909
|
+
const snapshot = ctx.value;
|
|
910
|
+
const chains = Array.from(snapshot.chains.values());
|
|
911
|
+
const expectedOmnichainStatus = getOmnichainIndexingStatus(chains);
|
|
912
|
+
const actualOmnichainStatus = snapshot.omnichainStatus;
|
|
913
|
+
if (expectedOmnichainStatus !== actualOmnichainStatus) {
|
|
914
|
+
ctx.issues.push({
|
|
915
|
+
code: "custom",
|
|
916
|
+
input: snapshot,
|
|
917
|
+
message: `'${actualOmnichainStatus}' is an invalid omnichainStatus. Expected '${expectedOmnichainStatus}' based on the statuses of individual chains.`
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
function invariant_omnichainIndexingCursorLowerThanEarliestStartBlockAcrossQueuedChains(ctx) {
|
|
922
|
+
const snapshot = ctx.value;
|
|
923
|
+
const queuedChains = Array.from(snapshot.chains.values()).filter(
|
|
924
|
+
(chain) => chain.chainStatus === ChainIndexingStatusIds.Queued
|
|
925
|
+
);
|
|
926
|
+
if (queuedChains.length === 0) {
|
|
927
|
+
return;
|
|
928
|
+
}
|
|
929
|
+
const queuedChainStartBlocks = queuedChains.map((chain) => chain.config.startBlock.timestamp);
|
|
930
|
+
const queuedChainEarliestStartBlock = Math.min(...queuedChainStartBlocks);
|
|
931
|
+
if (snapshot.omnichainIndexingCursor >= queuedChainEarliestStartBlock) {
|
|
932
|
+
ctx.issues.push({
|
|
933
|
+
code: "custom",
|
|
934
|
+
input: snapshot,
|
|
935
|
+
message: "`omnichainIndexingCursor` must be lower than the earliest start block across all queued chains."
|
|
936
|
+
});
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
function invariant_omnichainIndexingCursorLowerThanOrEqualToLatestBackfillEndBlockAcrossBackfillChains(ctx) {
|
|
940
|
+
const snapshot = ctx.value;
|
|
941
|
+
const backfillChains = Array.from(snapshot.chains.values()).filter(
|
|
942
|
+
(chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill
|
|
943
|
+
);
|
|
944
|
+
if (backfillChains.length === 0) {
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
947
|
+
const backfillEndBlocks = backfillChains.map((chain) => chain.backfillEndBlock.timestamp);
|
|
948
|
+
const highestBackfillEndBlock = Math.max(...backfillEndBlocks);
|
|
949
|
+
if (snapshot.omnichainIndexingCursor > highestBackfillEndBlock) {
|
|
950
|
+
ctx.issues.push({
|
|
951
|
+
code: "custom",
|
|
952
|
+
input: snapshot,
|
|
953
|
+
message: "`omnichainIndexingCursor` must be lower than or equal to the highest `backfillEndBlock` across all backfill chains."
|
|
954
|
+
});
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
function invariant_omnichainIndexingCursorIsEqualToHighestLatestIndexedBlockAcrossIndexedChain(ctx) {
|
|
958
|
+
const snapshot = ctx.value;
|
|
959
|
+
const indexedChains = Array.from(snapshot.chains.values()).filter(
|
|
960
|
+
(chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill || chain.chainStatus === ChainIndexingStatusIds.Completed || chain.chainStatus === ChainIndexingStatusIds.Following
|
|
961
|
+
);
|
|
962
|
+
if (indexedChains.length === 0) {
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
const indexedChainLatestIndexedBlocks = indexedChains.map(
|
|
966
|
+
(chain) => chain.latestIndexedBlock.timestamp
|
|
967
|
+
);
|
|
968
|
+
const indexedChainHighestLatestIndexedBlock = Math.max(...indexedChainLatestIndexedBlocks);
|
|
969
|
+
if (snapshot.omnichainIndexingCursor !== indexedChainHighestLatestIndexedBlock) {
|
|
970
|
+
ctx.issues.push({
|
|
971
|
+
code: "custom",
|
|
972
|
+
input: snapshot,
|
|
973
|
+
message: "`omnichainIndexingCursor` must be same as the highest `latestIndexedBlock` across all indexed chains."
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
function invariant_omnichainSnapshotUnstartedHasValidChains(ctx) {
|
|
978
|
+
const chains = ctx.value;
|
|
979
|
+
const hasValidChains = checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted(
|
|
980
|
+
Array.from(chains.values())
|
|
981
|
+
);
|
|
982
|
+
if (hasValidChains === false) {
|
|
983
|
+
ctx.issues.push({
|
|
984
|
+
code: "custom",
|
|
985
|
+
input: chains,
|
|
986
|
+
message: `For omnichain status snapshot 'unstarted', all chains must have "queued" status.`
|
|
987
|
+
});
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
function invariant_omnichainStatusSnapshotBackfillHasValidChains(ctx) {
|
|
991
|
+
const chains = ctx.value;
|
|
992
|
+
const hasValidChains = checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill(
|
|
993
|
+
Array.from(chains.values())
|
|
994
|
+
);
|
|
995
|
+
if (hasValidChains === false) {
|
|
996
|
+
ctx.issues.push({
|
|
997
|
+
code: "custom",
|
|
998
|
+
input: chains,
|
|
999
|
+
message: `For omnichain status snapshot 'backfill', at least one chain must be in "backfill" status and each chain has to have a status of either "queued", "backfill" or "completed".`
|
|
1000
|
+
});
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
function invariant_omnichainStatusSnapshotCompletedHasValidChains(ctx) {
|
|
1004
|
+
const chains = ctx.value;
|
|
1005
|
+
const hasValidChains = checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted(
|
|
1006
|
+
Array.from(chains.values())
|
|
1007
|
+
);
|
|
1008
|
+
if (hasValidChains === false) {
|
|
1009
|
+
ctx.issues.push({
|
|
1010
|
+
code: "custom",
|
|
1011
|
+
input: chains,
|
|
1012
|
+
message: `For omnichain status snapshot 'completed', all chains must have "completed" status.`
|
|
1013
|
+
});
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
function invariant_slowestChainEqualsToOmnichainSnapshotTime(ctx) {
|
|
1017
|
+
const { slowestChainIndexingCursor, omnichainSnapshot } = ctx.value;
|
|
1018
|
+
const { omnichainIndexingCursor } = omnichainSnapshot;
|
|
1019
|
+
if (slowestChainIndexingCursor !== omnichainIndexingCursor) {
|
|
1020
|
+
console.log("invariant_slowestChainEqualsToOmnichainSnapshotTime", {
|
|
1021
|
+
slowestChainIndexingCursor,
|
|
1022
|
+
omnichainIndexingCursor
|
|
1023
|
+
});
|
|
1024
|
+
ctx.issues.push({
|
|
1025
|
+
code: "custom",
|
|
1026
|
+
input: ctx.value,
|
|
1027
|
+
message: `'slowestChainIndexingCursor' must be equal to 'omnichainSnapshot.omnichainIndexingCursor'`
|
|
1028
|
+
});
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
function invariant_snapshotTimeIsTheHighestKnownBlockTimestamp(ctx) {
|
|
1032
|
+
const { snapshotTime, omnichainSnapshot } = ctx.value;
|
|
1033
|
+
const chains = Array.from(omnichainSnapshot.chains.values());
|
|
1034
|
+
const startBlockTimestamps = chains.map((chain) => chain.config.startBlock.timestamp);
|
|
1035
|
+
const endBlockTimestamps = chains.filter((chain) => chain.config.configType === ChainIndexingConfigTypeIds.Definite).map((chain) => chain.config.endBlock.timestamp);
|
|
1036
|
+
const backfillEndBlockTimestamps = chains.filter((chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill).map((chain) => chain.backfillEndBlock.timestamp);
|
|
1037
|
+
const latestKnownBlockTimestamps = chains.filter((chain) => chain.chainStatus === ChainIndexingStatusIds.Following).map((chain) => chain.latestKnownBlock.timestamp);
|
|
1038
|
+
const highestKnownBlockTimestamp = Math.max(
|
|
1039
|
+
...startBlockTimestamps,
|
|
1040
|
+
...endBlockTimestamps,
|
|
1041
|
+
...backfillEndBlockTimestamps,
|
|
1042
|
+
...latestKnownBlockTimestamps
|
|
1043
|
+
);
|
|
1044
|
+
if (snapshotTime < highestKnownBlockTimestamp) {
|
|
1045
|
+
ctx.issues.push({
|
|
1046
|
+
code: "custom",
|
|
1047
|
+
input: ctx.value,
|
|
1048
|
+
message: `'snapshotTime' must be greater than or equal to the "highest known block timestamp" (${highestKnownBlockTimestamp})`
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
function invariant_realtimeIndexingStatusProjectionProjectedAtIsAfterOrEqualToSnapshotTime(ctx) {
|
|
1053
|
+
const projection = ctx.value;
|
|
1054
|
+
const { snapshot, projectedAt } = projection;
|
|
1055
|
+
if (snapshot.snapshotTime > projectedAt) {
|
|
1056
|
+
ctx.issues.push({
|
|
1057
|
+
code: "custom",
|
|
1058
|
+
input: projection,
|
|
1059
|
+
message: "`projectedAt` must be after or same as `snapshot.snapshotTime`."
|
|
1060
|
+
});
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
function invariant_realtimeIndexingStatusProjectionWorstCaseDistanceIsCorrect(ctx) {
|
|
1064
|
+
const projection = ctx.value;
|
|
1065
|
+
const { projectedAt, snapshot, worstCaseDistance } = projection;
|
|
1066
|
+
const { omnichainSnapshot } = snapshot;
|
|
1067
|
+
const expectedWorstCaseDistance = projectedAt - omnichainSnapshot.omnichainIndexingCursor;
|
|
1068
|
+
if (worstCaseDistance !== expectedWorstCaseDistance) {
|
|
1069
|
+
ctx.issues.push({
|
|
1070
|
+
code: "custom",
|
|
1071
|
+
input: projection,
|
|
1072
|
+
message: "`worstCaseDistance` must be the exact difference between `projectedAt` and `snapshot.omnichainIndexingCursor`."
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
|
|
726
1077
|
// src/ensindexer/indexing-status/zod-schemas.ts
|
|
727
|
-
var makeChainIndexingConfigSchema = (valueLabel = "Value") => z3.discriminatedUnion("
|
|
1078
|
+
var makeChainIndexingConfigSchema = (valueLabel = "Value") => z3.discriminatedUnion("configType", [
|
|
728
1079
|
z3.strictObject({
|
|
729
|
-
|
|
730
|
-
startBlock: makeBlockRefSchema(valueLabel)
|
|
731
|
-
endBlock: z3.null()
|
|
1080
|
+
configType: z3.literal(ChainIndexingConfigTypeIds.Indefinite),
|
|
1081
|
+
startBlock: makeBlockRefSchema(valueLabel)
|
|
732
1082
|
}),
|
|
733
1083
|
z3.strictObject({
|
|
734
|
-
|
|
1084
|
+
configType: z3.literal(ChainIndexingConfigTypeIds.Definite),
|
|
735
1085
|
startBlock: makeBlockRefSchema(valueLabel),
|
|
736
1086
|
endBlock: makeBlockRefSchema(valueLabel)
|
|
737
1087
|
})
|
|
738
1088
|
]);
|
|
739
|
-
var
|
|
740
|
-
|
|
1089
|
+
var makeChainIndexingStatusSnapshotQueuedSchema = (valueLabel = "Value") => z3.strictObject({
|
|
1090
|
+
chainStatus: z3.literal(ChainIndexingStatusIds.Queued),
|
|
741
1091
|
config: makeChainIndexingConfigSchema(valueLabel)
|
|
742
|
-
}).
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
error: `config.startBlock must be before or same as config.endBlock.`
|
|
746
|
-
}
|
|
747
|
-
);
|
|
748
|
-
var makeChainIndexingBackfillStatusSchema = (valueLabel = "Value") => z3.strictObject({
|
|
749
|
-
status: z3.literal(ChainIndexingStatusIds.Backfill),
|
|
1092
|
+
}).check(invariant_chainSnapshotQueuedBlocks);
|
|
1093
|
+
var makeChainIndexingStatusSnapshotBackfillSchema = (valueLabel = "Value") => z3.strictObject({
|
|
1094
|
+
chainStatus: z3.literal(ChainIndexingStatusIds.Backfill),
|
|
750
1095
|
config: makeChainIndexingConfigSchema(valueLabel),
|
|
751
1096
|
latestIndexedBlock: makeBlockRefSchema(valueLabel),
|
|
752
|
-
latestSyncedBlock: makeBlockRefSchema(valueLabel),
|
|
753
1097
|
backfillEndBlock: makeBlockRefSchema(valueLabel)
|
|
754
|
-
}).
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
error: `config.startBlock must be before or same as latestIndexedBlock.`
|
|
758
|
-
}
|
|
759
|
-
).refine(
|
|
760
|
-
({ latestIndexedBlock, latestSyncedBlock }) => isBeforeOrEqualTo(latestIndexedBlock, latestSyncedBlock),
|
|
761
|
-
{
|
|
762
|
-
error: `latestIndexedBlock must be before or same as latestSyncedBlock.`
|
|
763
|
-
}
|
|
764
|
-
).refine(
|
|
765
|
-
({ latestSyncedBlock, backfillEndBlock }) => isBeforeOrEqualTo(latestSyncedBlock, backfillEndBlock),
|
|
766
|
-
{
|
|
767
|
-
error: `latestSyncedBlock must be before or same as backfillEndBlock.`
|
|
768
|
-
}
|
|
769
|
-
).refine(
|
|
770
|
-
({ config, backfillEndBlock }) => config.endBlock === null || isEqualTo(backfillEndBlock, config.endBlock),
|
|
771
|
-
{
|
|
772
|
-
error: `backfillEndBlock must be the same as config.endBlock.`
|
|
773
|
-
}
|
|
774
|
-
);
|
|
775
|
-
var makeChainIndexingFollowingStatusSchema = (valueLabel = "Value") => z3.strictObject({
|
|
776
|
-
status: z3.literal(ChainIndexingStatusIds.Following),
|
|
1098
|
+
}).check(invariant_chainSnapshotBackfillBlocks);
|
|
1099
|
+
var makeChainIndexingStatusSnapshotCompletedSchema = (valueLabel = "Value") => z3.strictObject({
|
|
1100
|
+
chainStatus: z3.literal(ChainIndexingStatusIds.Completed),
|
|
777
1101
|
config: z3.strictObject({
|
|
778
|
-
|
|
779
|
-
startBlock: makeBlockRefSchema(valueLabel)
|
|
780
|
-
}),
|
|
781
|
-
latestIndexedBlock: makeBlockRefSchema(valueLabel),
|
|
782
|
-
latestKnownBlock: makeBlockRefSchema(valueLabel),
|
|
783
|
-
approxRealtimeDistance: makeDurationSchema(valueLabel)
|
|
784
|
-
}).refine(
|
|
785
|
-
({ config, latestIndexedBlock }) => isBeforeOrEqualTo(config.startBlock, latestIndexedBlock),
|
|
786
|
-
{
|
|
787
|
-
error: `config.startBlock must be before or same as latestIndexedBlock.`
|
|
788
|
-
}
|
|
789
|
-
).refine(
|
|
790
|
-
({ latestIndexedBlock, latestKnownBlock }) => isBeforeOrEqualTo(latestIndexedBlock, latestKnownBlock),
|
|
791
|
-
{
|
|
792
|
-
error: `latestIndexedBlock must be before or same as latestKnownBlock.`
|
|
793
|
-
}
|
|
794
|
-
);
|
|
795
|
-
var makeChainIndexingCompletedStatusSchema = (valueLabel = "Value") => z3.strictObject({
|
|
796
|
-
status: z3.literal(ChainIndexingStatusIds.Completed),
|
|
797
|
-
config: z3.strictObject({
|
|
798
|
-
strategy: z3.literal(ChainIndexingStrategyIds.Definite),
|
|
1102
|
+
configType: z3.literal(ChainIndexingConfigTypeIds.Definite),
|
|
799
1103
|
startBlock: makeBlockRefSchema(valueLabel),
|
|
800
1104
|
endBlock: makeBlockRefSchema(valueLabel)
|
|
801
1105
|
}),
|
|
802
1106
|
latestIndexedBlock: makeBlockRefSchema(valueLabel)
|
|
803
|
-
}).
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
)
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
)
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
makeChainIndexingCompletedStatusSchema(valueLabel)
|
|
1107
|
+
}).check(invariant_chainSnapshotCompletedBlocks);
|
|
1108
|
+
var makeChainIndexingStatusSnapshotFollowingSchema = (valueLabel = "Value") => z3.strictObject({
|
|
1109
|
+
chainStatus: z3.literal(ChainIndexingStatusIds.Following),
|
|
1110
|
+
config: z3.strictObject({
|
|
1111
|
+
configType: z3.literal(ChainIndexingConfigTypeIds.Indefinite),
|
|
1112
|
+
startBlock: makeBlockRefSchema(valueLabel)
|
|
1113
|
+
}),
|
|
1114
|
+
latestIndexedBlock: makeBlockRefSchema(valueLabel),
|
|
1115
|
+
latestKnownBlock: makeBlockRefSchema(valueLabel)
|
|
1116
|
+
}).check(invariant_chainSnapshotFollowingBlocks);
|
|
1117
|
+
var makeChainIndexingStatusSnapshotSchema = (valueLabel = "Value") => z3.discriminatedUnion("chainStatus", [
|
|
1118
|
+
makeChainIndexingStatusSnapshotQueuedSchema(valueLabel),
|
|
1119
|
+
makeChainIndexingStatusSnapshotBackfillSchema(valueLabel),
|
|
1120
|
+
makeChainIndexingStatusSnapshotCompletedSchema(valueLabel),
|
|
1121
|
+
makeChainIndexingStatusSnapshotFollowingSchema(valueLabel)
|
|
819
1122
|
]);
|
|
820
|
-
var makeChainIndexingStatusesSchema = (valueLabel = "Value") => z3.record(makeChainIdStringSchema(),
|
|
821
|
-
error: "Chains
|
|
1123
|
+
var makeChainIndexingStatusesSchema = (valueLabel = "Value") => z3.record(makeChainIdStringSchema(), makeChainIndexingStatusSnapshotSchema(valueLabel), {
|
|
1124
|
+
error: "Chains indexing statuses must be an object mapping valid chain IDs to their indexing status snapshots."
|
|
822
1125
|
}).transform((serializedChainsIndexingStatus) => {
|
|
823
1126
|
const chainsIndexingStatus = /* @__PURE__ */ new Map();
|
|
824
1127
|
for (const [chainIdString, chainStatus] of Object.entries(serializedChainsIndexingStatus)) {
|
|
@@ -826,164 +1129,164 @@ var makeChainIndexingStatusesSchema = (valueLabel = "Value") => z3.record(makeCh
|
|
|
826
1129
|
}
|
|
827
1130
|
return chainsIndexingStatus;
|
|
828
1131
|
});
|
|
829
|
-
var
|
|
830
|
-
|
|
831
|
-
chains: makeChainIndexingStatusesSchema(valueLabel).
|
|
832
|
-
(chains) => checkChainIndexingStatusesForUnstartedOverallStatus(Array.from(chains.values())),
|
|
833
|
-
{
|
|
834
|
-
error: `${valueLabel} at least one chain must be in "unstarted" status and
|
|
835
|
-
each chain has to have a status of either "unstarted", or "completed"`
|
|
836
|
-
}
|
|
837
|
-
).transform((chains) => chains)
|
|
838
|
-
}).refine(
|
|
839
|
-
(indexingStatus) => {
|
|
840
|
-
const chains = Array.from(indexingStatus.chains.values());
|
|
841
|
-
return getOverallIndexingStatus(chains) === indexingStatus.overallStatus;
|
|
842
|
-
},
|
|
843
|
-
{ error: `${valueLabel} is an invalid overallStatus.` }
|
|
844
|
-
);
|
|
845
|
-
var makeBackfillOverallStatusSchema = (valueLabel) => z3.strictObject({
|
|
846
|
-
overallStatus: z3.literal(OverallIndexingStatusIds.Backfill),
|
|
847
|
-
chains: makeChainIndexingStatusesSchema(valueLabel).refine(
|
|
848
|
-
(chains) => checkChainIndexingStatusesForBackfillOverallStatus(Array.from(chains.values())),
|
|
849
|
-
{
|
|
850
|
-
error: `${valueLabel} at least one chain must be in "backfill" status and
|
|
851
|
-
each chain has to have a status of either "unstarted", "backfill" or "completed"`
|
|
852
|
-
}
|
|
853
|
-
).transform((chains) => chains),
|
|
1132
|
+
var makeOmnichainIndexingStatusSnapshotUnstartedSchema = (valueLabel) => z3.strictObject({
|
|
1133
|
+
omnichainStatus: z3.literal(OmnichainIndexingStatusIds.Unstarted),
|
|
1134
|
+
chains: makeChainIndexingStatusesSchema(valueLabel).check(invariant_omnichainSnapshotUnstartedHasValidChains).transform((chains) => chains),
|
|
854
1135
|
omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
|
|
855
|
-
})
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
)
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
{
|
|
871
|
-
error: "omnichainIndexingCursor must be lower than or equal to the earliest config.startBlock across all standby chains"
|
|
872
|
-
}
|
|
873
|
-
);
|
|
874
|
-
var makeCompletedOverallStatusSchema = (valueLabel) => z3.strictObject({
|
|
875
|
-
overallStatus: z3.literal(OverallIndexingStatusIds.Completed),
|
|
876
|
-
chains: makeChainIndexingStatusesSchema(valueLabel).refine(
|
|
877
|
-
(chains) => checkChainIndexingStatusesForCompletedOverallStatus(Array.from(chains.values())),
|
|
878
|
-
{
|
|
879
|
-
error: `${valueLabel} all chains must have "completed" status`
|
|
880
|
-
}
|
|
881
|
-
).transform((chains) => chains)
|
|
882
|
-
}).refine(
|
|
883
|
-
(indexingStatus) => {
|
|
884
|
-
const chains = Array.from(indexingStatus.chains.values());
|
|
885
|
-
return getOverallIndexingStatus(chains) === indexingStatus.overallStatus;
|
|
886
|
-
},
|
|
887
|
-
{ error: `${valueLabel} is an invalid overallStatus.` }
|
|
888
|
-
);
|
|
889
|
-
var makeFollowingOverallStatusSchema = (valueLabel) => z3.strictObject({
|
|
890
|
-
overallStatus: z3.literal(OverallIndexingStatusIds.Following),
|
|
1136
|
+
});
|
|
1137
|
+
var makeOmnichainIndexingStatusSnapshotBackfillSchema = (valueLabel) => z3.strictObject({
|
|
1138
|
+
omnichainStatus: z3.literal(OmnichainIndexingStatusIds.Backfill),
|
|
1139
|
+
chains: makeChainIndexingStatusesSchema(valueLabel).check(invariant_omnichainStatusSnapshotBackfillHasValidChains).transform(
|
|
1140
|
+
(chains) => chains
|
|
1141
|
+
),
|
|
1142
|
+
omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
|
|
1143
|
+
});
|
|
1144
|
+
var makeOmnichainIndexingStatusSnapshotCompletedSchema = (valueLabel) => z3.strictObject({
|
|
1145
|
+
omnichainStatus: z3.literal(OmnichainIndexingStatusIds.Completed),
|
|
1146
|
+
chains: makeChainIndexingStatusesSchema(valueLabel).check(invariant_omnichainStatusSnapshotCompletedHasValidChains).transform((chains) => chains),
|
|
1147
|
+
omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
|
|
1148
|
+
});
|
|
1149
|
+
var makeOmnichainIndexingStatusSnapshotFollowingSchema = (valueLabel) => z3.strictObject({
|
|
1150
|
+
omnichainStatus: z3.literal(OmnichainIndexingStatusIds.Following),
|
|
891
1151
|
chains: makeChainIndexingStatusesSchema(valueLabel),
|
|
892
|
-
overallApproxRealtimeDistance: makeDurationSchema(valueLabel),
|
|
893
1152
|
omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
|
|
894
|
-
}).refine(
|
|
895
|
-
(indexingStatus) => {
|
|
896
|
-
const chains = Array.from(indexingStatus.chains.values());
|
|
897
|
-
return getOverallIndexingStatus(chains) === indexingStatus.overallStatus;
|
|
898
|
-
},
|
|
899
|
-
{ error: `${valueLabel} is an invalid overallStatus.` }
|
|
900
|
-
).refine(
|
|
901
|
-
(indexingStatus) => checkChainIndexingStatusesForFollowingOverallStatus(
|
|
902
|
-
Array.from(indexingStatus.chains.values())
|
|
903
|
-
),
|
|
904
|
-
{
|
|
905
|
-
error: `${valueLabel} at least one chain must be in "following" status`
|
|
906
|
-
}
|
|
907
|
-
).refine(
|
|
908
|
-
(indexingStatus) => {
|
|
909
|
-
const chains = Array.from(indexingStatus.chains.values());
|
|
910
|
-
return getOverallApproxRealtimeDistance(chains) === indexingStatus.overallApproxRealtimeDistance;
|
|
911
|
-
},
|
|
912
|
-
{ error: `${valueLabel} is an invalid overallApproxRealtimeDistance.` }
|
|
913
|
-
).refine(
|
|
914
|
-
(indexingStatus) => {
|
|
915
|
-
const chains = Array.from(indexingStatus.chains.values());
|
|
916
|
-
const standbyChainStartBlocks = getStandbyChains(chains).map(
|
|
917
|
-
(chain) => chain.config.startBlock.timestamp
|
|
918
|
-
);
|
|
919
|
-
const standbyChainEarliestStartBlocks = Math.min(...standbyChainStartBlocks);
|
|
920
|
-
return indexingStatus.omnichainIndexingCursor <= standbyChainEarliestStartBlocks;
|
|
921
|
-
},
|
|
922
|
-
{
|
|
923
|
-
error: "omnichainIndexingCursor must be lower than or equal to the earliest config.startBlock across all standby chains"
|
|
924
|
-
}
|
|
925
|
-
);
|
|
926
|
-
var makeErrorSchemaOverallStatusSchema = (valueLabel) => z3.strictObject({
|
|
927
|
-
overallStatus: z3.literal(OverallIndexingStatusIds.IndexerError)
|
|
928
1153
|
});
|
|
929
|
-
var
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
1154
|
+
var makeOmnichainIndexingStatusSnapshotSchema = (valueLabel = "Omnichain Indexing Snapshot") => z3.discriminatedUnion("omnichainStatus", [
|
|
1155
|
+
makeOmnichainIndexingStatusSnapshotUnstartedSchema(valueLabel),
|
|
1156
|
+
makeOmnichainIndexingStatusSnapshotBackfillSchema(valueLabel),
|
|
1157
|
+
makeOmnichainIndexingStatusSnapshotCompletedSchema(valueLabel),
|
|
1158
|
+
makeOmnichainIndexingStatusSnapshotFollowingSchema(valueLabel)
|
|
1159
|
+
]).check(invariant_omnichainSnapshotStatusIsConsistentWithChainSnapshot).check(invariant_omnichainIndexingCursorLowerThanEarliestStartBlockAcrossQueuedChains).check(
|
|
1160
|
+
invariant_omnichainIndexingCursorLowerThanOrEqualToLatestBackfillEndBlockAcrossBackfillChains
|
|
1161
|
+
).check(invariant_omnichainIndexingCursorIsEqualToHighestLatestIndexedBlockAcrossIndexedChain);
|
|
1162
|
+
var makeCrossChainIndexingStatusSnapshotOmnichainSchema = (valueLabel = "Cross-chain Indexing Status Snapshot Omnichain") => z3.strictObject({
|
|
1163
|
+
strategy: z3.literal(CrossChainIndexingStrategyIds.Omnichain),
|
|
1164
|
+
slowestChainIndexingCursor: makeUnixTimestampSchema(valueLabel),
|
|
1165
|
+
snapshotTime: makeUnixTimestampSchema(valueLabel),
|
|
1166
|
+
omnichainSnapshot: makeOmnichainIndexingStatusSnapshotSchema(valueLabel)
|
|
1167
|
+
}).check(invariant_slowestChainEqualsToOmnichainSnapshotTime).check(invariant_snapshotTimeIsTheHighestKnownBlockTimestamp);
|
|
1168
|
+
var makeCrossChainIndexingStatusSnapshotSchema = (valueLabel = "Cross-chain Indexing Status Snapshot") => z3.discriminatedUnion("strategy", [
|
|
1169
|
+
makeCrossChainIndexingStatusSnapshotOmnichainSchema(valueLabel)
|
|
935
1170
|
]);
|
|
1171
|
+
var makeRealtimeIndexingStatusProjectionSchema = (valueLabel = "Realtime Indexing Status Projection") => z3.strictObject({
|
|
1172
|
+
projectedAt: makeUnixTimestampSchema(valueLabel),
|
|
1173
|
+
worstCaseDistance: makeDurationSchema(valueLabel),
|
|
1174
|
+
snapshot: makeCrossChainIndexingStatusSnapshotSchema(valueLabel)
|
|
1175
|
+
}).check(invariant_realtimeIndexingStatusProjectionProjectedAtIsAfterOrEqualToSnapshotTime).check(invariant_realtimeIndexingStatusProjectionWorstCaseDistanceIsCorrect);
|
|
936
1176
|
|
|
937
1177
|
// src/ensindexer/indexing-status/deserialize.ts
|
|
938
|
-
function
|
|
939
|
-
const schema =
|
|
940
|
-
const parsed = schema.safeParse(
|
|
1178
|
+
function deserializeChainIndexingStatusSnapshot(maybeSnapshot, valueLabel) {
|
|
1179
|
+
const schema = makeChainIndexingStatusSnapshotSchema(valueLabel);
|
|
1180
|
+
const parsed = schema.safeParse(maybeSnapshot);
|
|
1181
|
+
if (parsed.error) {
|
|
1182
|
+
throw new Error(
|
|
1183
|
+
`Cannot deserialize into ChainIndexingStatusSnapshot:
|
|
1184
|
+
${prettifyError3(parsed.error)}
|
|
1185
|
+
`
|
|
1186
|
+
);
|
|
1187
|
+
}
|
|
1188
|
+
return parsed.data;
|
|
1189
|
+
}
|
|
1190
|
+
function deserializeOmnichainIndexingStatusSnapshot(maybeSnapshot, valueLabel) {
|
|
1191
|
+
const schema = makeOmnichainIndexingStatusSnapshotSchema(valueLabel);
|
|
1192
|
+
const parsed = schema.safeParse(maybeSnapshot);
|
|
941
1193
|
if (parsed.error) {
|
|
942
1194
|
throw new Error(
|
|
943
|
-
`Cannot deserialize
|
|
1195
|
+
`Cannot deserialize into OmnichainIndexingStatusSnapshot:
|
|
944
1196
|
${prettifyError3(parsed.error)}
|
|
945
1197
|
`
|
|
946
1198
|
);
|
|
947
1199
|
}
|
|
948
1200
|
return parsed.data;
|
|
949
1201
|
}
|
|
1202
|
+
function deserializeCrossChainIndexingStatusSnapshot(maybeSnapshot, valueLabel) {
|
|
1203
|
+
const schema = makeCrossChainIndexingStatusSnapshotSchema(valueLabel);
|
|
1204
|
+
const parsed = schema.safeParse(maybeSnapshot);
|
|
1205
|
+
if (parsed.error) {
|
|
1206
|
+
throw new Error(
|
|
1207
|
+
`Cannot deserialize into CrossChainIndexingStatusSnapshot:
|
|
1208
|
+
${prettifyError3(parsed.error)}
|
|
1209
|
+
`
|
|
1210
|
+
);
|
|
1211
|
+
}
|
|
1212
|
+
return parsed.data;
|
|
1213
|
+
}
|
|
1214
|
+
function deserializeRealtimeIndexingStatusProjection(maybeProjection, valueLabel) {
|
|
1215
|
+
const schema = makeRealtimeIndexingStatusProjectionSchema(valueLabel);
|
|
1216
|
+
const parsed = schema.safeParse(maybeProjection);
|
|
1217
|
+
if (parsed.error) {
|
|
1218
|
+
throw new Error(
|
|
1219
|
+
`Cannot deserialize into RealtimeIndexingStatusProjection:
|
|
1220
|
+
${prettifyError3(parsed.error)}
|
|
1221
|
+
`
|
|
1222
|
+
);
|
|
1223
|
+
}
|
|
1224
|
+
return parsed.data;
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
// src/ensindexer/indexing-status/projection.ts
|
|
1228
|
+
function createRealtimeIndexingStatusProjection(snapshot, now) {
|
|
1229
|
+
const projectedAt = Math.max(now, snapshot.snapshotTime);
|
|
1230
|
+
return {
|
|
1231
|
+
projectedAt,
|
|
1232
|
+
worstCaseDistance: projectedAt - snapshot.slowestChainIndexingCursor,
|
|
1233
|
+
snapshot
|
|
1234
|
+
};
|
|
1235
|
+
}
|
|
950
1236
|
|
|
951
1237
|
// src/ensindexer/indexing-status/serialize.ts
|
|
952
|
-
function
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
1238
|
+
function serializeCrossChainIndexingStatusSnapshotOmnichain({
|
|
1239
|
+
strategy,
|
|
1240
|
+
slowestChainIndexingCursor,
|
|
1241
|
+
snapshotTime,
|
|
1242
|
+
omnichainSnapshot
|
|
1243
|
+
}) {
|
|
1244
|
+
return {
|
|
1245
|
+
strategy,
|
|
1246
|
+
slowestChainIndexingCursor,
|
|
1247
|
+
snapshotTime,
|
|
1248
|
+
omnichainSnapshot: serializeOmnichainIndexingStatusSnapshot(omnichainSnapshot)
|
|
1249
|
+
};
|
|
1250
|
+
}
|
|
1251
|
+
function serializeRealtimeIndexingStatusProjection(indexingProjection) {
|
|
1252
|
+
return {
|
|
1253
|
+
projectedAt: indexingProjection.projectedAt,
|
|
1254
|
+
worstCaseDistance: indexingProjection.worstCaseDistance,
|
|
1255
|
+
snapshot: serializeCrossChainIndexingStatusSnapshotOmnichain(indexingProjection.snapshot)
|
|
1256
|
+
};
|
|
1257
|
+
}
|
|
1258
|
+
function serializeChainIndexingSnapshots(chains) {
|
|
1259
|
+
const serializedSnapshots = {};
|
|
1260
|
+
for (const [chainId, snapshot] of chains.entries()) {
|
|
1261
|
+
serializedSnapshots[serializeChainId(chainId)] = snapshot;
|
|
956
1262
|
}
|
|
957
|
-
return
|
|
1263
|
+
return serializedSnapshots;
|
|
958
1264
|
}
|
|
959
|
-
function
|
|
960
|
-
switch (indexingStatus.
|
|
961
|
-
case
|
|
1265
|
+
function serializeOmnichainIndexingStatusSnapshot(indexingStatus) {
|
|
1266
|
+
switch (indexingStatus.omnichainStatus) {
|
|
1267
|
+
case OmnichainIndexingStatusIds.Unstarted:
|
|
962
1268
|
return {
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
return {
|
|
967
|
-
overallStatus: OverallIndexingStatusIds.Unstarted,
|
|
968
|
-
chains: serializeChainIndexingStatuses(indexingStatus.chains)
|
|
1269
|
+
omnichainStatus: OmnichainIndexingStatusIds.Unstarted,
|
|
1270
|
+
chains: serializeChainIndexingSnapshots(indexingStatus.chains),
|
|
1271
|
+
omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
|
|
969
1272
|
};
|
|
970
|
-
case
|
|
1273
|
+
case OmnichainIndexingStatusIds.Backfill:
|
|
971
1274
|
return {
|
|
972
|
-
|
|
973
|
-
chains:
|
|
1275
|
+
omnichainStatus: OmnichainIndexingStatusIds.Backfill,
|
|
1276
|
+
chains: serializeChainIndexingSnapshots(indexingStatus.chains),
|
|
974
1277
|
omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
|
|
975
1278
|
};
|
|
976
|
-
case
|
|
1279
|
+
case OmnichainIndexingStatusIds.Completed: {
|
|
977
1280
|
return {
|
|
978
|
-
|
|
979
|
-
chains:
|
|
1281
|
+
omnichainStatus: OmnichainIndexingStatusIds.Completed,
|
|
1282
|
+
chains: serializeChainIndexingSnapshots(indexingStatus.chains),
|
|
1283
|
+
omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
|
|
980
1284
|
};
|
|
981
1285
|
}
|
|
982
|
-
case
|
|
1286
|
+
case OmnichainIndexingStatusIds.Following:
|
|
983
1287
|
return {
|
|
984
|
-
|
|
985
|
-
chains:
|
|
986
|
-
overallApproxRealtimeDistance: indexingStatus.overallApproxRealtimeDistance,
|
|
1288
|
+
omnichainStatus: OmnichainIndexingStatusIds.Following,
|
|
1289
|
+
chains: serializeChainIndexingSnapshots(indexingStatus.chains),
|
|
987
1290
|
omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
|
|
988
1291
|
};
|
|
989
1292
|
}
|
|
@@ -1019,17 +1322,42 @@ var ATTR_PROTOCOL_NAME = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol`;
|
|
|
1019
1322
|
var ATTR_PROTOCOL_STEP = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol.step`;
|
|
1020
1323
|
var ATTR_PROTOCOL_STEP_RESULT = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol.step.result`;
|
|
1021
1324
|
|
|
1022
|
-
// src/api/
|
|
1325
|
+
// src/api/deserialize.ts
|
|
1023
1326
|
import { prettifyError as prettifyError4 } from "zod/v4";
|
|
1024
1327
|
|
|
1025
1328
|
// src/api/zod-schemas.ts
|
|
1026
1329
|
import z4 from "zod/v4";
|
|
1330
|
+
|
|
1331
|
+
// src/api/types.ts
|
|
1332
|
+
var IndexingStatusResponseCodes = {
|
|
1333
|
+
/**
|
|
1334
|
+
* Represents that the indexing status is available.
|
|
1335
|
+
*/
|
|
1336
|
+
Ok: "ok",
|
|
1337
|
+
/**
|
|
1338
|
+
* Represents that the indexing status is unavailable.
|
|
1339
|
+
*/
|
|
1340
|
+
Error: "error"
|
|
1341
|
+
};
|
|
1342
|
+
|
|
1343
|
+
// src/api/zod-schemas.ts
|
|
1027
1344
|
var ErrorResponseSchema = z4.object({
|
|
1028
1345
|
message: z4.string(),
|
|
1029
1346
|
details: z4.optional(z4.unknown())
|
|
1030
1347
|
});
|
|
1348
|
+
var makeIndexingStatusResponseOkSchema = (valueLabel = "Indexing Status Response OK") => z4.strictObject({
|
|
1349
|
+
responseCode: z4.literal(IndexingStatusResponseCodes.Ok),
|
|
1350
|
+
realtimeProjection: makeRealtimeIndexingStatusProjectionSchema(valueLabel)
|
|
1351
|
+
});
|
|
1352
|
+
var makeIndexingStatusResponseErrorSchema = (valueLabel = "Indexing Status Response Error") => z4.strictObject({
|
|
1353
|
+
responseCode: z4.literal(IndexingStatusResponseCodes.Error)
|
|
1354
|
+
});
|
|
1355
|
+
var makeIndexingStatusResponseSchema = (valueLabel = "Indexing Status Response") => z4.discriminatedUnion("responseCode", [
|
|
1356
|
+
makeIndexingStatusResponseOkSchema(valueLabel),
|
|
1357
|
+
makeIndexingStatusResponseErrorSchema(valueLabel)
|
|
1358
|
+
]);
|
|
1031
1359
|
|
|
1032
|
-
// src/api/
|
|
1360
|
+
// src/api/deserialize.ts
|
|
1033
1361
|
function deserializeErrorResponse(maybeErrorResponse) {
|
|
1034
1362
|
const parsed = ErrorResponseSchema.safeParse(maybeErrorResponse);
|
|
1035
1363
|
if (parsed.error) {
|
|
@@ -1039,12 +1367,28 @@ ${prettifyError4(parsed.error)}
|
|
|
1039
1367
|
}
|
|
1040
1368
|
return parsed.data;
|
|
1041
1369
|
}
|
|
1370
|
+
function deserializeIndexingStatusResponse(maybeResponse) {
|
|
1371
|
+
const parsed = makeIndexingStatusResponseSchema().safeParse(maybeResponse);
|
|
1372
|
+
if (parsed.error) {
|
|
1373
|
+
throw new Error(`Cannot deserialize IndexingStatusResponse:
|
|
1374
|
+
${prettifyError4(parsed.error)}
|
|
1375
|
+
`);
|
|
1376
|
+
}
|
|
1377
|
+
return parsed.data;
|
|
1378
|
+
}
|
|
1042
1379
|
|
|
1043
|
-
// src/api/
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1380
|
+
// src/api/serialize.ts
|
|
1381
|
+
function serializeIndexingStatusResponse(response) {
|
|
1382
|
+
switch (response.responseCode) {
|
|
1383
|
+
case IndexingStatusResponseCodes.Ok:
|
|
1384
|
+
return {
|
|
1385
|
+
responseCode: response.responseCode,
|
|
1386
|
+
realtimeProjection: serializeRealtimeIndexingStatusProjection(response.realtimeProjection)
|
|
1387
|
+
};
|
|
1388
|
+
case IndexingStatusResponseCodes.Error:
|
|
1389
|
+
return response;
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1048
1392
|
|
|
1049
1393
|
// src/client-error.ts
|
|
1050
1394
|
var ClientError = class _ClientError extends Error {
|
|
@@ -1082,6 +1426,9 @@ var ENSNodeClient = class _ENSNodeClient {
|
|
|
1082
1426
|
/**
|
|
1083
1427
|
* Resolves records for an ENS name (Forward Resolution).
|
|
1084
1428
|
*
|
|
1429
|
+
* The returned `name` field, if set, is guaranteed to be a [Normalized Name](https://ensnode.io/docs/reference/terminology#normalized-name).
|
|
1430
|
+
* If the name record returned by the resolver is not normalized, `null` is returned as if no name record was set.
|
|
1431
|
+
*
|
|
1085
1432
|
* @param name The ENS Name whose records to resolve
|
|
1086
1433
|
* @param selection selection of Resolver records
|
|
1087
1434
|
* @param options additional options
|
|
@@ -1133,9 +1480,13 @@ var ENSNodeClient = class _ENSNodeClient {
|
|
|
1133
1480
|
/**
|
|
1134
1481
|
* Resolves the primary name of a specified address (Reverse Resolution) on a specific chain.
|
|
1135
1482
|
*
|
|
1136
|
-
* If the `address` specifies a valid
|
|
1137
|
-
*
|
|
1138
|
-
*
|
|
1483
|
+
* If the chainId-specific Primary Name is not defined, but the `address` specifies a valid
|
|
1484
|
+
* [ENSIP-19 Default Name](https://docs.ens.domains/ensip/19/#default-primary-name), the Default
|
|
1485
|
+
* Name will be returned. You _may_ query the Default EVM Chain Id (`0`) in order to determine the
|
|
1486
|
+
* `address`'s Default Name directly.
|
|
1487
|
+
*
|
|
1488
|
+
* The returned Primary Name, if set, is guaranteed to be a [Normalized Name](https://ensnode.io/docs/reference/terminology#normalized-name).
|
|
1489
|
+
* If the primary name set for the address is not normalized, `null` is returned as if no primary name was set.
|
|
1139
1490
|
*
|
|
1140
1491
|
* @param address The Address whose Primary Name to resolve
|
|
1141
1492
|
* @param chainId The chain id within which to query the address' ENSIP-19 Multichain Primary Name
|
|
@@ -1175,10 +1526,14 @@ var ENSNodeClient = class _ENSNodeClient {
|
|
|
1175
1526
|
/**
|
|
1176
1527
|
* Resolves the primary names of a specified address across multiple chains.
|
|
1177
1528
|
*
|
|
1178
|
-
*
|
|
1179
|
-
*
|
|
1180
|
-
*
|
|
1181
|
-
* should rely on the aforementioned per-chain defaulting behavior.
|
|
1529
|
+
* For each Primary Name, if the chainId-specific Primary Name is not defined, but the `address`
|
|
1530
|
+
* specifies a valid [ENSIP-19 Default Name](https://docs.ens.domains/ensip/19/#default-primary-name),
|
|
1531
|
+
* the Default Name will be returned. You _may not_ query the Default EVM Chain Id (`0`) directly,
|
|
1532
|
+
* and should rely on the aforementioned per-chain defaulting behavior.
|
|
1533
|
+
*
|
|
1534
|
+
* Each returned Primary Name, if set, is guaranteed to be a [Normalized Name](https://ensnode.io/docs/reference/terminology#normalized-name).
|
|
1535
|
+
* If the primary name set for the address on any chain is not normalized, `null` is returned for
|
|
1536
|
+
* that chain as if no primary name was set.
|
|
1182
1537
|
*
|
|
1183
1538
|
* @param address The Address whose Primary Names to resolve
|
|
1184
1539
|
* @param options additional options
|
|
@@ -1196,12 +1551,12 @@ var ENSNodeClient = class _ENSNodeClient {
|
|
|
1196
1551
|
*
|
|
1197
1552
|
* console.log(names);
|
|
1198
1553
|
* // {
|
|
1199
|
-
* // "1": "gregskril.eth",
|
|
1200
|
-
* // "10": "gregskril.eth",
|
|
1201
|
-
* // "8453": "greg.base.eth", //
|
|
1202
|
-
* // "42161": "gregskril.eth",
|
|
1203
|
-
* // "59144": "gregskril.eth",
|
|
1204
|
-
* // "534352": "gregskril.eth"
|
|
1554
|
+
* // "1": "gregskril.eth", // Default Primary Name
|
|
1555
|
+
* // "10": "gregskril.eth", // Default Primary Name
|
|
1556
|
+
* // "8453": "greg.base.eth", // Base-specific Primary Name!
|
|
1557
|
+
* // "42161": "gregskril.eth", // Default Primary Name
|
|
1558
|
+
* // "59144": "gregskril.eth", // Default Primary Name
|
|
1559
|
+
* // "534352": "gregskril.eth" // Default Primary Name
|
|
1205
1560
|
* // }
|
|
1206
1561
|
*
|
|
1207
1562
|
* // Resolve the address' Primary Names on specific chain Ids
|
|
@@ -1256,28 +1611,14 @@ var ENSNodeClient = class _ENSNodeClient {
|
|
|
1256
1611
|
/**
|
|
1257
1612
|
* Fetch ENSNode Indexing Status
|
|
1258
1613
|
*
|
|
1259
|
-
* Fetch the ENSNode's multichain indexing status.
|
|
1260
|
-
*
|
|
1261
|
-
* @param options additional options
|
|
1262
|
-
* @param options.maxRealtimeDistance the max allowed distance between the
|
|
1263
|
-
* latest indexed block of each chain and the "tip" of all indexed chains.
|
|
1264
|
-
* Setting this parameter influences the HTTP response code as follows:
|
|
1265
|
-
* - Success (200 OK): The latest indexed block of each chain is within the
|
|
1266
|
-
* requested distance from realtime.
|
|
1267
|
-
* - Service Unavailable (503): The latest indexed block of each chain is NOT
|
|
1268
|
-
* within the requested distance from realtime.
|
|
1269
|
-
*
|
|
1270
1614
|
* @returns {IndexingStatusResponse}
|
|
1271
1615
|
*
|
|
1272
1616
|
* @throws if the ENSNode request fails
|
|
1273
1617
|
* @throws if the ENSNode API returns an error response
|
|
1274
1618
|
* @throws if the ENSNode response breaks required invariants
|
|
1275
1619
|
*/
|
|
1276
|
-
async indexingStatus(
|
|
1620
|
+
async indexingStatus() {
|
|
1277
1621
|
const url = new URL(`/api/indexing-status`, this.options.url);
|
|
1278
|
-
if (typeof options?.maxRealtimeDistance !== "undefined") {
|
|
1279
|
-
url.searchParams.set("maxRealtimeDistance", `${options.maxRealtimeDistance}`);
|
|
1280
|
-
}
|
|
1281
1622
|
const response = await fetch(url);
|
|
1282
1623
|
let responseData;
|
|
1283
1624
|
try {
|
|
@@ -1286,40 +1627,48 @@ var ENSNodeClient = class _ENSNodeClient {
|
|
|
1286
1627
|
throw new Error("Malformed response data: invalid JSON");
|
|
1287
1628
|
}
|
|
1288
1629
|
if (!response.ok) {
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
console.error(
|
|
1298
|
-
"Indexing Status API: Requested realtime indexing distance not achieved error"
|
|
1299
|
-
);
|
|
1300
|
-
return deserializeENSIndexerIndexingStatus(
|
|
1301
|
-
responseData
|
|
1302
|
-
);
|
|
1303
|
-
}
|
|
1304
|
-
default: {
|
|
1305
|
-
const errorResponse = deserializeErrorResponse(responseData);
|
|
1306
|
-
throw new Error(`Fetching ENSNode Indexing Status Failed: ${errorResponse.message}`);
|
|
1307
|
-
}
|
|
1630
|
+
let errorResponse;
|
|
1631
|
+
try {
|
|
1632
|
+
errorResponse = deserializeErrorResponse(responseData);
|
|
1633
|
+
} catch {
|
|
1634
|
+
console.log("Indexing Status API: handling a known indexing status server error.");
|
|
1635
|
+
}
|
|
1636
|
+
if (typeof errorResponse !== "undefined") {
|
|
1637
|
+
throw new Error(`Fetching ENSNode Indexing Status Failed: ${errorResponse.message}`);
|
|
1308
1638
|
}
|
|
1309
1639
|
}
|
|
1310
|
-
return
|
|
1311
|
-
responseData
|
|
1312
|
-
);
|
|
1640
|
+
return deserializeIndexingStatusResponse(responseData);
|
|
1313
1641
|
}
|
|
1314
1642
|
};
|
|
1315
1643
|
|
|
1316
1644
|
// src/resolution/resolver-records-selection.ts
|
|
1317
1645
|
var isSelectionEmpty = (selection) => !selection.name && !selection.addresses?.length && !selection.texts?.length;
|
|
1318
1646
|
|
|
1647
|
+
// src/resolution/types.ts
|
|
1648
|
+
var ResolutionStatusIds = {
|
|
1649
|
+
/**
|
|
1650
|
+
* Represents that the `Identity` is not resolved yet.
|
|
1651
|
+
*/
|
|
1652
|
+
Unresolved: "unresolved",
|
|
1653
|
+
/**
|
|
1654
|
+
* Represents that resolution of the `Identity` resulted in a named identity.
|
|
1655
|
+
*/
|
|
1656
|
+
Named: "named",
|
|
1657
|
+
/**
|
|
1658
|
+
* Represents that resolution of the `Identity` resulted in an unnamed identity.
|
|
1659
|
+
*/
|
|
1660
|
+
Unnamed: "unnamed",
|
|
1661
|
+
/**
|
|
1662
|
+
* Represents that attempted resolution of the `Identity` resulted in an error
|
|
1663
|
+
* and therefore it is unknown if the `Identity` resolves to a named or unnamed identity.
|
|
1664
|
+
*/
|
|
1665
|
+
Unknown: "unknown"
|
|
1666
|
+
};
|
|
1667
|
+
|
|
1319
1668
|
// src/resolution/default-records-selection.ts
|
|
1320
1669
|
import {
|
|
1321
1670
|
DatasourceNames,
|
|
1322
|
-
ENSNamespaceIds as
|
|
1671
|
+
ENSNamespaceIds as ENSNamespaceIds3,
|
|
1323
1672
|
maybeGetDatasource
|
|
1324
1673
|
} from "@ensnode/datasources";
|
|
1325
1674
|
var getENSIP19SupportedCoinTypes = (namespace) => uniq(
|
|
@@ -1331,6 +1680,9 @@ var getENSIP19SupportedCoinTypes = (namespace) => uniq(
|
|
|
1331
1680
|
maybeGetDatasource(namespace, DatasourceNames.ReverseResolverScroll)
|
|
1332
1681
|
].filter((ds) => ds !== void 0).map((ds) => ds.chain.id)
|
|
1333
1682
|
).map(evmChainIdToCoinType);
|
|
1683
|
+
var getCommonCoinTypes = (namespace) => {
|
|
1684
|
+
return [ETH_COIN_TYPE, ...getENSIP19SupportedCoinTypes(namespace)];
|
|
1685
|
+
};
|
|
1334
1686
|
var TEXTS = [
|
|
1335
1687
|
"url",
|
|
1336
1688
|
"avatar",
|
|
@@ -1342,31 +1694,57 @@ var TEXTS = [
|
|
|
1342
1694
|
"com.github"
|
|
1343
1695
|
];
|
|
1344
1696
|
var DefaultRecordsSelection = {
|
|
1345
|
-
[
|
|
1346
|
-
addresses:
|
|
1697
|
+
[ENSNamespaceIds3.Mainnet]: {
|
|
1698
|
+
addresses: getCommonCoinTypes(ENSNamespaceIds3.Mainnet),
|
|
1347
1699
|
texts: TEXTS
|
|
1348
1700
|
},
|
|
1349
|
-
[
|
|
1350
|
-
addresses:
|
|
1701
|
+
[ENSNamespaceIds3.Sepolia]: {
|
|
1702
|
+
addresses: getCommonCoinTypes(ENSNamespaceIds3.Sepolia),
|
|
1351
1703
|
texts: TEXTS
|
|
1352
1704
|
},
|
|
1353
|
-
[
|
|
1354
|
-
addresses:
|
|
1705
|
+
[ENSNamespaceIds3.Holesky]: {
|
|
1706
|
+
addresses: getCommonCoinTypes(ENSNamespaceIds3.Holesky),
|
|
1355
1707
|
texts: TEXTS
|
|
1356
1708
|
},
|
|
1357
|
-
[
|
|
1358
|
-
addresses:
|
|
1709
|
+
[ENSNamespaceIds3.EnsTestEnv]: {
|
|
1710
|
+
addresses: getCommonCoinTypes(ENSNamespaceIds3.EnsTestEnv),
|
|
1359
1711
|
texts: TEXTS
|
|
1360
1712
|
}
|
|
1361
1713
|
};
|
|
1714
|
+
|
|
1715
|
+
// src/resolution/ensip19-chainid.ts
|
|
1716
|
+
import { getENSRootChainId as getENSRootChainId2 } from "@ensnode/datasources";
|
|
1717
|
+
import { mainnet } from "viem/chains";
|
|
1718
|
+
var getResolvePrimaryNameChainIdParam = (chainId, namespaceId) => {
|
|
1719
|
+
const ensRootChainId = getENSRootChainId2(namespaceId);
|
|
1720
|
+
return chainId === ensRootChainId ? mainnet.id : chainId;
|
|
1721
|
+
};
|
|
1722
|
+
var translateDefaultableChainIdToChainId = (chainId, namespaceId) => {
|
|
1723
|
+
return chainId === DEFAULT_EVM_CHAIN_ID ? getENSRootChainId2(namespaceId) : chainId;
|
|
1724
|
+
};
|
|
1725
|
+
|
|
1726
|
+
// src/resolution/identity.ts
|
|
1727
|
+
import { getENSRootChainId as getENSRootChainId3 } from "@ensnode/datasources";
|
|
1728
|
+
function buildUnresolvedIdentity(address, namespaceId, chainId) {
|
|
1729
|
+
return {
|
|
1730
|
+
resolutionStatus: ResolutionStatusIds.Unresolved,
|
|
1731
|
+
chainId: chainId ?? getENSRootChainId3(namespaceId),
|
|
1732
|
+
address
|
|
1733
|
+
};
|
|
1734
|
+
}
|
|
1735
|
+
function isResolvedIdentity(identity) {
|
|
1736
|
+
return identity.resolutionStatus !== ResolutionStatusIds.Unresolved;
|
|
1737
|
+
}
|
|
1362
1738
|
export {
|
|
1739
|
+
ADDR_REVERSE_NODE,
|
|
1363
1740
|
ATTR_PROTOCOL_NAME,
|
|
1364
1741
|
ATTR_PROTOCOL_STEP,
|
|
1365
1742
|
ATTR_PROTOCOL_STEP_RESULT,
|
|
1366
1743
|
BASENAMES_NODE,
|
|
1744
|
+
ChainIndexingConfigTypeIds,
|
|
1367
1745
|
ChainIndexingStatusIds,
|
|
1368
|
-
ChainIndexingStrategyIds,
|
|
1369
1746
|
ClientError,
|
|
1747
|
+
CrossChainIndexingStrategyIds,
|
|
1370
1748
|
DEFAULT_ENSNODE_API_URL,
|
|
1371
1749
|
DEFAULT_EVM_CHAIN_ID,
|
|
1372
1750
|
DEFAULT_EVM_COIN_TYPE,
|
|
@@ -1379,73 +1757,86 @@ export {
|
|
|
1379
1757
|
IndexingStatusResponseCodes,
|
|
1380
1758
|
LINEANAMES_NODE,
|
|
1381
1759
|
LruCache,
|
|
1382
|
-
|
|
1760
|
+
OmnichainIndexingStatusIds,
|
|
1383
1761
|
PROTOCOL_ATTRIBUTE_PREFIX,
|
|
1384
1762
|
PluginName,
|
|
1385
|
-
REVERSE_ROOT_NODES,
|
|
1386
1763
|
ROOT_NODE,
|
|
1764
|
+
ResolutionStatusIds,
|
|
1387
1765
|
ReverseResolutionProtocolStep,
|
|
1388
1766
|
TraceableENSProtocol,
|
|
1389
1767
|
accountIdEqual,
|
|
1390
1768
|
addrReverseLabel,
|
|
1769
|
+
asLowerCaseAddress,
|
|
1770
|
+
beautifyName,
|
|
1391
1771
|
bigintToCoinType,
|
|
1392
1772
|
buildEnsRainbowClientLabelSet,
|
|
1393
1773
|
buildLabelSetId,
|
|
1394
1774
|
buildLabelSetVersion,
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1775
|
+
buildUnresolvedIdentity,
|
|
1776
|
+
checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill,
|
|
1777
|
+
checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted,
|
|
1778
|
+
checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing,
|
|
1779
|
+
checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted,
|
|
1399
1780
|
coinTypeReverseLabel,
|
|
1400
1781
|
coinTypeToEvmChainId,
|
|
1401
1782
|
createIndexingConfig,
|
|
1783
|
+
createRealtimeIndexingStatusProjection,
|
|
1784
|
+
decodeDNSEncodedLiteralName,
|
|
1785
|
+
decodeDNSEncodedName,
|
|
1402
1786
|
deserializeBlockNumber,
|
|
1403
1787
|
deserializeBlockRef,
|
|
1404
1788
|
deserializeBlockrange,
|
|
1405
1789
|
deserializeChainId,
|
|
1790
|
+
deserializeChainIndexingStatusSnapshot,
|
|
1791
|
+
deserializeCrossChainIndexingStatusSnapshot,
|
|
1406
1792
|
deserializeDatetime,
|
|
1407
1793
|
deserializeDuration,
|
|
1408
|
-
deserializeENSIndexerIndexingStatus,
|
|
1409
1794
|
deserializeENSIndexerPublicConfig,
|
|
1410
1795
|
deserializeErrorResponse,
|
|
1796
|
+
deserializeIndexingStatusResponse,
|
|
1797
|
+
deserializeOmnichainIndexingStatusSnapshot,
|
|
1798
|
+
deserializeRealtimeIndexingStatusProjection,
|
|
1799
|
+
deserializeUnixTimestamp,
|
|
1411
1800
|
deserializeUrl,
|
|
1801
|
+
encodeLabelHash,
|
|
1412
1802
|
evmChainIdToCoinType,
|
|
1413
|
-
|
|
1803
|
+
getCommonCoinTypes,
|
|
1804
|
+
getENSRootChainId,
|
|
1414
1805
|
getNameHierarchy,
|
|
1415
1806
|
getOmnichainIndexingCursor,
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
getStandbyChains,
|
|
1807
|
+
getOmnichainIndexingStatus,
|
|
1808
|
+
getResolvePrimaryNameChainIdParam,
|
|
1419
1809
|
getTimestampForHighestOmnichainKnownBlock,
|
|
1420
1810
|
getTimestampForLowestOmnichainStartBlock,
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1811
|
+
interpretedLabelsToInterpretedName,
|
|
1812
|
+
isHttpProtocol,
|
|
1813
|
+
isNormalizedLabel,
|
|
1814
|
+
isNormalizedName,
|
|
1815
|
+
isResolvedIdentity,
|
|
1425
1816
|
isSelectionEmpty,
|
|
1426
1817
|
isSubgraphCompatible,
|
|
1818
|
+
isWebSocketProtocol,
|
|
1427
1819
|
labelHashToBytes,
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
makeIndexedChainIdsSchema,
|
|
1433
|
-
makeLabelSetIdSchema,
|
|
1434
|
-
makeLabelSetVersionSchema,
|
|
1435
|
-
makePluginsListSchema,
|
|
1820
|
+
labelhashLiteralLabel,
|
|
1821
|
+
literalLabelToInterpretedLabel,
|
|
1822
|
+
literalLabelsToInterpretedName,
|
|
1823
|
+
literalLabelsToLiteralName,
|
|
1436
1824
|
makeSubdomainNode,
|
|
1437
|
-
maybeHealLabelByReverseAddress,
|
|
1438
1825
|
parseNonNegativeInteger,
|
|
1439
1826
|
parseReverseName,
|
|
1440
1827
|
reverseName,
|
|
1441
1828
|
serializeChainId,
|
|
1442
|
-
|
|
1829
|
+
serializeChainIndexingSnapshots,
|
|
1830
|
+
serializeCrossChainIndexingStatusSnapshotOmnichain,
|
|
1443
1831
|
serializeDatetime,
|
|
1444
|
-
serializeENSIndexerIndexingStatus,
|
|
1445
1832
|
serializeENSIndexerPublicConfig,
|
|
1446
1833
|
serializeIndexedChainIds,
|
|
1834
|
+
serializeIndexingStatusResponse,
|
|
1835
|
+
serializeOmnichainIndexingStatusSnapshot,
|
|
1836
|
+
serializeRealtimeIndexingStatusProjection,
|
|
1447
1837
|
serializeUrl,
|
|
1448
|
-
|
|
1838
|
+
sortChainStatusesByStartBlockAsc,
|
|
1839
|
+
translateDefaultableChainIdToChainId,
|
|
1449
1840
|
uint256ToHex32,
|
|
1450
1841
|
uniq,
|
|
1451
1842
|
validateSupportedLabelSetAndVersion
|