@ensnode/ensnode-sdk 0.35.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 +49 -10
- package/dist/index.d.ts +1203 -602
- package/dist/index.js +882 -530
- 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,96 +34,8 @@ var bigintToCoinType = (value) => {
|
|
|
33
34
|
return Number(value);
|
|
34
35
|
};
|
|
35
36
|
|
|
36
|
-
// src/ens/reverse-name.ts
|
|
37
|
-
var addrReverseLabel = (address) => address.slice(2).toLowerCase();
|
|
38
|
-
var coinTypeReverseLabel = (coinType) => coinType.toString(16);
|
|
39
|
-
function reverseName(address, coinType) {
|
|
40
|
-
const label = addrReverseLabel(address);
|
|
41
|
-
const middle = (() => {
|
|
42
|
-
switch (coinType) {
|
|
43
|
-
case ETH_COIN_TYPE:
|
|
44
|
-
return "addr";
|
|
45
|
-
case DEFAULT_EVM_COIN_TYPE:
|
|
46
|
-
return "default";
|
|
47
|
-
default:
|
|
48
|
-
return coinTypeReverseLabel(coinType);
|
|
49
|
-
}
|
|
50
|
-
})();
|
|
51
|
-
return `${label}.${middle}.reverse`;
|
|
52
|
-
}
|
|
53
|
-
|
|
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
37
|
// src/ens/names.ts
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
// src/ens/types.ts
|
|
100
|
-
import { ENSNamespaceIds } from "@ensnode/datasources";
|
|
101
|
-
|
|
102
|
-
// src/ens/parse-reverse-name.ts
|
|
103
|
-
import { getAddress, hexToBigInt } from "viem";
|
|
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
|
-
}
|
|
38
|
+
import { ens_beautify } from "@adraffy/ens-normalize";
|
|
126
39
|
|
|
127
40
|
// src/ens/is-normalized.ts
|
|
128
41
|
import { normalize } from "viem/ens";
|
|
@@ -143,14 +56,47 @@ function isNormalizedLabel(label) {
|
|
|
143
56
|
}
|
|
144
57
|
}
|
|
145
58
|
|
|
146
|
-
// src/ens/
|
|
147
|
-
var
|
|
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
|
+
};
|
|
148
71
|
|
|
149
|
-
// src/
|
|
150
|
-
|
|
72
|
+
// src/ens/reverse-name.ts
|
|
73
|
+
var addrReverseLabel = (address) => address.slice(2);
|
|
74
|
+
var coinTypeReverseLabel = (coinType) => coinType.toString(16);
|
|
75
|
+
function reverseName(address, coinType) {
|
|
76
|
+
const label = addrReverseLabel(address);
|
|
77
|
+
const middle = (() => {
|
|
78
|
+
switch (coinType) {
|
|
79
|
+
case ETH_COIN_TYPE:
|
|
80
|
+
return "addr";
|
|
81
|
+
case DEFAULT_EVM_COIN_TYPE:
|
|
82
|
+
return "default";
|
|
83
|
+
default:
|
|
84
|
+
return coinTypeReverseLabel(coinType);
|
|
85
|
+
}
|
|
86
|
+
})();
|
|
87
|
+
return `${label}.${middle}.reverse`;
|
|
88
|
+
}
|
|
151
89
|
|
|
152
|
-
// src/
|
|
153
|
-
import
|
|
90
|
+
// src/ens/types.ts
|
|
91
|
+
import { ENSNamespaceIds } from "@ensnode/datasources";
|
|
92
|
+
|
|
93
|
+
// src/ens/parse-reverse-name.ts
|
|
94
|
+
import { hexToBigInt, isAddress as isAddress2 } from "viem";
|
|
95
|
+
|
|
96
|
+
// src/shared/address.ts
|
|
97
|
+
function asLowerCaseAddress(address) {
|
|
98
|
+
return address.toLowerCase();
|
|
99
|
+
}
|
|
154
100
|
|
|
155
101
|
// src/shared/cache.ts
|
|
156
102
|
var LruCache = class {
|
|
@@ -219,6 +165,7 @@ function serializeUrl(url) {
|
|
|
219
165
|
import { prettifyError } from "zod/v4";
|
|
220
166
|
|
|
221
167
|
// src/shared/zod-schemas.ts
|
|
168
|
+
import { isAddress } from "viem";
|
|
222
169
|
import z from "zod/v4";
|
|
223
170
|
var makeIntegerSchema = (valueLabel = "Value") => z.int({
|
|
224
171
|
error: `${valueLabel} must be an integer.`
|
|
@@ -232,7 +179,7 @@ var makeNonNegativeIntegerSchema = (valueLabel = "Value") => makeIntegerSchema(v
|
|
|
232
179
|
var makeDurationSchema = (valueLabel = "Value") => z.coerce.number({
|
|
233
180
|
error: `${valueLabel} must be a number.`
|
|
234
181
|
}).pipe(makeNonNegativeIntegerSchema(valueLabel));
|
|
235
|
-
var makeChainIdSchema = (valueLabel = "Chain ID") => makePositiveIntegerSchema(valueLabel);
|
|
182
|
+
var makeChainIdSchema = (valueLabel = "Chain ID") => makePositiveIntegerSchema(valueLabel).transform((val) => val);
|
|
236
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}`));
|
|
237
184
|
var makeDatetimeSchema = (valueLabel = "Datetime string") => z.iso.datetime({ error: `${valueLabel} must be a string in ISO 8601 format.` }).transform((v) => new Date(v));
|
|
238
185
|
var makeUnixTimestampSchema = (valueLabel = "Timestamp") => makeIntegerSchema(valueLabel);
|
|
@@ -293,6 +240,16 @@ ${prettifyError(parsed.error)}
|
|
|
293
240
|
}
|
|
294
241
|
return parsed.data;
|
|
295
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
|
+
}
|
|
296
253
|
function deserializeUrl(maybeUrl, valueLabel) {
|
|
297
254
|
const schema = makeUrlSchema(valueLabel);
|
|
298
255
|
const parsed = schema.safeParse(maybeUrl);
|
|
@@ -350,24 +307,115 @@ var accountIdEqual = (a, b) => {
|
|
|
350
307
|
return a.chainId === b.chainId && isAddressEqual(a.address, b.address);
|
|
351
308
|
};
|
|
352
309
|
|
|
310
|
+
// src/shared/labelhash.ts
|
|
311
|
+
import { keccak256 as keccak2562, stringToBytes } from "viem";
|
|
312
|
+
var labelhashLiteralLabel = (label) => keccak2562(stringToBytes(label));
|
|
313
|
+
|
|
353
314
|
// src/shared/interpretation.ts
|
|
354
|
-
|
|
355
|
-
function interpretLiteralLabel(label) {
|
|
315
|
+
function literalLabelToInterpretedLabel(label) {
|
|
356
316
|
if (isNormalizedLabel(label)) return label;
|
|
357
|
-
return encodeLabelHash(
|
|
317
|
+
return encodeLabelHash(labelhashLiteralLabel(label));
|
|
358
318
|
}
|
|
359
|
-
function
|
|
360
|
-
|
|
361
|
-
|
|
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(".");
|
|
362
327
|
}
|
|
363
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
|
+
|
|
364
412
|
// src/ensindexer/config/types.ts
|
|
365
413
|
var PluginName = /* @__PURE__ */ ((PluginName2) => {
|
|
366
414
|
PluginName2["Subgraph"] = "subgraph";
|
|
367
415
|
PluginName2["Basenames"] = "basenames";
|
|
368
416
|
PluginName2["Lineanames"] = "lineanames";
|
|
369
417
|
PluginName2["ThreeDNS"] = "threedns";
|
|
370
|
-
PluginName2["
|
|
418
|
+
PluginName2["ProtocolAcceleration"] = "protocol-acceleration";
|
|
371
419
|
PluginName2["Referrals"] = "referrals";
|
|
372
420
|
PluginName2["TokenScope"] = "tokenscope";
|
|
373
421
|
return PluginName2;
|
|
@@ -376,25 +424,32 @@ var PluginName = /* @__PURE__ */ ((PluginName2) => {
|
|
|
376
424
|
// src/ensindexer/config/helpers.ts
|
|
377
425
|
function isSubgraphCompatible(config) {
|
|
378
426
|
const onlySubgraphPluginActivated = config.plugins.length === 1 && config.plugins[0] === "subgraph" /* Subgraph */;
|
|
379
|
-
const
|
|
380
|
-
const
|
|
381
|
-
|
|
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
|
+
}
|
|
382
443
|
}
|
|
383
444
|
|
|
384
445
|
// src/ensindexer/config/zod-schemas.ts
|
|
385
446
|
var makeIndexedChainIdsSchema = (valueLabel = "Indexed Chain IDs") => z2.array(makeChainIdSchema(valueLabel), {
|
|
386
447
|
error: `${valueLabel} must be an array.`
|
|
387
448
|
}).min(1, { error: `${valueLabel} list must include at least one element.` }).transform((v) => new Set(v));
|
|
388
|
-
var makePluginsListSchema = (valueLabel = "Plugins") => z2.array(
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
).join(", ")}`
|
|
393
|
-
})
|
|
394
|
-
).min(1, {
|
|
395
|
-
error: `${valueLabel} must be a list with at least one valid plugin name. Valid plugins are: ${Object.values(
|
|
396
|
-
PluginName
|
|
397
|
-
).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`
|
|
398
453
|
}).refine((arr) => arr.length === uniq(arr).length, {
|
|
399
454
|
error: `${valueLabel} cannot contain duplicate values.`
|
|
400
455
|
});
|
|
@@ -425,55 +480,39 @@ var makeFullyPinnedLabelSetSchema = (valueLabel = "Label set") => {
|
|
|
425
480
|
});
|
|
426
481
|
};
|
|
427
482
|
var makeNonEmptyStringSchema = (valueLabel = "Value") => z2.string().nonempty({ error: `${valueLabel} must be a non-empty string.` });
|
|
428
|
-
var
|
|
483
|
+
var makeENSIndexerVersionInfoSchema = (valueLabel = "Value") => z2.strictObject(
|
|
429
484
|
{
|
|
430
485
|
nodejs: makeNonEmptyStringSchema(),
|
|
431
486
|
ponder: makeNonEmptyStringSchema(),
|
|
487
|
+
ensDb: makeNonEmptyStringSchema(),
|
|
488
|
+
ensIndexer: makeNonEmptyStringSchema(),
|
|
489
|
+
ensNormalize: makeNonEmptyStringSchema(),
|
|
432
490
|
ensRainbow: makeNonEmptyStringSchema(),
|
|
433
491
|
ensRainbowSchema: makePositiveIntegerSchema()
|
|
434
492
|
},
|
|
435
493
|
{
|
|
436
|
-
error: `${valueLabel} must be a valid
|
|
494
|
+
error: `${valueLabel} must be a valid ENSIndexerVersionInfo object.`
|
|
437
495
|
}
|
|
438
|
-
);
|
|
439
|
-
function invariant_reverseResolversPluginNeedsResolverRecords(ctx) {
|
|
440
|
-
const { value: config } = ctx;
|
|
441
|
-
const reverseResolversPluginActive = config.plugins.includes("reverse-resolvers" /* ReverseResolvers */);
|
|
442
|
-
if (reverseResolversPluginActive && !config.indexAdditionalResolverRecords) {
|
|
443
|
-
ctx.issues.push({
|
|
444
|
-
code: "custom",
|
|
445
|
-
input: config,
|
|
446
|
-
message: `The '${"reverse-resolvers" /* ReverseResolvers */}' plugin requires 'indexAdditionalResolverRecords' to be 'true'.`
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
|
-
}
|
|
496
|
+
).check(invariant_ensDbVersionIsSameAsEnsIndexerVersion);
|
|
450
497
|
function invariant_isSubgraphCompatibleRequirements(ctx) {
|
|
451
498
|
const { value: config } = ctx;
|
|
452
|
-
if (config.isSubgraphCompatible
|
|
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'`;
|
|
499
|
+
if (config.isSubgraphCompatible && !isSubgraphCompatible(config)) {
|
|
454
500
|
ctx.issues.push({
|
|
455
501
|
code: "custom",
|
|
456
502
|
input: config,
|
|
457
|
-
message
|
|
503
|
+
message: `'isSubgraphCompatible' requires only the '${"subgraph" /* Subgraph */}' plugin to be active and labelSet must be {labelSetId: "subgraph", labelSetVersion: 0}`
|
|
458
504
|
});
|
|
459
505
|
}
|
|
460
506
|
}
|
|
461
507
|
var makeENSIndexerPublicConfigSchema = (valueLabel = "ENSIndexerPublicConfig") => z2.object({
|
|
462
|
-
ensAdminUrl: makeUrlSchema(`${valueLabel}.ensAdminUrl`),
|
|
463
|
-
ensNodePublicUrl: makeUrlSchema(`${valueLabel}.ensNodePublicUrl`),
|
|
464
508
|
labelSet: makeFullyPinnedLabelSetSchema(`${valueLabel}.labelSet`),
|
|
465
|
-
healReverseAddresses: z2.boolean({ error: `${valueLabel}.healReverseAddresses` }),
|
|
466
|
-
indexAdditionalResolverRecords: z2.boolean({
|
|
467
|
-
error: `${valueLabel}.indexAdditionalResolverRecords`
|
|
468
|
-
}),
|
|
469
|
-
replaceUnnormalized: z2.boolean({ error: `${valueLabel}.replaceUnnormalized` }),
|
|
470
509
|
indexedChainIds: makeIndexedChainIdsSchema(`${valueLabel}.indexedChainIds`),
|
|
471
510
|
isSubgraphCompatible: z2.boolean({ error: `${valueLabel}.isSubgraphCompatible` }),
|
|
472
511
|
namespace: makeENSNamespaceIdSchema(`${valueLabel}.namespace`),
|
|
473
512
|
plugins: makePluginsListSchema(`${valueLabel}.plugins`),
|
|
474
513
|
databaseSchemaName: makeDatabaseSchemaNameSchema(`${valueLabel}.databaseSchemaName`),
|
|
475
|
-
|
|
476
|
-
}).check(
|
|
514
|
+
versionInfo: makeENSIndexerVersionInfoSchema(`${valueLabel}.versionInfo`)
|
|
515
|
+
}).check(invariant_isSubgraphCompatibleRequirements);
|
|
477
516
|
|
|
478
517
|
// src/ensindexer/config/deserialize.ts
|
|
479
518
|
function deserializeENSIndexerPublicConfig(maybeConfig, valueLabel) {
|
|
@@ -493,32 +532,22 @@ function serializeIndexedChainIds(indexedChainIds) {
|
|
|
493
532
|
}
|
|
494
533
|
function serializeENSIndexerPublicConfig(config) {
|
|
495
534
|
const {
|
|
496
|
-
ensAdminUrl,
|
|
497
|
-
ensNodePublicUrl,
|
|
498
535
|
labelSet,
|
|
499
536
|
indexedChainIds,
|
|
500
537
|
databaseSchemaName,
|
|
501
|
-
healReverseAddresses,
|
|
502
|
-
indexAdditionalResolverRecords,
|
|
503
|
-
replaceUnnormalized,
|
|
504
538
|
isSubgraphCompatible: isSubgraphCompatible2,
|
|
505
539
|
namespace,
|
|
506
540
|
plugins,
|
|
507
|
-
|
|
541
|
+
versionInfo
|
|
508
542
|
} = config;
|
|
509
543
|
return {
|
|
510
|
-
ensAdminUrl: serializeUrl(ensAdminUrl),
|
|
511
|
-
ensNodePublicUrl: serializeUrl(ensNodePublicUrl),
|
|
512
544
|
labelSet,
|
|
513
545
|
indexedChainIds: serializeIndexedChainIds(indexedChainIds),
|
|
514
546
|
databaseSchemaName,
|
|
515
|
-
healReverseAddresses,
|
|
516
|
-
indexAdditionalResolverRecords,
|
|
517
|
-
replaceUnnormalized,
|
|
518
547
|
isSubgraphCompatible: isSubgraphCompatible2,
|
|
519
548
|
namespace,
|
|
520
549
|
plugins,
|
|
521
|
-
|
|
550
|
+
versionInfo
|
|
522
551
|
};
|
|
523
552
|
}
|
|
524
553
|
|
|
@@ -552,7 +581,7 @@ function validateSupportedLabelSetAndVersion(serverSet, clientSet) {
|
|
|
552
581
|
}
|
|
553
582
|
|
|
554
583
|
// src/ensindexer/config/label-utils.ts
|
|
555
|
-
import { hexToBytes } from "viem";
|
|
584
|
+
import { hexToBytes as hexToBytes2 } from "viem";
|
|
556
585
|
function labelHashToBytes(labelHash) {
|
|
557
586
|
try {
|
|
558
587
|
if (labelHash.length !== 66) {
|
|
@@ -564,7 +593,7 @@ function labelHashToBytes(labelHash) {
|
|
|
564
593
|
if (!labelHash.startsWith("0x")) {
|
|
565
594
|
throw new Error("Labelhash must be 0x-prefixed");
|
|
566
595
|
}
|
|
567
|
-
const bytes =
|
|
596
|
+
const bytes = hexToBytes2(labelHash);
|
|
568
597
|
if (bytes.length !== 32) {
|
|
569
598
|
throw new Error(`Invalid labelHash length ${bytes.length} bytes (expected 32)`);
|
|
570
599
|
}
|
|
@@ -608,6 +637,92 @@ import { prettifyError as prettifyError3 } from "zod/v4";
|
|
|
608
637
|
// src/ensindexer/indexing-status/zod-schemas.ts
|
|
609
638
|
import z3 from "zod/v4";
|
|
610
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
|
+
|
|
611
726
|
// src/shared/block-ref.ts
|
|
612
727
|
function isBefore(blockA, blockB) {
|
|
613
728
|
return blockA.number < blockB.number && blockA.timestamp < blockB.timestamp;
|
|
@@ -619,49 +734,21 @@ function isBeforeOrEqualTo(blockA, blockB) {
|
|
|
619
734
|
return isBefore(blockA, blockB) || isEqualTo(blockA, blockB);
|
|
620
735
|
}
|
|
621
736
|
|
|
622
|
-
// src/ensindexer/indexing-status/types.ts
|
|
623
|
-
var ChainIndexingStatusIds = {
|
|
624
|
-
Unstarted: "unstarted",
|
|
625
|
-
Backfill: "backfill",
|
|
626
|
-
Following: "following",
|
|
627
|
-
Completed: "completed"
|
|
628
|
-
};
|
|
629
|
-
var OverallIndexingStatusIds = {
|
|
630
|
-
Unstarted: "unstarted",
|
|
631
|
-
Backfill: "backfill",
|
|
632
|
-
Following: "following",
|
|
633
|
-
Completed: "completed",
|
|
634
|
-
IndexerError: "indexer-error"
|
|
635
|
-
};
|
|
636
|
-
var ChainIndexingStrategyIds = {
|
|
637
|
-
Indefinite: "indefinite",
|
|
638
|
-
Definite: "definite"
|
|
639
|
-
};
|
|
640
|
-
|
|
641
737
|
// src/ensindexer/indexing-status/helpers.ts
|
|
642
|
-
function
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
if (chainStatuses.some((chainStatus) => chainStatus === ChainIndexingStatusIds.Following)) {
|
|
646
|
-
overallStatus = OverallIndexingStatusIds.Following;
|
|
647
|
-
} else if (chainStatuses.some((chainStatus) => chainStatus === ChainIndexingStatusIds.Backfill)) {
|
|
648
|
-
overallStatus = OverallIndexingStatusIds.Backfill;
|
|
649
|
-
} else if (chainStatuses.some((chainStatus) => chainStatus === ChainIndexingStatusIds.Unstarted)) {
|
|
650
|
-
overallStatus = OverallIndexingStatusIds.Unstarted;
|
|
651
|
-
} else {
|
|
652
|
-
overallStatus = OverallIndexingStatusIds.Completed;
|
|
738
|
+
function getOmnichainIndexingStatus(chains) {
|
|
739
|
+
if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing(chains)) {
|
|
740
|
+
return OmnichainIndexingStatusIds.Following;
|
|
653
741
|
}
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
742
|
+
if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill(chains)) {
|
|
743
|
+
return OmnichainIndexingStatusIds.Backfill;
|
|
744
|
+
}
|
|
745
|
+
if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted(chains)) {
|
|
746
|
+
return OmnichainIndexingStatusIds.Unstarted;
|
|
747
|
+
}
|
|
748
|
+
if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted(chains)) {
|
|
749
|
+
return OmnichainIndexingStatusIds.Completed;
|
|
662
750
|
}
|
|
663
|
-
|
|
664
|
-
return approxRealtimeDistance;
|
|
751
|
+
throw new Error(`Unable to determine omnichain indexing status for provided chains.`);
|
|
665
752
|
}
|
|
666
753
|
function getTimestampForLowestOmnichainStartBlock(chains) {
|
|
667
754
|
const earliestKnownBlockTimestamps = chains.map(
|
|
@@ -672,8 +759,8 @@ function getTimestampForLowestOmnichainStartBlock(chains) {
|
|
|
672
759
|
function getTimestampForHighestOmnichainKnownBlock(chains) {
|
|
673
760
|
const latestKnownBlockTimestamps = [];
|
|
674
761
|
for (const chain of chains) {
|
|
675
|
-
switch (chain.
|
|
676
|
-
case ChainIndexingStatusIds.
|
|
762
|
+
switch (chain.chainStatus) {
|
|
763
|
+
case ChainIndexingStatusIds.Queued:
|
|
677
764
|
if (chain.config.endBlock) {
|
|
678
765
|
latestKnownBlockTimestamps.push(chain.config.endBlock.timestamp);
|
|
679
766
|
}
|
|
@@ -692,159 +779,349 @@ function getTimestampForHighestOmnichainKnownBlock(chains) {
|
|
|
692
779
|
return Math.max(...latestKnownBlockTimestamps);
|
|
693
780
|
}
|
|
694
781
|
function getOmnichainIndexingCursor(chains) {
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
(chain) => chain.
|
|
700
|
-
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
(
|
|
705
|
-
|
|
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);
|
|
706
794
|
}
|
|
707
795
|
function createIndexingConfig(startBlock, endBlock) {
|
|
708
796
|
if (endBlock) {
|
|
709
797
|
return {
|
|
710
|
-
|
|
798
|
+
configType: ChainIndexingConfigTypeIds.Definite,
|
|
711
799
|
startBlock,
|
|
712
800
|
endBlock
|
|
713
801
|
};
|
|
714
802
|
}
|
|
715
803
|
return {
|
|
716
|
-
|
|
717
|
-
startBlock
|
|
718
|
-
endBlock: null
|
|
804
|
+
configType: ChainIndexingConfigTypeIds.Indefinite,
|
|
805
|
+
startBlock
|
|
719
806
|
};
|
|
720
807
|
}
|
|
721
|
-
function
|
|
722
|
-
return chains.every((chain) => chain.
|
|
808
|
+
function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted(chains) {
|
|
809
|
+
return chains.every((chain) => chain.chainStatus === ChainIndexingStatusIds.Queued);
|
|
723
810
|
}
|
|
724
|
-
function
|
|
811
|
+
function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill(chains) {
|
|
725
812
|
const atLeastOneChainInTargetStatus = chains.some(
|
|
726
|
-
(chain) => chain.
|
|
813
|
+
(chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill
|
|
727
814
|
);
|
|
728
815
|
const otherChainsHaveValidStatuses = chains.every(
|
|
729
|
-
(chain) => chain.
|
|
816
|
+
(chain) => chain.chainStatus === ChainIndexingStatusIds.Queued || chain.chainStatus === ChainIndexingStatusIds.Backfill || chain.chainStatus === ChainIndexingStatusIds.Completed
|
|
730
817
|
);
|
|
731
818
|
return atLeastOneChainInTargetStatus && otherChainsHaveValidStatuses;
|
|
732
819
|
}
|
|
733
|
-
function
|
|
820
|
+
function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted(chains) {
|
|
734
821
|
const allChainsHaveValidStatuses = chains.every(
|
|
735
|
-
(chain) => chain.
|
|
822
|
+
(chain) => chain.chainStatus === ChainIndexingStatusIds.Completed
|
|
736
823
|
);
|
|
737
824
|
return allChainsHaveValidStatuses;
|
|
738
825
|
}
|
|
739
|
-
function
|
|
826
|
+
function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing(chains) {
|
|
740
827
|
const allChainsHaveValidStatuses = chains.some(
|
|
741
|
-
(chain) => chain.
|
|
828
|
+
(chain) => chain.chainStatus === ChainIndexingStatusIds.Following
|
|
742
829
|
);
|
|
743
830
|
return allChainsHaveValidStatuses;
|
|
744
831
|
}
|
|
745
|
-
function
|
|
832
|
+
function sortChainStatusesByStartBlockAsc(chains) {
|
|
746
833
|
chains.sort(
|
|
747
834
|
([, chainA], [, chainB]) => chainA.config.startBlock.timestamp - chainB.config.startBlock.timestamp
|
|
748
835
|
);
|
|
749
836
|
return chains;
|
|
750
837
|
}
|
|
751
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
|
+
|
|
752
1077
|
// src/ensindexer/indexing-status/zod-schemas.ts
|
|
753
|
-
var makeChainIndexingConfigSchema = (valueLabel = "Value") => z3.discriminatedUnion("
|
|
1078
|
+
var makeChainIndexingConfigSchema = (valueLabel = "Value") => z3.discriminatedUnion("configType", [
|
|
754
1079
|
z3.strictObject({
|
|
755
|
-
|
|
756
|
-
startBlock: makeBlockRefSchema(valueLabel)
|
|
757
|
-
endBlock: z3.null()
|
|
1080
|
+
configType: z3.literal(ChainIndexingConfigTypeIds.Indefinite),
|
|
1081
|
+
startBlock: makeBlockRefSchema(valueLabel)
|
|
758
1082
|
}),
|
|
759
1083
|
z3.strictObject({
|
|
760
|
-
|
|
1084
|
+
configType: z3.literal(ChainIndexingConfigTypeIds.Definite),
|
|
761
1085
|
startBlock: makeBlockRefSchema(valueLabel),
|
|
762
1086
|
endBlock: makeBlockRefSchema(valueLabel)
|
|
763
1087
|
})
|
|
764
1088
|
]);
|
|
765
|
-
var
|
|
766
|
-
|
|
1089
|
+
var makeChainIndexingStatusSnapshotQueuedSchema = (valueLabel = "Value") => z3.strictObject({
|
|
1090
|
+
chainStatus: z3.literal(ChainIndexingStatusIds.Queued),
|
|
767
1091
|
config: makeChainIndexingConfigSchema(valueLabel)
|
|
768
|
-
}).
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
error: `config.startBlock must be before or same as config.endBlock.`
|
|
772
|
-
}
|
|
773
|
-
);
|
|
774
|
-
var makeChainIndexingBackfillStatusSchema = (valueLabel = "Value") => z3.strictObject({
|
|
775
|
-
status: z3.literal(ChainIndexingStatusIds.Backfill),
|
|
1092
|
+
}).check(invariant_chainSnapshotQueuedBlocks);
|
|
1093
|
+
var makeChainIndexingStatusSnapshotBackfillSchema = (valueLabel = "Value") => z3.strictObject({
|
|
1094
|
+
chainStatus: z3.literal(ChainIndexingStatusIds.Backfill),
|
|
776
1095
|
config: makeChainIndexingConfigSchema(valueLabel),
|
|
777
1096
|
latestIndexedBlock: makeBlockRefSchema(valueLabel),
|
|
778
|
-
latestSyncedBlock: makeBlockRefSchema(valueLabel),
|
|
779
1097
|
backfillEndBlock: makeBlockRefSchema(valueLabel)
|
|
780
|
-
}).
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
error: `config.startBlock must be before or same as latestIndexedBlock.`
|
|
784
|
-
}
|
|
785
|
-
).refine(
|
|
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),
|
|
792
|
-
{
|
|
793
|
-
error: `latestSyncedBlock must be before or same as backfillEndBlock.`
|
|
794
|
-
}
|
|
795
|
-
).refine(
|
|
796
|
-
({ config, backfillEndBlock }) => config.endBlock === null || isEqualTo(backfillEndBlock, config.endBlock),
|
|
797
|
-
{
|
|
798
|
-
error: `backfillEndBlock must be the same as config.endBlock.`
|
|
799
|
-
}
|
|
800
|
-
);
|
|
801
|
-
var makeChainIndexingFollowingStatusSchema = (valueLabel = "Value") => z3.strictObject({
|
|
802
|
-
status: z3.literal(ChainIndexingStatusIds.Following),
|
|
803
|
-
config: z3.strictObject({
|
|
804
|
-
strategy: z3.literal(ChainIndexingStrategyIds.Indefinite),
|
|
805
|
-
startBlock: makeBlockRefSchema(valueLabel)
|
|
806
|
-
}),
|
|
807
|
-
latestIndexedBlock: makeBlockRefSchema(valueLabel),
|
|
808
|
-
latestKnownBlock: makeBlockRefSchema(valueLabel),
|
|
809
|
-
approxRealtimeDistance: makeDurationSchema(valueLabel)
|
|
810
|
-
}).refine(
|
|
811
|
-
({ config, latestIndexedBlock }) => isBeforeOrEqualTo(config.startBlock, latestIndexedBlock),
|
|
812
|
-
{
|
|
813
|
-
error: `config.startBlock must be before or same as latestIndexedBlock.`
|
|
814
|
-
}
|
|
815
|
-
).refine(
|
|
816
|
-
({ latestIndexedBlock, latestKnownBlock }) => isBeforeOrEqualTo(latestIndexedBlock, latestKnownBlock),
|
|
817
|
-
{
|
|
818
|
-
error: `latestIndexedBlock must be before or same as latestKnownBlock.`
|
|
819
|
-
}
|
|
820
|
-
);
|
|
821
|
-
var makeChainIndexingCompletedStatusSchema = (valueLabel = "Value") => z3.strictObject({
|
|
822
|
-
status: z3.literal(ChainIndexingStatusIds.Completed),
|
|
1098
|
+
}).check(invariant_chainSnapshotBackfillBlocks);
|
|
1099
|
+
var makeChainIndexingStatusSnapshotCompletedSchema = (valueLabel = "Value") => z3.strictObject({
|
|
1100
|
+
chainStatus: z3.literal(ChainIndexingStatusIds.Completed),
|
|
823
1101
|
config: z3.strictObject({
|
|
824
|
-
|
|
1102
|
+
configType: z3.literal(ChainIndexingConfigTypeIds.Definite),
|
|
825
1103
|
startBlock: makeBlockRefSchema(valueLabel),
|
|
826
1104
|
endBlock: makeBlockRefSchema(valueLabel)
|
|
827
1105
|
}),
|
|
828
1106
|
latestIndexedBlock: makeBlockRefSchema(valueLabel)
|
|
829
|
-
}).
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
)
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
)
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
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)
|
|
845
1122
|
]);
|
|
846
|
-
var makeChainIndexingStatusesSchema = (valueLabel = "Value") => z3.record(makeChainIdStringSchema(),
|
|
847
|
-
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."
|
|
848
1125
|
}).transform((serializedChainsIndexingStatus) => {
|
|
849
1126
|
const chainsIndexingStatus = /* @__PURE__ */ new Map();
|
|
850
1127
|
for (const [chainIdString, chainStatus] of Object.entries(serializedChainsIndexingStatus)) {
|
|
@@ -852,121 +1129,94 @@ var makeChainIndexingStatusesSchema = (valueLabel = "Value") => z3.record(makeCh
|
|
|
852
1129
|
}
|
|
853
1130
|
return chainsIndexingStatus;
|
|
854
1131
|
});
|
|
855
|
-
var
|
|
856
|
-
|
|
857
|
-
chains: makeChainIndexingStatusesSchema(valueLabel).
|
|
858
|
-
(chains) => checkChainIndexingStatusesForUnstartedOverallStatus(Array.from(chains.values())),
|
|
859
|
-
{
|
|
860
|
-
error: `${valueLabel} at least one chain must be in "unstarted" status and
|
|
861
|
-
each chain has to have a status of either "unstarted", or "completed"`
|
|
862
|
-
}
|
|
863
|
-
).transform((chains) => chains)
|
|
864
|
-
}).refine(
|
|
865
|
-
(indexingStatus) => {
|
|
866
|
-
const chains = Array.from(indexingStatus.chains.values());
|
|
867
|
-
return getOverallIndexingStatus(chains) === indexingStatus.overallStatus;
|
|
868
|
-
},
|
|
869
|
-
{ error: `${valueLabel} is an invalid overallStatus.` }
|
|
870
|
-
);
|
|
871
|
-
var makeBackfillOverallStatusSchema = (valueLabel) => z3.strictObject({
|
|
872
|
-
overallStatus: z3.literal(OverallIndexingStatusIds.Backfill),
|
|
873
|
-
chains: makeChainIndexingStatusesSchema(valueLabel).refine(
|
|
874
|
-
(chains) => checkChainIndexingStatusesForBackfillOverallStatus(Array.from(chains.values())),
|
|
875
|
-
{
|
|
876
|
-
error: `${valueLabel} at least one chain must be in "backfill" status and
|
|
877
|
-
each chain has to have a status of either "unstarted", "backfill" or "completed"`
|
|
878
|
-
}
|
|
879
|
-
).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),
|
|
880
1135
|
omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
|
|
881
|
-
})
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
)
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
{
|
|
897
|
-
error: "omnichainIndexingCursor must be lower than or equal to the earliest config.startBlock across all standby chains"
|
|
898
|
-
}
|
|
899
|
-
);
|
|
900
|
-
var makeCompletedOverallStatusSchema = (valueLabel) => z3.strictObject({
|
|
901
|
-
overallStatus: z3.literal(OverallIndexingStatusIds.Completed),
|
|
902
|
-
chains: makeChainIndexingStatusesSchema(valueLabel).refine(
|
|
903
|
-
(chains) => checkChainIndexingStatusesForCompletedOverallStatus(Array.from(chains.values())),
|
|
904
|
-
{
|
|
905
|
-
error: `${valueLabel} all chains must have "completed" status`
|
|
906
|
-
}
|
|
907
|
-
).transform((chains) => chains)
|
|
908
|
-
}).refine(
|
|
909
|
-
(indexingStatus) => {
|
|
910
|
-
const chains = Array.from(indexingStatus.chains.values());
|
|
911
|
-
return getOverallIndexingStatus(chains) === indexingStatus.overallStatus;
|
|
912
|
-
},
|
|
913
|
-
{ error: `${valueLabel} is an invalid overallStatus.` }
|
|
914
|
-
);
|
|
915
|
-
var makeFollowingOverallStatusSchema = (valueLabel) => z3.strictObject({
|
|
916
|
-
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),
|
|
917
1151
|
chains: makeChainIndexingStatusesSchema(valueLabel),
|
|
918
|
-
overallApproxRealtimeDistance: makeDurationSchema(valueLabel),
|
|
919
1152
|
omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
|
|
920
|
-
}).refine(
|
|
921
|
-
(indexingStatus) => {
|
|
922
|
-
const chains = Array.from(indexingStatus.chains.values());
|
|
923
|
-
return getOverallIndexingStatus(chains) === indexingStatus.overallStatus;
|
|
924
|
-
},
|
|
925
|
-
{ error: `${valueLabel} is an invalid overallStatus.` }
|
|
926
|
-
).refine(
|
|
927
|
-
(indexingStatus) => checkChainIndexingStatusesForFollowingOverallStatus(
|
|
928
|
-
Array.from(indexingStatus.chains.values())
|
|
929
|
-
),
|
|
930
|
-
{
|
|
931
|
-
error: `${valueLabel} at least one chain must be in "following" status`
|
|
932
|
-
}
|
|
933
|
-
).refine(
|
|
934
|
-
(indexingStatus) => {
|
|
935
|
-
const chains = Array.from(indexingStatus.chains.values());
|
|
936
|
-
return getOverallApproxRealtimeDistance(chains) === indexingStatus.overallApproxRealtimeDistance;
|
|
937
|
-
},
|
|
938
|
-
{ error: `${valueLabel} is an invalid overallApproxRealtimeDistance.` }
|
|
939
|
-
).refine(
|
|
940
|
-
(indexingStatus) => {
|
|
941
|
-
const chains = Array.from(indexingStatus.chains.values());
|
|
942
|
-
const standbyChainStartBlocks = getStandbyChains(chains).map(
|
|
943
|
-
(chain) => chain.config.startBlock.timestamp
|
|
944
|
-
);
|
|
945
|
-
const standbyChainEarliestStartBlocks = Math.min(...standbyChainStartBlocks);
|
|
946
|
-
return indexingStatus.omnichainIndexingCursor <= standbyChainEarliestStartBlocks;
|
|
947
|
-
},
|
|
948
|
-
{
|
|
949
|
-
error: "omnichainIndexingCursor must be lower than or equal to the earliest config.startBlock across all standby chains"
|
|
950
|
-
}
|
|
951
|
-
);
|
|
952
|
-
var makeErrorSchemaOverallStatusSchema = (valueLabel) => z3.strictObject({
|
|
953
|
-
overallStatus: z3.literal(OverallIndexingStatusIds.IndexerError)
|
|
954
1153
|
});
|
|
955
|
-
var
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
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)
|
|
961
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);
|
|
962
1176
|
|
|
963
1177
|
// src/ensindexer/indexing-status/deserialize.ts
|
|
964
|
-
function
|
|
965
|
-
const schema =
|
|
966
|
-
const parsed = schema.safeParse(
|
|
1178
|
+
function deserializeChainIndexingStatusSnapshot(maybeSnapshot, valueLabel) {
|
|
1179
|
+
const schema = makeChainIndexingStatusSnapshotSchema(valueLabel);
|
|
1180
|
+
const parsed = schema.safeParse(maybeSnapshot);
|
|
967
1181
|
if (parsed.error) {
|
|
968
1182
|
throw new Error(
|
|
969
|
-
`Cannot deserialize
|
|
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);
|
|
1193
|
+
if (parsed.error) {
|
|
1194
|
+
throw new Error(
|
|
1195
|
+
`Cannot deserialize into OmnichainIndexingStatusSnapshot:
|
|
1196
|
+
${prettifyError3(parsed.error)}
|
|
1197
|
+
`
|
|
1198
|
+
);
|
|
1199
|
+
}
|
|
1200
|
+
return parsed.data;
|
|
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:
|
|
970
1220
|
${prettifyError3(parsed.error)}
|
|
971
1221
|
`
|
|
972
1222
|
);
|
|
@@ -974,42 +1224,69 @@ ${prettifyError3(parsed.error)}
|
|
|
974
1224
|
return parsed.data;
|
|
975
1225
|
}
|
|
976
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
|
+
}
|
|
1236
|
+
|
|
977
1237
|
// src/ensindexer/indexing-status/serialize.ts
|
|
978
|
-
function
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
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;
|
|
982
1262
|
}
|
|
983
|
-
return
|
|
1263
|
+
return serializedSnapshots;
|
|
984
1264
|
}
|
|
985
|
-
function
|
|
986
|
-
switch (indexingStatus.
|
|
987
|
-
case
|
|
988
|
-
return {
|
|
989
|
-
overallStatus: OverallIndexingStatusIds.IndexerError
|
|
990
|
-
};
|
|
991
|
-
case OverallIndexingStatusIds.Unstarted:
|
|
1265
|
+
function serializeOmnichainIndexingStatusSnapshot(indexingStatus) {
|
|
1266
|
+
switch (indexingStatus.omnichainStatus) {
|
|
1267
|
+
case OmnichainIndexingStatusIds.Unstarted:
|
|
992
1268
|
return {
|
|
993
|
-
|
|
994
|
-
chains:
|
|
1269
|
+
omnichainStatus: OmnichainIndexingStatusIds.Unstarted,
|
|
1270
|
+
chains: serializeChainIndexingSnapshots(indexingStatus.chains),
|
|
1271
|
+
omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
|
|
995
1272
|
};
|
|
996
|
-
case
|
|
1273
|
+
case OmnichainIndexingStatusIds.Backfill:
|
|
997
1274
|
return {
|
|
998
|
-
|
|
999
|
-
chains:
|
|
1275
|
+
omnichainStatus: OmnichainIndexingStatusIds.Backfill,
|
|
1276
|
+
chains: serializeChainIndexingSnapshots(indexingStatus.chains),
|
|
1000
1277
|
omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
|
|
1001
1278
|
};
|
|
1002
|
-
case
|
|
1279
|
+
case OmnichainIndexingStatusIds.Completed: {
|
|
1003
1280
|
return {
|
|
1004
|
-
|
|
1005
|
-
chains:
|
|
1281
|
+
omnichainStatus: OmnichainIndexingStatusIds.Completed,
|
|
1282
|
+
chains: serializeChainIndexingSnapshots(indexingStatus.chains),
|
|
1283
|
+
omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
|
|
1006
1284
|
};
|
|
1007
1285
|
}
|
|
1008
|
-
case
|
|
1286
|
+
case OmnichainIndexingStatusIds.Following:
|
|
1009
1287
|
return {
|
|
1010
|
-
|
|
1011
|
-
chains:
|
|
1012
|
-
overallApproxRealtimeDistance: indexingStatus.overallApproxRealtimeDistance,
|
|
1288
|
+
omnichainStatus: OmnichainIndexingStatusIds.Following,
|
|
1289
|
+
chains: serializeChainIndexingSnapshots(indexingStatus.chains),
|
|
1013
1290
|
omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
|
|
1014
1291
|
};
|
|
1015
1292
|
}
|
|
@@ -1045,17 +1322,42 @@ var ATTR_PROTOCOL_NAME = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol`;
|
|
|
1045
1322
|
var ATTR_PROTOCOL_STEP = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol.step`;
|
|
1046
1323
|
var ATTR_PROTOCOL_STEP_RESULT = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol.step.result`;
|
|
1047
1324
|
|
|
1048
|
-
// src/api/
|
|
1325
|
+
// src/api/deserialize.ts
|
|
1049
1326
|
import { prettifyError as prettifyError4 } from "zod/v4";
|
|
1050
1327
|
|
|
1051
1328
|
// src/api/zod-schemas.ts
|
|
1052
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
|
|
1053
1344
|
var ErrorResponseSchema = z4.object({
|
|
1054
1345
|
message: z4.string(),
|
|
1055
1346
|
details: z4.optional(z4.unknown())
|
|
1056
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
|
+
]);
|
|
1057
1359
|
|
|
1058
|
-
// src/api/
|
|
1360
|
+
// src/api/deserialize.ts
|
|
1059
1361
|
function deserializeErrorResponse(maybeErrorResponse) {
|
|
1060
1362
|
const parsed = ErrorResponseSchema.safeParse(maybeErrorResponse);
|
|
1061
1363
|
if (parsed.error) {
|
|
@@ -1065,12 +1367,28 @@ ${prettifyError4(parsed.error)}
|
|
|
1065
1367
|
}
|
|
1066
1368
|
return parsed.data;
|
|
1067
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
|
+
}
|
|
1068
1379
|
|
|
1069
|
-
// src/api/
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
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
|
+
}
|
|
1074
1392
|
|
|
1075
1393
|
// src/client-error.ts
|
|
1076
1394
|
var ClientError = class _ClientError extends Error {
|
|
@@ -1162,9 +1480,10 @@ var ENSNodeClient = class _ENSNodeClient {
|
|
|
1162
1480
|
/**
|
|
1163
1481
|
* Resolves the primary name of a specified address (Reverse Resolution) on a specific chain.
|
|
1164
1482
|
*
|
|
1165
|
-
* If the `address` specifies a valid
|
|
1166
|
-
*
|
|
1167
|
-
*
|
|
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.
|
|
1168
1487
|
*
|
|
1169
1488
|
* The returned Primary Name, if set, is guaranteed to be a [Normalized Name](https://ensnode.io/docs/reference/terminology#normalized-name).
|
|
1170
1489
|
* If the primary name set for the address is not normalized, `null` is returned as if no primary name was set.
|
|
@@ -1207,13 +1526,14 @@ var ENSNodeClient = class _ENSNodeClient {
|
|
|
1207
1526
|
/**
|
|
1208
1527
|
* Resolves the primary names of a specified address across multiple chains.
|
|
1209
1528
|
*
|
|
1210
|
-
*
|
|
1211
|
-
*
|
|
1212
|
-
*
|
|
1213
|
-
* 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.
|
|
1214
1533
|
*
|
|
1215
1534
|
* 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
|
|
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.
|
|
1217
1537
|
*
|
|
1218
1538
|
* @param address The Address whose Primary Names to resolve
|
|
1219
1539
|
* @param options additional options
|
|
@@ -1231,12 +1551,12 @@ var ENSNodeClient = class _ENSNodeClient {
|
|
|
1231
1551
|
*
|
|
1232
1552
|
* console.log(names);
|
|
1233
1553
|
* // {
|
|
1234
|
-
* // "1": "gregskril.eth",
|
|
1235
|
-
* // "10": "gregskril.eth",
|
|
1236
|
-
* // "8453": "greg.base.eth", //
|
|
1237
|
-
* // "42161": "gregskril.eth",
|
|
1238
|
-
* // "59144": "gregskril.eth",
|
|
1239
|
-
* // "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
|
|
1240
1560
|
* // }
|
|
1241
1561
|
*
|
|
1242
1562
|
* // Resolve the address' Primary Names on specific chain Ids
|
|
@@ -1291,28 +1611,14 @@ var ENSNodeClient = class _ENSNodeClient {
|
|
|
1291
1611
|
/**
|
|
1292
1612
|
* Fetch ENSNode Indexing Status
|
|
1293
1613
|
*
|
|
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
1614
|
* @returns {IndexingStatusResponse}
|
|
1306
1615
|
*
|
|
1307
1616
|
* @throws if the ENSNode request fails
|
|
1308
1617
|
* @throws if the ENSNode API returns an error response
|
|
1309
1618
|
* @throws if the ENSNode response breaks required invariants
|
|
1310
1619
|
*/
|
|
1311
|
-
async indexingStatus(
|
|
1620
|
+
async indexingStatus() {
|
|
1312
1621
|
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
1622
|
const response = await fetch(url);
|
|
1317
1623
|
let responseData;
|
|
1318
1624
|
try {
|
|
@@ -1321,40 +1627,48 @@ var ENSNodeClient = class _ENSNodeClient {
|
|
|
1321
1627
|
throw new Error("Malformed response data: invalid JSON");
|
|
1322
1628
|
}
|
|
1323
1629
|
if (!response.ok) {
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
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
|
-
}
|
|
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}`);
|
|
1343
1638
|
}
|
|
1344
1639
|
}
|
|
1345
|
-
return
|
|
1346
|
-
responseData
|
|
1347
|
-
);
|
|
1640
|
+
return deserializeIndexingStatusResponse(responseData);
|
|
1348
1641
|
}
|
|
1349
1642
|
};
|
|
1350
1643
|
|
|
1351
1644
|
// src/resolution/resolver-records-selection.ts
|
|
1352
1645
|
var isSelectionEmpty = (selection) => !selection.name && !selection.addresses?.length && !selection.texts?.length;
|
|
1353
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
|
+
|
|
1354
1668
|
// src/resolution/default-records-selection.ts
|
|
1355
1669
|
import {
|
|
1356
1670
|
DatasourceNames,
|
|
1357
|
-
ENSNamespaceIds as
|
|
1671
|
+
ENSNamespaceIds as ENSNamespaceIds3,
|
|
1358
1672
|
maybeGetDatasource
|
|
1359
1673
|
} from "@ensnode/datasources";
|
|
1360
1674
|
var getENSIP19SupportedCoinTypes = (namespace) => uniq(
|
|
@@ -1366,6 +1680,9 @@ var getENSIP19SupportedCoinTypes = (namespace) => uniq(
|
|
|
1366
1680
|
maybeGetDatasource(namespace, DatasourceNames.ReverseResolverScroll)
|
|
1367
1681
|
].filter((ds) => ds !== void 0).map((ds) => ds.chain.id)
|
|
1368
1682
|
).map(evmChainIdToCoinType);
|
|
1683
|
+
var getCommonCoinTypes = (namespace) => {
|
|
1684
|
+
return [ETH_COIN_TYPE, ...getENSIP19SupportedCoinTypes(namespace)];
|
|
1685
|
+
};
|
|
1369
1686
|
var TEXTS = [
|
|
1370
1687
|
"url",
|
|
1371
1688
|
"avatar",
|
|
@@ -1377,31 +1694,57 @@ var TEXTS = [
|
|
|
1377
1694
|
"com.github"
|
|
1378
1695
|
];
|
|
1379
1696
|
var DefaultRecordsSelection = {
|
|
1380
|
-
[
|
|
1381
|
-
addresses:
|
|
1697
|
+
[ENSNamespaceIds3.Mainnet]: {
|
|
1698
|
+
addresses: getCommonCoinTypes(ENSNamespaceIds3.Mainnet),
|
|
1382
1699
|
texts: TEXTS
|
|
1383
1700
|
},
|
|
1384
|
-
[
|
|
1385
|
-
addresses:
|
|
1701
|
+
[ENSNamespaceIds3.Sepolia]: {
|
|
1702
|
+
addresses: getCommonCoinTypes(ENSNamespaceIds3.Sepolia),
|
|
1386
1703
|
texts: TEXTS
|
|
1387
1704
|
},
|
|
1388
|
-
[
|
|
1389
|
-
addresses:
|
|
1705
|
+
[ENSNamespaceIds3.Holesky]: {
|
|
1706
|
+
addresses: getCommonCoinTypes(ENSNamespaceIds3.Holesky),
|
|
1390
1707
|
texts: TEXTS
|
|
1391
1708
|
},
|
|
1392
|
-
[
|
|
1393
|
-
addresses:
|
|
1709
|
+
[ENSNamespaceIds3.EnsTestEnv]: {
|
|
1710
|
+
addresses: getCommonCoinTypes(ENSNamespaceIds3.EnsTestEnv),
|
|
1394
1711
|
texts: TEXTS
|
|
1395
1712
|
}
|
|
1396
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
|
+
}
|
|
1397
1738
|
export {
|
|
1739
|
+
ADDR_REVERSE_NODE,
|
|
1398
1740
|
ATTR_PROTOCOL_NAME,
|
|
1399
1741
|
ATTR_PROTOCOL_STEP,
|
|
1400
1742
|
ATTR_PROTOCOL_STEP_RESULT,
|
|
1401
1743
|
BASENAMES_NODE,
|
|
1744
|
+
ChainIndexingConfigTypeIds,
|
|
1402
1745
|
ChainIndexingStatusIds,
|
|
1403
|
-
ChainIndexingStrategyIds,
|
|
1404
1746
|
ClientError,
|
|
1747
|
+
CrossChainIndexingStrategyIds,
|
|
1405
1748
|
DEFAULT_ENSNODE_API_URL,
|
|
1406
1749
|
DEFAULT_EVM_CHAIN_ID,
|
|
1407
1750
|
DEFAULT_EVM_COIN_TYPE,
|
|
@@ -1414,77 +1757,86 @@ export {
|
|
|
1414
1757
|
IndexingStatusResponseCodes,
|
|
1415
1758
|
LINEANAMES_NODE,
|
|
1416
1759
|
LruCache,
|
|
1417
|
-
|
|
1760
|
+
OmnichainIndexingStatusIds,
|
|
1418
1761
|
PROTOCOL_ATTRIBUTE_PREFIX,
|
|
1419
1762
|
PluginName,
|
|
1420
|
-
REVERSE_ROOT_NODES,
|
|
1421
1763
|
ROOT_NODE,
|
|
1764
|
+
ResolutionStatusIds,
|
|
1422
1765
|
ReverseResolutionProtocolStep,
|
|
1423
1766
|
TraceableENSProtocol,
|
|
1424
1767
|
accountIdEqual,
|
|
1425
1768
|
addrReverseLabel,
|
|
1769
|
+
asLowerCaseAddress,
|
|
1770
|
+
beautifyName,
|
|
1426
1771
|
bigintToCoinType,
|
|
1427
1772
|
buildEnsRainbowClientLabelSet,
|
|
1428
1773
|
buildLabelSetId,
|
|
1429
1774
|
buildLabelSetVersion,
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1775
|
+
buildUnresolvedIdentity,
|
|
1776
|
+
checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill,
|
|
1777
|
+
checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted,
|
|
1778
|
+
checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing,
|
|
1779
|
+
checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted,
|
|
1434
1780
|
coinTypeReverseLabel,
|
|
1435
1781
|
coinTypeToEvmChainId,
|
|
1436
1782
|
createIndexingConfig,
|
|
1783
|
+
createRealtimeIndexingStatusProjection,
|
|
1784
|
+
decodeDNSEncodedLiteralName,
|
|
1785
|
+
decodeDNSEncodedName,
|
|
1437
1786
|
deserializeBlockNumber,
|
|
1438
1787
|
deserializeBlockRef,
|
|
1439
1788
|
deserializeBlockrange,
|
|
1440
1789
|
deserializeChainId,
|
|
1790
|
+
deserializeChainIndexingStatusSnapshot,
|
|
1791
|
+
deserializeCrossChainIndexingStatusSnapshot,
|
|
1441
1792
|
deserializeDatetime,
|
|
1442
1793
|
deserializeDuration,
|
|
1443
|
-
deserializeENSIndexerIndexingStatus,
|
|
1444
1794
|
deserializeENSIndexerPublicConfig,
|
|
1445
1795
|
deserializeErrorResponse,
|
|
1796
|
+
deserializeIndexingStatusResponse,
|
|
1797
|
+
deserializeOmnichainIndexingStatusSnapshot,
|
|
1798
|
+
deserializeRealtimeIndexingStatusProjection,
|
|
1799
|
+
deserializeUnixTimestamp,
|
|
1446
1800
|
deserializeUrl,
|
|
1447
1801
|
encodeLabelHash,
|
|
1448
1802
|
evmChainIdToCoinType,
|
|
1449
|
-
|
|
1803
|
+
getCommonCoinTypes,
|
|
1804
|
+
getENSRootChainId,
|
|
1450
1805
|
getNameHierarchy,
|
|
1451
1806
|
getOmnichainIndexingCursor,
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
getStandbyChains,
|
|
1807
|
+
getOmnichainIndexingStatus,
|
|
1808
|
+
getResolvePrimaryNameChainIdParam,
|
|
1455
1809
|
getTimestampForHighestOmnichainKnownBlock,
|
|
1456
1810
|
getTimestampForLowestOmnichainStartBlock,
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
invariant_isSubgraphCompatibleRequirements,
|
|
1460
|
-
invariant_reverseResolversPluginNeedsResolverRecords,
|
|
1461
|
-
isLabelIndexable,
|
|
1811
|
+
interpretedLabelsToInterpretedName,
|
|
1812
|
+
isHttpProtocol,
|
|
1462
1813
|
isNormalizedLabel,
|
|
1463
1814
|
isNormalizedName,
|
|
1815
|
+
isResolvedIdentity,
|
|
1464
1816
|
isSelectionEmpty,
|
|
1465
1817
|
isSubgraphCompatible,
|
|
1818
|
+
isWebSocketProtocol,
|
|
1466
1819
|
labelHashToBytes,
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
makeIndexedChainIdsSchema,
|
|
1472
|
-
makeLabelSetIdSchema,
|
|
1473
|
-
makeLabelSetVersionSchema,
|
|
1474
|
-
makePluginsListSchema,
|
|
1820
|
+
labelhashLiteralLabel,
|
|
1821
|
+
literalLabelToInterpretedLabel,
|
|
1822
|
+
literalLabelsToInterpretedName,
|
|
1823
|
+
literalLabelsToLiteralName,
|
|
1475
1824
|
makeSubdomainNode,
|
|
1476
|
-
maybeHealLabelByReverseAddress,
|
|
1477
1825
|
parseNonNegativeInteger,
|
|
1478
1826
|
parseReverseName,
|
|
1479
1827
|
reverseName,
|
|
1480
1828
|
serializeChainId,
|
|
1481
|
-
|
|
1829
|
+
serializeChainIndexingSnapshots,
|
|
1830
|
+
serializeCrossChainIndexingStatusSnapshotOmnichain,
|
|
1482
1831
|
serializeDatetime,
|
|
1483
|
-
serializeENSIndexerIndexingStatus,
|
|
1484
1832
|
serializeENSIndexerPublicConfig,
|
|
1485
1833
|
serializeIndexedChainIds,
|
|
1834
|
+
serializeIndexingStatusResponse,
|
|
1835
|
+
serializeOmnichainIndexingStatusSnapshot,
|
|
1836
|
+
serializeRealtimeIndexingStatusProjection,
|
|
1486
1837
|
serializeUrl,
|
|
1487
|
-
|
|
1838
|
+
sortChainStatusesByStartBlockAsc,
|
|
1839
|
+
translateDefaultableChainIdToChainId,
|
|
1488
1840
|
uint256ToHex32,
|
|
1489
1841
|
uniq,
|
|
1490
1842
|
validateSupportedLabelSetAndVersion
|