@ensnode/ensnode-sdk 0.0.0-next-20260102143513
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/LICENSE +21 -0
- package/README.md +192 -0
- package/dist/index.cjs +4396 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +4592 -0
- package/dist/index.d.ts +4592 -0
- package/dist/index.js +4378 -0
- package/dist/index.js.map +1 -0
- package/package.json +66 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,4378 @@
|
|
|
1
|
+
// src/ensapi/config/deserialize.ts
|
|
2
|
+
import { prettifyError as prettifyError2, ZodError } from "zod/v4";
|
|
3
|
+
|
|
4
|
+
// src/ensapi/config/zod-schemas.ts
|
|
5
|
+
import { z as z4 } from "zod/v4";
|
|
6
|
+
|
|
7
|
+
// src/ensindexer/config/zod-schemas.ts
|
|
8
|
+
import z2 from "zod/v4";
|
|
9
|
+
|
|
10
|
+
// src/shared/account-id.ts
|
|
11
|
+
import { isAddressEqual } from "viem";
|
|
12
|
+
var accountIdEqual = (a, b) => {
|
|
13
|
+
return a.chainId === b.chainId && isAddressEqual(a.address, b.address);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// src/shared/address.ts
|
|
17
|
+
function asLowerCaseAddress(address) {
|
|
18
|
+
return address.toLowerCase();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// src/shared/cache/lru-cache.ts
|
|
22
|
+
var LruCache = class {
|
|
23
|
+
_cache = /* @__PURE__ */ new Map();
|
|
24
|
+
_capacity;
|
|
25
|
+
/**
|
|
26
|
+
* Create a new LRU cache with the given capacity.
|
|
27
|
+
*
|
|
28
|
+
* @param capacity The maximum number of items in the cache. If set to 0, the cache is effectively disabled.
|
|
29
|
+
* @throws Error if capacity is not a non-negative integer.
|
|
30
|
+
*/
|
|
31
|
+
constructor(capacity) {
|
|
32
|
+
if (!Number.isInteger(capacity)) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
`LruCache requires capacity to be an integer but a capacity of ${capacity} was requested.`
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
if (capacity < 0) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
`LruCache requires a non-negative capacity but a capacity of ${capacity} was requested.`
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
this._capacity = capacity;
|
|
43
|
+
}
|
|
44
|
+
set(key, value) {
|
|
45
|
+
this._cache.set(key, value);
|
|
46
|
+
if (this._cache.size > this._capacity) {
|
|
47
|
+
const oldestKey = this._cache.keys().next().value;
|
|
48
|
+
this._cache.delete(oldestKey);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
get(key) {
|
|
52
|
+
const value = this._cache.get(key);
|
|
53
|
+
if (value) {
|
|
54
|
+
this._cache.delete(key);
|
|
55
|
+
this._cache.set(key, value);
|
|
56
|
+
}
|
|
57
|
+
return value;
|
|
58
|
+
}
|
|
59
|
+
clear() {
|
|
60
|
+
this._cache.clear();
|
|
61
|
+
}
|
|
62
|
+
get size() {
|
|
63
|
+
return this._cache.size;
|
|
64
|
+
}
|
|
65
|
+
get capacity() {
|
|
66
|
+
return this._capacity;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// src/shared/cache/swr-cache.ts
|
|
71
|
+
import { secondsToMilliseconds } from "date-fns";
|
|
72
|
+
import { getUnixTime } from "date-fns/getUnixTime";
|
|
73
|
+
|
|
74
|
+
// src/shared/deserialize.ts
|
|
75
|
+
import { prettifyError } from "zod/v4";
|
|
76
|
+
|
|
77
|
+
// src/shared/zod-schemas.ts
|
|
78
|
+
import { AccountId as CaipAccountId } from "caip";
|
|
79
|
+
import { isAddress as isAddress2, isHex as isHex2, size } from "viem";
|
|
80
|
+
import z from "zod/v4";
|
|
81
|
+
|
|
82
|
+
// src/ens/index.ts
|
|
83
|
+
import { getENSRootChainId } from "@ensnode/datasources";
|
|
84
|
+
|
|
85
|
+
// src/ens/coin-type.ts
|
|
86
|
+
import {
|
|
87
|
+
coinTypeToEvmChainId as _coinTypeToEvmChainId,
|
|
88
|
+
evmChainIdToCoinType as _evmChainIdToCoinType
|
|
89
|
+
} from "@ensdomains/address-encoder/utils";
|
|
90
|
+
var ETH_COIN_TYPE = 60;
|
|
91
|
+
var DEFAULT_EVM_CHAIN_ID = 0;
|
|
92
|
+
var DEFAULT_EVM_COIN_TYPE = 2147483648;
|
|
93
|
+
var coinTypeToEvmChainId = (coinType) => {
|
|
94
|
+
if (coinType === ETH_COIN_TYPE) return 1;
|
|
95
|
+
return _coinTypeToEvmChainId(coinType);
|
|
96
|
+
};
|
|
97
|
+
var evmChainIdToCoinType = (chainId) => {
|
|
98
|
+
if (chainId === 1) return ETH_COIN_TYPE;
|
|
99
|
+
return _evmChainIdToCoinType(chainId);
|
|
100
|
+
};
|
|
101
|
+
var bigintToCoinType = (value) => {
|
|
102
|
+
if (value > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
103
|
+
throw new Error(`'${value}' cannot represent as CoinType, it is too large.`);
|
|
104
|
+
}
|
|
105
|
+
return Number(value);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// src/ens/constants.ts
|
|
109
|
+
import { namehash } from "viem";
|
|
110
|
+
var ROOT_NODE = namehash("");
|
|
111
|
+
var ETH_NODE = namehash("eth");
|
|
112
|
+
var BASENAMES_NODE = namehash("base.eth");
|
|
113
|
+
var LINEANAMES_NODE = namehash("linea.eth");
|
|
114
|
+
var ADDR_REVERSE_NODE = namehash("addr.reverse");
|
|
115
|
+
|
|
116
|
+
// src/ens/dns-encoded-name.ts
|
|
117
|
+
import { bytesToString, hexToBytes } from "viem";
|
|
118
|
+
function decodeDNSEncodedLiteralName(packet) {
|
|
119
|
+
return decodeDNSEncodedName(packet);
|
|
120
|
+
}
|
|
121
|
+
function decodeDNSEncodedName(packet) {
|
|
122
|
+
const segments = [];
|
|
123
|
+
const bytes = hexToBytes(packet);
|
|
124
|
+
if (bytes.length === 0) throw new Error(`Packet is empty.`);
|
|
125
|
+
let offset = 0;
|
|
126
|
+
while (offset < bytes.length) {
|
|
127
|
+
const len = bytes[offset];
|
|
128
|
+
if (len === void 0) {
|
|
129
|
+
throw new Error(`Invariant: bytes[offset] is undefined after offset < bytes.length check.`);
|
|
130
|
+
}
|
|
131
|
+
if (len < 0 || len > 255) {
|
|
132
|
+
throw new Error(
|
|
133
|
+
`Invariant: this should be literally impossible, but an unsigned byte was less than zero or greater than 255. The value in question is ${len}`
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
if (len === 0) break;
|
|
137
|
+
const segment = bytesToString(bytes.subarray(offset + 1, offset + len + 1));
|
|
138
|
+
segments.push(segment);
|
|
139
|
+
offset += len + 1;
|
|
140
|
+
}
|
|
141
|
+
if (offset >= bytes.length) throw new Error(`Overflow, offset >= bytes.length`);
|
|
142
|
+
if (offset !== bytes.length - 1) throw new Error(`Junk at end of name`);
|
|
143
|
+
return segments;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// src/ens/labelhash.ts
|
|
147
|
+
import { isHex } from "viem";
|
|
148
|
+
function isLabelHash(maybeLabelHash) {
|
|
149
|
+
const expectedLength = maybeLabelHash.length === 66;
|
|
150
|
+
const expectedEncoding = isHex(maybeLabelHash);
|
|
151
|
+
const expectedCasing = maybeLabelHash === maybeLabelHash.toLowerCase();
|
|
152
|
+
return expectedLength && expectedEncoding && expectedCasing;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// src/ens/encode-labelhash.ts
|
|
156
|
+
var encodeLabelHash = (labelHash) => `[${labelHash.slice(2)}]`;
|
|
157
|
+
function isEncodedLabelHash(maybeEncodedLabelHash) {
|
|
158
|
+
const expectedFormatting = maybeEncodedLabelHash.startsWith("[") && maybeEncodedLabelHash.endsWith("]");
|
|
159
|
+
const includesLabelHash = isLabelHash(`0x${maybeEncodedLabelHash.slice(1, -1)}`);
|
|
160
|
+
return expectedFormatting && includesLabelHash;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// src/ens/is-normalized.ts
|
|
164
|
+
import { normalize } from "viem/ens";
|
|
165
|
+
function isNormalizedName(name) {
|
|
166
|
+
try {
|
|
167
|
+
return name === normalize(name);
|
|
168
|
+
} catch {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function isNormalizedLabel(label) {
|
|
173
|
+
if (label === "") return false;
|
|
174
|
+
if (label.includes(".")) return false;
|
|
175
|
+
try {
|
|
176
|
+
return label === normalize(label);
|
|
177
|
+
} catch {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// src/ens/names.ts
|
|
183
|
+
import { ens_beautify } from "@adraffy/ens-normalize";
|
|
184
|
+
var ENS_ROOT = "";
|
|
185
|
+
var getNameHierarchy = (name) => name.split(".").map((_, i, labels) => labels.slice(i).join("."));
|
|
186
|
+
var getParentNameFQDN = (name) => {
|
|
187
|
+
if (name === ENS_ROOT) {
|
|
188
|
+
throw new Error("There is no parent name for ENS Root.");
|
|
189
|
+
}
|
|
190
|
+
const labels = name.split(".");
|
|
191
|
+
if (labels.length === 1) {
|
|
192
|
+
return ENS_ROOT;
|
|
193
|
+
}
|
|
194
|
+
return labels.slice(1).join(".");
|
|
195
|
+
};
|
|
196
|
+
var beautifyName = (name) => {
|
|
197
|
+
const beautifiedLabels = name.split(".").map((label) => {
|
|
198
|
+
if (isNormalizedLabel(label)) {
|
|
199
|
+
return ens_beautify(label);
|
|
200
|
+
} else {
|
|
201
|
+
return label;
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
return beautifiedLabels.join(".");
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
// src/ens/parse-reverse-name.ts
|
|
208
|
+
import { hexToBigInt, isAddress } from "viem";
|
|
209
|
+
var REVERSE_NAME_REGEX = /^([0-9a-fA-F]+)\.([0-9a-f]{1,64}|addr|default)\.reverse$/;
|
|
210
|
+
var parseAddressLabel = (addressLabel) => {
|
|
211
|
+
const maybeAddress = `0x${addressLabel}`;
|
|
212
|
+
if (!isAddress(maybeAddress)) {
|
|
213
|
+
throw new Error(`Invalid EVM address "${maybeAddress}"`);
|
|
214
|
+
}
|
|
215
|
+
return asLowerCaseAddress(maybeAddress);
|
|
216
|
+
};
|
|
217
|
+
var parseCoinTypeLabel = (coinTypeLabel) => {
|
|
218
|
+
if (coinTypeLabel === "default") return DEFAULT_EVM_COIN_TYPE;
|
|
219
|
+
if (coinTypeLabel === "addr") return ETH_COIN_TYPE;
|
|
220
|
+
return bigintToCoinType(hexToBigInt(`0x${coinTypeLabel}`));
|
|
221
|
+
};
|
|
222
|
+
function parseReverseName(name) {
|
|
223
|
+
const match = name.match(REVERSE_NAME_REGEX);
|
|
224
|
+
if (!match) return null;
|
|
225
|
+
try {
|
|
226
|
+
const [, addressLabel, coinTypeLabel] = match;
|
|
227
|
+
if (!addressLabel) return null;
|
|
228
|
+
if (!coinTypeLabel) return null;
|
|
229
|
+
return {
|
|
230
|
+
address: parseAddressLabel(addressLabel),
|
|
231
|
+
coinType: parseCoinTypeLabel(coinTypeLabel)
|
|
232
|
+
};
|
|
233
|
+
} catch {
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// src/ens/reverse-name.ts
|
|
239
|
+
var addrReverseLabel = (address) => address.slice(2);
|
|
240
|
+
var coinTypeReverseLabel = (coinType) => coinType.toString(16);
|
|
241
|
+
function reverseName(address, coinType) {
|
|
242
|
+
const label = addrReverseLabel(address);
|
|
243
|
+
const middle = (() => {
|
|
244
|
+
switch (coinType) {
|
|
245
|
+
case ETH_COIN_TYPE:
|
|
246
|
+
return "addr";
|
|
247
|
+
case DEFAULT_EVM_COIN_TYPE:
|
|
248
|
+
return "default";
|
|
249
|
+
default:
|
|
250
|
+
return coinTypeReverseLabel(coinType);
|
|
251
|
+
}
|
|
252
|
+
})();
|
|
253
|
+
return `${label}.${middle}.reverse`;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// src/ens/subname-helpers.ts
|
|
257
|
+
import { concat, keccak256, toHex } from "viem";
|
|
258
|
+
var makeSubdomainNode = (labelHash, node) => keccak256(concat([node, labelHash]));
|
|
259
|
+
var uint256ToHex32 = (num) => toHex(num, { size: 32 });
|
|
260
|
+
|
|
261
|
+
// src/ens/types.ts
|
|
262
|
+
import { ENSNamespaceIds } from "@ensnode/datasources";
|
|
263
|
+
|
|
264
|
+
// src/shared/currencies.ts
|
|
265
|
+
var CurrencyIds = {
|
|
266
|
+
ETH: "ETH",
|
|
267
|
+
USDC: "USDC",
|
|
268
|
+
DAI: "DAI"
|
|
269
|
+
};
|
|
270
|
+
var currencyInfo = {
|
|
271
|
+
[CurrencyIds.ETH]: {
|
|
272
|
+
id: CurrencyIds.ETH,
|
|
273
|
+
name: "ETH",
|
|
274
|
+
decimals: 18
|
|
275
|
+
},
|
|
276
|
+
[CurrencyIds.USDC]: {
|
|
277
|
+
id: CurrencyIds.USDC,
|
|
278
|
+
name: "USDC",
|
|
279
|
+
decimals: 6
|
|
280
|
+
},
|
|
281
|
+
[CurrencyIds.DAI]: {
|
|
282
|
+
id: CurrencyIds.DAI,
|
|
283
|
+
name: "Dai Stablecoin",
|
|
284
|
+
decimals: 18
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
function getCurrencyInfo(currencyId) {
|
|
288
|
+
return currencyInfo[currencyId];
|
|
289
|
+
}
|
|
290
|
+
function priceEth(amount) {
|
|
291
|
+
return {
|
|
292
|
+
amount,
|
|
293
|
+
currency: CurrencyIds.ETH
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
function priceUsdc(amount) {
|
|
297
|
+
return {
|
|
298
|
+
amount,
|
|
299
|
+
currency: CurrencyIds.USDC
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
function priceDai(amount) {
|
|
303
|
+
return {
|
|
304
|
+
amount,
|
|
305
|
+
currency: CurrencyIds.DAI
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
function isPriceCurrencyEqual(priceA, priceB) {
|
|
309
|
+
return priceA.currency === priceB.currency;
|
|
310
|
+
}
|
|
311
|
+
function isPriceEqual(priceA, priceB) {
|
|
312
|
+
return isPriceCurrencyEqual(priceA, priceB) && priceA.amount === priceB.amount;
|
|
313
|
+
}
|
|
314
|
+
function addPrices(...prices) {
|
|
315
|
+
const firstPrice = prices[0];
|
|
316
|
+
const allPricesInSameCurrency = prices.every((price) => isPriceCurrencyEqual(firstPrice, price));
|
|
317
|
+
if (allPricesInSameCurrency === false) {
|
|
318
|
+
throw new Error("All prices must have the same currency to be added together.");
|
|
319
|
+
}
|
|
320
|
+
const { currency } = firstPrice;
|
|
321
|
+
return prices.reduce(
|
|
322
|
+
(acc, price) => ({
|
|
323
|
+
amount: acc.amount + price.amount,
|
|
324
|
+
currency
|
|
325
|
+
}),
|
|
326
|
+
{
|
|
327
|
+
amount: 0n,
|
|
328
|
+
currency: firstPrice.currency
|
|
329
|
+
}
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// src/shared/reinterpretation.ts
|
|
334
|
+
import { labelhash as labelToLabelHash } from "viem";
|
|
335
|
+
function reinterpretLabel(label) {
|
|
336
|
+
if (label === "") {
|
|
337
|
+
throw new Error(
|
|
338
|
+
`Cannot reinterpret an empty label that violates the invariants of an InterpretedLabel.`
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
if (isEncodedLabelHash(label)) return label;
|
|
342
|
+
if (isNormalizedLabel(label)) return label;
|
|
343
|
+
return encodeLabelHash(labelToLabelHash(label));
|
|
344
|
+
}
|
|
345
|
+
function reinterpretName(name) {
|
|
346
|
+
if (name === "") return name;
|
|
347
|
+
const interpretedLabels = name.split(".");
|
|
348
|
+
const reinterpretedLabels = interpretedLabels.map(reinterpretLabel);
|
|
349
|
+
const reinterpretedName = reinterpretedLabels.join(".");
|
|
350
|
+
return reinterpretedName;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// src/shared/zod-schemas.ts
|
|
354
|
+
var makeFiniteNonNegativeNumberSchema = (valueLabel = "Value") => z.number({
|
|
355
|
+
// NOTE: Zod's implementation of `number` automatically rejects NaN and Infinity values.
|
|
356
|
+
// and therefore the finite check is implicit.
|
|
357
|
+
error: `${valueLabel} must be a finite number.`
|
|
358
|
+
}).nonnegative({
|
|
359
|
+
error: `${valueLabel} must be a non-negative number (>=0).`
|
|
360
|
+
});
|
|
361
|
+
var makeIntegerSchema = (valueLabel = "Value") => z.int({
|
|
362
|
+
error: `${valueLabel} must be an integer.`
|
|
363
|
+
});
|
|
364
|
+
var makePositiveIntegerSchema = (valueLabel = "Value") => makeIntegerSchema(valueLabel).positive({
|
|
365
|
+
error: `${valueLabel} must be a positive integer (>0).`
|
|
366
|
+
});
|
|
367
|
+
var makeNonNegativeIntegerSchema = (valueLabel = "Value") => makeIntegerSchema(valueLabel).nonnegative({
|
|
368
|
+
error: `${valueLabel} must be a non-negative integer (>=0).`
|
|
369
|
+
});
|
|
370
|
+
var makeDurationSchema = (valueLabel = "Value") => z.coerce.number({
|
|
371
|
+
error: `${valueLabel} must be a number.`
|
|
372
|
+
}).pipe(makeNonNegativeIntegerSchema(valueLabel));
|
|
373
|
+
var makeChainIdSchema = (valueLabel = "Chain ID") => makePositiveIntegerSchema(valueLabel).transform((val) => val);
|
|
374
|
+
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}`));
|
|
375
|
+
var makeLowercaseAddressSchema = (valueLabel = "EVM address") => z.string().check((ctx) => {
|
|
376
|
+
if (!isAddress2(ctx.value)) {
|
|
377
|
+
ctx.issues.push({
|
|
378
|
+
code: "custom",
|
|
379
|
+
message: `${valueLabel} must be a valid EVM address`,
|
|
380
|
+
input: ctx.value
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
}).transform((val) => asLowerCaseAddress(val));
|
|
384
|
+
var makeDatetimeSchema = (valueLabel = "Datetime string") => z.iso.datetime({ error: `${valueLabel} must be a string in ISO 8601 format.` }).transform((v) => new Date(v));
|
|
385
|
+
var makeUnixTimestampSchema = (valueLabel = "Timestamp") => makeIntegerSchema(valueLabel);
|
|
386
|
+
var makeUrlSchema = (valueLabel = "Value") => z.url({
|
|
387
|
+
error: `${valueLabel} must be a valid URL string (e.g., http://localhost:8080 or https://example.com).`,
|
|
388
|
+
abort: true
|
|
389
|
+
}).transform((v) => new URL(v));
|
|
390
|
+
var makeBlockNumberSchema = (valueLabel = "Block number") => makeNonNegativeIntegerSchema(valueLabel);
|
|
391
|
+
var makeBlockrangeSchema = (valueLabel = "Value") => z.strictObject(
|
|
392
|
+
{
|
|
393
|
+
startBlock: makeBlockNumberSchema(`${valueLabel}.startBlock`).optional(),
|
|
394
|
+
endBlock: makeBlockNumberSchema(`${valueLabel}.endBlock`).optional()
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
error: `${valueLabel} must be a valid Blockrange object.`
|
|
398
|
+
}
|
|
399
|
+
).refine(
|
|
400
|
+
(v) => {
|
|
401
|
+
if (v.startBlock && v.endBlock) {
|
|
402
|
+
return v.startBlock <= v.endBlock;
|
|
403
|
+
}
|
|
404
|
+
return true;
|
|
405
|
+
},
|
|
406
|
+
{ error: `${valueLabel}: startBlock must be before or equal to endBlock` }
|
|
407
|
+
);
|
|
408
|
+
var makeBlockRefSchema = (valueLabel = "Value") => z.strictObject(
|
|
409
|
+
{
|
|
410
|
+
timestamp: makeUnixTimestampSchema(`${valueLabel}.timestamp`),
|
|
411
|
+
number: makeBlockNumberSchema(`${valueLabel}.number`)
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
error: `${valueLabel} must be a valid BlockRef object.`
|
|
415
|
+
}
|
|
416
|
+
);
|
|
417
|
+
var makeENSNamespaceIdSchema = (valueLabel = "ENSNamespaceId") => z.enum(ENSNamespaceIds, {
|
|
418
|
+
error() {
|
|
419
|
+
return `Invalid ${valueLabel}. Supported ENS namespace IDs are: ${Object.keys(ENSNamespaceIds).join(", ")}`;
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
var makePriceAmountSchema = (valueLabel = "Amount") => z.coerce.bigint({
|
|
423
|
+
error: `${valueLabel} must represent a bigint.`
|
|
424
|
+
}).nonnegative({
|
|
425
|
+
error: `${valueLabel} must not be negative.`
|
|
426
|
+
});
|
|
427
|
+
var makePriceCurrencySchema = (currency, valueLabel = "Price Currency") => z.strictObject({
|
|
428
|
+
amount: makePriceAmountSchema(`${valueLabel} amount`),
|
|
429
|
+
currency: z.literal(currency, {
|
|
430
|
+
error: `${valueLabel} currency must be set to '${currency}'.`
|
|
431
|
+
})
|
|
432
|
+
});
|
|
433
|
+
var makePriceEthSchema = (valueLabel = "Price ETH") => makePriceCurrencySchema(CurrencyIds.ETH, valueLabel).transform((v) => v);
|
|
434
|
+
var makeAccountIdSchema = (valueLabel = "AccountId") => z.strictObject({
|
|
435
|
+
chainId: makeChainIdSchema(`${valueLabel} chain ID`),
|
|
436
|
+
address: makeLowercaseAddressSchema(`${valueLabel} address`)
|
|
437
|
+
});
|
|
438
|
+
var makeAccountIdStringSchema = (valueLabel = "Account ID String") => z.coerce.string().transform((v) => {
|
|
439
|
+
const result = new CaipAccountId(v);
|
|
440
|
+
return {
|
|
441
|
+
chainId: Number(result.chainId.reference),
|
|
442
|
+
address: result.address
|
|
443
|
+
};
|
|
444
|
+
}).pipe(makeAccountIdSchema(valueLabel));
|
|
445
|
+
var makeHexStringSchema = (options, valueLabel = "String representation of bytes array") => z.string().check(function invariant_isHexEncoded(ctx) {
|
|
446
|
+
if (!isHex2(ctx.value)) {
|
|
447
|
+
ctx.issues.push({
|
|
448
|
+
code: "custom",
|
|
449
|
+
input: ctx.value,
|
|
450
|
+
message: `${valueLabel} must be a hexadecimal value which starts with '0x'.`
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
}).transform((v) => v).check(function invariant_encodesRequiredBytesCount(ctx) {
|
|
454
|
+
const expectedBytesCount = options.bytesCount;
|
|
455
|
+
const actualBytesCount = size(ctx.value);
|
|
456
|
+
if (actualBytesCount !== expectedBytesCount) {
|
|
457
|
+
ctx.issues.push({
|
|
458
|
+
code: "custom",
|
|
459
|
+
input: ctx.value,
|
|
460
|
+
message: `${valueLabel} must represent exactly ${expectedBytesCount} bytes. Currently represented bytes count: ${actualBytesCount}.`
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
var makeNodeSchema = (valueLabel = "Node") => makeHexStringSchema({ bytesCount: 32 }, valueLabel);
|
|
465
|
+
var makeTransactionHashSchema = (valueLabel = "Transaction hash") => makeHexStringSchema({ bytesCount: 32 }, valueLabel);
|
|
466
|
+
var makeReinterpretedNameSchema = (valueLabel = "Reinterpreted Name") => z.string().transform((v) => v).check((ctx) => {
|
|
467
|
+
try {
|
|
468
|
+
reinterpretName(ctx.value);
|
|
469
|
+
} catch (error) {
|
|
470
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
471
|
+
ctx.issues.push({
|
|
472
|
+
code: "custom",
|
|
473
|
+
input: ctx.value,
|
|
474
|
+
message: `${valueLabel} cannot be reinterpreted: ${errorMessage}`
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
}).transform(reinterpretName);
|
|
478
|
+
|
|
479
|
+
// src/shared/deserialize.ts
|
|
480
|
+
function deserializeChainId(maybeChainId, valueLabel) {
|
|
481
|
+
const schema = makeChainIdStringSchema(valueLabel);
|
|
482
|
+
const parsed = schema.safeParse(maybeChainId);
|
|
483
|
+
if (parsed.error) {
|
|
484
|
+
throw new Error(`Cannot deserialize ChainId:
|
|
485
|
+
${prettifyError(parsed.error)}
|
|
486
|
+
`);
|
|
487
|
+
}
|
|
488
|
+
return parsed.data;
|
|
489
|
+
}
|
|
490
|
+
function deserializeDatetime(maybeDatetime, valueLabel) {
|
|
491
|
+
const schema = makeDatetimeSchema(valueLabel);
|
|
492
|
+
const parsed = schema.safeParse(maybeDatetime);
|
|
493
|
+
if (parsed.error) {
|
|
494
|
+
throw new Error(`Cannot deserialize Datetime:
|
|
495
|
+
${prettifyError(parsed.error)}
|
|
496
|
+
`);
|
|
497
|
+
}
|
|
498
|
+
return parsed.data;
|
|
499
|
+
}
|
|
500
|
+
function deserializeUnixTimestamp(maybeTimestamp, valueLabel) {
|
|
501
|
+
const schema = makeUnixTimestampSchema(valueLabel);
|
|
502
|
+
const parsed = schema.safeParse(maybeTimestamp);
|
|
503
|
+
if (parsed.error) {
|
|
504
|
+
throw new Error(`Cannot deserialize Unix Timestamp:
|
|
505
|
+
${prettifyError(parsed.error)}
|
|
506
|
+
`);
|
|
507
|
+
}
|
|
508
|
+
return parsed.data;
|
|
509
|
+
}
|
|
510
|
+
function deserializeUrl(maybeUrl, valueLabel) {
|
|
511
|
+
const schema = makeUrlSchema(valueLabel);
|
|
512
|
+
const parsed = schema.safeParse(maybeUrl);
|
|
513
|
+
if (parsed.error) {
|
|
514
|
+
throw new Error(`Cannot deserialize URL:
|
|
515
|
+
${prettifyError(parsed.error)}
|
|
516
|
+
`);
|
|
517
|
+
}
|
|
518
|
+
return parsed.data;
|
|
519
|
+
}
|
|
520
|
+
function deserializeBlockNumber(maybeBlockNumber, valueLabel) {
|
|
521
|
+
const schema = makeBlockNumberSchema(valueLabel);
|
|
522
|
+
const parsed = schema.safeParse(maybeBlockNumber);
|
|
523
|
+
if (parsed.error) {
|
|
524
|
+
throw new Error(`Cannot deserialize BlockNumber:
|
|
525
|
+
${prettifyError(parsed.error)}
|
|
526
|
+
`);
|
|
527
|
+
}
|
|
528
|
+
return parsed.data;
|
|
529
|
+
}
|
|
530
|
+
function deserializeBlockrange(maybeBlockrange, valueLabel) {
|
|
531
|
+
const schema = makeBlockrangeSchema(valueLabel);
|
|
532
|
+
const parsed = schema.safeParse(maybeBlockrange);
|
|
533
|
+
if (parsed.error) {
|
|
534
|
+
throw new Error(`Cannot deserialize Blockrange:
|
|
535
|
+
${prettifyError(parsed.error)}
|
|
536
|
+
`);
|
|
537
|
+
}
|
|
538
|
+
return parsed.data;
|
|
539
|
+
}
|
|
540
|
+
function deserializeBlockRef(maybeBlockRef, valueLabel) {
|
|
541
|
+
const schema = makeBlockRefSchema(valueLabel);
|
|
542
|
+
const parsed = schema.safeParse(maybeBlockRef);
|
|
543
|
+
if (parsed.error) {
|
|
544
|
+
throw new Error(`Cannot deserialize BlockRef:
|
|
545
|
+
${prettifyError(parsed.error)}
|
|
546
|
+
`);
|
|
547
|
+
}
|
|
548
|
+
return parsed.data;
|
|
549
|
+
}
|
|
550
|
+
function deserializeDuration(maybeDuration, valueLabel) {
|
|
551
|
+
const schema = makeDurationSchema(valueLabel);
|
|
552
|
+
const parsed = schema.safeParse(maybeDuration);
|
|
553
|
+
if (parsed.error) {
|
|
554
|
+
throw new RangeError(`Cannot deserialize Duration:
|
|
555
|
+
${prettifyError(parsed.error)}
|
|
556
|
+
`);
|
|
557
|
+
}
|
|
558
|
+
return parsed.data;
|
|
559
|
+
}
|
|
560
|
+
function parseAccountId(maybeAccountId, valueLabel) {
|
|
561
|
+
const schema = makeAccountIdStringSchema(valueLabel);
|
|
562
|
+
const parsed = schema.safeParse(maybeAccountId);
|
|
563
|
+
if (parsed.error) {
|
|
564
|
+
throw new RangeError(`Cannot deserialize AccountId:
|
|
565
|
+
${prettifyError(parsed.error)}
|
|
566
|
+
`);
|
|
567
|
+
}
|
|
568
|
+
return parsed.data;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// src/shared/datetime.ts
|
|
572
|
+
function durationBetween(start, end) {
|
|
573
|
+
return deserializeDuration(end - start, "Duration");
|
|
574
|
+
}
|
|
575
|
+
function addDuration(timestamp, duration) {
|
|
576
|
+
return deserializeUnixTimestamp(timestamp + duration, "UnixTimestamp");
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// src/shared/cache/swr-cache.ts
|
|
580
|
+
var SWRCache = class {
|
|
581
|
+
constructor(options) {
|
|
582
|
+
this.options = options;
|
|
583
|
+
if (options.proactiveRevalidationInterval) {
|
|
584
|
+
this.backgroundInterval = setInterval(
|
|
585
|
+
() => this.revalidate(),
|
|
586
|
+
secondsToMilliseconds(options.proactiveRevalidationInterval)
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
if (options.proactivelyInitialize) this.revalidate();
|
|
590
|
+
}
|
|
591
|
+
cache = null;
|
|
592
|
+
inProgressRevalidate = null;
|
|
593
|
+
backgroundInterval = null;
|
|
594
|
+
async revalidate() {
|
|
595
|
+
if (!this.inProgressRevalidate) {
|
|
596
|
+
this.inProgressRevalidate = this.options.fn().then((result) => {
|
|
597
|
+
this.cache = {
|
|
598
|
+
result,
|
|
599
|
+
updatedAt: getUnixTime(/* @__PURE__ */ new Date())
|
|
600
|
+
};
|
|
601
|
+
}).catch((error) => {
|
|
602
|
+
if (!this.cache) {
|
|
603
|
+
this.cache = {
|
|
604
|
+
// ensure thrown value is always an Error instance
|
|
605
|
+
result: error instanceof Error ? error : new Error(String(error)),
|
|
606
|
+
updatedAt: getUnixTime(/* @__PURE__ */ new Date())
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
}).finally(() => {
|
|
610
|
+
this.inProgressRevalidate = null;
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
return this.inProgressRevalidate;
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Read the most recently cached result from the `SWRCache`.
|
|
617
|
+
*
|
|
618
|
+
* @returns a `ValueType` that was most recently successfully returned by `fn` or `Error` if `fn`
|
|
619
|
+
* has never successfully returned.
|
|
620
|
+
*/
|
|
621
|
+
async read() {
|
|
622
|
+
if (!this.cache) await this.revalidate();
|
|
623
|
+
if (!this.cache) throw new Error("never");
|
|
624
|
+
if (durationBetween(this.cache.updatedAt, getUnixTime(/* @__PURE__ */ new Date())) > this.options.ttl) {
|
|
625
|
+
this.revalidate();
|
|
626
|
+
}
|
|
627
|
+
return this.cache.result;
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Destroys the background revalidation interval, if exists.
|
|
631
|
+
*/
|
|
632
|
+
destroy() {
|
|
633
|
+
if (this.backgroundInterval) {
|
|
634
|
+
clearInterval(this.backgroundInterval);
|
|
635
|
+
this.backgroundInterval = null;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
|
|
640
|
+
// src/shared/cache/ttl-cache.ts
|
|
641
|
+
import { getUnixTime as getUnixTime2 } from "date-fns/getUnixTime";
|
|
642
|
+
var TtlCache = class {
|
|
643
|
+
_cache = /* @__PURE__ */ new Map();
|
|
644
|
+
_ttl;
|
|
645
|
+
/**
|
|
646
|
+
* Create a new TTL cache with the given TTL.
|
|
647
|
+
*
|
|
648
|
+
* @param ttl Time-to-live duration in seconds. Items expire after this duration.
|
|
649
|
+
*/
|
|
650
|
+
constructor(ttl) {
|
|
651
|
+
this._ttl = ttl;
|
|
652
|
+
}
|
|
653
|
+
_cleanup() {
|
|
654
|
+
const now = getUnixTime2(/* @__PURE__ */ new Date());
|
|
655
|
+
for (const [key, entry] of this._cache.entries()) {
|
|
656
|
+
if (entry.expiresAt <= now) {
|
|
657
|
+
this._cache.delete(key);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
set(key, value) {
|
|
662
|
+
this._cleanup();
|
|
663
|
+
const expiresAt = addDuration(getUnixTime2(/* @__PURE__ */ new Date()), this._ttl);
|
|
664
|
+
this._cache.set(key, { value, expiresAt });
|
|
665
|
+
}
|
|
666
|
+
get(key) {
|
|
667
|
+
this._cleanup();
|
|
668
|
+
const entry = this._cache.get(key);
|
|
669
|
+
if (!entry) {
|
|
670
|
+
return void 0;
|
|
671
|
+
}
|
|
672
|
+
if (entry.expiresAt <= getUnixTime2(/* @__PURE__ */ new Date())) {
|
|
673
|
+
this._cache.delete(key);
|
|
674
|
+
return void 0;
|
|
675
|
+
}
|
|
676
|
+
return entry.value;
|
|
677
|
+
}
|
|
678
|
+
clear() {
|
|
679
|
+
this._cache.clear();
|
|
680
|
+
}
|
|
681
|
+
get size() {
|
|
682
|
+
this._cleanup();
|
|
683
|
+
return this._cache.size;
|
|
684
|
+
}
|
|
685
|
+
get capacity() {
|
|
686
|
+
return Number.MAX_SAFE_INTEGER;
|
|
687
|
+
}
|
|
688
|
+
has(key) {
|
|
689
|
+
this._cleanup();
|
|
690
|
+
const entry = this._cache.get(key);
|
|
691
|
+
if (!entry) {
|
|
692
|
+
return false;
|
|
693
|
+
}
|
|
694
|
+
if (entry.expiresAt <= getUnixTime2(/* @__PURE__ */ new Date())) {
|
|
695
|
+
this._cache.delete(key);
|
|
696
|
+
return false;
|
|
697
|
+
}
|
|
698
|
+
return true;
|
|
699
|
+
}
|
|
700
|
+
delete(key) {
|
|
701
|
+
return this._cache.delete(key);
|
|
702
|
+
}
|
|
703
|
+
};
|
|
704
|
+
|
|
705
|
+
// src/shared/collections.ts
|
|
706
|
+
var uniq = (arr) => [...new Set(arr)];
|
|
707
|
+
|
|
708
|
+
// src/shared/datasource-contract.ts
|
|
709
|
+
import { maybeGetDatasource } from "@ensnode/datasources";
|
|
710
|
+
var maybeGetDatasourceContract = (namespaceId, datasourceName, contractName) => {
|
|
711
|
+
const datasource = maybeGetDatasource(namespaceId, datasourceName);
|
|
712
|
+
if (!datasource) return void 0;
|
|
713
|
+
const address = datasource.contracts[contractName]?.address;
|
|
714
|
+
if (address === void 0 || Array.isArray(address)) return void 0;
|
|
715
|
+
return {
|
|
716
|
+
chainId: datasource.chain.id,
|
|
717
|
+
address
|
|
718
|
+
};
|
|
719
|
+
};
|
|
720
|
+
var getDatasourceContract = (namespaceId, datasourceName, contractName) => {
|
|
721
|
+
const contract = maybeGetDatasourceContract(namespaceId, datasourceName, contractName);
|
|
722
|
+
if (!contract) {
|
|
723
|
+
throw new Error(
|
|
724
|
+
`Expected contract not found for ${namespaceId} ${datasourceName} ${contractName}`
|
|
725
|
+
);
|
|
726
|
+
}
|
|
727
|
+
return contract;
|
|
728
|
+
};
|
|
729
|
+
|
|
730
|
+
// src/shared/labelhash.ts
|
|
731
|
+
import { keccak256 as keccak2562, stringToBytes } from "viem";
|
|
732
|
+
var labelhashLiteralLabel = (label) => keccak2562(stringToBytes(label));
|
|
733
|
+
|
|
734
|
+
// src/shared/interpretation.ts
|
|
735
|
+
function literalLabelToInterpretedLabel(label) {
|
|
736
|
+
if (isNormalizedLabel(label)) return label;
|
|
737
|
+
return encodeLabelHash(labelhashLiteralLabel(label));
|
|
738
|
+
}
|
|
739
|
+
function literalLabelsToInterpretedName(labels) {
|
|
740
|
+
return labels.map(literalLabelToInterpretedLabel).join(".");
|
|
741
|
+
}
|
|
742
|
+
function interpretedLabelsToInterpretedName(labels) {
|
|
743
|
+
return labels.join(".");
|
|
744
|
+
}
|
|
745
|
+
function literalLabelsToLiteralName(labels) {
|
|
746
|
+
return labels.join(".");
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// src/shared/null-bytes.ts
|
|
750
|
+
var hasNullByte = (value) => value.indexOf("\0") !== -1;
|
|
751
|
+
var stripNullBytes = (value) => value.replaceAll("\0", "");
|
|
752
|
+
|
|
753
|
+
// src/shared/numbers.ts
|
|
754
|
+
function bigIntToNumber(n) {
|
|
755
|
+
if (n < Number.MIN_SAFE_INTEGER) {
|
|
756
|
+
throw new Error(
|
|
757
|
+
`The bigint '${n.toString()}' value is too low to be to converted into a number.'`
|
|
758
|
+
);
|
|
759
|
+
}
|
|
760
|
+
if (n > Number.MAX_SAFE_INTEGER) {
|
|
761
|
+
throw new Error(
|
|
762
|
+
`The bigint '${n.toString()}' value is too high to be to converted into a number.'`
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
return Number(n);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
// src/shared/serialize.ts
|
|
769
|
+
import { AccountId as CaipAccountId2 } from "caip";
|
|
770
|
+
function serializeChainId(chainId) {
|
|
771
|
+
return chainId.toString();
|
|
772
|
+
}
|
|
773
|
+
function serializeDatetime(datetime) {
|
|
774
|
+
return datetime.toISOString();
|
|
775
|
+
}
|
|
776
|
+
function serializeUrl(url) {
|
|
777
|
+
return url.toString();
|
|
778
|
+
}
|
|
779
|
+
function serializePrice(price) {
|
|
780
|
+
return {
|
|
781
|
+
currency: price.currency,
|
|
782
|
+
amount: price.amount.toString()
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
function serializePriceEth(price) {
|
|
786
|
+
return serializePrice(price);
|
|
787
|
+
}
|
|
788
|
+
function formatAccountId(accountId) {
|
|
789
|
+
return CaipAccountId2.format({
|
|
790
|
+
chainId: { namespace: "eip155", reference: accountId.chainId.toString() },
|
|
791
|
+
address: accountId.address
|
|
792
|
+
}).toLowerCase();
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
// src/shared/url.ts
|
|
796
|
+
function isHttpProtocol(url) {
|
|
797
|
+
return ["http:", "https:"].includes(url.protocol);
|
|
798
|
+
}
|
|
799
|
+
function isWebSocketProtocol(url) {
|
|
800
|
+
return ["ws:", "wss:"].includes(url.protocol);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// src/ensindexer/config/is-subgraph-compatible.ts
|
|
804
|
+
import { ENSNamespaceIds as ENSNamespaceIds2 } from "@ensnode/datasources";
|
|
805
|
+
|
|
806
|
+
// src/ensindexer/config/types.ts
|
|
807
|
+
var PluginName = /* @__PURE__ */ ((PluginName2) => {
|
|
808
|
+
PluginName2["Subgraph"] = "subgraph";
|
|
809
|
+
PluginName2["Basenames"] = "basenames";
|
|
810
|
+
PluginName2["Lineanames"] = "lineanames";
|
|
811
|
+
PluginName2["ThreeDNS"] = "threedns";
|
|
812
|
+
PluginName2["ProtocolAcceleration"] = "protocol-acceleration";
|
|
813
|
+
PluginName2["Registrars"] = "registrars";
|
|
814
|
+
PluginName2["TokenScope"] = "tokenscope";
|
|
815
|
+
return PluginName2;
|
|
816
|
+
})(PluginName || {});
|
|
817
|
+
|
|
818
|
+
// src/ensindexer/config/is-subgraph-compatible.ts
|
|
819
|
+
function isSubgraphCompatible(config) {
|
|
820
|
+
const onlySubgraphPluginActivated = config.plugins.length === 1 && config.plugins[0] === "subgraph" /* Subgraph */;
|
|
821
|
+
const isSubgraphLabelSet = config.labelSet.labelSetId === "subgraph" && config.labelSet.labelSetVersion === 0;
|
|
822
|
+
const isEnsTestEnvLabelSet = config.labelSet.labelSetId === "ens-test-env" && config.labelSet.labelSetVersion === 0;
|
|
823
|
+
const labelSetIsSubgraphCompatible = isSubgraphLabelSet || config.namespace === ENSNamespaceIds2.EnsTestEnv && isEnsTestEnvLabelSet;
|
|
824
|
+
return onlySubgraphPluginActivated && labelSetIsSubgraphCompatible;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
// src/ensindexer/config/validations.ts
|
|
828
|
+
function invariant_ensDbVersionIsSameAsEnsIndexerVersion(ctx) {
|
|
829
|
+
const versionInfo = ctx.value;
|
|
830
|
+
if (versionInfo.ensDb !== versionInfo.ensIndexer) {
|
|
831
|
+
ctx.issues.push({
|
|
832
|
+
code: "custom",
|
|
833
|
+
input: versionInfo,
|
|
834
|
+
message: "`ensDb` version must be same as `ensIndexer` version"
|
|
835
|
+
});
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
// src/ensindexer/config/zod-schemas.ts
|
|
840
|
+
var makeIndexedChainIdsSchema = (valueLabel = "Indexed Chain IDs") => z2.array(makeChainIdSchema(valueLabel), {
|
|
841
|
+
error: `${valueLabel} must be an array.`
|
|
842
|
+
}).min(1, { error: `${valueLabel} list must include at least one element.` }).transform((v) => new Set(v));
|
|
843
|
+
var makePluginsListSchema = (valueLabel = "Plugins") => z2.array(z2.string(), {
|
|
844
|
+
error: `${valueLabel} must be a list of strings.`
|
|
845
|
+
}).min(1, {
|
|
846
|
+
error: `${valueLabel} must be a list of strings with at least one string value`
|
|
847
|
+
}).refine((arr) => arr.length === uniq(arr).length, {
|
|
848
|
+
error: `${valueLabel} cannot contain duplicate values.`
|
|
849
|
+
});
|
|
850
|
+
var makeDatabaseSchemaNameSchema = (valueLabel = "Database schema name") => z2.string({ error: `${valueLabel} must be a string` }).trim().nonempty({
|
|
851
|
+
error: `${valueLabel} is required and must be a non-empty string.`
|
|
852
|
+
});
|
|
853
|
+
var makeLabelSetIdSchema = (valueLabel) => {
|
|
854
|
+
return z2.string({ error: `${valueLabel} must be a string` }).min(1, { error: `${valueLabel} must be 1-50 characters long` }).max(50, { error: `${valueLabel} must be 1-50 characters long` }).regex(/^[a-z-]+$/, {
|
|
855
|
+
error: `${valueLabel} can only contain lowercase letters (a-z) and hyphens (-)`
|
|
856
|
+
});
|
|
857
|
+
};
|
|
858
|
+
var makeLabelSetVersionSchema = (valueLabel) => {
|
|
859
|
+
return z2.coerce.number({ error: `${valueLabel} must be an integer.` }).pipe(makeNonNegativeIntegerSchema(valueLabel));
|
|
860
|
+
};
|
|
861
|
+
var makeFullyPinnedLabelSetSchema = (valueLabel = "Label set") => {
|
|
862
|
+
let valueLabelLabelSetId = valueLabel;
|
|
863
|
+
let valueLabelLabelSetVersion = valueLabel;
|
|
864
|
+
if (valueLabel === "LABEL_SET") {
|
|
865
|
+
valueLabelLabelSetId = "LABEL_SET_ID";
|
|
866
|
+
valueLabelLabelSetVersion = "LABEL_SET_VERSION";
|
|
867
|
+
} else {
|
|
868
|
+
valueLabelLabelSetId = `${valueLabel}.labelSetId`;
|
|
869
|
+
valueLabelLabelSetVersion = `${valueLabel}.labelSetVersion`;
|
|
870
|
+
}
|
|
871
|
+
return z2.object({
|
|
872
|
+
labelSetId: makeLabelSetIdSchema(valueLabelLabelSetId),
|
|
873
|
+
labelSetVersion: makeLabelSetVersionSchema(valueLabelLabelSetVersion)
|
|
874
|
+
});
|
|
875
|
+
};
|
|
876
|
+
var makeNonEmptyStringSchema = (valueLabel = "Value") => z2.string().nonempty({ error: `${valueLabel} must be a non-empty string.` });
|
|
877
|
+
var makeENSIndexerVersionInfoSchema = (valueLabel = "Value") => z2.strictObject(
|
|
878
|
+
{
|
|
879
|
+
nodejs: makeNonEmptyStringSchema(),
|
|
880
|
+
ponder: makeNonEmptyStringSchema(),
|
|
881
|
+
ensDb: makeNonEmptyStringSchema(),
|
|
882
|
+
ensIndexer: makeNonEmptyStringSchema(),
|
|
883
|
+
ensNormalize: makeNonEmptyStringSchema(),
|
|
884
|
+
ensRainbow: makeNonEmptyStringSchema(),
|
|
885
|
+
ensRainbowSchema: makePositiveIntegerSchema()
|
|
886
|
+
},
|
|
887
|
+
{
|
|
888
|
+
error: `${valueLabel} must be a valid ENSIndexerVersionInfo object.`
|
|
889
|
+
}
|
|
890
|
+
).check(invariant_ensDbVersionIsSameAsEnsIndexerVersion);
|
|
891
|
+
function invariant_isSubgraphCompatibleRequirements(ctx) {
|
|
892
|
+
const { value: config } = ctx;
|
|
893
|
+
if (config.isSubgraphCompatible && !isSubgraphCompatible(config)) {
|
|
894
|
+
ctx.issues.push({
|
|
895
|
+
code: "custom",
|
|
896
|
+
input: config,
|
|
897
|
+
message: `'isSubgraphCompatible' requires only the '${"subgraph" /* Subgraph */}' plugin to be active and labelSet must be {labelSetId: "subgraph", labelSetVersion: 0}`
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
var makeENSIndexerPublicConfigSchema = (valueLabel = "ENSIndexerPublicConfig") => z2.object({
|
|
902
|
+
labelSet: makeFullyPinnedLabelSetSchema(`${valueLabel}.labelSet`),
|
|
903
|
+
indexedChainIds: makeIndexedChainIdsSchema(`${valueLabel}.indexedChainIds`),
|
|
904
|
+
isSubgraphCompatible: z2.boolean({ error: `${valueLabel}.isSubgraphCompatible` }),
|
|
905
|
+
namespace: makeENSNamespaceIdSchema(`${valueLabel}.namespace`),
|
|
906
|
+
plugins: makePluginsListSchema(`${valueLabel}.plugins`),
|
|
907
|
+
databaseSchemaName: makeDatabaseSchemaNameSchema(`${valueLabel}.databaseSchemaName`),
|
|
908
|
+
versionInfo: makeENSIndexerVersionInfoSchema(`${valueLabel}.versionInfo`)
|
|
909
|
+
}).check(invariant_isSubgraphCompatibleRequirements);
|
|
910
|
+
|
|
911
|
+
// src/shared/config/thegraph.ts
|
|
912
|
+
import { z as z3 } from "zod/v4";
|
|
913
|
+
var TheGraphCannotFallbackReasonSchema = z3.enum({
|
|
914
|
+
NotSubgraphCompatible: "not-subgraph-compatible",
|
|
915
|
+
NoApiKey: "no-api-key",
|
|
916
|
+
NoSubgraphUrl: "no-subgraph-url"
|
|
917
|
+
});
|
|
918
|
+
var TheGraphFallbackSchema = z3.discriminatedUnion("canFallback", [
|
|
919
|
+
z3.strictObject({
|
|
920
|
+
canFallback: z3.literal(true),
|
|
921
|
+
url: z3.string()
|
|
922
|
+
}),
|
|
923
|
+
z3.strictObject({
|
|
924
|
+
canFallback: z3.literal(false),
|
|
925
|
+
reason: TheGraphCannotFallbackReasonSchema
|
|
926
|
+
})
|
|
927
|
+
]);
|
|
928
|
+
|
|
929
|
+
// src/ensapi/config/zod-schemas.ts
|
|
930
|
+
function makeENSApiPublicConfigSchema(valueLabel) {
|
|
931
|
+
const label = valueLabel ?? "ENSApiPublicConfig";
|
|
932
|
+
return z4.strictObject({
|
|
933
|
+
version: z4.string().min(1, `${label}.version must be a non-empty string`),
|
|
934
|
+
theGraphFallback: TheGraphFallbackSchema,
|
|
935
|
+
ensIndexerPublicConfig: makeENSIndexerPublicConfigSchema(`${label}.ensIndexerPublicConfig`)
|
|
936
|
+
});
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
// src/ensapi/config/deserialize.ts
|
|
940
|
+
function deserializeENSApiPublicConfig(maybeConfig, valueLabel) {
|
|
941
|
+
const schema = makeENSApiPublicConfigSchema(valueLabel);
|
|
942
|
+
try {
|
|
943
|
+
return schema.parse(maybeConfig);
|
|
944
|
+
} catch (error) {
|
|
945
|
+
if (error instanceof ZodError) {
|
|
946
|
+
throw new Error(`Cannot deserialize ENSApiPublicConfig:
|
|
947
|
+
${prettifyError2(error)}
|
|
948
|
+
`);
|
|
949
|
+
}
|
|
950
|
+
throw error;
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
// src/ensindexer/config/deserialize.ts
|
|
955
|
+
import { prettifyError as prettifyError3 } from "zod/v4";
|
|
956
|
+
function deserializeENSIndexerPublicConfig(maybeConfig, valueLabel) {
|
|
957
|
+
const schema = makeENSIndexerPublicConfigSchema(valueLabel);
|
|
958
|
+
const parsed = schema.safeParse(maybeConfig);
|
|
959
|
+
if (parsed.error) {
|
|
960
|
+
throw new Error(`Cannot deserialize ENSIndexerPublicConfig:
|
|
961
|
+
${prettifyError3(parsed.error)}
|
|
962
|
+
`);
|
|
963
|
+
}
|
|
964
|
+
return parsed.data;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
// src/ensindexer/config/label-utils.ts
|
|
968
|
+
import { hexToBytes as hexToBytes2 } from "viem";
|
|
969
|
+
function labelHashToBytes(labelHash) {
|
|
970
|
+
try {
|
|
971
|
+
if (labelHash.length !== 66) {
|
|
972
|
+
throw new Error(`Invalid labelHash length ${labelHash.length} characters (expected 66)`);
|
|
973
|
+
}
|
|
974
|
+
if (labelHash !== labelHash.toLowerCase()) {
|
|
975
|
+
throw new Error("Labelhash must be in lowercase");
|
|
976
|
+
}
|
|
977
|
+
if (!labelHash.startsWith("0x")) {
|
|
978
|
+
throw new Error("Labelhash must be 0x-prefixed");
|
|
979
|
+
}
|
|
980
|
+
const bytes = hexToBytes2(labelHash);
|
|
981
|
+
if (bytes.length !== 32) {
|
|
982
|
+
throw new Error(`Invalid labelHash length ${bytes.length} bytes (expected 32)`);
|
|
983
|
+
}
|
|
984
|
+
return bytes;
|
|
985
|
+
} catch (e) {
|
|
986
|
+
if (e instanceof Error) {
|
|
987
|
+
throw e;
|
|
988
|
+
}
|
|
989
|
+
throw new Error("Invalid hex format");
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
// src/ensindexer/config/labelset-utils.ts
|
|
994
|
+
function buildLabelSetId(maybeLabelSetId) {
|
|
995
|
+
return makeLabelSetIdSchema("LabelSetId").parse(maybeLabelSetId);
|
|
996
|
+
}
|
|
997
|
+
function buildLabelSetVersion(maybeLabelSetVersion) {
|
|
998
|
+
return makeLabelSetVersionSchema("LabelSetVersion").parse(maybeLabelSetVersion);
|
|
999
|
+
}
|
|
1000
|
+
function buildEnsRainbowClientLabelSet(labelSetId, labelSetVersion) {
|
|
1001
|
+
if (labelSetVersion !== void 0 && labelSetId === void 0) {
|
|
1002
|
+
throw new Error("When a labelSetVersion is defined, labelSetId must also be defined.");
|
|
1003
|
+
}
|
|
1004
|
+
return { labelSetId, labelSetVersion };
|
|
1005
|
+
}
|
|
1006
|
+
function validateSupportedLabelSetAndVersion(serverSet, clientSet) {
|
|
1007
|
+
if (clientSet.labelSetId === void 0) {
|
|
1008
|
+
return;
|
|
1009
|
+
}
|
|
1010
|
+
if (serverSet.labelSetId !== clientSet.labelSetId) {
|
|
1011
|
+
throw new Error(
|
|
1012
|
+
`Server label set ID "${serverSet.labelSetId}" does not match client's requested label set ID "${clientSet.labelSetId}".`
|
|
1013
|
+
);
|
|
1014
|
+
}
|
|
1015
|
+
if (clientSet.labelSetVersion !== void 0 && serverSet.highestLabelSetVersion < clientSet.labelSetVersion) {
|
|
1016
|
+
throw new Error(
|
|
1017
|
+
`Server highest label set version ${serverSet.highestLabelSetVersion} is less than client's requested version ${clientSet.labelSetVersion} for label set ID "${clientSet.labelSetId}".`
|
|
1018
|
+
);
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
// src/ensindexer/config/parsing.ts
|
|
1023
|
+
function parseNonNegativeInteger(maybeNumber) {
|
|
1024
|
+
const trimmed = maybeNumber.trim();
|
|
1025
|
+
if (!trimmed) {
|
|
1026
|
+
throw new Error("Input cannot be empty");
|
|
1027
|
+
}
|
|
1028
|
+
if (trimmed === "-0") {
|
|
1029
|
+
throw new Error("Negative zero is not a valid non-negative integer");
|
|
1030
|
+
}
|
|
1031
|
+
const num = Number(maybeNumber);
|
|
1032
|
+
if (Number.isNaN(num)) {
|
|
1033
|
+
throw new Error(`"${maybeNumber}" is not a valid number`);
|
|
1034
|
+
}
|
|
1035
|
+
if (!Number.isFinite(num)) {
|
|
1036
|
+
throw new Error(`"${maybeNumber}" is not a finite number`);
|
|
1037
|
+
}
|
|
1038
|
+
if (!Number.isInteger(num)) {
|
|
1039
|
+
throw new Error(`"${maybeNumber}" is not an integer`);
|
|
1040
|
+
}
|
|
1041
|
+
if (num < 0) {
|
|
1042
|
+
throw new Error(`"${maybeNumber}" is not a non-negative integer`);
|
|
1043
|
+
}
|
|
1044
|
+
return num;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
// src/ensindexer/config/serialize.ts
|
|
1048
|
+
function serializeIndexedChainIds(indexedChainIds) {
|
|
1049
|
+
return Array.from(indexedChainIds);
|
|
1050
|
+
}
|
|
1051
|
+
function serializeENSIndexerPublicConfig(config) {
|
|
1052
|
+
const {
|
|
1053
|
+
labelSet,
|
|
1054
|
+
indexedChainIds,
|
|
1055
|
+
databaseSchemaName,
|
|
1056
|
+
isSubgraphCompatible: isSubgraphCompatible2,
|
|
1057
|
+
namespace,
|
|
1058
|
+
plugins,
|
|
1059
|
+
versionInfo
|
|
1060
|
+
} = config;
|
|
1061
|
+
return {
|
|
1062
|
+
labelSet,
|
|
1063
|
+
indexedChainIds: serializeIndexedChainIds(indexedChainIds),
|
|
1064
|
+
databaseSchemaName,
|
|
1065
|
+
isSubgraphCompatible: isSubgraphCompatible2,
|
|
1066
|
+
namespace,
|
|
1067
|
+
plugins,
|
|
1068
|
+
versionInfo
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
// src/ensindexer/indexing-status/deserialize.ts
|
|
1073
|
+
import { prettifyError as prettifyError4 } from "zod/v4";
|
|
1074
|
+
|
|
1075
|
+
// src/ensindexer/indexing-status/zod-schemas.ts
|
|
1076
|
+
import z5 from "zod/v4";
|
|
1077
|
+
|
|
1078
|
+
// src/ensindexer/indexing-status/types.ts
|
|
1079
|
+
var ChainIndexingConfigTypeIds = {
|
|
1080
|
+
/**
|
|
1081
|
+
* Represents that indexing of the chain should be performed for an indefinite range.
|
|
1082
|
+
*/
|
|
1083
|
+
Indefinite: "indefinite",
|
|
1084
|
+
/**
|
|
1085
|
+
* Represents that indexing of the chain should be performed for a definite range.
|
|
1086
|
+
*/
|
|
1087
|
+
Definite: "definite"
|
|
1088
|
+
};
|
|
1089
|
+
var ChainIndexingStatusIds = {
|
|
1090
|
+
/**
|
|
1091
|
+
* Represents that indexing of the chain is not ready to begin yet because:
|
|
1092
|
+
* - ENSIndexer is in its initialization phase and the data to build a
|
|
1093
|
+
* "true" {@link ChainIndexingSnapshot} for the chain is still being loaded; or
|
|
1094
|
+
* - ENSIndexer is using an omnichain indexing strategy and the
|
|
1095
|
+
* `omnichainIndexingCursor` is <= `config.startBlock.timestamp` for the chain's
|
|
1096
|
+
* {@link ChainIndexingSnapshot}.
|
|
1097
|
+
*/
|
|
1098
|
+
Queued: "chain-queued",
|
|
1099
|
+
/**
|
|
1100
|
+
* Represents that indexing of the chain is in progress and under a special
|
|
1101
|
+
* "backfill" phase that optimizes for accelerated indexing until reaching the
|
|
1102
|
+
* "fixed target" `backfillEndBlock`.
|
|
1103
|
+
*/
|
|
1104
|
+
Backfill: "chain-backfill",
|
|
1105
|
+
/**
|
|
1106
|
+
* Represents that the "backfill" phase of indexing the chain is completed
|
|
1107
|
+
* and that the chain is configured to be indexed for an indefinite range.
|
|
1108
|
+
* Therefore, indexing of the chain remains indefinitely in progress where
|
|
1109
|
+
* ENSIndexer will continuously work to discover and index new blocks as they
|
|
1110
|
+
* are added to the chain across time.
|
|
1111
|
+
*/
|
|
1112
|
+
Following: "chain-following",
|
|
1113
|
+
/**
|
|
1114
|
+
* Represents that indexing of the chain is completed as the chain is configured
|
|
1115
|
+
* to be indexed for a definite range and the indexing of all blocks through
|
|
1116
|
+
* that definite range is completed.
|
|
1117
|
+
*/
|
|
1118
|
+
Completed: "chain-completed"
|
|
1119
|
+
};
|
|
1120
|
+
var OmnichainIndexingStatusIds = {
|
|
1121
|
+
/**
|
|
1122
|
+
* Represents that omnichain indexing is not ready to begin yet because
|
|
1123
|
+
* ENSIndexer is in its initialization phase and the data to build a "true"
|
|
1124
|
+
* {@link OmnichainIndexingStatusSnapshot} is still being loaded.
|
|
1125
|
+
*/
|
|
1126
|
+
Unstarted: "omnichain-unstarted",
|
|
1127
|
+
/**
|
|
1128
|
+
* Represents that omnichain indexing is in an overall "backfill" status because
|
|
1129
|
+
* - At least one indexed chain has a `chainStatus` of
|
|
1130
|
+
* {@link ChainIndexingStatusIds.Backfill}; and
|
|
1131
|
+
* - No indexed chain has a `chainStatus` of {@link ChainIndexingStatusIds.Following}.
|
|
1132
|
+
*/
|
|
1133
|
+
Backfill: "omnichain-backfill",
|
|
1134
|
+
/**
|
|
1135
|
+
* Represents that omnichain indexing is in an overall "following" status because
|
|
1136
|
+
* at least one indexed chain has a `chainStatus` of
|
|
1137
|
+
* {@link ChainIndexingStatusIds.Following}.
|
|
1138
|
+
*/
|
|
1139
|
+
Following: "omnichain-following",
|
|
1140
|
+
/**
|
|
1141
|
+
* Represents that omnichain indexing has completed because all indexed chains have
|
|
1142
|
+
* a `chainStatus` of {@link ChainIndexingStatusIds.Completed}.
|
|
1143
|
+
*/
|
|
1144
|
+
Completed: "omnichain-completed"
|
|
1145
|
+
};
|
|
1146
|
+
var CrossChainIndexingStrategyIds = {
|
|
1147
|
+
/**
|
|
1148
|
+
* Represents that the indexing of events across all indexed chains will
|
|
1149
|
+
* proceed in a deterministic "omnichain" ordering by block timestamp, chain ID,
|
|
1150
|
+
* and block number.
|
|
1151
|
+
*
|
|
1152
|
+
* This strategy is "deterministic" in that the order of processing cross-chain indexed
|
|
1153
|
+
* events and each resulting indexed data state transition recorded in ENSDb is always
|
|
1154
|
+
* the same for each ENSIndexer instance operating with an equivalent
|
|
1155
|
+
* `ENSIndexerConfig` and ENSIndexer version. However it also has the drawbacks of:
|
|
1156
|
+
* - increased indexing latency that must wait for the slowest indexed chain to
|
|
1157
|
+
* add new blocks or to discover new blocks through the configured RPCs.
|
|
1158
|
+
* - if any indexed chain gets "stuck" due to chain or RPC failures, all indexed chains
|
|
1159
|
+
* will be affected.
|
|
1160
|
+
*/
|
|
1161
|
+
Omnichain: "omnichain"
|
|
1162
|
+
};
|
|
1163
|
+
|
|
1164
|
+
// src/shared/block-ref.ts
|
|
1165
|
+
function isBefore(blockA, blockB) {
|
|
1166
|
+
return blockA.number < blockB.number && blockA.timestamp < blockB.timestamp;
|
|
1167
|
+
}
|
|
1168
|
+
function isEqualTo(blockA, blockB) {
|
|
1169
|
+
return blockA.number === blockB.number && blockA.timestamp === blockB.timestamp;
|
|
1170
|
+
}
|
|
1171
|
+
function isBeforeOrEqualTo(blockA, blockB) {
|
|
1172
|
+
return isBefore(blockA, blockB) || isEqualTo(blockA, blockB);
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
// src/ensindexer/indexing-status/helpers.ts
|
|
1176
|
+
function getOmnichainIndexingStatus(chains) {
|
|
1177
|
+
if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing(chains)) {
|
|
1178
|
+
return OmnichainIndexingStatusIds.Following;
|
|
1179
|
+
}
|
|
1180
|
+
if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill(chains)) {
|
|
1181
|
+
return OmnichainIndexingStatusIds.Backfill;
|
|
1182
|
+
}
|
|
1183
|
+
if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted(chains)) {
|
|
1184
|
+
return OmnichainIndexingStatusIds.Unstarted;
|
|
1185
|
+
}
|
|
1186
|
+
if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted(chains)) {
|
|
1187
|
+
return OmnichainIndexingStatusIds.Completed;
|
|
1188
|
+
}
|
|
1189
|
+
throw new Error(`Unable to determine omnichain indexing status for provided chains.`);
|
|
1190
|
+
}
|
|
1191
|
+
function getTimestampForLowestOmnichainStartBlock(chains) {
|
|
1192
|
+
const earliestKnownBlockTimestamps = chains.map(
|
|
1193
|
+
(chain) => chain.config.startBlock.timestamp
|
|
1194
|
+
);
|
|
1195
|
+
return Math.min(...earliestKnownBlockTimestamps);
|
|
1196
|
+
}
|
|
1197
|
+
function getTimestampForHighestOmnichainKnownBlock(chains) {
|
|
1198
|
+
const latestKnownBlockTimestamps = [];
|
|
1199
|
+
for (const chain of chains) {
|
|
1200
|
+
switch (chain.chainStatus) {
|
|
1201
|
+
case ChainIndexingStatusIds.Queued:
|
|
1202
|
+
if (chain.config.configType === ChainIndexingConfigTypeIds.Definite && chain.config.endBlock) {
|
|
1203
|
+
latestKnownBlockTimestamps.push(chain.config.endBlock.timestamp);
|
|
1204
|
+
}
|
|
1205
|
+
break;
|
|
1206
|
+
case ChainIndexingStatusIds.Backfill:
|
|
1207
|
+
latestKnownBlockTimestamps.push(chain.backfillEndBlock.timestamp);
|
|
1208
|
+
break;
|
|
1209
|
+
case ChainIndexingStatusIds.Completed:
|
|
1210
|
+
latestKnownBlockTimestamps.push(chain.latestIndexedBlock.timestamp);
|
|
1211
|
+
break;
|
|
1212
|
+
case ChainIndexingStatusIds.Following:
|
|
1213
|
+
latestKnownBlockTimestamps.push(chain.latestKnownBlock.timestamp);
|
|
1214
|
+
break;
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
return Math.max(...latestKnownBlockTimestamps);
|
|
1218
|
+
}
|
|
1219
|
+
function getOmnichainIndexingCursor(chains) {
|
|
1220
|
+
if (chains.length === 0) {
|
|
1221
|
+
throw new Error(`Unable to determine omnichain indexing cursor when no chains were provided.`);
|
|
1222
|
+
}
|
|
1223
|
+
if (getOmnichainIndexingStatus(chains) === OmnichainIndexingStatusIds.Unstarted) {
|
|
1224
|
+
const earliestStartBlockTimestamps = chains.map((chain) => chain.config.startBlock.timestamp);
|
|
1225
|
+
return Math.min(...earliestStartBlockTimestamps) - 1;
|
|
1226
|
+
}
|
|
1227
|
+
const latestIndexedBlockTimestamps = chains.filter((chain) => chain.chainStatus !== ChainIndexingStatusIds.Queued).map((chain) => chain.latestIndexedBlock.timestamp);
|
|
1228
|
+
if (latestIndexedBlockTimestamps.length < 1) {
|
|
1229
|
+
throw new Error("latestIndexedBlockTimestamps array must include at least one element");
|
|
1230
|
+
}
|
|
1231
|
+
return Math.max(...latestIndexedBlockTimestamps);
|
|
1232
|
+
}
|
|
1233
|
+
function createIndexingConfig(startBlock, endBlock) {
|
|
1234
|
+
if (endBlock) {
|
|
1235
|
+
return {
|
|
1236
|
+
configType: ChainIndexingConfigTypeIds.Definite,
|
|
1237
|
+
startBlock,
|
|
1238
|
+
endBlock
|
|
1239
|
+
};
|
|
1240
|
+
}
|
|
1241
|
+
return {
|
|
1242
|
+
configType: ChainIndexingConfigTypeIds.Indefinite,
|
|
1243
|
+
startBlock
|
|
1244
|
+
};
|
|
1245
|
+
}
|
|
1246
|
+
function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted(chains) {
|
|
1247
|
+
return chains.every((chain) => chain.chainStatus === ChainIndexingStatusIds.Queued);
|
|
1248
|
+
}
|
|
1249
|
+
function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill(chains) {
|
|
1250
|
+
const atLeastOneChainInTargetStatus = chains.some(
|
|
1251
|
+
(chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill
|
|
1252
|
+
);
|
|
1253
|
+
const otherChainsHaveValidStatuses = chains.every(
|
|
1254
|
+
(chain) => chain.chainStatus === ChainIndexingStatusIds.Queued || chain.chainStatus === ChainIndexingStatusIds.Backfill || chain.chainStatus === ChainIndexingStatusIds.Completed
|
|
1255
|
+
);
|
|
1256
|
+
return atLeastOneChainInTargetStatus && otherChainsHaveValidStatuses;
|
|
1257
|
+
}
|
|
1258
|
+
function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted(chains) {
|
|
1259
|
+
const allChainsHaveValidStatuses = chains.every(
|
|
1260
|
+
(chain) => chain.chainStatus === ChainIndexingStatusIds.Completed
|
|
1261
|
+
);
|
|
1262
|
+
return allChainsHaveValidStatuses;
|
|
1263
|
+
}
|
|
1264
|
+
function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing(chains) {
|
|
1265
|
+
const allChainsHaveValidStatuses = chains.some(
|
|
1266
|
+
(chain) => chain.chainStatus === ChainIndexingStatusIds.Following
|
|
1267
|
+
);
|
|
1268
|
+
return allChainsHaveValidStatuses;
|
|
1269
|
+
}
|
|
1270
|
+
function sortChainStatusesByStartBlockAsc(chains) {
|
|
1271
|
+
chains.sort(
|
|
1272
|
+
([, chainA], [, chainB]) => chainA.config.startBlock.timestamp - chainB.config.startBlock.timestamp
|
|
1273
|
+
);
|
|
1274
|
+
return chains;
|
|
1275
|
+
}
|
|
1276
|
+
function getLatestIndexedBlockRef(indexingStatus, chainId) {
|
|
1277
|
+
const chainIndexingStatus = indexingStatus.omnichainSnapshot.chains.get(chainId);
|
|
1278
|
+
if (chainIndexingStatus === void 0) {
|
|
1279
|
+
return null;
|
|
1280
|
+
}
|
|
1281
|
+
if (chainIndexingStatus.chainStatus === ChainIndexingStatusIds.Queued) {
|
|
1282
|
+
return null;
|
|
1283
|
+
}
|
|
1284
|
+
return chainIndexingStatus.latestIndexedBlock;
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
// src/ensindexer/indexing-status/validations.ts
|
|
1288
|
+
function invariant_chainSnapshotQueuedBlocks(ctx) {
|
|
1289
|
+
const { config } = ctx.value;
|
|
1290
|
+
if (config.configType === ChainIndexingConfigTypeIds.Indefinite) {
|
|
1291
|
+
return;
|
|
1292
|
+
}
|
|
1293
|
+
if (config.endBlock && isBeforeOrEqualTo(config.startBlock, config.endBlock) === false) {
|
|
1294
|
+
ctx.issues.push({
|
|
1295
|
+
code: "custom",
|
|
1296
|
+
input: ctx.value,
|
|
1297
|
+
message: "`config.startBlock` must be before or same as `config.endBlock`."
|
|
1298
|
+
});
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
function invariant_chainSnapshotBackfillBlocks(ctx) {
|
|
1302
|
+
const { config, latestIndexedBlock, backfillEndBlock } = ctx.value;
|
|
1303
|
+
if (isBeforeOrEqualTo(config.startBlock, latestIndexedBlock) === false) {
|
|
1304
|
+
ctx.issues.push({
|
|
1305
|
+
code: "custom",
|
|
1306
|
+
input: ctx.value,
|
|
1307
|
+
message: "`config.startBlock` must be before or same as `latestIndexedBlock`."
|
|
1308
|
+
});
|
|
1309
|
+
}
|
|
1310
|
+
if (isBeforeOrEqualTo(latestIndexedBlock, backfillEndBlock) === false) {
|
|
1311
|
+
ctx.issues.push({
|
|
1312
|
+
code: "custom",
|
|
1313
|
+
input: ctx.value,
|
|
1314
|
+
message: "`latestIndexedBlock` must be before or same as `backfillEndBlock`."
|
|
1315
|
+
});
|
|
1316
|
+
}
|
|
1317
|
+
if (config.configType === ChainIndexingConfigTypeIds.Indefinite) {
|
|
1318
|
+
return;
|
|
1319
|
+
}
|
|
1320
|
+
if (config.endBlock && isEqualTo(backfillEndBlock, config.endBlock) === false) {
|
|
1321
|
+
ctx.issues.push({
|
|
1322
|
+
code: "custom",
|
|
1323
|
+
input: ctx.value,
|
|
1324
|
+
message: "`backfillEndBlock` must be the same as `config.endBlock`."
|
|
1325
|
+
});
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
function invariant_chainSnapshotCompletedBlocks(ctx) {
|
|
1329
|
+
const { config, latestIndexedBlock } = ctx.value;
|
|
1330
|
+
if (isBeforeOrEqualTo(config.startBlock, latestIndexedBlock) === false) {
|
|
1331
|
+
ctx.issues.push({
|
|
1332
|
+
code: "custom",
|
|
1333
|
+
input: ctx.value,
|
|
1334
|
+
message: "`config.startBlock` must be before or same as `latestIndexedBlock`."
|
|
1335
|
+
});
|
|
1336
|
+
}
|
|
1337
|
+
if (isBeforeOrEqualTo(latestIndexedBlock, config.endBlock) === false) {
|
|
1338
|
+
ctx.issues.push({
|
|
1339
|
+
code: "custom",
|
|
1340
|
+
input: ctx.value,
|
|
1341
|
+
message: "`latestIndexedBlock` must be before or same as `config.endBlock`."
|
|
1342
|
+
});
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
function invariant_chainSnapshotFollowingBlocks(ctx) {
|
|
1346
|
+
const { config, latestIndexedBlock, latestKnownBlock } = ctx.value;
|
|
1347
|
+
if (isBeforeOrEqualTo(config.startBlock, latestIndexedBlock) === false) {
|
|
1348
|
+
ctx.issues.push({
|
|
1349
|
+
code: "custom",
|
|
1350
|
+
input: ctx.value,
|
|
1351
|
+
message: "`config.startBlock` must be before or same as `latestIndexedBlock`."
|
|
1352
|
+
});
|
|
1353
|
+
}
|
|
1354
|
+
if (isBeforeOrEqualTo(latestIndexedBlock, latestKnownBlock) === false) {
|
|
1355
|
+
ctx.issues.push({
|
|
1356
|
+
code: "custom",
|
|
1357
|
+
input: ctx.value,
|
|
1358
|
+
message: "`latestIndexedBlock` must be before or same as `latestKnownBlock`."
|
|
1359
|
+
});
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
function invariant_omnichainSnapshotStatusIsConsistentWithChainSnapshot(ctx) {
|
|
1363
|
+
const snapshot = ctx.value;
|
|
1364
|
+
const chains = Array.from(snapshot.chains.values());
|
|
1365
|
+
const expectedOmnichainStatus = getOmnichainIndexingStatus(chains);
|
|
1366
|
+
const actualOmnichainStatus = snapshot.omnichainStatus;
|
|
1367
|
+
if (expectedOmnichainStatus !== actualOmnichainStatus) {
|
|
1368
|
+
ctx.issues.push({
|
|
1369
|
+
code: "custom",
|
|
1370
|
+
input: snapshot,
|
|
1371
|
+
message: `'${actualOmnichainStatus}' is an invalid omnichainStatus. Expected '${expectedOmnichainStatus}' based on the statuses of individual chains.`
|
|
1372
|
+
});
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
function invariant_omnichainIndexingCursorLowerThanEarliestStartBlockAcrossQueuedChains(ctx) {
|
|
1376
|
+
const snapshot = ctx.value;
|
|
1377
|
+
const queuedChains = Array.from(snapshot.chains.values()).filter(
|
|
1378
|
+
(chain) => chain.chainStatus === ChainIndexingStatusIds.Queued
|
|
1379
|
+
);
|
|
1380
|
+
if (queuedChains.length === 0) {
|
|
1381
|
+
return;
|
|
1382
|
+
}
|
|
1383
|
+
const queuedChainStartBlocks = queuedChains.map((chain) => chain.config.startBlock.timestamp);
|
|
1384
|
+
const queuedChainEarliestStartBlock = Math.min(...queuedChainStartBlocks);
|
|
1385
|
+
if (snapshot.omnichainIndexingCursor >= queuedChainEarliestStartBlock) {
|
|
1386
|
+
ctx.issues.push({
|
|
1387
|
+
code: "custom",
|
|
1388
|
+
input: snapshot,
|
|
1389
|
+
message: "`omnichainIndexingCursor` must be lower than the earliest start block across all queued chains."
|
|
1390
|
+
});
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
function invariant_omnichainIndexingCursorLowerThanOrEqualToLatestBackfillEndBlockAcrossBackfillChains(ctx) {
|
|
1394
|
+
const snapshot = ctx.value;
|
|
1395
|
+
const backfillChains = Array.from(snapshot.chains.values()).filter(
|
|
1396
|
+
(chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill
|
|
1397
|
+
);
|
|
1398
|
+
if (backfillChains.length === 0) {
|
|
1399
|
+
return;
|
|
1400
|
+
}
|
|
1401
|
+
const backfillEndBlocks = backfillChains.map((chain) => chain.backfillEndBlock.timestamp);
|
|
1402
|
+
const highestBackfillEndBlock = Math.max(...backfillEndBlocks);
|
|
1403
|
+
if (snapshot.omnichainIndexingCursor > highestBackfillEndBlock) {
|
|
1404
|
+
ctx.issues.push({
|
|
1405
|
+
code: "custom",
|
|
1406
|
+
input: snapshot,
|
|
1407
|
+
message: "`omnichainIndexingCursor` must be lower than or equal to the highest `backfillEndBlock` across all backfill chains."
|
|
1408
|
+
});
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
function invariant_omnichainIndexingCursorIsEqualToHighestLatestIndexedBlockAcrossIndexedChain(ctx) {
|
|
1412
|
+
const snapshot = ctx.value;
|
|
1413
|
+
const indexedChains = Array.from(snapshot.chains.values()).filter(
|
|
1414
|
+
(chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill || chain.chainStatus === ChainIndexingStatusIds.Completed || chain.chainStatus === ChainIndexingStatusIds.Following
|
|
1415
|
+
);
|
|
1416
|
+
if (indexedChains.length === 0) {
|
|
1417
|
+
return;
|
|
1418
|
+
}
|
|
1419
|
+
const indexedChainLatestIndexedBlocks = indexedChains.map(
|
|
1420
|
+
(chain) => chain.latestIndexedBlock.timestamp
|
|
1421
|
+
);
|
|
1422
|
+
const indexedChainHighestLatestIndexedBlock = Math.max(...indexedChainLatestIndexedBlocks);
|
|
1423
|
+
if (snapshot.omnichainIndexingCursor !== indexedChainHighestLatestIndexedBlock) {
|
|
1424
|
+
ctx.issues.push({
|
|
1425
|
+
code: "custom",
|
|
1426
|
+
input: snapshot,
|
|
1427
|
+
message: "`omnichainIndexingCursor` must be same as the highest `latestIndexedBlock` across all indexed chains."
|
|
1428
|
+
});
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
function invariant_omnichainSnapshotUnstartedHasValidChains(ctx) {
|
|
1432
|
+
const chains = ctx.value;
|
|
1433
|
+
const hasValidChains = checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted(
|
|
1434
|
+
Array.from(chains.values())
|
|
1435
|
+
);
|
|
1436
|
+
if (hasValidChains === false) {
|
|
1437
|
+
ctx.issues.push({
|
|
1438
|
+
code: "custom",
|
|
1439
|
+
input: chains,
|
|
1440
|
+
message: `For omnichain status snapshot 'unstarted', all chains must have "queued" status.`
|
|
1441
|
+
});
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
function invariant_omnichainStatusSnapshotBackfillHasValidChains(ctx) {
|
|
1445
|
+
const chains = ctx.value;
|
|
1446
|
+
const hasValidChains = checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill(
|
|
1447
|
+
Array.from(chains.values())
|
|
1448
|
+
);
|
|
1449
|
+
if (hasValidChains === false) {
|
|
1450
|
+
ctx.issues.push({
|
|
1451
|
+
code: "custom",
|
|
1452
|
+
input: chains,
|
|
1453
|
+
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".`
|
|
1454
|
+
});
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
function invariant_omnichainStatusSnapshotCompletedHasValidChains(ctx) {
|
|
1458
|
+
const chains = ctx.value;
|
|
1459
|
+
const hasValidChains = checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted(
|
|
1460
|
+
Array.from(chains.values())
|
|
1461
|
+
);
|
|
1462
|
+
if (hasValidChains === false) {
|
|
1463
|
+
ctx.issues.push({
|
|
1464
|
+
code: "custom",
|
|
1465
|
+
input: chains,
|
|
1466
|
+
message: `For omnichain status snapshot 'completed', all chains must have "completed" status.`
|
|
1467
|
+
});
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
function invariant_slowestChainEqualsToOmnichainSnapshotTime(ctx) {
|
|
1471
|
+
const { slowestChainIndexingCursor, omnichainSnapshot } = ctx.value;
|
|
1472
|
+
const { omnichainIndexingCursor } = omnichainSnapshot;
|
|
1473
|
+
if (slowestChainIndexingCursor !== omnichainIndexingCursor) {
|
|
1474
|
+
console.log("invariant_slowestChainEqualsToOmnichainSnapshotTime", {
|
|
1475
|
+
slowestChainIndexingCursor,
|
|
1476
|
+
omnichainIndexingCursor
|
|
1477
|
+
});
|
|
1478
|
+
ctx.issues.push({
|
|
1479
|
+
code: "custom",
|
|
1480
|
+
input: ctx.value,
|
|
1481
|
+
message: `'slowestChainIndexingCursor' must be equal to 'omnichainSnapshot.omnichainIndexingCursor'`
|
|
1482
|
+
});
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
function invariant_snapshotTimeIsTheHighestKnownBlockTimestamp(ctx) {
|
|
1486
|
+
const { snapshotTime, omnichainSnapshot } = ctx.value;
|
|
1487
|
+
const chains = Array.from(omnichainSnapshot.chains.values());
|
|
1488
|
+
const startBlockTimestamps = chains.map((chain) => chain.config.startBlock.timestamp);
|
|
1489
|
+
const endBlockTimestamps = chains.map((chain) => chain.config).filter((chainConfig) => chainConfig.configType === ChainIndexingConfigTypeIds.Definite).map((chainConfig) => chainConfig.endBlock.timestamp);
|
|
1490
|
+
const backfillEndBlockTimestamps = chains.filter((chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill).map((chain) => chain.backfillEndBlock.timestamp);
|
|
1491
|
+
const latestKnownBlockTimestamps = chains.filter((chain) => chain.chainStatus === ChainIndexingStatusIds.Following).map((chain) => chain.latestKnownBlock.timestamp);
|
|
1492
|
+
const highestKnownBlockTimestamp = Math.max(
|
|
1493
|
+
...startBlockTimestamps,
|
|
1494
|
+
...endBlockTimestamps,
|
|
1495
|
+
...backfillEndBlockTimestamps,
|
|
1496
|
+
...latestKnownBlockTimestamps
|
|
1497
|
+
);
|
|
1498
|
+
if (snapshotTime < highestKnownBlockTimestamp) {
|
|
1499
|
+
ctx.issues.push({
|
|
1500
|
+
code: "custom",
|
|
1501
|
+
input: ctx.value,
|
|
1502
|
+
message: `'snapshotTime' must be greater than or equal to the "highest known block timestamp" (${highestKnownBlockTimestamp})`
|
|
1503
|
+
});
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
function invariant_realtimeIndexingStatusProjectionProjectedAtIsAfterOrEqualToSnapshotTime(ctx) {
|
|
1507
|
+
const projection = ctx.value;
|
|
1508
|
+
const { snapshot, projectedAt } = projection;
|
|
1509
|
+
if (snapshot.snapshotTime > projectedAt) {
|
|
1510
|
+
ctx.issues.push({
|
|
1511
|
+
code: "custom",
|
|
1512
|
+
input: projection,
|
|
1513
|
+
message: "`projectedAt` must be after or same as `snapshot.snapshotTime`."
|
|
1514
|
+
});
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
function invariant_realtimeIndexingStatusProjectionWorstCaseDistanceIsCorrect(ctx) {
|
|
1518
|
+
const projection = ctx.value;
|
|
1519
|
+
const { projectedAt, snapshot, worstCaseDistance } = projection;
|
|
1520
|
+
const { omnichainSnapshot } = snapshot;
|
|
1521
|
+
const expectedWorstCaseDistance = projectedAt - omnichainSnapshot.omnichainIndexingCursor;
|
|
1522
|
+
if (worstCaseDistance !== expectedWorstCaseDistance) {
|
|
1523
|
+
ctx.issues.push({
|
|
1524
|
+
code: "custom",
|
|
1525
|
+
input: projection,
|
|
1526
|
+
message: "`worstCaseDistance` must be the exact difference between `projectedAt` and `snapshot.omnichainIndexingCursor`."
|
|
1527
|
+
});
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
// src/ensindexer/indexing-status/zod-schemas.ts
|
|
1532
|
+
var makeChainIndexingConfigSchema = (valueLabel = "Value") => z5.discriminatedUnion("configType", [
|
|
1533
|
+
z5.strictObject({
|
|
1534
|
+
configType: z5.literal(ChainIndexingConfigTypeIds.Indefinite),
|
|
1535
|
+
startBlock: makeBlockRefSchema(valueLabel)
|
|
1536
|
+
}),
|
|
1537
|
+
z5.strictObject({
|
|
1538
|
+
configType: z5.literal(ChainIndexingConfigTypeIds.Definite),
|
|
1539
|
+
startBlock: makeBlockRefSchema(valueLabel),
|
|
1540
|
+
endBlock: makeBlockRefSchema(valueLabel)
|
|
1541
|
+
})
|
|
1542
|
+
]);
|
|
1543
|
+
var makeChainIndexingStatusSnapshotQueuedSchema = (valueLabel = "Value") => z5.strictObject({
|
|
1544
|
+
chainStatus: z5.literal(ChainIndexingStatusIds.Queued),
|
|
1545
|
+
config: makeChainIndexingConfigSchema(valueLabel)
|
|
1546
|
+
}).check(invariant_chainSnapshotQueuedBlocks);
|
|
1547
|
+
var makeChainIndexingStatusSnapshotBackfillSchema = (valueLabel = "Value") => z5.strictObject({
|
|
1548
|
+
chainStatus: z5.literal(ChainIndexingStatusIds.Backfill),
|
|
1549
|
+
config: makeChainIndexingConfigSchema(valueLabel),
|
|
1550
|
+
latestIndexedBlock: makeBlockRefSchema(valueLabel),
|
|
1551
|
+
backfillEndBlock: makeBlockRefSchema(valueLabel)
|
|
1552
|
+
}).check(invariant_chainSnapshotBackfillBlocks);
|
|
1553
|
+
var makeChainIndexingStatusSnapshotCompletedSchema = (valueLabel = "Value") => z5.strictObject({
|
|
1554
|
+
chainStatus: z5.literal(ChainIndexingStatusIds.Completed),
|
|
1555
|
+
config: z5.strictObject({
|
|
1556
|
+
configType: z5.literal(ChainIndexingConfigTypeIds.Definite),
|
|
1557
|
+
startBlock: makeBlockRefSchema(valueLabel),
|
|
1558
|
+
endBlock: makeBlockRefSchema(valueLabel)
|
|
1559
|
+
}),
|
|
1560
|
+
latestIndexedBlock: makeBlockRefSchema(valueLabel)
|
|
1561
|
+
}).check(invariant_chainSnapshotCompletedBlocks);
|
|
1562
|
+
var makeChainIndexingStatusSnapshotFollowingSchema = (valueLabel = "Value") => z5.strictObject({
|
|
1563
|
+
chainStatus: z5.literal(ChainIndexingStatusIds.Following),
|
|
1564
|
+
config: z5.strictObject({
|
|
1565
|
+
configType: z5.literal(ChainIndexingConfigTypeIds.Indefinite),
|
|
1566
|
+
startBlock: makeBlockRefSchema(valueLabel)
|
|
1567
|
+
}),
|
|
1568
|
+
latestIndexedBlock: makeBlockRefSchema(valueLabel),
|
|
1569
|
+
latestKnownBlock: makeBlockRefSchema(valueLabel)
|
|
1570
|
+
}).check(invariant_chainSnapshotFollowingBlocks);
|
|
1571
|
+
var makeChainIndexingStatusSnapshotSchema = (valueLabel = "Value") => z5.discriminatedUnion("chainStatus", [
|
|
1572
|
+
makeChainIndexingStatusSnapshotQueuedSchema(valueLabel),
|
|
1573
|
+
makeChainIndexingStatusSnapshotBackfillSchema(valueLabel),
|
|
1574
|
+
makeChainIndexingStatusSnapshotCompletedSchema(valueLabel),
|
|
1575
|
+
makeChainIndexingStatusSnapshotFollowingSchema(valueLabel)
|
|
1576
|
+
]);
|
|
1577
|
+
var makeChainIndexingStatusesSchema = (valueLabel = "Value") => z5.record(makeChainIdStringSchema(), makeChainIndexingStatusSnapshotSchema(valueLabel), {
|
|
1578
|
+
error: "Chains indexing statuses must be an object mapping valid chain IDs to their indexing status snapshots."
|
|
1579
|
+
}).transform((serializedChainsIndexingStatus) => {
|
|
1580
|
+
const chainsIndexingStatus = /* @__PURE__ */ new Map();
|
|
1581
|
+
for (const [chainIdString, chainStatus] of Object.entries(serializedChainsIndexingStatus)) {
|
|
1582
|
+
chainsIndexingStatus.set(deserializeChainId(chainIdString), chainStatus);
|
|
1583
|
+
}
|
|
1584
|
+
return chainsIndexingStatus;
|
|
1585
|
+
});
|
|
1586
|
+
var makeOmnichainIndexingStatusSnapshotUnstartedSchema = (valueLabel) => z5.strictObject({
|
|
1587
|
+
omnichainStatus: z5.literal(OmnichainIndexingStatusIds.Unstarted),
|
|
1588
|
+
chains: makeChainIndexingStatusesSchema(valueLabel).check(invariant_omnichainSnapshotUnstartedHasValidChains).transform((chains) => chains),
|
|
1589
|
+
omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
|
|
1590
|
+
});
|
|
1591
|
+
var makeOmnichainIndexingStatusSnapshotBackfillSchema = (valueLabel) => z5.strictObject({
|
|
1592
|
+
omnichainStatus: z5.literal(OmnichainIndexingStatusIds.Backfill),
|
|
1593
|
+
chains: makeChainIndexingStatusesSchema(valueLabel).check(invariant_omnichainStatusSnapshotBackfillHasValidChains).transform(
|
|
1594
|
+
(chains) => chains
|
|
1595
|
+
),
|
|
1596
|
+
omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
|
|
1597
|
+
});
|
|
1598
|
+
var makeOmnichainIndexingStatusSnapshotCompletedSchema = (valueLabel) => z5.strictObject({
|
|
1599
|
+
omnichainStatus: z5.literal(OmnichainIndexingStatusIds.Completed),
|
|
1600
|
+
chains: makeChainIndexingStatusesSchema(valueLabel).check(invariant_omnichainStatusSnapshotCompletedHasValidChains).transform((chains) => chains),
|
|
1601
|
+
omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
|
|
1602
|
+
});
|
|
1603
|
+
var makeOmnichainIndexingStatusSnapshotFollowingSchema = (valueLabel) => z5.strictObject({
|
|
1604
|
+
omnichainStatus: z5.literal(OmnichainIndexingStatusIds.Following),
|
|
1605
|
+
chains: makeChainIndexingStatusesSchema(valueLabel),
|
|
1606
|
+
omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel)
|
|
1607
|
+
});
|
|
1608
|
+
var makeOmnichainIndexingStatusSnapshotSchema = (valueLabel = "Omnichain Indexing Snapshot") => z5.discriminatedUnion("omnichainStatus", [
|
|
1609
|
+
makeOmnichainIndexingStatusSnapshotUnstartedSchema(valueLabel),
|
|
1610
|
+
makeOmnichainIndexingStatusSnapshotBackfillSchema(valueLabel),
|
|
1611
|
+
makeOmnichainIndexingStatusSnapshotCompletedSchema(valueLabel),
|
|
1612
|
+
makeOmnichainIndexingStatusSnapshotFollowingSchema(valueLabel)
|
|
1613
|
+
]).check(invariant_omnichainSnapshotStatusIsConsistentWithChainSnapshot).check(invariant_omnichainIndexingCursorLowerThanEarliestStartBlockAcrossQueuedChains).check(
|
|
1614
|
+
invariant_omnichainIndexingCursorLowerThanOrEqualToLatestBackfillEndBlockAcrossBackfillChains
|
|
1615
|
+
).check(invariant_omnichainIndexingCursorIsEqualToHighestLatestIndexedBlockAcrossIndexedChain);
|
|
1616
|
+
var makeCrossChainIndexingStatusSnapshotOmnichainSchema = (valueLabel = "Cross-chain Indexing Status Snapshot Omnichain") => z5.strictObject({
|
|
1617
|
+
strategy: z5.literal(CrossChainIndexingStrategyIds.Omnichain),
|
|
1618
|
+
slowestChainIndexingCursor: makeUnixTimestampSchema(valueLabel),
|
|
1619
|
+
snapshotTime: makeUnixTimestampSchema(valueLabel),
|
|
1620
|
+
omnichainSnapshot: makeOmnichainIndexingStatusSnapshotSchema(valueLabel)
|
|
1621
|
+
}).check(invariant_slowestChainEqualsToOmnichainSnapshotTime).check(invariant_snapshotTimeIsTheHighestKnownBlockTimestamp);
|
|
1622
|
+
var makeCrossChainIndexingStatusSnapshotSchema = (valueLabel = "Cross-chain Indexing Status Snapshot") => z5.discriminatedUnion("strategy", [
|
|
1623
|
+
makeCrossChainIndexingStatusSnapshotOmnichainSchema(valueLabel)
|
|
1624
|
+
]);
|
|
1625
|
+
var makeRealtimeIndexingStatusProjectionSchema = (valueLabel = "Realtime Indexing Status Projection") => z5.strictObject({
|
|
1626
|
+
projectedAt: makeUnixTimestampSchema(valueLabel),
|
|
1627
|
+
worstCaseDistance: makeDurationSchema(valueLabel),
|
|
1628
|
+
snapshot: makeCrossChainIndexingStatusSnapshotSchema(valueLabel)
|
|
1629
|
+
}).check(invariant_realtimeIndexingStatusProjectionProjectedAtIsAfterOrEqualToSnapshotTime).check(invariant_realtimeIndexingStatusProjectionWorstCaseDistanceIsCorrect);
|
|
1630
|
+
|
|
1631
|
+
// src/ensindexer/indexing-status/deserialize.ts
|
|
1632
|
+
function deserializeChainIndexingStatusSnapshot(maybeSnapshot, valueLabel) {
|
|
1633
|
+
const schema = makeChainIndexingStatusSnapshotSchema(valueLabel);
|
|
1634
|
+
const parsed = schema.safeParse(maybeSnapshot);
|
|
1635
|
+
if (parsed.error) {
|
|
1636
|
+
throw new Error(
|
|
1637
|
+
`Cannot deserialize into ChainIndexingStatusSnapshot:
|
|
1638
|
+
${prettifyError4(parsed.error)}
|
|
1639
|
+
`
|
|
1640
|
+
);
|
|
1641
|
+
}
|
|
1642
|
+
return parsed.data;
|
|
1643
|
+
}
|
|
1644
|
+
function deserializeOmnichainIndexingStatusSnapshot(maybeSnapshot, valueLabel) {
|
|
1645
|
+
const schema = makeOmnichainIndexingStatusSnapshotSchema(valueLabel);
|
|
1646
|
+
const parsed = schema.safeParse(maybeSnapshot);
|
|
1647
|
+
if (parsed.error) {
|
|
1648
|
+
throw new Error(
|
|
1649
|
+
`Cannot deserialize into OmnichainIndexingStatusSnapshot:
|
|
1650
|
+
${prettifyError4(parsed.error)}
|
|
1651
|
+
`
|
|
1652
|
+
);
|
|
1653
|
+
}
|
|
1654
|
+
return parsed.data;
|
|
1655
|
+
}
|
|
1656
|
+
function deserializeCrossChainIndexingStatusSnapshot(maybeSnapshot, valueLabel) {
|
|
1657
|
+
const schema = makeCrossChainIndexingStatusSnapshotSchema(valueLabel);
|
|
1658
|
+
const parsed = schema.safeParse(maybeSnapshot);
|
|
1659
|
+
if (parsed.error) {
|
|
1660
|
+
throw new Error(
|
|
1661
|
+
`Cannot deserialize into CrossChainIndexingStatusSnapshot:
|
|
1662
|
+
${prettifyError4(parsed.error)}
|
|
1663
|
+
`
|
|
1664
|
+
);
|
|
1665
|
+
}
|
|
1666
|
+
return parsed.data;
|
|
1667
|
+
}
|
|
1668
|
+
function deserializeRealtimeIndexingStatusProjection(maybeProjection, valueLabel) {
|
|
1669
|
+
const schema = makeRealtimeIndexingStatusProjectionSchema(valueLabel);
|
|
1670
|
+
const parsed = schema.safeParse(maybeProjection);
|
|
1671
|
+
if (parsed.error) {
|
|
1672
|
+
throw new Error(
|
|
1673
|
+
`Cannot deserialize into RealtimeIndexingStatusProjection:
|
|
1674
|
+
${prettifyError4(parsed.error)}
|
|
1675
|
+
`
|
|
1676
|
+
);
|
|
1677
|
+
}
|
|
1678
|
+
return parsed.data;
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
// src/ensindexer/indexing-status/projection.ts
|
|
1682
|
+
function createRealtimeIndexingStatusProjection(snapshot, now) {
|
|
1683
|
+
const projectedAt = Math.max(now, snapshot.snapshotTime);
|
|
1684
|
+
return {
|
|
1685
|
+
projectedAt,
|
|
1686
|
+
worstCaseDistance: projectedAt - snapshot.slowestChainIndexingCursor,
|
|
1687
|
+
snapshot
|
|
1688
|
+
};
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
// src/ensindexer/indexing-status/serialize.ts
|
|
1692
|
+
function serializeCrossChainIndexingStatusSnapshotOmnichain({
|
|
1693
|
+
strategy,
|
|
1694
|
+
slowestChainIndexingCursor,
|
|
1695
|
+
snapshotTime,
|
|
1696
|
+
omnichainSnapshot
|
|
1697
|
+
}) {
|
|
1698
|
+
return {
|
|
1699
|
+
strategy,
|
|
1700
|
+
slowestChainIndexingCursor,
|
|
1701
|
+
snapshotTime,
|
|
1702
|
+
omnichainSnapshot: serializeOmnichainIndexingStatusSnapshot(omnichainSnapshot)
|
|
1703
|
+
};
|
|
1704
|
+
}
|
|
1705
|
+
function serializeRealtimeIndexingStatusProjection(indexingProjection) {
|
|
1706
|
+
return {
|
|
1707
|
+
projectedAt: indexingProjection.projectedAt,
|
|
1708
|
+
worstCaseDistance: indexingProjection.worstCaseDistance,
|
|
1709
|
+
snapshot: serializeCrossChainIndexingStatusSnapshotOmnichain(indexingProjection.snapshot)
|
|
1710
|
+
};
|
|
1711
|
+
}
|
|
1712
|
+
function serializeChainIndexingSnapshots(chains) {
|
|
1713
|
+
const serializedSnapshots = {};
|
|
1714
|
+
for (const [chainId, snapshot] of chains.entries()) {
|
|
1715
|
+
serializedSnapshots[serializeChainId(chainId)] = snapshot;
|
|
1716
|
+
}
|
|
1717
|
+
return serializedSnapshots;
|
|
1718
|
+
}
|
|
1719
|
+
function serializeOmnichainIndexingStatusSnapshot(indexingStatus) {
|
|
1720
|
+
switch (indexingStatus.omnichainStatus) {
|
|
1721
|
+
case OmnichainIndexingStatusIds.Unstarted:
|
|
1722
|
+
return {
|
|
1723
|
+
omnichainStatus: OmnichainIndexingStatusIds.Unstarted,
|
|
1724
|
+
chains: serializeChainIndexingSnapshots(indexingStatus.chains),
|
|
1725
|
+
omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
|
|
1726
|
+
};
|
|
1727
|
+
case OmnichainIndexingStatusIds.Backfill:
|
|
1728
|
+
return {
|
|
1729
|
+
omnichainStatus: OmnichainIndexingStatusIds.Backfill,
|
|
1730
|
+
chains: serializeChainIndexingSnapshots(indexingStatus.chains),
|
|
1731
|
+
omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
|
|
1732
|
+
};
|
|
1733
|
+
case OmnichainIndexingStatusIds.Completed: {
|
|
1734
|
+
return {
|
|
1735
|
+
omnichainStatus: OmnichainIndexingStatusIds.Completed,
|
|
1736
|
+
chains: serializeChainIndexingSnapshots(indexingStatus.chains),
|
|
1737
|
+
omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
|
|
1738
|
+
};
|
|
1739
|
+
}
|
|
1740
|
+
case OmnichainIndexingStatusIds.Following:
|
|
1741
|
+
return {
|
|
1742
|
+
omnichainStatus: OmnichainIndexingStatusIds.Following,
|
|
1743
|
+
chains: serializeChainIndexingSnapshots(indexingStatus.chains),
|
|
1744
|
+
omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor
|
|
1745
|
+
};
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
// src/ensapi/config/serialize.ts
|
|
1750
|
+
function serializeENSApiPublicConfig(config) {
|
|
1751
|
+
const { version, theGraphFallback, ensIndexerPublicConfig } = config;
|
|
1752
|
+
return {
|
|
1753
|
+
version,
|
|
1754
|
+
theGraphFallback,
|
|
1755
|
+
ensIndexerPublicConfig: serializeENSIndexerPublicConfig(ensIndexerPublicConfig)
|
|
1756
|
+
};
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
// src/api/config/deserialize.ts
|
|
1760
|
+
function deserializeConfigResponse(serializedResponse) {
|
|
1761
|
+
return deserializeENSApiPublicConfig(serializedResponse);
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
// src/api/config/serialize.ts
|
|
1765
|
+
function serializeConfigResponse(response) {
|
|
1766
|
+
return serializeENSApiPublicConfig(response);
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
// src/api/indexing-status/deserialize.ts
|
|
1770
|
+
import { prettifyError as prettifyError5 } from "zod/v4";
|
|
1771
|
+
|
|
1772
|
+
// src/api/indexing-status/zod-schemas.ts
|
|
1773
|
+
import z6 from "zod/v4";
|
|
1774
|
+
|
|
1775
|
+
// src/api/indexing-status/response.ts
|
|
1776
|
+
var IndexingStatusResponseCodes = {
|
|
1777
|
+
/**
|
|
1778
|
+
* Represents that the indexing status is available.
|
|
1779
|
+
*/
|
|
1780
|
+
Ok: "ok",
|
|
1781
|
+
/**
|
|
1782
|
+
* Represents that the indexing status is unavailable.
|
|
1783
|
+
*/
|
|
1784
|
+
Error: "error"
|
|
1785
|
+
};
|
|
1786
|
+
|
|
1787
|
+
// src/api/indexing-status/zod-schemas.ts
|
|
1788
|
+
var makeIndexingStatusResponseOkSchema = (valueLabel = "Indexing Status Response OK") => z6.strictObject({
|
|
1789
|
+
responseCode: z6.literal(IndexingStatusResponseCodes.Ok),
|
|
1790
|
+
realtimeProjection: makeRealtimeIndexingStatusProjectionSchema(valueLabel)
|
|
1791
|
+
});
|
|
1792
|
+
var makeIndexingStatusResponseErrorSchema = (_valueLabel = "Indexing Status Response Error") => z6.strictObject({
|
|
1793
|
+
responseCode: z6.literal(IndexingStatusResponseCodes.Error)
|
|
1794
|
+
});
|
|
1795
|
+
var makeIndexingStatusResponseSchema = (valueLabel = "Indexing Status Response") => z6.discriminatedUnion("responseCode", [
|
|
1796
|
+
makeIndexingStatusResponseOkSchema(valueLabel),
|
|
1797
|
+
makeIndexingStatusResponseErrorSchema(valueLabel)
|
|
1798
|
+
]);
|
|
1799
|
+
|
|
1800
|
+
// src/api/indexing-status/deserialize.ts
|
|
1801
|
+
function deserializeIndexingStatusResponse(maybeResponse) {
|
|
1802
|
+
const parsed = makeIndexingStatusResponseSchema().safeParse(maybeResponse);
|
|
1803
|
+
if (parsed.error) {
|
|
1804
|
+
throw new Error(`Cannot deserialize IndexingStatusResponse:
|
|
1805
|
+
${prettifyError5(parsed.error)}
|
|
1806
|
+
`);
|
|
1807
|
+
}
|
|
1808
|
+
return parsed.data;
|
|
1809
|
+
}
|
|
1810
|
+
|
|
1811
|
+
// src/api/indexing-status/serialize.ts
|
|
1812
|
+
function serializeIndexingStatusResponse(response) {
|
|
1813
|
+
switch (response.responseCode) {
|
|
1814
|
+
case IndexingStatusResponseCodes.Ok:
|
|
1815
|
+
return {
|
|
1816
|
+
responseCode: response.responseCode,
|
|
1817
|
+
realtimeProjection: serializeRealtimeIndexingStatusProjection(response.realtimeProjection)
|
|
1818
|
+
};
|
|
1819
|
+
case IndexingStatusResponseCodes.Error:
|
|
1820
|
+
return response;
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
|
|
1824
|
+
// src/api/name-tokens/deserialize.ts
|
|
1825
|
+
import { prettifyError as prettifyError7 } from "zod/v4";
|
|
1826
|
+
|
|
1827
|
+
// src/api/name-tokens/zod-schemas.ts
|
|
1828
|
+
import { namehash as namehash2 } from "viem";
|
|
1829
|
+
import z9 from "zod/v4";
|
|
1830
|
+
|
|
1831
|
+
// src/tokenscope/assets.ts
|
|
1832
|
+
import { AssetId as CaipAssetId2 } from "caip";
|
|
1833
|
+
import { isAddressEqual as isAddressEqual3, zeroAddress as zeroAddress3 } from "viem";
|
|
1834
|
+
import { prettifyError as prettifyError6 } from "zod/v4";
|
|
1835
|
+
|
|
1836
|
+
// src/tokenscope/zod-schemas.ts
|
|
1837
|
+
import { AssetId as CaipAssetId } from "caip";
|
|
1838
|
+
import { zeroAddress as zeroAddress2 } from "viem";
|
|
1839
|
+
import z7 from "zod/v4";
|
|
1840
|
+
|
|
1841
|
+
// src/tokenscope/name-token.ts
|
|
1842
|
+
import { isAddressEqual as isAddressEqual2, zeroAddress } from "viem";
|
|
1843
|
+
import { DatasourceNames } from "@ensnode/datasources";
|
|
1844
|
+
var NameTokenOwnershipTypes = {
|
|
1845
|
+
/**
|
|
1846
|
+
* Name Token is owned by NameWrapper account.
|
|
1847
|
+
*/
|
|
1848
|
+
NameWrapper: "namewrapper",
|
|
1849
|
+
/**
|
|
1850
|
+
* Name Token is owned fully onchain.
|
|
1851
|
+
*
|
|
1852
|
+
* This ownership type can only apply to direct subnames of `.eth`
|
|
1853
|
+
*/
|
|
1854
|
+
FullyOnchain: "fully-onchain",
|
|
1855
|
+
/**
|
|
1856
|
+
* Name Token ownership has been transferred to the null address.
|
|
1857
|
+
*/
|
|
1858
|
+
Burned: "burned",
|
|
1859
|
+
/**
|
|
1860
|
+
* Name Token ownership is unknown.
|
|
1861
|
+
*/
|
|
1862
|
+
Unknown: "unknown"
|
|
1863
|
+
};
|
|
1864
|
+
function serializeNameToken(nameToken) {
|
|
1865
|
+
return {
|
|
1866
|
+
token: serializeAssetId(nameToken.token),
|
|
1867
|
+
ownership: nameToken.ownership,
|
|
1868
|
+
mintStatus: nameToken.mintStatus
|
|
1869
|
+
};
|
|
1870
|
+
}
|
|
1871
|
+
function getNameWrapperAccounts(namespaceId) {
|
|
1872
|
+
const ethnamesNameWrapperAccount = getDatasourceContract(
|
|
1873
|
+
namespaceId,
|
|
1874
|
+
DatasourceNames.ENSRoot,
|
|
1875
|
+
"NameWrapper"
|
|
1876
|
+
);
|
|
1877
|
+
const lineanamesNameWrapperAccount = maybeGetDatasourceContract(
|
|
1878
|
+
namespaceId,
|
|
1879
|
+
DatasourceNames.Lineanames,
|
|
1880
|
+
"NameWrapper"
|
|
1881
|
+
);
|
|
1882
|
+
const nameWrapperAccounts = [
|
|
1883
|
+
// NameWrapper for direct subnames of .eth is defined for all ENS namespaces
|
|
1884
|
+
ethnamesNameWrapperAccount
|
|
1885
|
+
];
|
|
1886
|
+
if (lineanamesNameWrapperAccount) {
|
|
1887
|
+
nameWrapperAccounts.push(lineanamesNameWrapperAccount);
|
|
1888
|
+
}
|
|
1889
|
+
return nameWrapperAccounts;
|
|
1890
|
+
}
|
|
1891
|
+
function getNameTokenOwnership(namespaceId, name, owner) {
|
|
1892
|
+
const nameWrapperAccounts = getNameWrapperAccounts(namespaceId);
|
|
1893
|
+
const hasNameWrapperOwnership = nameWrapperAccounts.some(
|
|
1894
|
+
(nameWrapperAccount) => accountIdEqual(owner, nameWrapperAccount)
|
|
1895
|
+
);
|
|
1896
|
+
if (hasNameWrapperOwnership) {
|
|
1897
|
+
return {
|
|
1898
|
+
ownershipType: NameTokenOwnershipTypes.NameWrapper,
|
|
1899
|
+
owner
|
|
1900
|
+
};
|
|
1901
|
+
}
|
|
1902
|
+
if (isAddressEqual2(owner.address, zeroAddress)) {
|
|
1903
|
+
return {
|
|
1904
|
+
ownershipType: NameTokenOwnershipTypes.Burned,
|
|
1905
|
+
owner
|
|
1906
|
+
};
|
|
1907
|
+
}
|
|
1908
|
+
const parentName = getParentNameFQDN(name);
|
|
1909
|
+
if (parentName === "eth") {
|
|
1910
|
+
return {
|
|
1911
|
+
ownershipType: NameTokenOwnershipTypes.FullyOnchain,
|
|
1912
|
+
owner
|
|
1913
|
+
};
|
|
1914
|
+
}
|
|
1915
|
+
return {
|
|
1916
|
+
ownershipType: NameTokenOwnershipTypes.Unknown,
|
|
1917
|
+
owner
|
|
1918
|
+
};
|
|
1919
|
+
}
|
|
1920
|
+
|
|
1921
|
+
// src/tokenscope/zod-schemas.ts
|
|
1922
|
+
var tokenIdSchemaSerializable = z7.string();
|
|
1923
|
+
var tokenIdSchemaNative = z7.preprocess(
|
|
1924
|
+
(v) => typeof v === "string" ? BigInt(v) : v,
|
|
1925
|
+
z7.bigint().positive()
|
|
1926
|
+
);
|
|
1927
|
+
function makeTokenIdSchema(_valueLabel = "Token ID Schema", serializable = false) {
|
|
1928
|
+
if (serializable) {
|
|
1929
|
+
return tokenIdSchemaSerializable;
|
|
1930
|
+
} else {
|
|
1931
|
+
return tokenIdSchemaNative;
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
var makeAssetIdSchema = (valueLabel = "Asset ID Schema", serializable) => {
|
|
1935
|
+
return z7.object({
|
|
1936
|
+
assetNamespace: z7.enum(AssetNamespaces),
|
|
1937
|
+
contract: makeAccountIdSchema(valueLabel),
|
|
1938
|
+
tokenId: makeTokenIdSchema(valueLabel, serializable ?? false)
|
|
1939
|
+
});
|
|
1940
|
+
};
|
|
1941
|
+
var makeAssetIdStringSchema = (valueLabel = "Asset ID String Schema") => z7.preprocess((v) => {
|
|
1942
|
+
if (typeof v === "string") {
|
|
1943
|
+
const result = new CaipAssetId(v);
|
|
1944
|
+
return {
|
|
1945
|
+
assetNamespace: result.assetName.namespace,
|
|
1946
|
+
contract: {
|
|
1947
|
+
chainId: Number(result.chainId.reference),
|
|
1948
|
+
address: result.assetName.reference
|
|
1949
|
+
},
|
|
1950
|
+
tokenId: result.tokenId
|
|
1951
|
+
};
|
|
1952
|
+
}
|
|
1953
|
+
return v;
|
|
1954
|
+
}, makeAssetIdSchema(valueLabel));
|
|
1955
|
+
function invariant_nameTokenOwnershipHasNonZeroAddressOwner(ctx) {
|
|
1956
|
+
const ownership = ctx.value;
|
|
1957
|
+
if (ctx.value.owner.address === zeroAddress2) {
|
|
1958
|
+
ctx.issues.push({
|
|
1959
|
+
code: "custom",
|
|
1960
|
+
input: ctx.value,
|
|
1961
|
+
message: `Name Token Ownership with '${ownership.ownershipType}' must have 'address' other than the zero address.`
|
|
1962
|
+
});
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
var makeNameTokenOwnershipNameWrapperSchema = (valueLabel = "Name Token Ownership NameWrapper") => z7.object({
|
|
1966
|
+
ownershipType: z7.literal(NameTokenOwnershipTypes.NameWrapper),
|
|
1967
|
+
owner: makeAccountIdSchema(`${valueLabel}.owner`)
|
|
1968
|
+
}).check(invariant_nameTokenOwnershipHasNonZeroAddressOwner);
|
|
1969
|
+
var makeNameTokenOwnershipFullyOnchainSchema = (valueLabel = "Name Token Ownership Fully Onchain") => z7.object({
|
|
1970
|
+
ownershipType: z7.literal(NameTokenOwnershipTypes.FullyOnchain),
|
|
1971
|
+
owner: makeAccountIdSchema(`${valueLabel}.owner`)
|
|
1972
|
+
}).check(invariant_nameTokenOwnershipHasNonZeroAddressOwner);
|
|
1973
|
+
var makeNameTokenOwnershipBurnedSchema = (valueLabel = "Name Token Ownership Burned") => z7.object({
|
|
1974
|
+
ownershipType: z7.literal(NameTokenOwnershipTypes.Burned),
|
|
1975
|
+
owner: makeAccountIdSchema(`${valueLabel}.owner`)
|
|
1976
|
+
}).check(invariant_nameTokenOwnershipHasZeroAddressOwner);
|
|
1977
|
+
var makeNameTokenOwnershipUnknownSchema = (valueLabel = "Name Token Ownership Unknown") => z7.object({
|
|
1978
|
+
ownershipType: z7.literal(NameTokenOwnershipTypes.Unknown),
|
|
1979
|
+
owner: makeAccountIdSchema(`${valueLabel}.owner`)
|
|
1980
|
+
}).check(invariant_nameTokenOwnershipHasNonZeroAddressOwner);
|
|
1981
|
+
function invariant_nameTokenOwnershipHasZeroAddressOwner(ctx) {
|
|
1982
|
+
const ownership = ctx.value;
|
|
1983
|
+
if (ctx.value.owner.address !== zeroAddress2) {
|
|
1984
|
+
ctx.issues.push({
|
|
1985
|
+
code: "custom",
|
|
1986
|
+
input: ctx.value,
|
|
1987
|
+
message: `Name Token Ownership with '${ownership.ownershipType}' must have 'address' set to the zero address.`
|
|
1988
|
+
});
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
var makeNameTokenOwnershipSchema = (valueLabel = "Name Token Ownership") => z7.discriminatedUnion("ownershipType", [
|
|
1992
|
+
makeNameTokenOwnershipNameWrapperSchema(valueLabel),
|
|
1993
|
+
makeNameTokenOwnershipFullyOnchainSchema(valueLabel),
|
|
1994
|
+
makeNameTokenOwnershipBurnedSchema(valueLabel),
|
|
1995
|
+
makeNameTokenOwnershipUnknownSchema(valueLabel)
|
|
1996
|
+
]);
|
|
1997
|
+
var makeNameTokenSchema = (valueLabel = "Name Token Schema", serializable) => z7.object({
|
|
1998
|
+
token: makeAssetIdSchema(`${valueLabel}.token`, serializable),
|
|
1999
|
+
ownership: makeNameTokenOwnershipSchema(`${valueLabel}.ownership`),
|
|
2000
|
+
mintStatus: z7.enum(NFTMintStatuses)
|
|
2001
|
+
});
|
|
2002
|
+
|
|
2003
|
+
// src/tokenscope/assets.ts
|
|
2004
|
+
var AssetNamespaces = {
|
|
2005
|
+
ERC721: "erc721",
|
|
2006
|
+
ERC1155: "erc1155"
|
|
2007
|
+
};
|
|
2008
|
+
function serializeAssetId(assetId) {
|
|
2009
|
+
return {
|
|
2010
|
+
assetNamespace: assetId.assetNamespace,
|
|
2011
|
+
contract: assetId.contract,
|
|
2012
|
+
tokenId: uint256ToHex32(assetId.tokenId)
|
|
2013
|
+
};
|
|
2014
|
+
}
|
|
2015
|
+
function deserializeAssetId(maybeAssetId, valueLabel) {
|
|
2016
|
+
const schema = makeAssetIdSchema(valueLabel);
|
|
2017
|
+
const parsed = schema.safeParse(maybeAssetId);
|
|
2018
|
+
if (parsed.error) {
|
|
2019
|
+
throw new RangeError(`Cannot deserialize AssetId:
|
|
2020
|
+
${prettifyError6(parsed.error)}
|
|
2021
|
+
`);
|
|
2022
|
+
}
|
|
2023
|
+
return parsed.data;
|
|
2024
|
+
}
|
|
2025
|
+
function formatAssetId(assetId) {
|
|
2026
|
+
const { assetNamespace, contract, tokenId } = serializeAssetId(assetId);
|
|
2027
|
+
return CaipAssetId2.format({
|
|
2028
|
+
chainId: { namespace: "eip155", reference: contract.chainId.toString() },
|
|
2029
|
+
assetName: { namespace: assetNamespace, reference: contract.address },
|
|
2030
|
+
tokenId
|
|
2031
|
+
}).toLowerCase();
|
|
2032
|
+
}
|
|
2033
|
+
function parseAssetId(maybeAssetId, valueLabel) {
|
|
2034
|
+
const schema = makeAssetIdStringSchema(valueLabel);
|
|
2035
|
+
const parsed = schema.safeParse(maybeAssetId);
|
|
2036
|
+
if (parsed.error) {
|
|
2037
|
+
throw new RangeError(`Cannot parse AssetId:
|
|
2038
|
+
${prettifyError6(parsed.error)}
|
|
2039
|
+
`);
|
|
2040
|
+
}
|
|
2041
|
+
return parsed.data;
|
|
2042
|
+
}
|
|
2043
|
+
var buildAssetId = (contract, tokenId, assetNamespace) => {
|
|
2044
|
+
return {
|
|
2045
|
+
assetNamespace,
|
|
2046
|
+
contract,
|
|
2047
|
+
tokenId
|
|
2048
|
+
};
|
|
2049
|
+
};
|
|
2050
|
+
function serializeDomainAssetId(domainAsset) {
|
|
2051
|
+
return {
|
|
2052
|
+
...serializeAssetId(domainAsset),
|
|
2053
|
+
domainId: domainAsset.domainId
|
|
2054
|
+
};
|
|
2055
|
+
}
|
|
2056
|
+
var NFTMintStatuses = {
|
|
2057
|
+
Minted: "minted",
|
|
2058
|
+
Burned: "burned"
|
|
2059
|
+
};
|
|
2060
|
+
var formatNFTTransferEventMetadata = (metadata) => {
|
|
2061
|
+
const serializedAssetId = serializeAssetId(metadata.nft);
|
|
2062
|
+
return [
|
|
2063
|
+
`Event: ${metadata.eventHandlerName}`,
|
|
2064
|
+
`Chain ID: ${metadata.chainId}`,
|
|
2065
|
+
`Block Number: ${metadata.blockNumber}`,
|
|
2066
|
+
`Transaction Hash: ${metadata.transactionHash}`,
|
|
2067
|
+
`NFT: ${serializedAssetId}`
|
|
2068
|
+
].map((line) => ` - ${line}`).join("\n");
|
|
2069
|
+
};
|
|
2070
|
+
var NFTTransferTypes = {
|
|
2071
|
+
/**
|
|
2072
|
+
* Initial transfer from zeroAddress to a non-zeroAddress
|
|
2073
|
+
* Can happen at most once to a NFT AssetId
|
|
2074
|
+
*
|
|
2075
|
+
* Invariants:
|
|
2076
|
+
* - NFT is not indexed and therefore has no previous mint status or owner
|
|
2077
|
+
* - new NFT mint status is `minted`
|
|
2078
|
+
* - new NFT owner is a non-zeroAddress
|
|
2079
|
+
*/
|
|
2080
|
+
Mint: "mint",
|
|
2081
|
+
/**
|
|
2082
|
+
* Subsequent transfer from zeroAddress to a non-zeroAddress
|
|
2083
|
+
* Can happen any number of times to a NFT AssetId as it passes in a cycle from
|
|
2084
|
+
* mint -> burn -> remint -> burn -> remint -> ...
|
|
2085
|
+
*
|
|
2086
|
+
* Invariants:
|
|
2087
|
+
* - NFT is indexed
|
|
2088
|
+
* - previous NFT mint status was `burned`
|
|
2089
|
+
* - previous NFT owner is the zeroAddress
|
|
2090
|
+
* - new NFT mint status is `minted`
|
|
2091
|
+
* - new NFT owner is a non-zeroAddress
|
|
2092
|
+
*/
|
|
2093
|
+
Remint: "remint",
|
|
2094
|
+
/**
|
|
2095
|
+
* Special transfer type for improperly implemented NFT contracts that allow a NFT
|
|
2096
|
+
* that is currently minted to be reminted before an intermediate burn.
|
|
2097
|
+
*
|
|
2098
|
+
* Transfer from zeroAddress to non-zeroAddress for an indexed NFT where the
|
|
2099
|
+
* previously indexed nft had status `minted` with a non-zeroAddress owner.
|
|
2100
|
+
*
|
|
2101
|
+
* Invariants:
|
|
2102
|
+
* - NFT is indexed
|
|
2103
|
+
* - previous NFT mint status was `minted`
|
|
2104
|
+
* - previous NFT owner was a non-zeroAddress
|
|
2105
|
+
* - new NFT mint status is `minted`
|
|
2106
|
+
* - new NFT owner is a non-zeroAddress
|
|
2107
|
+
*/
|
|
2108
|
+
MintedRemint: "minted-remint",
|
|
2109
|
+
/**
|
|
2110
|
+
* Transfer from a non-zeroAddress to zeroAddress
|
|
2111
|
+
*
|
|
2112
|
+
* Invariants:
|
|
2113
|
+
* - NFT is indexed
|
|
2114
|
+
* - previous NFT mint status was `minted`
|
|
2115
|
+
* - previous NFT owner is a non-zeroAddress
|
|
2116
|
+
* - new NFT mint status is `burned`
|
|
2117
|
+
* - new NFT owner is the zeroAddress
|
|
2118
|
+
*/
|
|
2119
|
+
Burn: "burn",
|
|
2120
|
+
/**
|
|
2121
|
+
* Transfer from a non-zeroAddress to a distinct non-zeroAddress
|
|
2122
|
+
*
|
|
2123
|
+
* Invariants:
|
|
2124
|
+
* - NFT is indexed
|
|
2125
|
+
* - previous and new NFT mint status is `minted`
|
|
2126
|
+
* - previous and new NFT owner are distinct non-zeroAddress
|
|
2127
|
+
*/
|
|
2128
|
+
Transfer: "transfer",
|
|
2129
|
+
/**
|
|
2130
|
+
* Transfer from a non-zeroAddress to the same non-zeroAddress
|
|
2131
|
+
*
|
|
2132
|
+
* Invariants:
|
|
2133
|
+
* - NFT is indexed
|
|
2134
|
+
* - previous and new NFT mint status is `minted`
|
|
2135
|
+
* - previous and new NFT owner are equivalent non-zeroAddress
|
|
2136
|
+
*/
|
|
2137
|
+
SelfTransfer: "self-transfer",
|
|
2138
|
+
/**
|
|
2139
|
+
* Transfer from zeroAddress to zeroAddress for an indexed NFT
|
|
2140
|
+
*
|
|
2141
|
+
* Invariants:
|
|
2142
|
+
* - NFT is indexed
|
|
2143
|
+
* - previous and new NFT mint status is `burned`
|
|
2144
|
+
* - previous and new NFT owner are zeroAddress
|
|
2145
|
+
*/
|
|
2146
|
+
RemintBurn: "remint-burn",
|
|
2147
|
+
/**
|
|
2148
|
+
* Special transfer type for improperly implemented NFT contracts that allow a NFT
|
|
2149
|
+
* that is currently minted to be reminted again before an intermediate burn.
|
|
2150
|
+
*
|
|
2151
|
+
* Transfer from zeroAddress to zeroAddress for an indexed NFT where the
|
|
2152
|
+
* previously indexed nft had status `minted` with a non-zeroAddress owner.
|
|
2153
|
+
*
|
|
2154
|
+
* Invariants:
|
|
2155
|
+
* - NFT is indexed
|
|
2156
|
+
* - previous NFT mint status was `minted`
|
|
2157
|
+
* - previous NFT owner was a non-zeroAddress
|
|
2158
|
+
* - new NFT mint status is `burned`
|
|
2159
|
+
* - new NFT owner is the zeroAddress
|
|
2160
|
+
*/
|
|
2161
|
+
MintedRemintBurn: "minted-remint-burn",
|
|
2162
|
+
/**
|
|
2163
|
+
* Transfer from zeroAddress to zeroAddress for an unindexed NFT
|
|
2164
|
+
*
|
|
2165
|
+
* Invariants:
|
|
2166
|
+
* - NFT is not indexed and therefore has no previous mint status or owner
|
|
2167
|
+
* - NFT should remain unindexed and without any mint status or owner
|
|
2168
|
+
*/
|
|
2169
|
+
MintBurn: "mint-burn"
|
|
2170
|
+
};
|
|
2171
|
+
var getNFTTransferType = (from, to, allowMintedRemint, metadata, currentlyIndexedOwner) => {
|
|
2172
|
+
const isIndexed = currentlyIndexedOwner !== void 0;
|
|
2173
|
+
const isIndexedAsMinted = isIndexed && !isAddressEqual3(currentlyIndexedOwner, zeroAddress3);
|
|
2174
|
+
const isMint = isAddressEqual3(from, zeroAddress3);
|
|
2175
|
+
const isBurn = isAddressEqual3(to, zeroAddress3);
|
|
2176
|
+
const isSelfTransfer = isAddressEqual3(from, to);
|
|
2177
|
+
if (isIndexed && !isAddressEqual3(currentlyIndexedOwner, from)) {
|
|
2178
|
+
if (isMint && allowMintedRemint) {
|
|
2179
|
+
} else {
|
|
2180
|
+
throw new Error(
|
|
2181
|
+
`Error: Sending from ${from} conflicts with currently indexed owner ${currentlyIndexedOwner}.
|
|
2182
|
+
${formatNFTTransferEventMetadata(metadata)}`
|
|
2183
|
+
);
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
if (isSelfTransfer) {
|
|
2187
|
+
if (isMint) {
|
|
2188
|
+
if (!isIndexed) {
|
|
2189
|
+
return NFTTransferTypes.MintBurn;
|
|
2190
|
+
} else if (!isIndexedAsMinted) {
|
|
2191
|
+
return NFTTransferTypes.RemintBurn;
|
|
2192
|
+
} else if (allowMintedRemint) {
|
|
2193
|
+
return NFTTransferTypes.MintedRemintBurn;
|
|
2194
|
+
} else {
|
|
2195
|
+
throw new Error(
|
|
2196
|
+
`Error: Invalid state transition from minted -> remint-burn
|
|
2197
|
+
${formatNFTTransferEventMetadata(metadata)}`
|
|
2198
|
+
);
|
|
2199
|
+
}
|
|
2200
|
+
} else {
|
|
2201
|
+
if (!isIndexed) {
|
|
2202
|
+
throw new Error(
|
|
2203
|
+
`Error: Invalid state transition from unindexed -> self-transfer
|
|
2204
|
+
${formatNFTTransferEventMetadata(metadata)}`
|
|
2205
|
+
);
|
|
2206
|
+
} else if (!isIndexedAsMinted) {
|
|
2207
|
+
throw new Error(
|
|
2208
|
+
`Error: invalid state transition from burned -> self-transfer
|
|
2209
|
+
${formatNFTTransferEventMetadata(metadata)}`
|
|
2210
|
+
);
|
|
2211
|
+
} else {
|
|
2212
|
+
return NFTTransferTypes.SelfTransfer;
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
} else if (isMint) {
|
|
2216
|
+
if (!isIndexed) {
|
|
2217
|
+
return NFTTransferTypes.Mint;
|
|
2218
|
+
} else if (!isIndexedAsMinted) {
|
|
2219
|
+
return NFTTransferTypes.Remint;
|
|
2220
|
+
} else if (allowMintedRemint) {
|
|
2221
|
+
return NFTTransferTypes.MintedRemint;
|
|
2222
|
+
} else {
|
|
2223
|
+
throw new Error(
|
|
2224
|
+
`Error: Invalid state transition from minted -> mint
|
|
2225
|
+
${formatNFTTransferEventMetadata(metadata)}`
|
|
2226
|
+
);
|
|
2227
|
+
}
|
|
2228
|
+
} else if (isBurn) {
|
|
2229
|
+
if (!isIndexed) {
|
|
2230
|
+
throw new Error(
|
|
2231
|
+
`Error: Invalid state transition from unindexed -> burn
|
|
2232
|
+
${formatNFTTransferEventMetadata(metadata)}`
|
|
2233
|
+
);
|
|
2234
|
+
} else if (!isIndexedAsMinted) {
|
|
2235
|
+
throw new Error(
|
|
2236
|
+
`Error: Invalid state transition from burned -> burn
|
|
2237
|
+
${formatNFTTransferEventMetadata(metadata)}`
|
|
2238
|
+
);
|
|
2239
|
+
} else {
|
|
2240
|
+
return NFTTransferTypes.Burn;
|
|
2241
|
+
}
|
|
2242
|
+
} else {
|
|
2243
|
+
if (!isIndexed) {
|
|
2244
|
+
throw new Error(
|
|
2245
|
+
`Error: Invalid state transition from unindexed -> transfer
|
|
2246
|
+
${formatNFTTransferEventMetadata(metadata)}`
|
|
2247
|
+
);
|
|
2248
|
+
} else if (!isIndexedAsMinted) {
|
|
2249
|
+
throw new Error(
|
|
2250
|
+
`Error: Invalid state transition from burned -> transfer
|
|
2251
|
+
${formatNFTTransferEventMetadata(metadata)}`
|
|
2252
|
+
);
|
|
2253
|
+
} else {
|
|
2254
|
+
return NFTTransferTypes.Transfer;
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
};
|
|
2258
|
+
|
|
2259
|
+
// src/api/shared/errors/zod-schemas.ts
|
|
2260
|
+
import z8 from "zod/v4";
|
|
2261
|
+
var ErrorResponseSchema = z8.object({
|
|
2262
|
+
message: z8.string(),
|
|
2263
|
+
details: z8.optional(z8.unknown())
|
|
2264
|
+
});
|
|
2265
|
+
|
|
2266
|
+
// src/api/name-tokens/response.ts
|
|
2267
|
+
var NameTokensResponseCodes = {
|
|
2268
|
+
/**
|
|
2269
|
+
* Represents a response when Name Tokens API can respond with requested data.
|
|
2270
|
+
*/
|
|
2271
|
+
Ok: "ok",
|
|
2272
|
+
/**
|
|
2273
|
+
* Represents a response when Name Tokens API could not respond with requested data.
|
|
2274
|
+
*/
|
|
2275
|
+
Error: "error"
|
|
2276
|
+
};
|
|
2277
|
+
var NameTokensResponseErrorCodes = {
|
|
2278
|
+
/**
|
|
2279
|
+
* Name tokens not indexed
|
|
2280
|
+
*
|
|
2281
|
+
* Represents an error when tokens for the requested name are not indexed by
|
|
2282
|
+
* the ENSNode instance's configuration.
|
|
2283
|
+
*/
|
|
2284
|
+
NameTokensNotIndexed: "name-tokens-not-indexed",
|
|
2285
|
+
/**
|
|
2286
|
+
* Unsupported ENSIndexer Config
|
|
2287
|
+
*
|
|
2288
|
+
* Represents a prerequisites error when connected ENSIndexer config lacks
|
|
2289
|
+
* params required to enable Name Tokens API.
|
|
2290
|
+
*/
|
|
2291
|
+
EnsIndexerConfigUnsupported: "unsupported-ensindexer-config",
|
|
2292
|
+
/**
|
|
2293
|
+
* Unsupported Indexing Status
|
|
2294
|
+
*
|
|
2295
|
+
* Represents a prerequisites error when Indexing Status has not yet reached
|
|
2296
|
+
* status required to enable Name Tokens API.
|
|
2297
|
+
*/
|
|
2298
|
+
IndexingStatusUnsupported: "unsupported-indexing-status"
|
|
2299
|
+
};
|
|
2300
|
+
|
|
2301
|
+
// src/api/name-tokens/zod-schemas.ts
|
|
2302
|
+
var makeRegisteredNameTokenSchema = (valueLabel = "Registered Name Token", serializable) => z9.object({
|
|
2303
|
+
domainId: makeNodeSchema(`${valueLabel}.domainId`),
|
|
2304
|
+
name: makeReinterpretedNameSchema(valueLabel),
|
|
2305
|
+
tokens: z9.array(makeNameTokenSchema(`${valueLabel}.tokens`, serializable)).nonempty(),
|
|
2306
|
+
expiresAt: makeUnixTimestampSchema(`${valueLabel}.expiresAt`),
|
|
2307
|
+
accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`)
|
|
2308
|
+
}).check(function invariant_nameIsAssociatedWithDomainId(ctx) {
|
|
2309
|
+
const { name, domainId } = ctx.value;
|
|
2310
|
+
if (namehash2(name) !== domainId) {
|
|
2311
|
+
ctx.issues.push({
|
|
2312
|
+
code: "custom",
|
|
2313
|
+
input: ctx.value,
|
|
2314
|
+
message: `'name' must be associated with 'domainId': ${domainId}`
|
|
2315
|
+
});
|
|
2316
|
+
}
|
|
2317
|
+
}).check(
|
|
2318
|
+
function invariant_nameTokensOwnershipTypeNameWrapperRequiresOwnershipTypeFullyOnchainOrUnknown(ctx) {
|
|
2319
|
+
const { tokens } = ctx.value;
|
|
2320
|
+
const containsOwnershipNameWrapper = tokens.some(
|
|
2321
|
+
(t) => t.ownership.ownershipType === NameTokenOwnershipTypes.NameWrapper
|
|
2322
|
+
);
|
|
2323
|
+
const containsOwnershipFullyOnchainOrUnknown = tokens.some(
|
|
2324
|
+
(t) => t.ownership.ownershipType === NameTokenOwnershipTypes.FullyOnchain || t.ownership.ownershipType === NameTokenOwnershipTypes.Unknown
|
|
2325
|
+
);
|
|
2326
|
+
if (containsOwnershipNameWrapper && !containsOwnershipFullyOnchainOrUnknown) {
|
|
2327
|
+
ctx.issues.push({
|
|
2328
|
+
code: "custom",
|
|
2329
|
+
input: ctx.value,
|
|
2330
|
+
message: `'tokens' must contain name token with ownership type 'fully-onchain' or 'unknown' when name token with ownership type 'namewrapper' in listed`
|
|
2331
|
+
});
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
).check(function invariant_nameTokensContainAtMostOneWithOwnershipTypeEffective(ctx) {
|
|
2335
|
+
const { tokens } = ctx.value;
|
|
2336
|
+
const tokensCountWithOwnershipFullyOnchain = tokens.filter(
|
|
2337
|
+
(t) => t.ownership.ownershipType === NameTokenOwnershipTypes.FullyOnchain
|
|
2338
|
+
).length;
|
|
2339
|
+
if (tokensCountWithOwnershipFullyOnchain > 1) {
|
|
2340
|
+
ctx.issues.push({
|
|
2341
|
+
code: "custom",
|
|
2342
|
+
input: ctx.value,
|
|
2343
|
+
message: `'tokens' must contain at most one name token with ownership type 'fully-onchain', current count: ${tokensCountWithOwnershipFullyOnchain}`
|
|
2344
|
+
});
|
|
2345
|
+
}
|
|
2346
|
+
});
|
|
2347
|
+
var makeNameTokensResponseOkSchema = (valueLabel = "Name Tokens Response OK", serializable) => z9.strictObject({
|
|
2348
|
+
responseCode: z9.literal(NameTokensResponseCodes.Ok),
|
|
2349
|
+
registeredNameTokens: makeRegisteredNameTokenSchema(`${valueLabel}.nameTokens`, serializable)
|
|
2350
|
+
});
|
|
2351
|
+
var makeNameTokensResponseErrorNameTokensNotIndexedSchema = (_valueLabel = "Name Tokens Response Error Name Not Indexed") => z9.strictObject({
|
|
2352
|
+
responseCode: z9.literal(NameTokensResponseCodes.Error),
|
|
2353
|
+
errorCode: z9.literal(NameTokensResponseErrorCodes.NameTokensNotIndexed),
|
|
2354
|
+
error: ErrorResponseSchema
|
|
2355
|
+
});
|
|
2356
|
+
var makeNameTokensResponseErrorEnsIndexerConfigUnsupported = (_valueLabel = "Name Tokens Response Error ENSIndexer Config Unsupported") => z9.strictObject({
|
|
2357
|
+
responseCode: z9.literal(NameTokensResponseCodes.Error),
|
|
2358
|
+
errorCode: z9.literal(NameTokensResponseErrorCodes.EnsIndexerConfigUnsupported),
|
|
2359
|
+
error: ErrorResponseSchema
|
|
2360
|
+
});
|
|
2361
|
+
var makeNameTokensResponseErrorNameIndexingStatusUnsupported = (_valueLabel = "Name Tokens Response Error Indexing Status Unsupported") => z9.strictObject({
|
|
2362
|
+
responseCode: z9.literal(NameTokensResponseCodes.Error),
|
|
2363
|
+
errorCode: z9.literal(NameTokensResponseErrorCodes.IndexingStatusUnsupported),
|
|
2364
|
+
error: ErrorResponseSchema
|
|
2365
|
+
});
|
|
2366
|
+
var makeNameTokensResponseErrorSchema = (valueLabel = "Name Tokens Response Error") => z9.discriminatedUnion("errorCode", [
|
|
2367
|
+
makeNameTokensResponseErrorNameTokensNotIndexedSchema(valueLabel),
|
|
2368
|
+
makeNameTokensResponseErrorEnsIndexerConfigUnsupported(valueLabel),
|
|
2369
|
+
makeNameTokensResponseErrorNameIndexingStatusUnsupported(valueLabel)
|
|
2370
|
+
]);
|
|
2371
|
+
var makeNameTokensResponseSchema = (valueLabel = "Name Tokens Response", serializable) => {
|
|
2372
|
+
return z9.discriminatedUnion("responseCode", [
|
|
2373
|
+
makeNameTokensResponseOkSchema(valueLabel, serializable ?? false),
|
|
2374
|
+
makeNameTokensResponseErrorSchema(valueLabel)
|
|
2375
|
+
]);
|
|
2376
|
+
};
|
|
2377
|
+
|
|
2378
|
+
// src/api/name-tokens/deserialize.ts
|
|
2379
|
+
function deserializedNameTokensResponse(maybeResponse) {
|
|
2380
|
+
const parsed = makeNameTokensResponseSchema("Name Tokens Response", false).safeParse(
|
|
2381
|
+
maybeResponse
|
|
2382
|
+
);
|
|
2383
|
+
if (parsed.error) {
|
|
2384
|
+
throw new Error(`Cannot deserialize NameTokensResponse:
|
|
2385
|
+
${prettifyError7(parsed.error)}
|
|
2386
|
+
`);
|
|
2387
|
+
}
|
|
2388
|
+
return parsed.data;
|
|
2389
|
+
}
|
|
2390
|
+
|
|
2391
|
+
// src/api/name-tokens/prerequisites.ts
|
|
2392
|
+
var nameTokensPrerequisites = Object.freeze({
|
|
2393
|
+
/**
|
|
2394
|
+
* Required plugins to enable Name Tokens API routes.
|
|
2395
|
+
*
|
|
2396
|
+
* 1. `registrars` plugin is required so that data in the `registrationLifecycles`
|
|
2397
|
+
* table is populated.
|
|
2398
|
+
* 2. `tokenscope` plugin is required so that data in the `nameTokens`
|
|
2399
|
+
* table is populated.
|
|
2400
|
+
*/
|
|
2401
|
+
requiredPlugins: ["registrars" /* Registrars */, "tokenscope" /* TokenScope */],
|
|
2402
|
+
/**
|
|
2403
|
+
* Check if provided ENSApiPublicConfig supports the Name Tokens API.
|
|
2404
|
+
*/
|
|
2405
|
+
hasEnsIndexerConfigSupport(config) {
|
|
2406
|
+
return nameTokensPrerequisites.requiredPlugins.every(
|
|
2407
|
+
(plugin) => config.plugins.includes(plugin)
|
|
2408
|
+
);
|
|
2409
|
+
},
|
|
2410
|
+
/**
|
|
2411
|
+
* Required Indexing Status IDs
|
|
2412
|
+
*
|
|
2413
|
+
* Database indexes are created by the time the omnichain indexing status
|
|
2414
|
+
* is either `completed` or `following`.
|
|
2415
|
+
*/
|
|
2416
|
+
supportedIndexingStatusIds: [
|
|
2417
|
+
OmnichainIndexingStatusIds.Completed,
|
|
2418
|
+
OmnichainIndexingStatusIds.Following
|
|
2419
|
+
],
|
|
2420
|
+
/**
|
|
2421
|
+
* Check if provided indexing status supports the Name Tokens API.
|
|
2422
|
+
*/
|
|
2423
|
+
hasIndexingStatusSupport(omnichainIndexingStatusId) {
|
|
2424
|
+
return nameTokensPrerequisites.supportedIndexingStatusIds.some(
|
|
2425
|
+
(supportedIndexingStatusId) => supportedIndexingStatusId === omnichainIndexingStatusId
|
|
2426
|
+
);
|
|
2427
|
+
}
|
|
2428
|
+
});
|
|
2429
|
+
|
|
2430
|
+
// src/api/name-tokens/serialize.ts
|
|
2431
|
+
function serializeRegisteredNameTokens({
|
|
2432
|
+
domainId,
|
|
2433
|
+
name,
|
|
2434
|
+
tokens,
|
|
2435
|
+
expiresAt,
|
|
2436
|
+
accurateAsOf
|
|
2437
|
+
}) {
|
|
2438
|
+
return {
|
|
2439
|
+
domainId,
|
|
2440
|
+
name,
|
|
2441
|
+
tokens: tokens.map(serializeNameToken),
|
|
2442
|
+
expiresAt,
|
|
2443
|
+
accurateAsOf
|
|
2444
|
+
};
|
|
2445
|
+
}
|
|
2446
|
+
function serializeNameTokensResponse(response) {
|
|
2447
|
+
switch (response.responseCode) {
|
|
2448
|
+
case NameTokensResponseCodes.Ok:
|
|
2449
|
+
return {
|
|
2450
|
+
responseCode: response.responseCode,
|
|
2451
|
+
registeredNameTokens: serializeRegisteredNameTokens(response.registeredNameTokens)
|
|
2452
|
+
};
|
|
2453
|
+
case NameTokensResponseCodes.Error:
|
|
2454
|
+
return response;
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
|
|
2458
|
+
// src/api/registrar-actions/deserialize.ts
|
|
2459
|
+
import { prettifyError as prettifyError8 } from "zod/v4";
|
|
2460
|
+
|
|
2461
|
+
// src/api/registrar-actions/zod-schemas.ts
|
|
2462
|
+
import { namehash as namehash3 } from "viem/ens";
|
|
2463
|
+
import z12 from "zod/v4";
|
|
2464
|
+
|
|
2465
|
+
// ../ens-referrals/src/address.ts
|
|
2466
|
+
import { isAddress as isAddress3 } from "viem";
|
|
2467
|
+
|
|
2468
|
+
// ../ens-referrals/src/encoding.ts
|
|
2469
|
+
import { getAddress, pad, size as size2, slice, zeroAddress as zeroAddress4 } from "viem";
|
|
2470
|
+
var ENCODED_REFERRER_BYTE_OFFSET = 12;
|
|
2471
|
+
var ENCODED_REFERRER_BYTE_LENGTH = 32;
|
|
2472
|
+
var EXPECTED_ENCODED_REFERRER_PADDING = pad("0x", {
|
|
2473
|
+
size: ENCODED_REFERRER_BYTE_OFFSET,
|
|
2474
|
+
dir: "left"
|
|
2475
|
+
});
|
|
2476
|
+
var ZERO_ENCODED_REFERRER = pad("0x", {
|
|
2477
|
+
size: ENCODED_REFERRER_BYTE_LENGTH,
|
|
2478
|
+
dir: "left"
|
|
2479
|
+
});
|
|
2480
|
+
function decodeEncodedReferrer(encodedReferrer) {
|
|
2481
|
+
if (size2(encodedReferrer) !== ENCODED_REFERRER_BYTE_LENGTH) {
|
|
2482
|
+
throw new Error(
|
|
2483
|
+
`Encoded referrer value must be represented by ${ENCODED_REFERRER_BYTE_LENGTH} bytes.`
|
|
2484
|
+
);
|
|
2485
|
+
}
|
|
2486
|
+
const padding = slice(encodedReferrer, 0, ENCODED_REFERRER_BYTE_OFFSET);
|
|
2487
|
+
if (padding !== EXPECTED_ENCODED_REFERRER_PADDING) {
|
|
2488
|
+
return zeroAddress4;
|
|
2489
|
+
}
|
|
2490
|
+
const decodedReferrer = slice(encodedReferrer, ENCODED_REFERRER_BYTE_OFFSET);
|
|
2491
|
+
try {
|
|
2492
|
+
return getAddress(decodedReferrer);
|
|
2493
|
+
} catch {
|
|
2494
|
+
throw new Error(`Decoded referrer value must be a valid EVM address.`);
|
|
2495
|
+
}
|
|
2496
|
+
}
|
|
2497
|
+
|
|
2498
|
+
// ../ens-referrals/src/leaderboard-page.ts
|
|
2499
|
+
var REFERRERS_PER_LEADERBOARD_PAGE_MAX = 100;
|
|
2500
|
+
|
|
2501
|
+
// ../ens-referrals/src/link.ts
|
|
2502
|
+
import { getAddress as getAddress2 } from "viem";
|
|
2503
|
+
|
|
2504
|
+
// ../ens-referrals/src/referrer-detail.ts
|
|
2505
|
+
var ReferrerDetailTypeIds = {
|
|
2506
|
+
/**
|
|
2507
|
+
* Represents a referrer who is ranked on the leaderboard.
|
|
2508
|
+
*/
|
|
2509
|
+
Ranked: "ranked",
|
|
2510
|
+
/**
|
|
2511
|
+
* Represents a referrer who is not ranked on the leaderboard.
|
|
2512
|
+
*/
|
|
2513
|
+
Unranked: "unranked"
|
|
2514
|
+
};
|
|
2515
|
+
|
|
2516
|
+
// src/registrars/zod-schemas.ts
|
|
2517
|
+
import z10 from "zod/v4";
|
|
2518
|
+
|
|
2519
|
+
// src/registrars/registrar-action.ts
|
|
2520
|
+
var RegistrarActionTypes = {
|
|
2521
|
+
Registration: "registration",
|
|
2522
|
+
Renewal: "renewal"
|
|
2523
|
+
};
|
|
2524
|
+
function isRegistrarActionPricingAvailable(registrarActionPricing) {
|
|
2525
|
+
const { baseCost, premium, total } = registrarActionPricing;
|
|
2526
|
+
return baseCost !== null && premium !== null && total !== null;
|
|
2527
|
+
}
|
|
2528
|
+
function isRegistrarActionReferralAvailable(registrarActionReferral) {
|
|
2529
|
+
const { encodedReferrer, decodedReferrer } = registrarActionReferral;
|
|
2530
|
+
return encodedReferrer !== null && decodedReferrer !== null;
|
|
2531
|
+
}
|
|
2532
|
+
function serializeRegistrarActionPricing(pricing) {
|
|
2533
|
+
if (isRegistrarActionPricingAvailable(pricing)) {
|
|
2534
|
+
return {
|
|
2535
|
+
baseCost: serializePriceEth(pricing.baseCost),
|
|
2536
|
+
premium: serializePriceEth(pricing.premium),
|
|
2537
|
+
total: serializePriceEth(pricing.total)
|
|
2538
|
+
};
|
|
2539
|
+
}
|
|
2540
|
+
return pricing;
|
|
2541
|
+
}
|
|
2542
|
+
function serializeRegistrarAction(registrarAction) {
|
|
2543
|
+
return {
|
|
2544
|
+
id: registrarAction.id,
|
|
2545
|
+
type: registrarAction.type,
|
|
2546
|
+
incrementalDuration: registrarAction.incrementalDuration,
|
|
2547
|
+
registrant: registrarAction.registrant,
|
|
2548
|
+
registrationLifecycle: registrarAction.registrationLifecycle,
|
|
2549
|
+
pricing: serializeRegistrarActionPricing(registrarAction.pricing),
|
|
2550
|
+
referral: registrarAction.referral,
|
|
2551
|
+
block: registrarAction.block,
|
|
2552
|
+
transactionHash: registrarAction.transactionHash,
|
|
2553
|
+
eventIds: registrarAction.eventIds
|
|
2554
|
+
};
|
|
2555
|
+
}
|
|
2556
|
+
|
|
2557
|
+
// src/registrars/zod-schemas.ts
|
|
2558
|
+
var makeSubregistrySchema = (valueLabel = "Subregistry") => z10.object({
|
|
2559
|
+
subregistryId: makeAccountIdSchema(`${valueLabel} Subregistry ID`),
|
|
2560
|
+
node: makeNodeSchema(`${valueLabel} Node`)
|
|
2561
|
+
});
|
|
2562
|
+
var makeRegistrationLifecycleSchema = (valueLabel = "Registration Lifecycle") => z10.object({
|
|
2563
|
+
subregistry: makeSubregistrySchema(`${valueLabel} Subregistry`),
|
|
2564
|
+
node: makeNodeSchema(`${valueLabel} Node`),
|
|
2565
|
+
expiresAt: makeUnixTimestampSchema(`${valueLabel} Expires at`)
|
|
2566
|
+
});
|
|
2567
|
+
function invariant_registrarActionPricingTotalIsSumOfBaseCostAndPremium(ctx) {
|
|
2568
|
+
const { baseCost, premium, total } = ctx.value;
|
|
2569
|
+
const actualTotal = addPrices(baseCost, premium);
|
|
2570
|
+
if (!isPriceEqual(actualTotal, total)) {
|
|
2571
|
+
ctx.issues.push({
|
|
2572
|
+
code: "custom",
|
|
2573
|
+
input: ctx.value,
|
|
2574
|
+
message: `'total' must be equal to the sum of 'baseCost' and 'premium'`
|
|
2575
|
+
});
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2578
|
+
var makeRegistrarActionPricingSchema = (valueLabel = "Registrar Action Pricing") => z10.union([
|
|
2579
|
+
// pricing available
|
|
2580
|
+
z10.object({
|
|
2581
|
+
baseCost: makePriceEthSchema(`${valueLabel} Base Cost`),
|
|
2582
|
+
premium: makePriceEthSchema(`${valueLabel} Premium`),
|
|
2583
|
+
total: makePriceEthSchema(`${valueLabel} Total`)
|
|
2584
|
+
}).check(invariant_registrarActionPricingTotalIsSumOfBaseCostAndPremium).transform((v) => v),
|
|
2585
|
+
// pricing unknown
|
|
2586
|
+
z10.object({
|
|
2587
|
+
baseCost: z10.null(),
|
|
2588
|
+
premium: z10.null(),
|
|
2589
|
+
total: z10.null()
|
|
2590
|
+
}).transform((v) => v)
|
|
2591
|
+
]);
|
|
2592
|
+
function invariant_registrarActionDecodedReferrerBasedOnRawReferrer(ctx) {
|
|
2593
|
+
const { encodedReferrer, decodedReferrer } = ctx.value;
|
|
2594
|
+
try {
|
|
2595
|
+
const expectedDecodedReferrer = decodeEncodedReferrer(encodedReferrer).toLowerCase();
|
|
2596
|
+
if (decodedReferrer !== expectedDecodedReferrer) {
|
|
2597
|
+
ctx.issues.push({
|
|
2598
|
+
code: "custom",
|
|
2599
|
+
input: ctx.value,
|
|
2600
|
+
message: `'decodedReferrer' must be based on 'encodedReferrer'`
|
|
2601
|
+
});
|
|
2602
|
+
}
|
|
2603
|
+
} catch (error) {
|
|
2604
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
2605
|
+
ctx.issues.push({
|
|
2606
|
+
code: "custom",
|
|
2607
|
+
input: ctx.value,
|
|
2608
|
+
message: errorMessage
|
|
2609
|
+
});
|
|
2610
|
+
}
|
|
2611
|
+
}
|
|
2612
|
+
var makeRegistrarActionReferralSchema = (valueLabel = "Registrar Action Referral") => z10.union([
|
|
2613
|
+
// referral available
|
|
2614
|
+
z10.object({
|
|
2615
|
+
encodedReferrer: makeHexStringSchema(
|
|
2616
|
+
{ bytesCount: ENCODED_REFERRER_BYTE_LENGTH },
|
|
2617
|
+
`${valueLabel} Encoded Referrer`
|
|
2618
|
+
),
|
|
2619
|
+
decodedReferrer: makeLowercaseAddressSchema(`${valueLabel} Decoded Referrer`)
|
|
2620
|
+
}).check(invariant_registrarActionDecodedReferrerBasedOnRawReferrer),
|
|
2621
|
+
// referral not applicable
|
|
2622
|
+
z10.object({
|
|
2623
|
+
encodedReferrer: z10.null(),
|
|
2624
|
+
decodedReferrer: z10.null()
|
|
2625
|
+
})
|
|
2626
|
+
]);
|
|
2627
|
+
function invariant_eventIdsInitialElementIsTheActionId(ctx) {
|
|
2628
|
+
const { id, eventIds } = ctx.value;
|
|
2629
|
+
if (eventIds[0] !== id) {
|
|
2630
|
+
ctx.issues.push({
|
|
2631
|
+
code: "custom",
|
|
2632
|
+
input: ctx.value,
|
|
2633
|
+
message: "The initial element of `eventIds` must be the `id` value"
|
|
2634
|
+
});
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
2637
|
+
var EventIdSchema = z10.string().nonempty();
|
|
2638
|
+
var EventIdsSchema = z10.array(EventIdSchema).min(1).transform((v) => v);
|
|
2639
|
+
var makeBaseRegistrarActionSchema = (valueLabel = "Base Registrar Action") => z10.object({
|
|
2640
|
+
id: EventIdSchema,
|
|
2641
|
+
incrementalDuration: makeDurationSchema(`${valueLabel} Incremental Duration`),
|
|
2642
|
+
registrant: makeLowercaseAddressSchema(`${valueLabel} Registrant`),
|
|
2643
|
+
registrationLifecycle: makeRegistrationLifecycleSchema(
|
|
2644
|
+
`${valueLabel} Registration Lifecycle`
|
|
2645
|
+
),
|
|
2646
|
+
pricing: makeRegistrarActionPricingSchema(`${valueLabel} Pricing`),
|
|
2647
|
+
referral: makeRegistrarActionReferralSchema(`${valueLabel} Referral`),
|
|
2648
|
+
block: makeBlockRefSchema(`${valueLabel} Block`),
|
|
2649
|
+
transactionHash: makeTransactionHashSchema(`${valueLabel} Transaction Hash`),
|
|
2650
|
+
eventIds: EventIdsSchema
|
|
2651
|
+
}).check(invariant_eventIdsInitialElementIsTheActionId);
|
|
2652
|
+
var makeRegistrarActionRegistrationSchema = (valueLabel = "Registration ") => makeBaseRegistrarActionSchema(valueLabel).extend({
|
|
2653
|
+
type: z10.literal(RegistrarActionTypes.Registration)
|
|
2654
|
+
});
|
|
2655
|
+
var makeRegistrarActionRenewalSchema = (valueLabel = "Renewal") => makeBaseRegistrarActionSchema(valueLabel).extend({
|
|
2656
|
+
type: z10.literal(RegistrarActionTypes.Renewal)
|
|
2657
|
+
});
|
|
2658
|
+
var makeRegistrarActionSchema = (valueLabel = "Registrar Action") => z10.discriminatedUnion("type", [
|
|
2659
|
+
makeRegistrarActionRegistrationSchema(`${valueLabel} Registration`),
|
|
2660
|
+
makeRegistrarActionRenewalSchema(`${valueLabel} Renewal`)
|
|
2661
|
+
]);
|
|
2662
|
+
|
|
2663
|
+
// src/api/shared/pagination/zod-schemas.ts
|
|
2664
|
+
import z11 from "zod/v4";
|
|
2665
|
+
|
|
2666
|
+
// src/api/shared/pagination/request.ts
|
|
2667
|
+
var RECORDS_PER_PAGE_DEFAULT = 10;
|
|
2668
|
+
var RECORDS_PER_PAGE_MAX = 100;
|
|
2669
|
+
|
|
2670
|
+
// src/api/shared/pagination/zod-schemas.ts
|
|
2671
|
+
var makeRequestPageParamsSchema = (valueLabel = "RequestPageParams") => z11.object({
|
|
2672
|
+
page: makePositiveIntegerSchema(`${valueLabel}.page`),
|
|
2673
|
+
recordsPerPage: makePositiveIntegerSchema(`${valueLabel}.recordsPerPage`).max(
|
|
2674
|
+
RECORDS_PER_PAGE_MAX,
|
|
2675
|
+
`${valueLabel}.recordsPerPage must not exceed ${RECORDS_PER_PAGE_MAX}`
|
|
2676
|
+
)
|
|
2677
|
+
});
|
|
2678
|
+
var makeResponsePageContextSchemaWithNoRecords = (valueLabel = "ResponsePageContextWithNoRecords") => z11.object({
|
|
2679
|
+
totalRecords: z11.literal(0),
|
|
2680
|
+
totalPages: z11.literal(1),
|
|
2681
|
+
hasNext: z11.literal(false),
|
|
2682
|
+
hasPrev: z11.literal(false),
|
|
2683
|
+
startIndex: z11.undefined(),
|
|
2684
|
+
endIndex: z11.undefined()
|
|
2685
|
+
}).extend(makeRequestPageParamsSchema(valueLabel).shape);
|
|
2686
|
+
function invariant_responsePageWithRecordsIsCorrect(ctx) {
|
|
2687
|
+
const { hasNext, hasPrev, recordsPerPage, page, totalRecords, startIndex, endIndex } = ctx.value;
|
|
2688
|
+
const expectedHasNext = page * recordsPerPage < totalRecords;
|
|
2689
|
+
if (hasNext !== expectedHasNext) {
|
|
2690
|
+
ctx.issues.push({
|
|
2691
|
+
code: "custom",
|
|
2692
|
+
input: ctx.value,
|
|
2693
|
+
message: `hasNext must be equal to '${expectedHasNext ? "true" : "false"}'`
|
|
2694
|
+
});
|
|
2695
|
+
}
|
|
2696
|
+
const expectedHasPrev = page > 1;
|
|
2697
|
+
if (hasPrev !== expectedHasPrev) {
|
|
2698
|
+
ctx.issues.push({
|
|
2699
|
+
code: "custom",
|
|
2700
|
+
input: ctx.value,
|
|
2701
|
+
message: `hasPrev must be equal to '${expectedHasPrev ? "true" : "false"}'`
|
|
2702
|
+
});
|
|
2703
|
+
}
|
|
2704
|
+
if (endIndex < startIndex) {
|
|
2705
|
+
ctx.issues.push({
|
|
2706
|
+
code: "custom",
|
|
2707
|
+
input: ctx.value,
|
|
2708
|
+
message: `endIndex must be greater than or equal to startIndex`
|
|
2709
|
+
});
|
|
2710
|
+
}
|
|
2711
|
+
if (endIndex >= totalRecords) {
|
|
2712
|
+
ctx.issues.push({
|
|
2713
|
+
code: "custom",
|
|
2714
|
+
input: ctx.value,
|
|
2715
|
+
message: `endIndex must be lower than totalRecords`
|
|
2716
|
+
});
|
|
2717
|
+
}
|
|
2718
|
+
}
|
|
2719
|
+
var makeResponsePageContextSchemaWithRecords = (valueLabel = "ResponsePageContextWithRecords") => z11.object({
|
|
2720
|
+
totalRecords: makePositiveIntegerSchema(`${valueLabel}.totalRecords`),
|
|
2721
|
+
totalPages: makePositiveIntegerSchema(`${valueLabel}.totalPages`),
|
|
2722
|
+
hasNext: z11.boolean(),
|
|
2723
|
+
hasPrev: z11.boolean(),
|
|
2724
|
+
startIndex: makeNonNegativeIntegerSchema(`${valueLabel}.startIndex`),
|
|
2725
|
+
endIndex: makeNonNegativeIntegerSchema(`${valueLabel}.endIndex`)
|
|
2726
|
+
}).extend(makeRequestPageParamsSchema(valueLabel).shape).check(invariant_responsePageWithRecordsIsCorrect);
|
|
2727
|
+
var makeResponsePageContextSchema = (valueLabel = "ResponsePageContext") => z11.union([
|
|
2728
|
+
makeResponsePageContextSchemaWithNoRecords(valueLabel),
|
|
2729
|
+
makeResponsePageContextSchemaWithRecords(valueLabel)
|
|
2730
|
+
]);
|
|
2731
|
+
|
|
2732
|
+
// src/api/registrar-actions/response.ts
|
|
2733
|
+
var RegistrarActionsResponseCodes = {
|
|
2734
|
+
/**
|
|
2735
|
+
* Represents that Registrar Actions are available.
|
|
2736
|
+
*/
|
|
2737
|
+
Ok: "ok",
|
|
2738
|
+
/**
|
|
2739
|
+
* Represents that Registrar Actions are unavailable.
|
|
2740
|
+
*/
|
|
2741
|
+
Error: "error"
|
|
2742
|
+
};
|
|
2743
|
+
|
|
2744
|
+
// src/api/registrar-actions/zod-schemas.ts
|
|
2745
|
+
function invariant_registrationLifecycleNodeMatchesName(ctx) {
|
|
2746
|
+
const { name, action } = ctx.value;
|
|
2747
|
+
const expectedNode = action.registrationLifecycle.node;
|
|
2748
|
+
const actualNode = namehash3(name);
|
|
2749
|
+
if (actualNode !== expectedNode) {
|
|
2750
|
+
ctx.issues.push({
|
|
2751
|
+
code: "custom",
|
|
2752
|
+
input: ctx.value,
|
|
2753
|
+
message: `The 'action.registrationLifecycle.node' must match namehash of 'name'`
|
|
2754
|
+
});
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
2757
|
+
var makeNamedRegistrarActionSchema = (valueLabel = "Named Registrar Action") => z12.object({
|
|
2758
|
+
action: makeRegistrarActionSchema(valueLabel),
|
|
2759
|
+
name: makeReinterpretedNameSchema(valueLabel)
|
|
2760
|
+
}).check(invariant_registrationLifecycleNodeMatchesName);
|
|
2761
|
+
var makeRegistrarActionsResponseOkSchema = (valueLabel = "Registrar Actions Response OK") => z12.strictObject({
|
|
2762
|
+
responseCode: z12.literal(RegistrarActionsResponseCodes.Ok),
|
|
2763
|
+
registrarActions: z12.array(makeNamedRegistrarActionSchema(valueLabel)),
|
|
2764
|
+
pageContext: makeResponsePageContextSchema(`${valueLabel}.pageContext`)
|
|
2765
|
+
});
|
|
2766
|
+
var makeRegistrarActionsResponseErrorSchema = (_valueLabel = "Registrar Actions Response Error") => z12.strictObject({
|
|
2767
|
+
responseCode: z12.literal(RegistrarActionsResponseCodes.Error),
|
|
2768
|
+
error: ErrorResponseSchema
|
|
2769
|
+
});
|
|
2770
|
+
var makeRegistrarActionsResponseSchema = (valueLabel = "Registrar Actions Response") => z12.discriminatedUnion("responseCode", [
|
|
2771
|
+
makeRegistrarActionsResponseOkSchema(valueLabel),
|
|
2772
|
+
makeRegistrarActionsResponseErrorSchema(valueLabel)
|
|
2773
|
+
]);
|
|
2774
|
+
|
|
2775
|
+
// src/api/registrar-actions/deserialize.ts
|
|
2776
|
+
function deserializeRegistrarActionsResponse(maybeResponse) {
|
|
2777
|
+
const parsed = makeRegistrarActionsResponseSchema().safeParse(maybeResponse);
|
|
2778
|
+
if (parsed.error) {
|
|
2779
|
+
throw new Error(
|
|
2780
|
+
`Cannot deserialize RegistrarActionsResponse:
|
|
2781
|
+
${prettifyError8(parsed.error)}
|
|
2782
|
+
`
|
|
2783
|
+
);
|
|
2784
|
+
}
|
|
2785
|
+
return parsed.data;
|
|
2786
|
+
}
|
|
2787
|
+
|
|
2788
|
+
// src/api/registrar-actions/request.ts
|
|
2789
|
+
var RegistrarActionsFilterTypes = {
|
|
2790
|
+
BySubregistryNode: "bySubregistryNode",
|
|
2791
|
+
WithEncodedReferral: "withEncodedReferral",
|
|
2792
|
+
ByDecodedReferrer: "byDecodedReferrer",
|
|
2793
|
+
BeginTimestamp: "beginTimestamp",
|
|
2794
|
+
EndTimestamp: "endTimestamp"
|
|
2795
|
+
};
|
|
2796
|
+
var RegistrarActionsOrders = {
|
|
2797
|
+
LatestRegistrarActions: "orderBy[timestamp]=desc"
|
|
2798
|
+
};
|
|
2799
|
+
|
|
2800
|
+
// src/api/registrar-actions/filters.ts
|
|
2801
|
+
function byParentNode(parentNode) {
|
|
2802
|
+
if (typeof parentNode === "undefined") {
|
|
2803
|
+
return void 0;
|
|
2804
|
+
}
|
|
2805
|
+
return {
|
|
2806
|
+
filterType: RegistrarActionsFilterTypes.BySubregistryNode,
|
|
2807
|
+
value: parentNode
|
|
2808
|
+
};
|
|
2809
|
+
}
|
|
2810
|
+
function withReferral(withReferral2) {
|
|
2811
|
+
if (!withReferral2) {
|
|
2812
|
+
return void 0;
|
|
2813
|
+
}
|
|
2814
|
+
return {
|
|
2815
|
+
filterType: RegistrarActionsFilterTypes.WithEncodedReferral
|
|
2816
|
+
};
|
|
2817
|
+
}
|
|
2818
|
+
function byDecodedReferrer(decodedReferrer) {
|
|
2819
|
+
if (typeof decodedReferrer === "undefined") {
|
|
2820
|
+
return void 0;
|
|
2821
|
+
}
|
|
2822
|
+
return {
|
|
2823
|
+
filterType: RegistrarActionsFilterTypes.ByDecodedReferrer,
|
|
2824
|
+
value: decodedReferrer
|
|
2825
|
+
};
|
|
2826
|
+
}
|
|
2827
|
+
function beginTimestamp(timestamp) {
|
|
2828
|
+
if (typeof timestamp === "undefined") {
|
|
2829
|
+
return void 0;
|
|
2830
|
+
}
|
|
2831
|
+
return {
|
|
2832
|
+
filterType: RegistrarActionsFilterTypes.BeginTimestamp,
|
|
2833
|
+
value: timestamp
|
|
2834
|
+
};
|
|
2835
|
+
}
|
|
2836
|
+
function endTimestamp(timestamp) {
|
|
2837
|
+
if (typeof timestamp === "undefined") {
|
|
2838
|
+
return void 0;
|
|
2839
|
+
}
|
|
2840
|
+
return {
|
|
2841
|
+
filterType: RegistrarActionsFilterTypes.EndTimestamp,
|
|
2842
|
+
value: timestamp
|
|
2843
|
+
};
|
|
2844
|
+
}
|
|
2845
|
+
var registrarActionsFilter = {
|
|
2846
|
+
byParentNode,
|
|
2847
|
+
withReferral,
|
|
2848
|
+
byDecodedReferrer,
|
|
2849
|
+
beginTimestamp,
|
|
2850
|
+
endTimestamp
|
|
2851
|
+
};
|
|
2852
|
+
|
|
2853
|
+
// src/api/registrar-actions/prerequisites.ts
|
|
2854
|
+
var registrarActionsPrerequisites = Object.freeze({
|
|
2855
|
+
/**
|
|
2856
|
+
* Required plugins to enable Registrar Actions API routes.
|
|
2857
|
+
*
|
|
2858
|
+
* 1. `registrars` plugin is required so that data in the `registrarActions`
|
|
2859
|
+
* table is populated.
|
|
2860
|
+
* 2. `subgraph`, `basenames`, and `lineanames` are required to get the data
|
|
2861
|
+
* for the name associated with each registrar action.
|
|
2862
|
+
* 3. In theory not all of `subgraph`, `basenames`, and `lineanames` plugins
|
|
2863
|
+
* might be required. Ex: At least one, but the current logic in
|
|
2864
|
+
* the `registrars` plugin always indexes registrar actions across
|
|
2865
|
+
* Ethnames (subgraph), Basenames, and Lineanames and therefore we need to
|
|
2866
|
+
* ensure each value in the registrar actions table has
|
|
2867
|
+
* an associated record in the domains table.
|
|
2868
|
+
*/
|
|
2869
|
+
requiredPlugins: [
|
|
2870
|
+
"subgraph" /* Subgraph */,
|
|
2871
|
+
"basenames" /* Basenames */,
|
|
2872
|
+
"lineanames" /* Lineanames */,
|
|
2873
|
+
"registrars" /* Registrars */
|
|
2874
|
+
],
|
|
2875
|
+
/**
|
|
2876
|
+
* Check if provided ENSApiPublicConfig supports the Registrar Actions API.
|
|
2877
|
+
*/
|
|
2878
|
+
hasEnsIndexerConfigSupport(config) {
|
|
2879
|
+
return registrarActionsPrerequisites.requiredPlugins.every(
|
|
2880
|
+
(plugin) => config.plugins.includes(plugin)
|
|
2881
|
+
);
|
|
2882
|
+
},
|
|
2883
|
+
/**
|
|
2884
|
+
* Required Indexing Status IDs
|
|
2885
|
+
*
|
|
2886
|
+
* Database indexes are created by the time the omnichain indexing status
|
|
2887
|
+
* is either `completed` or `following`.
|
|
2888
|
+
*/
|
|
2889
|
+
supportedIndexingStatusIds: [
|
|
2890
|
+
OmnichainIndexingStatusIds.Completed,
|
|
2891
|
+
OmnichainIndexingStatusIds.Following
|
|
2892
|
+
],
|
|
2893
|
+
/**
|
|
2894
|
+
* Check if provided indexing status supports the Registrar Actions API.
|
|
2895
|
+
*/
|
|
2896
|
+
hasIndexingStatusSupport(omnichainIndexingStatusId) {
|
|
2897
|
+
return registrarActionsPrerequisites.supportedIndexingStatusIds.some(
|
|
2898
|
+
(supportedIndexingStatusId) => supportedIndexingStatusId === omnichainIndexingStatusId
|
|
2899
|
+
);
|
|
2900
|
+
}
|
|
2901
|
+
});
|
|
2902
|
+
|
|
2903
|
+
// src/registrars/basenames-subregistry.ts
|
|
2904
|
+
import {
|
|
2905
|
+
DatasourceNames as DatasourceNames2,
|
|
2906
|
+
ENSNamespaceIds as ENSNamespaceIds3,
|
|
2907
|
+
maybeGetDatasource as maybeGetDatasource2
|
|
2908
|
+
} from "@ensnode/datasources";
|
|
2909
|
+
function getBasenamesSubregistryId(namespace) {
|
|
2910
|
+
const datasource = maybeGetDatasource2(namespace, DatasourceNames2.Basenames);
|
|
2911
|
+
if (!datasource) {
|
|
2912
|
+
throw new Error(`Datasource not found for ${namespace} ${DatasourceNames2.Basenames}`);
|
|
2913
|
+
}
|
|
2914
|
+
const address = datasource.contracts.BaseRegistrar?.address;
|
|
2915
|
+
if (address === void 0 || Array.isArray(address)) {
|
|
2916
|
+
throw new Error(`BaseRegistrar contract not found or has multiple addresses for ${namespace}`);
|
|
2917
|
+
}
|
|
2918
|
+
return {
|
|
2919
|
+
chainId: datasource.chain.id,
|
|
2920
|
+
address
|
|
2921
|
+
};
|
|
2922
|
+
}
|
|
2923
|
+
function getBasenamesSubregistryManagedName(namespaceId) {
|
|
2924
|
+
switch (namespaceId) {
|
|
2925
|
+
case ENSNamespaceIds3.Mainnet:
|
|
2926
|
+
return "base.eth";
|
|
2927
|
+
case ENSNamespaceIds3.Sepolia:
|
|
2928
|
+
return "basetest.eth";
|
|
2929
|
+
case ENSNamespaceIds3.Holesky:
|
|
2930
|
+
case ENSNamespaceIds3.EnsTestEnv:
|
|
2931
|
+
throw new Error(
|
|
2932
|
+
`No registrar managed name is known for the 'basenames' subregistry within the "${namespaceId}" namespace.`
|
|
2933
|
+
);
|
|
2934
|
+
}
|
|
2935
|
+
}
|
|
2936
|
+
|
|
2937
|
+
// src/registrars/ethnames-subregistry.ts
|
|
2938
|
+
import {
|
|
2939
|
+
DatasourceNames as DatasourceNames3,
|
|
2940
|
+
ENSNamespaceIds as ENSNamespaceIds4,
|
|
2941
|
+
maybeGetDatasource as maybeGetDatasource3
|
|
2942
|
+
} from "@ensnode/datasources";
|
|
2943
|
+
function getEthnamesSubregistryId(namespace) {
|
|
2944
|
+
const datasource = maybeGetDatasource3(namespace, DatasourceNames3.ENSRoot);
|
|
2945
|
+
if (!datasource) {
|
|
2946
|
+
throw new Error(`Datasource not found for ${namespace} ${DatasourceNames3.ENSRoot}`);
|
|
2947
|
+
}
|
|
2948
|
+
const address = datasource.contracts.BaseRegistrar?.address;
|
|
2949
|
+
if (address === void 0 || Array.isArray(address)) {
|
|
2950
|
+
throw new Error(`BaseRegistrar contract not found or has multiple addresses for ${namespace}`);
|
|
2951
|
+
}
|
|
2952
|
+
return {
|
|
2953
|
+
chainId: datasource.chain.id,
|
|
2954
|
+
address
|
|
2955
|
+
};
|
|
2956
|
+
}
|
|
2957
|
+
function getEthnamesSubregistryManagedName(namespaceId) {
|
|
2958
|
+
switch (namespaceId) {
|
|
2959
|
+
case ENSNamespaceIds4.Mainnet:
|
|
2960
|
+
case ENSNamespaceIds4.Sepolia:
|
|
2961
|
+
case ENSNamespaceIds4.Holesky:
|
|
2962
|
+
case ENSNamespaceIds4.EnsTestEnv:
|
|
2963
|
+
return "eth";
|
|
2964
|
+
}
|
|
2965
|
+
}
|
|
2966
|
+
|
|
2967
|
+
// src/registrars/lineanames-subregistry.ts
|
|
2968
|
+
import {
|
|
2969
|
+
DatasourceNames as DatasourceNames4,
|
|
2970
|
+
ENSNamespaceIds as ENSNamespaceIds5,
|
|
2971
|
+
maybeGetDatasource as maybeGetDatasource4
|
|
2972
|
+
} from "@ensnode/datasources";
|
|
2973
|
+
function getLineanamesSubregistryId(namespace) {
|
|
2974
|
+
const datasource = maybeGetDatasource4(namespace, DatasourceNames4.Lineanames);
|
|
2975
|
+
if (!datasource) {
|
|
2976
|
+
throw new Error(`Datasource not found for ${namespace} ${DatasourceNames4.Lineanames}`);
|
|
2977
|
+
}
|
|
2978
|
+
const address = datasource.contracts.BaseRegistrar?.address;
|
|
2979
|
+
if (address === void 0 || Array.isArray(address)) {
|
|
2980
|
+
throw new Error(`BaseRegistrar contract not found or has multiple addresses for ${namespace}`);
|
|
2981
|
+
}
|
|
2982
|
+
return {
|
|
2983
|
+
chainId: datasource.chain.id,
|
|
2984
|
+
address
|
|
2985
|
+
};
|
|
2986
|
+
}
|
|
2987
|
+
function getLineanamesSubregistryManagedName(namespaceId) {
|
|
2988
|
+
switch (namespaceId) {
|
|
2989
|
+
case ENSNamespaceIds5.Mainnet:
|
|
2990
|
+
return "linea.eth";
|
|
2991
|
+
case ENSNamespaceIds5.Sepolia:
|
|
2992
|
+
return "linea-sepolia.eth";
|
|
2993
|
+
case ENSNamespaceIds5.Holesky:
|
|
2994
|
+
case ENSNamespaceIds5.EnsTestEnv:
|
|
2995
|
+
throw new Error(
|
|
2996
|
+
`No registrar managed name is known for the 'Lineanames' subregistry within the "${namespaceId}" namespace.`
|
|
2997
|
+
);
|
|
2998
|
+
}
|
|
2999
|
+
}
|
|
3000
|
+
|
|
3001
|
+
// src/api/registrar-actions/serialize.ts
|
|
3002
|
+
function serializeNamedRegistrarAction({
|
|
3003
|
+
action,
|
|
3004
|
+
name
|
|
3005
|
+
}) {
|
|
3006
|
+
return {
|
|
3007
|
+
action: serializeRegistrarAction(action),
|
|
3008
|
+
name
|
|
3009
|
+
};
|
|
3010
|
+
}
|
|
3011
|
+
function serializeRegistrarActionsResponse(response) {
|
|
3012
|
+
switch (response.responseCode) {
|
|
3013
|
+
case RegistrarActionsResponseCodes.Ok:
|
|
3014
|
+
return {
|
|
3015
|
+
responseCode: response.responseCode,
|
|
3016
|
+
registrarActions: response.registrarActions.map(serializeNamedRegistrarAction),
|
|
3017
|
+
pageContext: response.pageContext
|
|
3018
|
+
};
|
|
3019
|
+
case RegistrarActionsResponseCodes.Error:
|
|
3020
|
+
return response;
|
|
3021
|
+
}
|
|
3022
|
+
}
|
|
3023
|
+
|
|
3024
|
+
// src/api/shared/errors/deserialize.ts
|
|
3025
|
+
import { prettifyError as prettifyError9 } from "zod/v4";
|
|
3026
|
+
function deserializeErrorResponse(maybeErrorResponse) {
|
|
3027
|
+
const parsed = ErrorResponseSchema.safeParse(maybeErrorResponse);
|
|
3028
|
+
if (parsed.error) {
|
|
3029
|
+
throw new Error(`Cannot deserialize ErrorResponse:
|
|
3030
|
+
${prettifyError9(parsed.error)}
|
|
3031
|
+
`);
|
|
3032
|
+
}
|
|
3033
|
+
return parsed.data;
|
|
3034
|
+
}
|
|
3035
|
+
|
|
3036
|
+
// src/api/shared/pagination/build-page-context.ts
|
|
3037
|
+
function buildPageContext(page, recordsPerPage, totalRecords) {
|
|
3038
|
+
const totalPages = Math.max(1, Math.ceil(totalRecords / recordsPerPage));
|
|
3039
|
+
if (page > totalPages) {
|
|
3040
|
+
throw new Error(`Invalid page: page ${page} exceeds total pages ${totalPages}.`);
|
|
3041
|
+
}
|
|
3042
|
+
if (totalRecords === 0) {
|
|
3043
|
+
return {
|
|
3044
|
+
page,
|
|
3045
|
+
recordsPerPage,
|
|
3046
|
+
totalRecords: 0,
|
|
3047
|
+
totalPages: 1,
|
|
3048
|
+
hasNext: false,
|
|
3049
|
+
hasPrev: false,
|
|
3050
|
+
startIndex: void 0,
|
|
3051
|
+
endIndex: void 0
|
|
3052
|
+
};
|
|
3053
|
+
}
|
|
3054
|
+
const startIndex = (page - 1) * recordsPerPage;
|
|
3055
|
+
const maxTheoreticalIndexOnPage = startIndex + (recordsPerPage - 1);
|
|
3056
|
+
const endIndex = Math.min(maxTheoreticalIndexOnPage, totalRecords - 1);
|
|
3057
|
+
const hasNext = maxTheoreticalIndexOnPage < totalRecords - 1;
|
|
3058
|
+
const hasPrev = page > 1;
|
|
3059
|
+
return {
|
|
3060
|
+
page,
|
|
3061
|
+
recordsPerPage,
|
|
3062
|
+
totalRecords,
|
|
3063
|
+
totalPages,
|
|
3064
|
+
hasNext,
|
|
3065
|
+
hasPrev,
|
|
3066
|
+
startIndex,
|
|
3067
|
+
endIndex
|
|
3068
|
+
};
|
|
3069
|
+
}
|
|
3070
|
+
|
|
3071
|
+
// src/client-error.ts
|
|
3072
|
+
var ClientError = class _ClientError extends Error {
|
|
3073
|
+
details;
|
|
3074
|
+
constructor(message, details) {
|
|
3075
|
+
super(message);
|
|
3076
|
+
this.name = "ClientError";
|
|
3077
|
+
this.details = details;
|
|
3078
|
+
}
|
|
3079
|
+
static fromErrorResponse({ message, details }) {
|
|
3080
|
+
return new _ClientError(message, details);
|
|
3081
|
+
}
|
|
3082
|
+
};
|
|
3083
|
+
|
|
3084
|
+
// src/ensanalytics/deserialize.ts
|
|
3085
|
+
import { prettifyError as prettifyError10 } from "zod/v4";
|
|
3086
|
+
|
|
3087
|
+
// src/ensanalytics/zod-schemas.ts
|
|
3088
|
+
import z13 from "zod/v4";
|
|
3089
|
+
|
|
3090
|
+
// src/ensanalytics/types.ts
|
|
3091
|
+
var ReferrerLeaderboardPageResponseCodes = {
|
|
3092
|
+
/**
|
|
3093
|
+
* Represents that the requested referrer leaderboard page is available.
|
|
3094
|
+
*/
|
|
3095
|
+
Ok: "ok",
|
|
3096
|
+
/**
|
|
3097
|
+
* Represents that the referrer leaderboard data is not available.
|
|
3098
|
+
*/
|
|
3099
|
+
Error: "error"
|
|
3100
|
+
};
|
|
3101
|
+
var ReferrerDetailResponseCodes = {
|
|
3102
|
+
/**
|
|
3103
|
+
* Represents that the referrer detail data is available.
|
|
3104
|
+
*/
|
|
3105
|
+
Ok: "ok",
|
|
3106
|
+
/**
|
|
3107
|
+
* Represents that an error occurred while fetching the data.
|
|
3108
|
+
*/
|
|
3109
|
+
Error: "error"
|
|
3110
|
+
};
|
|
3111
|
+
|
|
3112
|
+
// src/ensanalytics/zod-schemas.ts
|
|
3113
|
+
var makeRevenueContributionSchema = (valueLabel = "RevenueContribution") => z13.coerce.bigint({
|
|
3114
|
+
error: `${valueLabel} must represent a bigint.`
|
|
3115
|
+
}).nonnegative({
|
|
3116
|
+
error: `${valueLabel} must not be negative.`
|
|
3117
|
+
});
|
|
3118
|
+
var makeReferralProgramRulesSchema = (valueLabel = "ReferralProgramRules") => z13.object({
|
|
3119
|
+
totalAwardPoolValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.totalAwardPoolValue`),
|
|
3120
|
+
maxQualifiedReferrers: makeNonNegativeIntegerSchema(`${valueLabel}.maxQualifiedReferrers`),
|
|
3121
|
+
startTime: makeUnixTimestampSchema(`${valueLabel}.startTime`),
|
|
3122
|
+
endTime: makeUnixTimestampSchema(`${valueLabel}.endTime`),
|
|
3123
|
+
subregistryId: makeAccountIdSchema(`${valueLabel}.subregistryId`)
|
|
3124
|
+
});
|
|
3125
|
+
var makeAwardedReferrerMetricsSchema = (valueLabel = "AwardedReferrerMetrics") => z13.object({
|
|
3126
|
+
referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`),
|
|
3127
|
+
totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`),
|
|
3128
|
+
totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`),
|
|
3129
|
+
totalRevenueContribution: makeRevenueContributionSchema(
|
|
3130
|
+
`${valueLabel}.totalRevenueContribution`
|
|
3131
|
+
),
|
|
3132
|
+
score: makeFiniteNonNegativeNumberSchema(`${valueLabel}.score`),
|
|
3133
|
+
rank: makePositiveIntegerSchema(`${valueLabel}.rank`),
|
|
3134
|
+
isQualified: z13.boolean(),
|
|
3135
|
+
finalScoreBoost: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScoreBoost`).max(
|
|
3136
|
+
1,
|
|
3137
|
+
`${valueLabel}.finalScoreBoost must be <= 1`
|
|
3138
|
+
),
|
|
3139
|
+
finalScore: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScore`),
|
|
3140
|
+
awardPoolShare: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolShare`).max(
|
|
3141
|
+
1,
|
|
3142
|
+
`${valueLabel}.awardPoolShare must be <= 1`
|
|
3143
|
+
),
|
|
3144
|
+
awardPoolApproxValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolApproxValue`)
|
|
3145
|
+
});
|
|
3146
|
+
var makeUnrankedReferrerMetricsSchema = (valueLabel = "UnrankedReferrerMetrics") => z13.object({
|
|
3147
|
+
referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`),
|
|
3148
|
+
totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`),
|
|
3149
|
+
totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`),
|
|
3150
|
+
totalRevenueContribution: makeRevenueContributionSchema(
|
|
3151
|
+
`${valueLabel}.totalRevenueContribution`
|
|
3152
|
+
),
|
|
3153
|
+
score: makeFiniteNonNegativeNumberSchema(`${valueLabel}.score`),
|
|
3154
|
+
rank: z13.null(),
|
|
3155
|
+
isQualified: z13.literal(false),
|
|
3156
|
+
finalScoreBoost: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScoreBoost`).max(
|
|
3157
|
+
1,
|
|
3158
|
+
`${valueLabel}.finalScoreBoost must be <= 1`
|
|
3159
|
+
),
|
|
3160
|
+
finalScore: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScore`),
|
|
3161
|
+
awardPoolShare: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolShare`).max(
|
|
3162
|
+
1,
|
|
3163
|
+
`${valueLabel}.awardPoolShare must be <= 1`
|
|
3164
|
+
),
|
|
3165
|
+
awardPoolApproxValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolApproxValue`)
|
|
3166
|
+
});
|
|
3167
|
+
var makeAggregatedReferrerMetricsSchema = (valueLabel = "AggregatedReferrerMetrics") => z13.object({
|
|
3168
|
+
grandTotalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.grandTotalReferrals`),
|
|
3169
|
+
grandTotalIncrementalDuration: makeDurationSchema(
|
|
3170
|
+
`${valueLabel}.grandTotalIncrementalDuration`
|
|
3171
|
+
),
|
|
3172
|
+
grandTotalRevenueContribution: makeRevenueContributionSchema(
|
|
3173
|
+
`${valueLabel}.grandTotalRevenueContribution`
|
|
3174
|
+
),
|
|
3175
|
+
grandTotalQualifiedReferrersFinalScore: makeFiniteNonNegativeNumberSchema(
|
|
3176
|
+
`${valueLabel}.grandTotalQualifiedReferrersFinalScore`
|
|
3177
|
+
),
|
|
3178
|
+
minFinalScoreToQualify: makeFiniteNonNegativeNumberSchema(
|
|
3179
|
+
`${valueLabel}.minFinalScoreToQualify`
|
|
3180
|
+
)
|
|
3181
|
+
});
|
|
3182
|
+
var makeReferrerLeaderboardPageContextSchema = (valueLabel = "ReferrerLeaderboardPageContext") => z13.object({
|
|
3183
|
+
page: makePositiveIntegerSchema(`${valueLabel}.page`),
|
|
3184
|
+
recordsPerPage: makePositiveIntegerSchema(`${valueLabel}.recordsPerPage`).max(
|
|
3185
|
+
REFERRERS_PER_LEADERBOARD_PAGE_MAX,
|
|
3186
|
+
`${valueLabel}.recordsPerPage must not exceed ${REFERRERS_PER_LEADERBOARD_PAGE_MAX}`
|
|
3187
|
+
),
|
|
3188
|
+
totalRecords: makeNonNegativeIntegerSchema(`${valueLabel}.totalRecords`),
|
|
3189
|
+
totalPages: makePositiveIntegerSchema(`${valueLabel}.totalPages`),
|
|
3190
|
+
hasNext: z13.boolean(),
|
|
3191
|
+
hasPrev: z13.boolean(),
|
|
3192
|
+
startIndex: z13.optional(makeNonNegativeIntegerSchema(`${valueLabel}.startIndex`)),
|
|
3193
|
+
endIndex: z13.optional(makeNonNegativeIntegerSchema(`${valueLabel}.endIndex`))
|
|
3194
|
+
});
|
|
3195
|
+
var makeReferrerLeaderboardPageSchema = (valueLabel = "ReferrerLeaderboardPage") => z13.object({
|
|
3196
|
+
rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),
|
|
3197
|
+
referrers: z13.array(makeAwardedReferrerMetricsSchema(`${valueLabel}.referrers[record]`)),
|
|
3198
|
+
aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),
|
|
3199
|
+
pageContext: makeReferrerLeaderboardPageContextSchema(`${valueLabel}.pageContext`),
|
|
3200
|
+
accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`)
|
|
3201
|
+
});
|
|
3202
|
+
var makeReferrerLeaderboardPageResponseOkSchema = (valueLabel = "ReferrerLeaderboardPageResponseOk") => z13.object({
|
|
3203
|
+
responseCode: z13.literal(ReferrerLeaderboardPageResponseCodes.Ok),
|
|
3204
|
+
data: makeReferrerLeaderboardPageSchema(`${valueLabel}.data`)
|
|
3205
|
+
});
|
|
3206
|
+
var makeReferrerLeaderboardPageResponseErrorSchema = (_valueLabel = "ReferrerLeaderboardPageResponseError") => z13.object({
|
|
3207
|
+
responseCode: z13.literal(ReferrerLeaderboardPageResponseCodes.Error),
|
|
3208
|
+
error: z13.string(),
|
|
3209
|
+
errorMessage: z13.string()
|
|
3210
|
+
});
|
|
3211
|
+
var makeReferrerLeaderboardPageResponseSchema = (valueLabel = "ReferrerLeaderboardPageResponse") => z13.union([
|
|
3212
|
+
makeReferrerLeaderboardPageResponseOkSchema(valueLabel),
|
|
3213
|
+
makeReferrerLeaderboardPageResponseErrorSchema(valueLabel)
|
|
3214
|
+
]);
|
|
3215
|
+
var makeReferrerDetailRankedSchema = (valueLabel = "ReferrerDetailRanked") => z13.object({
|
|
3216
|
+
type: z13.literal(ReferrerDetailTypeIds.Ranked),
|
|
3217
|
+
rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),
|
|
3218
|
+
referrer: makeAwardedReferrerMetricsSchema(`${valueLabel}.referrer`),
|
|
3219
|
+
aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),
|
|
3220
|
+
accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`)
|
|
3221
|
+
});
|
|
3222
|
+
var makeReferrerDetailUnrankedSchema = (valueLabel = "ReferrerDetailUnranked") => z13.object({
|
|
3223
|
+
type: z13.literal(ReferrerDetailTypeIds.Unranked),
|
|
3224
|
+
rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),
|
|
3225
|
+
referrer: makeUnrankedReferrerMetricsSchema(`${valueLabel}.referrer`),
|
|
3226
|
+
aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),
|
|
3227
|
+
accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`)
|
|
3228
|
+
});
|
|
3229
|
+
var makeReferrerDetailResponseOkSchema = (valueLabel = "ReferrerDetailResponse") => z13.object({
|
|
3230
|
+
responseCode: z13.literal(ReferrerDetailResponseCodes.Ok),
|
|
3231
|
+
data: z13.union([
|
|
3232
|
+
makeReferrerDetailRankedSchema(`${valueLabel}.data`),
|
|
3233
|
+
makeReferrerDetailUnrankedSchema(`${valueLabel}.data`)
|
|
3234
|
+
])
|
|
3235
|
+
});
|
|
3236
|
+
var makeReferrerDetailResponseErrorSchema = (_valueLabel = "ReferrerDetailResponse") => z13.object({
|
|
3237
|
+
responseCode: z13.literal(ReferrerDetailResponseCodes.Error),
|
|
3238
|
+
error: z13.string(),
|
|
3239
|
+
errorMessage: z13.string()
|
|
3240
|
+
});
|
|
3241
|
+
var makeReferrerDetailResponseSchema = (valueLabel = "ReferrerDetailResponse") => z13.union([
|
|
3242
|
+
makeReferrerDetailResponseOkSchema(valueLabel),
|
|
3243
|
+
makeReferrerDetailResponseErrorSchema(valueLabel)
|
|
3244
|
+
]);
|
|
3245
|
+
|
|
3246
|
+
// src/ensanalytics/deserialize.ts
|
|
3247
|
+
function deserializeRevenueContribution(value) {
|
|
3248
|
+
return BigInt(value);
|
|
3249
|
+
}
|
|
3250
|
+
function deserializeReferralProgramRules(rules) {
|
|
3251
|
+
return rules;
|
|
3252
|
+
}
|
|
3253
|
+
function deserializeAwardedReferrerMetrics(metrics) {
|
|
3254
|
+
return {
|
|
3255
|
+
referrer: metrics.referrer,
|
|
3256
|
+
totalReferrals: metrics.totalReferrals,
|
|
3257
|
+
totalIncrementalDuration: metrics.totalIncrementalDuration,
|
|
3258
|
+
totalRevenueContribution: deserializeRevenueContribution(metrics.totalRevenueContribution),
|
|
3259
|
+
score: metrics.score,
|
|
3260
|
+
rank: metrics.rank,
|
|
3261
|
+
isQualified: metrics.isQualified,
|
|
3262
|
+
finalScoreBoost: metrics.finalScoreBoost,
|
|
3263
|
+
finalScore: metrics.finalScore,
|
|
3264
|
+
awardPoolShare: metrics.awardPoolShare,
|
|
3265
|
+
awardPoolApproxValue: metrics.awardPoolApproxValue
|
|
3266
|
+
};
|
|
3267
|
+
}
|
|
3268
|
+
function deserializeUnrankedReferrerMetrics(metrics) {
|
|
3269
|
+
return {
|
|
3270
|
+
referrer: metrics.referrer,
|
|
3271
|
+
totalReferrals: metrics.totalReferrals,
|
|
3272
|
+
totalIncrementalDuration: metrics.totalIncrementalDuration,
|
|
3273
|
+
totalRevenueContribution: deserializeRevenueContribution(metrics.totalRevenueContribution),
|
|
3274
|
+
score: metrics.score,
|
|
3275
|
+
rank: metrics.rank,
|
|
3276
|
+
isQualified: metrics.isQualified,
|
|
3277
|
+
finalScoreBoost: metrics.finalScoreBoost,
|
|
3278
|
+
finalScore: metrics.finalScore,
|
|
3279
|
+
awardPoolShare: metrics.awardPoolShare,
|
|
3280
|
+
awardPoolApproxValue: metrics.awardPoolApproxValue
|
|
3281
|
+
};
|
|
3282
|
+
}
|
|
3283
|
+
function deserializeAggregatedReferrerMetrics(metrics) {
|
|
3284
|
+
return {
|
|
3285
|
+
grandTotalReferrals: metrics.grandTotalReferrals,
|
|
3286
|
+
grandTotalIncrementalDuration: metrics.grandTotalIncrementalDuration,
|
|
3287
|
+
grandTotalRevenueContribution: deserializeRevenueContribution(
|
|
3288
|
+
metrics.grandTotalRevenueContribution
|
|
3289
|
+
),
|
|
3290
|
+
grandTotalQualifiedReferrersFinalScore: metrics.grandTotalQualifiedReferrersFinalScore,
|
|
3291
|
+
minFinalScoreToQualify: metrics.minFinalScoreToQualify
|
|
3292
|
+
};
|
|
3293
|
+
}
|
|
3294
|
+
function deserializeReferrerLeaderboardPage(page) {
|
|
3295
|
+
return {
|
|
3296
|
+
rules: deserializeReferralProgramRules(page.rules),
|
|
3297
|
+
referrers: page.referrers.map(deserializeAwardedReferrerMetrics),
|
|
3298
|
+
aggregatedMetrics: deserializeAggregatedReferrerMetrics(page.aggregatedMetrics),
|
|
3299
|
+
pageContext: page.pageContext,
|
|
3300
|
+
accurateAsOf: page.accurateAsOf
|
|
3301
|
+
};
|
|
3302
|
+
}
|
|
3303
|
+
function deserializeReferrerDetailRanked(detail) {
|
|
3304
|
+
return {
|
|
3305
|
+
type: detail.type,
|
|
3306
|
+
rules: deserializeReferralProgramRules(detail.rules),
|
|
3307
|
+
referrer: deserializeAwardedReferrerMetrics(detail.referrer),
|
|
3308
|
+
aggregatedMetrics: deserializeAggregatedReferrerMetrics(detail.aggregatedMetrics),
|
|
3309
|
+
accurateAsOf: detail.accurateAsOf
|
|
3310
|
+
};
|
|
3311
|
+
}
|
|
3312
|
+
function deserializeReferrerDetailUnranked(detail) {
|
|
3313
|
+
return {
|
|
3314
|
+
type: detail.type,
|
|
3315
|
+
rules: deserializeReferralProgramRules(detail.rules),
|
|
3316
|
+
referrer: deserializeUnrankedReferrerMetrics(detail.referrer),
|
|
3317
|
+
aggregatedMetrics: deserializeAggregatedReferrerMetrics(detail.aggregatedMetrics),
|
|
3318
|
+
accurateAsOf: detail.accurateAsOf
|
|
3319
|
+
};
|
|
3320
|
+
}
|
|
3321
|
+
function deserializeReferrerLeaderboardPageResponse(maybeResponse, valueLabel) {
|
|
3322
|
+
let deserialized;
|
|
3323
|
+
switch (maybeResponse.responseCode) {
|
|
3324
|
+
case "ok": {
|
|
3325
|
+
deserialized = {
|
|
3326
|
+
responseCode: maybeResponse.responseCode,
|
|
3327
|
+
data: deserializeReferrerLeaderboardPage(maybeResponse.data)
|
|
3328
|
+
};
|
|
3329
|
+
break;
|
|
3330
|
+
}
|
|
3331
|
+
case "error":
|
|
3332
|
+
deserialized = maybeResponse;
|
|
3333
|
+
break;
|
|
3334
|
+
}
|
|
3335
|
+
const schema = makeReferrerLeaderboardPageResponseSchema(valueLabel);
|
|
3336
|
+
const parsed = schema.safeParse(deserialized);
|
|
3337
|
+
if (parsed.error) {
|
|
3338
|
+
throw new Error(
|
|
3339
|
+
`Cannot deserialize SerializedReferrerLeaderboardPageResponse:
|
|
3340
|
+
${prettifyError10(parsed.error)}
|
|
3341
|
+
`
|
|
3342
|
+
);
|
|
3343
|
+
}
|
|
3344
|
+
return parsed.data;
|
|
3345
|
+
}
|
|
3346
|
+
function deserializeReferrerDetailResponse(maybeResponse, valueLabel) {
|
|
3347
|
+
let deserialized;
|
|
3348
|
+
switch (maybeResponse.responseCode) {
|
|
3349
|
+
case "ok": {
|
|
3350
|
+
switch (maybeResponse.data.type) {
|
|
3351
|
+
case "ranked":
|
|
3352
|
+
deserialized = {
|
|
3353
|
+
responseCode: maybeResponse.responseCode,
|
|
3354
|
+
data: deserializeReferrerDetailRanked(maybeResponse.data)
|
|
3355
|
+
};
|
|
3356
|
+
break;
|
|
3357
|
+
case "unranked":
|
|
3358
|
+
deserialized = {
|
|
3359
|
+
responseCode: maybeResponse.responseCode,
|
|
3360
|
+
data: deserializeReferrerDetailUnranked(maybeResponse.data)
|
|
3361
|
+
};
|
|
3362
|
+
break;
|
|
3363
|
+
}
|
|
3364
|
+
break;
|
|
3365
|
+
}
|
|
3366
|
+
case "error":
|
|
3367
|
+
deserialized = maybeResponse;
|
|
3368
|
+
break;
|
|
3369
|
+
}
|
|
3370
|
+
const schema = makeReferrerDetailResponseSchema(valueLabel);
|
|
3371
|
+
const parsed = schema.safeParse(deserialized);
|
|
3372
|
+
if (parsed.error) {
|
|
3373
|
+
throw new Error(`Cannot deserialize ReferrerDetailResponse:
|
|
3374
|
+
${prettifyError10(parsed.error)}
|
|
3375
|
+
`);
|
|
3376
|
+
}
|
|
3377
|
+
return parsed.data;
|
|
3378
|
+
}
|
|
3379
|
+
|
|
3380
|
+
// src/ensanalytics/serialize.ts
|
|
3381
|
+
function serializeRevenueContribution(revenueContribution) {
|
|
3382
|
+
return revenueContribution.toString();
|
|
3383
|
+
}
|
|
3384
|
+
function serializeReferralProgramRules(rules) {
|
|
3385
|
+
return rules;
|
|
3386
|
+
}
|
|
3387
|
+
function serializeAwardedReferrerMetrics(metrics) {
|
|
3388
|
+
return {
|
|
3389
|
+
referrer: metrics.referrer,
|
|
3390
|
+
totalReferrals: metrics.totalReferrals,
|
|
3391
|
+
totalIncrementalDuration: metrics.totalIncrementalDuration,
|
|
3392
|
+
totalRevenueContribution: serializeRevenueContribution(metrics.totalRevenueContribution),
|
|
3393
|
+
score: metrics.score,
|
|
3394
|
+
rank: metrics.rank,
|
|
3395
|
+
isQualified: metrics.isQualified,
|
|
3396
|
+
finalScoreBoost: metrics.finalScoreBoost,
|
|
3397
|
+
finalScore: metrics.finalScore,
|
|
3398
|
+
awardPoolShare: metrics.awardPoolShare,
|
|
3399
|
+
awardPoolApproxValue: metrics.awardPoolApproxValue
|
|
3400
|
+
};
|
|
3401
|
+
}
|
|
3402
|
+
function serializeUnrankedReferrerMetrics(metrics) {
|
|
3403
|
+
return {
|
|
3404
|
+
referrer: metrics.referrer,
|
|
3405
|
+
totalReferrals: metrics.totalReferrals,
|
|
3406
|
+
totalIncrementalDuration: metrics.totalIncrementalDuration,
|
|
3407
|
+
totalRevenueContribution: serializeRevenueContribution(metrics.totalRevenueContribution),
|
|
3408
|
+
score: metrics.score,
|
|
3409
|
+
rank: metrics.rank,
|
|
3410
|
+
isQualified: metrics.isQualified,
|
|
3411
|
+
finalScoreBoost: metrics.finalScoreBoost,
|
|
3412
|
+
finalScore: metrics.finalScore,
|
|
3413
|
+
awardPoolShare: metrics.awardPoolShare,
|
|
3414
|
+
awardPoolApproxValue: metrics.awardPoolApproxValue
|
|
3415
|
+
};
|
|
3416
|
+
}
|
|
3417
|
+
function serializeAggregatedReferrerMetrics(metrics) {
|
|
3418
|
+
return {
|
|
3419
|
+
grandTotalReferrals: metrics.grandTotalReferrals,
|
|
3420
|
+
grandTotalIncrementalDuration: metrics.grandTotalIncrementalDuration,
|
|
3421
|
+
grandTotalRevenueContribution: serializeRevenueContribution(
|
|
3422
|
+
metrics.grandTotalRevenueContribution
|
|
3423
|
+
),
|
|
3424
|
+
grandTotalQualifiedReferrersFinalScore: metrics.grandTotalQualifiedReferrersFinalScore,
|
|
3425
|
+
minFinalScoreToQualify: metrics.minFinalScoreToQualify
|
|
3426
|
+
};
|
|
3427
|
+
}
|
|
3428
|
+
function serializeReferrerLeaderboardPage(page) {
|
|
3429
|
+
return {
|
|
3430
|
+
rules: serializeReferralProgramRules(page.rules),
|
|
3431
|
+
referrers: page.referrers.map(serializeAwardedReferrerMetrics),
|
|
3432
|
+
aggregatedMetrics: serializeAggregatedReferrerMetrics(page.aggregatedMetrics),
|
|
3433
|
+
pageContext: page.pageContext,
|
|
3434
|
+
accurateAsOf: page.accurateAsOf
|
|
3435
|
+
};
|
|
3436
|
+
}
|
|
3437
|
+
function serializeReferrerDetailRanked(detail) {
|
|
3438
|
+
return {
|
|
3439
|
+
type: detail.type,
|
|
3440
|
+
rules: serializeReferralProgramRules(detail.rules),
|
|
3441
|
+
referrer: serializeAwardedReferrerMetrics(detail.referrer),
|
|
3442
|
+
aggregatedMetrics: serializeAggregatedReferrerMetrics(detail.aggregatedMetrics),
|
|
3443
|
+
accurateAsOf: detail.accurateAsOf
|
|
3444
|
+
};
|
|
3445
|
+
}
|
|
3446
|
+
function serializeReferrerDetailUnranked(detail) {
|
|
3447
|
+
return {
|
|
3448
|
+
type: detail.type,
|
|
3449
|
+
rules: serializeReferralProgramRules(detail.rules),
|
|
3450
|
+
referrer: serializeUnrankedReferrerMetrics(detail.referrer),
|
|
3451
|
+
aggregatedMetrics: serializeAggregatedReferrerMetrics(detail.aggregatedMetrics),
|
|
3452
|
+
accurateAsOf: detail.accurateAsOf
|
|
3453
|
+
};
|
|
3454
|
+
}
|
|
3455
|
+
function serializeReferrerLeaderboardPageResponse(response) {
|
|
3456
|
+
switch (response.responseCode) {
|
|
3457
|
+
case ReferrerLeaderboardPageResponseCodes.Ok:
|
|
3458
|
+
return {
|
|
3459
|
+
responseCode: response.responseCode,
|
|
3460
|
+
data: serializeReferrerLeaderboardPage(response.data)
|
|
3461
|
+
};
|
|
3462
|
+
case ReferrerLeaderboardPageResponseCodes.Error:
|
|
3463
|
+
return response;
|
|
3464
|
+
}
|
|
3465
|
+
}
|
|
3466
|
+
function serializeReferrerDetailResponse(response) {
|
|
3467
|
+
switch (response.responseCode) {
|
|
3468
|
+
case ReferrerDetailResponseCodes.Ok:
|
|
3469
|
+
switch (response.data.type) {
|
|
3470
|
+
case "ranked":
|
|
3471
|
+
return {
|
|
3472
|
+
responseCode: response.responseCode,
|
|
3473
|
+
data: serializeReferrerDetailRanked(response.data)
|
|
3474
|
+
};
|
|
3475
|
+
case "unranked":
|
|
3476
|
+
return {
|
|
3477
|
+
responseCode: response.responseCode,
|
|
3478
|
+
data: serializeReferrerDetailUnranked(response.data)
|
|
3479
|
+
};
|
|
3480
|
+
}
|
|
3481
|
+
break;
|
|
3482
|
+
case ReferrerDetailResponseCodes.Error:
|
|
3483
|
+
return response;
|
|
3484
|
+
}
|
|
3485
|
+
}
|
|
3486
|
+
|
|
3487
|
+
// src/client.ts
|
|
3488
|
+
var DEFAULT_ENSNODE_API_URL = "https://api.alpha.ensnode.io";
|
|
3489
|
+
var ENSNodeClient = class _ENSNodeClient {
|
|
3490
|
+
options;
|
|
3491
|
+
static defaultOptions() {
|
|
3492
|
+
return {
|
|
3493
|
+
url: new URL(DEFAULT_ENSNODE_API_URL)
|
|
3494
|
+
};
|
|
3495
|
+
}
|
|
3496
|
+
constructor(options = {}) {
|
|
3497
|
+
this.options = {
|
|
3498
|
+
..._ENSNodeClient.defaultOptions(),
|
|
3499
|
+
...options
|
|
3500
|
+
};
|
|
3501
|
+
}
|
|
3502
|
+
getOptions() {
|
|
3503
|
+
return Object.freeze({
|
|
3504
|
+
url: new URL(this.options.url.href)
|
|
3505
|
+
});
|
|
3506
|
+
}
|
|
3507
|
+
/**
|
|
3508
|
+
* Resolves records for an ENS name (Forward Resolution).
|
|
3509
|
+
*
|
|
3510
|
+
* The returned `name` field, if set, is guaranteed to be a [Normalized Name](https://ensnode.io/docs/reference/terminology#normalized-name).
|
|
3511
|
+
* If the name record returned by the resolver is not normalized, `null` is returned as if no name record was set.
|
|
3512
|
+
*
|
|
3513
|
+
* @param name The ENS Name whose records to resolve
|
|
3514
|
+
* @param selection selection of Resolver records
|
|
3515
|
+
* @param options additional options
|
|
3516
|
+
* @param options.accelerate whether to attempt Protocol Acceleration (default false)
|
|
3517
|
+
* @param options.trace whether to include a trace in the response (default false)
|
|
3518
|
+
* @returns ResolveRecordsResponse<SELECTION>
|
|
3519
|
+
* @throws If the request fails or the ENSNode API returns an error response
|
|
3520
|
+
*
|
|
3521
|
+
* @example
|
|
3522
|
+
* ```typescript
|
|
3523
|
+
* const { records } = await client.resolveRecords("jesse.base.eth", {
|
|
3524
|
+
* addresses: [60],
|
|
3525
|
+
* texts: ["avatar", "com.twitter"]
|
|
3526
|
+
* });
|
|
3527
|
+
*
|
|
3528
|
+
* console.log(records);
|
|
3529
|
+
* // {
|
|
3530
|
+
* // addresses: {
|
|
3531
|
+
* // 60: "0xabcd..."
|
|
3532
|
+
* // },
|
|
3533
|
+
* // texts: {
|
|
3534
|
+
* // avatar: "https://example.com/image.jpg",
|
|
3535
|
+
* // "com.twitter": null, // if not set, for example
|
|
3536
|
+
* // }
|
|
3537
|
+
* // }
|
|
3538
|
+
* ```
|
|
3539
|
+
*/
|
|
3540
|
+
async resolveRecords(name, selection, options) {
|
|
3541
|
+
const url = new URL(`/api/resolve/records/${encodeURIComponent(name)}`, this.options.url);
|
|
3542
|
+
if (selection.name) {
|
|
3543
|
+
url.searchParams.set("name", "true");
|
|
3544
|
+
}
|
|
3545
|
+
if (selection.addresses && selection.addresses.length > 0) {
|
|
3546
|
+
url.searchParams.set("addresses", selection.addresses.join(","));
|
|
3547
|
+
}
|
|
3548
|
+
if (selection.texts && selection.texts.length > 0) {
|
|
3549
|
+
url.searchParams.set("texts", selection.texts.join(","));
|
|
3550
|
+
}
|
|
3551
|
+
if (options?.trace) url.searchParams.set("trace", "true");
|
|
3552
|
+
if (options?.accelerate) url.searchParams.set("accelerate", "true");
|
|
3553
|
+
const response = await fetch(url);
|
|
3554
|
+
if (!response.ok) {
|
|
3555
|
+
const error = await response.json();
|
|
3556
|
+
throw ClientError.fromErrorResponse(error);
|
|
3557
|
+
}
|
|
3558
|
+
const data = await response.json();
|
|
3559
|
+
return data;
|
|
3560
|
+
}
|
|
3561
|
+
/**
|
|
3562
|
+
* Resolves the primary name of a specified address (Reverse Resolution) on a specific chain.
|
|
3563
|
+
*
|
|
3564
|
+
* If the chainId-specific Primary Name is not defined, but the `address` specifies a valid
|
|
3565
|
+
* [ENSIP-19 Default Name](https://docs.ens.domains/ensip/19/#default-primary-name), the Default
|
|
3566
|
+
* Name will be returned. You _may_ query the Default EVM Chain Id (`0`) in order to determine the
|
|
3567
|
+
* `address`'s Default Name directly.
|
|
3568
|
+
*
|
|
3569
|
+
* The returned Primary Name, if set, is guaranteed to be a [Normalized Name](https://ensnode.io/docs/reference/terminology#normalized-name).
|
|
3570
|
+
* If the primary name set for the address is not normalized, `null` is returned as if no primary name was set.
|
|
3571
|
+
*
|
|
3572
|
+
* @param address The Address whose Primary Name to resolve
|
|
3573
|
+
* @param chainId The chain id within which to query the address' ENSIP-19 Multichain Primary Name
|
|
3574
|
+
* @param options additional options
|
|
3575
|
+
* @param options.accelerate whether to attempt Protocol Acceleration (default false)
|
|
3576
|
+
* @param options.trace whether to include a trace in the response (default false)
|
|
3577
|
+
* @returns ResolvePrimaryNameResponse
|
|
3578
|
+
* @throws If the request fails or the ENSNode API returns an error response
|
|
3579
|
+
*
|
|
3580
|
+
* @example
|
|
3581
|
+
* ```typescript
|
|
3582
|
+
* // Resolve the address' Primary Name on Ethereum Mainnet
|
|
3583
|
+
* const { name } = await client.resolvePrimaryName("0x179A862703a4adfb29896552DF9e307980D19285", 1);
|
|
3584
|
+
* // name === 'gregskril.eth'
|
|
3585
|
+
*
|
|
3586
|
+
* // Resolve the address' Primary Name on Base
|
|
3587
|
+
* const { name } = await client.resolvePrimaryName("0x179A862703a4adfb29896552DF9e307980D19285", 8453);
|
|
3588
|
+
* // name === 'greg.base.eth'
|
|
3589
|
+
*
|
|
3590
|
+
* // Resolve the address' Default Primary Name
|
|
3591
|
+
* const { name } = await client.resolvePrimaryName("0x179A862703a4adfb29896552DF9e307980D19285", 0);
|
|
3592
|
+
* // name === 'gregskril.eth'
|
|
3593
|
+
* ```
|
|
3594
|
+
*/
|
|
3595
|
+
async resolvePrimaryName(address, chainId, options) {
|
|
3596
|
+
const url = new URL(`/api/resolve/primary-name/${address}/${chainId}`, this.options.url);
|
|
3597
|
+
if (options?.trace) url.searchParams.set("trace", "true");
|
|
3598
|
+
if (options?.accelerate) url.searchParams.set("accelerate", "true");
|
|
3599
|
+
const response = await fetch(url);
|
|
3600
|
+
if (!response.ok) {
|
|
3601
|
+
const error = await response.json();
|
|
3602
|
+
throw ClientError.fromErrorResponse(error);
|
|
3603
|
+
}
|
|
3604
|
+
const data = await response.json();
|
|
3605
|
+
return data;
|
|
3606
|
+
}
|
|
3607
|
+
/**
|
|
3608
|
+
* Resolves the primary names of a specified address across multiple chains.
|
|
3609
|
+
*
|
|
3610
|
+
* For each Primary Name, if the chainId-specific Primary Name is not defined, but the `address`
|
|
3611
|
+
* specifies a valid [ENSIP-19 Default Name](https://docs.ens.domains/ensip/19/#default-primary-name),
|
|
3612
|
+
* the Default Name will be returned. You _may not_ query the Default EVM Chain Id (`0`) directly,
|
|
3613
|
+
* and should rely on the aforementioned per-chain defaulting behavior.
|
|
3614
|
+
*
|
|
3615
|
+
* Each returned Primary Name, if set, is guaranteed to be a [Normalized Name](https://ensnode.io/docs/reference/terminology#normalized-name).
|
|
3616
|
+
* If the primary name set for the address on any chain is not normalized, `null` is returned for
|
|
3617
|
+
* that chain as if no primary name was set.
|
|
3618
|
+
*
|
|
3619
|
+
* @param address The Address whose Primary Names to resolve
|
|
3620
|
+
* @param options additional options
|
|
3621
|
+
* @param options.chainIds The set of chain ids within which to query the address' ENSIP-19
|
|
3622
|
+
* Multichain Primary Name (default: all ENSIP-19 supported chains)
|
|
3623
|
+
* @param options.accelerate whether to attempt Protocol Acceleration (default: true)
|
|
3624
|
+
* @param options.trace whether to include a trace in the response (default: false)
|
|
3625
|
+
* @returns ResolvePrimaryNamesResponse
|
|
3626
|
+
* @throws If the request fails or the ENSNode API returns an error response
|
|
3627
|
+
*
|
|
3628
|
+
* @example
|
|
3629
|
+
* ```typescript
|
|
3630
|
+
* // Resolve the address' Primary Names on all ENSIP-19 supported chain ids
|
|
3631
|
+
* const { names } = await client.resolvePrimaryNames("0x179A862703a4adfb29896552DF9e307980D19285");
|
|
3632
|
+
*
|
|
3633
|
+
* console.log(names);
|
|
3634
|
+
* // {
|
|
3635
|
+
* // "1": "gregskril.eth", // Default Primary Name
|
|
3636
|
+
* // "10": "gregskril.eth", // Default Primary Name
|
|
3637
|
+
* // "8453": "greg.base.eth", // Base-specific Primary Name!
|
|
3638
|
+
* // "42161": "gregskril.eth", // Default Primary Name
|
|
3639
|
+
* // "59144": "gregskril.eth", // Default Primary Name
|
|
3640
|
+
* // "534352": "gregskril.eth" // Default Primary Name
|
|
3641
|
+
* // }
|
|
3642
|
+
*
|
|
3643
|
+
* // Resolve the address' Primary Names on specific chain Ids
|
|
3644
|
+
* const { names } = await client.resolvePrimaryNames("0xabcd...", [1, 8453]);
|
|
3645
|
+
*
|
|
3646
|
+
* console.log(names);
|
|
3647
|
+
* // {
|
|
3648
|
+
* // "1": "gregskril.eth",
|
|
3649
|
+
* // "8453": "greg.base.eth", // base-specific Primary Name!
|
|
3650
|
+
* // }
|
|
3651
|
+
* ```
|
|
3652
|
+
*/
|
|
3653
|
+
async resolvePrimaryNames(address, options) {
|
|
3654
|
+
const url = new URL(`/api/resolve/primary-names/${address}`, this.options.url);
|
|
3655
|
+
if (options?.chainIds) url.searchParams.set("chainIds", options.chainIds.join(","));
|
|
3656
|
+
if (options?.trace) url.searchParams.set("trace", "true");
|
|
3657
|
+
if (options?.accelerate) url.searchParams.set("accelerate", "true");
|
|
3658
|
+
const response = await fetch(url);
|
|
3659
|
+
if (!response.ok) {
|
|
3660
|
+
const error = await response.json();
|
|
3661
|
+
throw ClientError.fromErrorResponse(error);
|
|
3662
|
+
}
|
|
3663
|
+
const data = await response.json();
|
|
3664
|
+
return data;
|
|
3665
|
+
}
|
|
3666
|
+
/**
|
|
3667
|
+
* Fetch ENSNode Config
|
|
3668
|
+
*
|
|
3669
|
+
* Fetch the ENSNode's configuration.
|
|
3670
|
+
*
|
|
3671
|
+
* @returns {ConfigResponse}
|
|
3672
|
+
*
|
|
3673
|
+
* @throws if the ENSNode request fails
|
|
3674
|
+
* @throws if the ENSNode API returns an error response
|
|
3675
|
+
* @throws if the ENSNode response breaks required invariants
|
|
3676
|
+
*/
|
|
3677
|
+
async config() {
|
|
3678
|
+
const url = new URL(`/api/config`, this.options.url);
|
|
3679
|
+
const response = await fetch(url);
|
|
3680
|
+
let responseData;
|
|
3681
|
+
try {
|
|
3682
|
+
responseData = await response.json();
|
|
3683
|
+
} catch {
|
|
3684
|
+
throw new Error("Malformed response data: invalid JSON");
|
|
3685
|
+
}
|
|
3686
|
+
if (!response.ok) {
|
|
3687
|
+
const errorResponse = deserializeErrorResponse(responseData);
|
|
3688
|
+
throw new Error(`Fetching ENSNode Config Failed: ${errorResponse.message}`);
|
|
3689
|
+
}
|
|
3690
|
+
return deserializeConfigResponse(responseData);
|
|
3691
|
+
}
|
|
3692
|
+
/**
|
|
3693
|
+
* Fetch ENSNode Indexing Status
|
|
3694
|
+
*
|
|
3695
|
+
* @returns {IndexingStatusResponse}
|
|
3696
|
+
*
|
|
3697
|
+
* @throws if the ENSNode request fails
|
|
3698
|
+
* @throws if the ENSNode API returns an error response
|
|
3699
|
+
* @throws if the ENSNode response breaks required invariants
|
|
3700
|
+
*/
|
|
3701
|
+
async indexingStatus() {
|
|
3702
|
+
const url = new URL(`/api/indexing-status`, this.options.url);
|
|
3703
|
+
const response = await fetch(url);
|
|
3704
|
+
let responseData;
|
|
3705
|
+
try {
|
|
3706
|
+
responseData = await response.json();
|
|
3707
|
+
} catch {
|
|
3708
|
+
throw new Error("Malformed response data: invalid JSON");
|
|
3709
|
+
}
|
|
3710
|
+
if (!response.ok) {
|
|
3711
|
+
let errorResponse;
|
|
3712
|
+
try {
|
|
3713
|
+
errorResponse = deserializeErrorResponse(responseData);
|
|
3714
|
+
} catch {
|
|
3715
|
+
console.log("Indexing Status API: handling a known indexing status server error.");
|
|
3716
|
+
}
|
|
3717
|
+
if (typeof errorResponse !== "undefined") {
|
|
3718
|
+
throw new Error(`Fetching ENSNode Indexing Status Failed: ${errorResponse.message}`);
|
|
3719
|
+
}
|
|
3720
|
+
}
|
|
3721
|
+
return deserializeIndexingStatusResponse(responseData);
|
|
3722
|
+
}
|
|
3723
|
+
/**
|
|
3724
|
+
* Fetch Referrer Leaderboard Page
|
|
3725
|
+
*
|
|
3726
|
+
* Retrieves a paginated list of referrer leaderboard metrics with contribution percentages.
|
|
3727
|
+
* Each referrer's contribution is calculated as a percentage of the grand totals across all referrers.
|
|
3728
|
+
*
|
|
3729
|
+
* @param request - Pagination parameters
|
|
3730
|
+
* @param request.page - The page number to retrieve (1-indexed, default: 1)
|
|
3731
|
+
* @param request.recordsPerPage - Number of records per page (default: 25, max: 100)
|
|
3732
|
+
* @returns {ReferrerLeaderboardPageResponse}
|
|
3733
|
+
*
|
|
3734
|
+
* @throws if the ENSNode request fails
|
|
3735
|
+
* @throws if the ENSNode API returns an error response
|
|
3736
|
+
* @throws if the ENSNode response breaks required invariants
|
|
3737
|
+
*
|
|
3738
|
+
* @example
|
|
3739
|
+
* ```typescript
|
|
3740
|
+
* // Get first page with default page size (25 records)
|
|
3741
|
+
* const response = await client.getReferrerLeaderboardPage();
|
|
3742
|
+
* if (response.responseCode === ReferrerLeaderboardPageResponseCodes.Ok) {
|
|
3743
|
+
* const {
|
|
3744
|
+
* aggregatedMetrics,
|
|
3745
|
+
* referrers,
|
|
3746
|
+
* rules,
|
|
3747
|
+
* pageContext,
|
|
3748
|
+
* updatedAt
|
|
3749
|
+
* } = response.data;
|
|
3750
|
+
* console.log(aggregatedMetrics);
|
|
3751
|
+
* console.log(referrers);
|
|
3752
|
+
* console.log(rules);
|
|
3753
|
+
* console.log(updatedAt);
|
|
3754
|
+
* console.log(`Page ${pageContext.page} of ${pageContext.totalPages}`);
|
|
3755
|
+
* }
|
|
3756
|
+
* ```
|
|
3757
|
+
*
|
|
3758
|
+
* @example
|
|
3759
|
+
* ```typescript
|
|
3760
|
+
* // Get second page with 50 records per page
|
|
3761
|
+
* const response = await client.getReferrerLeaderboardPage({ page: 2, recordsPerPage: 50 });
|
|
3762
|
+
* ```
|
|
3763
|
+
*
|
|
3764
|
+
* @example
|
|
3765
|
+
* ```typescript
|
|
3766
|
+
* // Handle error response, ie. when Referrer Leaderboard is not currently available.
|
|
3767
|
+
* const response = await client.getReferrerLeaderboardPage();
|
|
3768
|
+
*
|
|
3769
|
+
* if (response.responseCode === ReferrerLeaderboardPageResponseCodes.Error) {
|
|
3770
|
+
* console.error(response.error);
|
|
3771
|
+
* console.error(response.errorMessage);
|
|
3772
|
+
* }
|
|
3773
|
+
* ```
|
|
3774
|
+
*/
|
|
3775
|
+
async getReferrerLeaderboardPage(request) {
|
|
3776
|
+
const url = new URL(`/ensanalytics/referrers`, this.options.url);
|
|
3777
|
+
if (request?.page) url.searchParams.set("page", request.page.toString());
|
|
3778
|
+
if (request?.recordsPerPage)
|
|
3779
|
+
url.searchParams.set("recordsPerPage", request.recordsPerPage.toString());
|
|
3780
|
+
const response = await fetch(url);
|
|
3781
|
+
let responseData;
|
|
3782
|
+
try {
|
|
3783
|
+
responseData = await response.json();
|
|
3784
|
+
} catch {
|
|
3785
|
+
throw new Error("Malformed response data: invalid JSON");
|
|
3786
|
+
}
|
|
3787
|
+
return deserializeReferrerLeaderboardPageResponse(
|
|
3788
|
+
responseData
|
|
3789
|
+
);
|
|
3790
|
+
}
|
|
3791
|
+
/**
|
|
3792
|
+
* Fetch Referrer Detail
|
|
3793
|
+
*
|
|
3794
|
+
* Retrieves detailed information about a specific referrer, whether they are on the
|
|
3795
|
+
* leaderboard or not.
|
|
3796
|
+
*
|
|
3797
|
+
* The response data is a discriminated union type with a `type` field:
|
|
3798
|
+
*
|
|
3799
|
+
* **For referrers on the leaderboard** (`ReferrerDetailRanked`):
|
|
3800
|
+
* - `type`: {@link ReferrerDetailTypeIds.Ranked}
|
|
3801
|
+
* - `referrer`: The `AwardedReferrerMetrics` from @namehash/ens-referrals
|
|
3802
|
+
* - `rules`: The referral program rules
|
|
3803
|
+
* - `aggregatedMetrics`: Aggregated metrics for all referrers on the leaderboard
|
|
3804
|
+
* - `accurateAsOf`: Unix timestamp indicating when the data was last updated
|
|
3805
|
+
*
|
|
3806
|
+
* **For referrers NOT on the leaderboard** (`ReferrerDetailUnranked`):
|
|
3807
|
+
* - `type`: {@link ReferrerDetailTypeIds.Unranked}
|
|
3808
|
+
* - `referrer`: The `UnrankedReferrerMetrics` from @namehash/ens-referrals
|
|
3809
|
+
* - `rules`: The referral program rules
|
|
3810
|
+
* - `aggregatedMetrics`: Aggregated metrics for all referrers on the leaderboard
|
|
3811
|
+
* - `accurateAsOf`: Unix timestamp indicating when the data was last updated
|
|
3812
|
+
*
|
|
3813
|
+
* @see {@link https://www.npmjs.com/package/@namehash/ens-referrals|@namehash/ens-referrals} for calculation details
|
|
3814
|
+
*
|
|
3815
|
+
* @param request The referrer address to query
|
|
3816
|
+
* @returns {ReferrerDetailResponse} Returns the referrer detail response
|
|
3817
|
+
*
|
|
3818
|
+
* @throws if the ENSNode request fails
|
|
3819
|
+
* @throws if the response data is malformed
|
|
3820
|
+
*
|
|
3821
|
+
* @example
|
|
3822
|
+
* ```typescript
|
|
3823
|
+
* // Get referrer detail for a specific address
|
|
3824
|
+
* const response = await client.getReferrerDetail({
|
|
3825
|
+
* referrer: "0x1234567890123456789012345678901234567890"
|
|
3826
|
+
* });
|
|
3827
|
+
* if (response.responseCode === ReferrerDetailResponseCodes.Ok) {
|
|
3828
|
+
* const { type, referrer, rules, aggregatedMetrics, accurateAsOf } = response.data;
|
|
3829
|
+
* console.log(type); // ReferrerDetailTypeIds.Ranked or ReferrerDetailTypeIds.Unranked
|
|
3830
|
+
* console.log(referrer);
|
|
3831
|
+
* console.log(accurateAsOf);
|
|
3832
|
+
* }
|
|
3833
|
+
* ```
|
|
3834
|
+
*
|
|
3835
|
+
* @example
|
|
3836
|
+
* ```typescript
|
|
3837
|
+
* // Use discriminated union to check if referrer is ranked
|
|
3838
|
+
* const response = await client.getReferrerDetail({
|
|
3839
|
+
* referrer: "0x1234567890123456789012345678901234567890"
|
|
3840
|
+
* });
|
|
3841
|
+
* if (response.responseCode === ReferrerDetailResponseCodes.Ok) {
|
|
3842
|
+
* if (response.data.type === ReferrerDetailTypeIds.Ranked) {
|
|
3843
|
+
* // TypeScript knows this is ReferrerDetailRanked
|
|
3844
|
+
* console.log(`Rank: ${response.data.referrer.rank}`);
|
|
3845
|
+
* console.log(`Qualified: ${response.data.referrer.isQualified}`);
|
|
3846
|
+
* console.log(`Award Pool Share: ${response.data.referrer.awardPoolShare * 100}%`);
|
|
3847
|
+
* } else {
|
|
3848
|
+
* // TypeScript knows this is ReferrerDetailUnranked
|
|
3849
|
+
* console.log("Referrer is not on the leaderboard (no referrals yet)");
|
|
3850
|
+
* }
|
|
3851
|
+
* }
|
|
3852
|
+
* ```
|
|
3853
|
+
*
|
|
3854
|
+
* @example
|
|
3855
|
+
* ```typescript
|
|
3856
|
+
* // Handle error response, ie. when Referrer Detail is not currently available.
|
|
3857
|
+
* const response = await client.getReferrerDetail({
|
|
3858
|
+
* referrer: "0x1234567890123456789012345678901234567890"
|
|
3859
|
+
* });
|
|
3860
|
+
*
|
|
3861
|
+
* if (response.responseCode === ReferrerDetailResponseCodes.Error) {
|
|
3862
|
+
* console.error(response.error);
|
|
3863
|
+
* console.error(response.errorMessage);
|
|
3864
|
+
* }
|
|
3865
|
+
* ```
|
|
3866
|
+
*/
|
|
3867
|
+
async getReferrerDetail(request) {
|
|
3868
|
+
const url = new URL(
|
|
3869
|
+
`/api/ensanalytics/referrers/${encodeURIComponent(request.referrer)}`,
|
|
3870
|
+
this.options.url
|
|
3871
|
+
);
|
|
3872
|
+
const response = await fetch(url);
|
|
3873
|
+
let responseData;
|
|
3874
|
+
try {
|
|
3875
|
+
responseData = await response.json();
|
|
3876
|
+
} catch {
|
|
3877
|
+
throw new Error("Malformed response data: invalid JSON");
|
|
3878
|
+
}
|
|
3879
|
+
return deserializeReferrerDetailResponse(responseData);
|
|
3880
|
+
}
|
|
3881
|
+
/**
|
|
3882
|
+
* Fetch ENSNode Registrar Actions
|
|
3883
|
+
*
|
|
3884
|
+
* Retrieves a paginated list of registrar actions with optional filters.
|
|
3885
|
+
*
|
|
3886
|
+
* @param request is a request configuration.
|
|
3887
|
+
* @param request.page sets the page number to retrieve (1-indexed, default: 1)
|
|
3888
|
+
* @param request.recordsPerPage sets the number of records per page (default: 10, max: 100)
|
|
3889
|
+
* @param request.filters is an optional request filter configuration.
|
|
3890
|
+
* @param request.order sets the order of results in the response by field and direction.
|
|
3891
|
+
* @returns {RegistrarActionsResponse}
|
|
3892
|
+
*
|
|
3893
|
+
* @throws if the ENSNode request fails
|
|
3894
|
+
* @throws if the ENSNode API returns an error response
|
|
3895
|
+
* @throws if the ENSNode response breaks required invariants
|
|
3896
|
+
*
|
|
3897
|
+
* @example
|
|
3898
|
+
* ```ts
|
|
3899
|
+
* import {
|
|
3900
|
+
* registrarActionsFilter,
|
|
3901
|
+
* ENSNodeClient,
|
|
3902
|
+
* } from "@ensnode/ensnode-sdk";
|
|
3903
|
+
* import { namehash } from "viem/ens";
|
|
3904
|
+
*
|
|
3905
|
+
* const client: ENSNodeClient;
|
|
3906
|
+
*
|
|
3907
|
+
* // Get first page with default page size (10 records)
|
|
3908
|
+
* const response = await client.registrarActions();
|
|
3909
|
+
* if (response.responseCode === RegistrarActionsResponseCodes.Ok) {
|
|
3910
|
+
* const { registrarActions, pageContext } = response;
|
|
3911
|
+
* console.log(registrarActions);
|
|
3912
|
+
* console.log(`Page ${pageContext.page} of ${pageContext.totalPages}`);
|
|
3913
|
+
* }
|
|
3914
|
+
*
|
|
3915
|
+
* // Get second page with 25 records per page
|
|
3916
|
+
* const response = await client.registrarActions({
|
|
3917
|
+
* page: 2,
|
|
3918
|
+
* recordsPerPage: 25,
|
|
3919
|
+
* });
|
|
3920
|
+
*
|
|
3921
|
+
* // get latest registrar action records associated with
|
|
3922
|
+
* // subregistry managing `eth` name
|
|
3923
|
+
* await client.registrarActions({
|
|
3924
|
+
* filters: [registrarActionsFilter.byParentNode(namehash('eth'))],
|
|
3925
|
+
* });
|
|
3926
|
+
*
|
|
3927
|
+
* // get latest registrar action records which include referral info
|
|
3928
|
+
* await client.registrarActions({
|
|
3929
|
+
* filters: [registrarActionsFilter.withReferral(true)],
|
|
3930
|
+
* });
|
|
3931
|
+
*
|
|
3932
|
+
* // get latest registrar action records for a specific decoded referrer
|
|
3933
|
+
* await client.registrarActions({
|
|
3934
|
+
* filters: [registrarActionsFilter.byDecodedReferrer("0x1234567890123456789012345678901234567890")],
|
|
3935
|
+
* });
|
|
3936
|
+
*
|
|
3937
|
+
* // get latest 10 registrar action records associated with
|
|
3938
|
+
* // subregistry managing `base.eth` name
|
|
3939
|
+
* await client.registrarActions({
|
|
3940
|
+
* filters: [registrarActionsFilter.byParentNode(namehash('base.eth'))],
|
|
3941
|
+
* recordsPerPage: 10
|
|
3942
|
+
* });
|
|
3943
|
+
*
|
|
3944
|
+
* // get registrar actions within a specific time range
|
|
3945
|
+
* const beginTimestamp = 1764547200; // Dec 1, 2025, 00:00:00 UTC
|
|
3946
|
+
* const endTimestamp = 1767225600; // Jan 1, 2026, 00:00:00 UTC
|
|
3947
|
+
* await client.registrarActions({
|
|
3948
|
+
* filters: [
|
|
3949
|
+
* registrarActionsFilter.beginTimestamp(beginTimestamp),
|
|
3950
|
+
* registrarActionsFilter.endTimestamp(endTimestamp),
|
|
3951
|
+
* ],
|
|
3952
|
+
* });
|
|
3953
|
+
*
|
|
3954
|
+
* // get registrar actions from a specific timestamp onwards
|
|
3955
|
+
* await client.registrarActions({
|
|
3956
|
+
* filters: [registrarActionsFilter.beginTimestamp(1764547200)],
|
|
3957
|
+
* });
|
|
3958
|
+
*
|
|
3959
|
+
* // get registrar actions up to a specific timestamp
|
|
3960
|
+
* await client.registrarActions({
|
|
3961
|
+
* filters: [registrarActionsFilter.endTimestamp(1767225600)],
|
|
3962
|
+
* });
|
|
3963
|
+
* ```
|
|
3964
|
+
*/
|
|
3965
|
+
async registrarActions(request = {}) {
|
|
3966
|
+
const buildUrlPath = (filters) => {
|
|
3967
|
+
const bySubregistryNodeFilter = filters?.find(
|
|
3968
|
+
(f) => f.filterType === RegistrarActionsFilterTypes.BySubregistryNode
|
|
3969
|
+
);
|
|
3970
|
+
return bySubregistryNodeFilter ? new URL(`/api/registrar-actions/${bySubregistryNodeFilter.value}`, this.options.url) : new URL(`/api/registrar-actions`, this.options.url);
|
|
3971
|
+
};
|
|
3972
|
+
const buildWithReferralArg = (filters) => {
|
|
3973
|
+
const withReferralFilter = filters?.find(
|
|
3974
|
+
(f) => f.filterType === RegistrarActionsFilterTypes.WithEncodedReferral
|
|
3975
|
+
);
|
|
3976
|
+
return withReferralFilter ? { key: "withReferral", value: "true" } : null;
|
|
3977
|
+
};
|
|
3978
|
+
const buildDecodedReferrerArg = (filters) => {
|
|
3979
|
+
const decodedReferrerFilter = filters?.find(
|
|
3980
|
+
(f) => f.filterType === RegistrarActionsFilterTypes.ByDecodedReferrer
|
|
3981
|
+
);
|
|
3982
|
+
return decodedReferrerFilter ? { key: "decodedReferrer", value: decodedReferrerFilter.value } : null;
|
|
3983
|
+
};
|
|
3984
|
+
const buildBeginTimestampArg = (filters) => {
|
|
3985
|
+
const beginTimestampFilter = filters?.find(
|
|
3986
|
+
(f) => f.filterType === RegistrarActionsFilterTypes.BeginTimestamp
|
|
3987
|
+
);
|
|
3988
|
+
return beginTimestampFilter ? { key: "beginTimestamp", value: beginTimestampFilter.value.toString() } : null;
|
|
3989
|
+
};
|
|
3990
|
+
const buildEndTimestampArg = (filters) => {
|
|
3991
|
+
const endTimestampFilter = filters?.find(
|
|
3992
|
+
(f) => f.filterType === RegistrarActionsFilterTypes.EndTimestamp
|
|
3993
|
+
);
|
|
3994
|
+
return endTimestampFilter ? { key: "endTimestamp", value: endTimestampFilter.value.toString() } : null;
|
|
3995
|
+
};
|
|
3996
|
+
const buildOrderArg = (order) => {
|
|
3997
|
+
switch (order) {
|
|
3998
|
+
case RegistrarActionsOrders.LatestRegistrarActions: {
|
|
3999
|
+
const [field, direction] = order.split("=");
|
|
4000
|
+
return {
|
|
4001
|
+
key: `sort[${field}]`,
|
|
4002
|
+
value: `${direction}`
|
|
4003
|
+
};
|
|
4004
|
+
}
|
|
4005
|
+
}
|
|
4006
|
+
};
|
|
4007
|
+
const url = buildUrlPath(request.filters);
|
|
4008
|
+
if (request.order) {
|
|
4009
|
+
const orderArgs = buildOrderArg(request.order);
|
|
4010
|
+
url.searchParams.set(orderArgs.key, orderArgs.value);
|
|
4011
|
+
}
|
|
4012
|
+
if (request.page) {
|
|
4013
|
+
url.searchParams.set("page", request.page.toString());
|
|
4014
|
+
}
|
|
4015
|
+
if (request.recordsPerPage) {
|
|
4016
|
+
url.searchParams.set("recordsPerPage", request.recordsPerPage.toString());
|
|
4017
|
+
}
|
|
4018
|
+
const referralArg = buildWithReferralArg(request.filters);
|
|
4019
|
+
if (referralArg) {
|
|
4020
|
+
url.searchParams.set(referralArg.key, referralArg.value);
|
|
4021
|
+
}
|
|
4022
|
+
const decodedReferrerArg = buildDecodedReferrerArg(request.filters);
|
|
4023
|
+
if (decodedReferrerArg) {
|
|
4024
|
+
url.searchParams.set(decodedReferrerArg.key, decodedReferrerArg.value);
|
|
4025
|
+
}
|
|
4026
|
+
const beginTimestampArg = buildBeginTimestampArg(request.filters);
|
|
4027
|
+
if (beginTimestampArg) {
|
|
4028
|
+
url.searchParams.set(beginTimestampArg.key, beginTimestampArg.value);
|
|
4029
|
+
}
|
|
4030
|
+
const endTimestampArg = buildEndTimestampArg(request.filters);
|
|
4031
|
+
if (endTimestampArg) {
|
|
4032
|
+
url.searchParams.set(endTimestampArg.key, endTimestampArg.value);
|
|
4033
|
+
}
|
|
4034
|
+
const response = await fetch(url);
|
|
4035
|
+
let responseData;
|
|
4036
|
+
try {
|
|
4037
|
+
responseData = await response.json();
|
|
4038
|
+
} catch {
|
|
4039
|
+
throw new Error("Malformed response data: invalid JSON");
|
|
4040
|
+
}
|
|
4041
|
+
if (!response.ok) {
|
|
4042
|
+
let errorResponse;
|
|
4043
|
+
try {
|
|
4044
|
+
errorResponse = deserializeErrorResponse(responseData);
|
|
4045
|
+
} catch {
|
|
4046
|
+
console.log("Registrar Actions API: handling a known server error.");
|
|
4047
|
+
}
|
|
4048
|
+
if (typeof errorResponse !== "undefined") {
|
|
4049
|
+
throw new Error(`Fetching ENSNode Registrar Actions Failed: ${errorResponse.message}`);
|
|
4050
|
+
}
|
|
4051
|
+
}
|
|
4052
|
+
return deserializeRegistrarActionsResponse(responseData);
|
|
4053
|
+
}
|
|
4054
|
+
/**
|
|
4055
|
+
* Fetch Name Tokens for requested name.
|
|
4056
|
+
*
|
|
4057
|
+
* @param request.name - Name for which Name Tokens will be fetched.
|
|
4058
|
+
* @returns {NameTokensResponse}
|
|
4059
|
+
*
|
|
4060
|
+
* @throws if the ENSNode request fails
|
|
4061
|
+
* @throws if the ENSNode API returns an error response
|
|
4062
|
+
* @throws if the ENSNode response breaks required invariants
|
|
4063
|
+
*
|
|
4064
|
+
* @example
|
|
4065
|
+
* ```ts
|
|
4066
|
+
* import {
|
|
4067
|
+
* ENSNodeClient,
|
|
4068
|
+
* } from "@ensnode/ensnode-sdk";
|
|
4069
|
+
* import { namehash } from "viem/ens";
|
|
4070
|
+
*
|
|
4071
|
+
* const client: ENSNodeClient;
|
|
4072
|
+
*
|
|
4073
|
+
* // get latest name token records from the indexed subregistry based on the requested name
|
|
4074
|
+
* const response = await client.nameTokens({
|
|
4075
|
+
* name: "vitalik.eth"
|
|
4076
|
+
* });
|
|
4077
|
+
*
|
|
4078
|
+
* const response = await client.nameTokens({
|
|
4079
|
+
* domainId: "0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835" // namehash('vitalik.eth')
|
|
4080
|
+
* })
|
|
4081
|
+
* ```
|
|
4082
|
+
*/
|
|
4083
|
+
async nameTokens(request) {
|
|
4084
|
+
const url = new URL(`/api/name-tokens`, this.options.url);
|
|
4085
|
+
if (request.name !== void 0) {
|
|
4086
|
+
url.searchParams.set("name", request.name);
|
|
4087
|
+
} else if (request.domainId !== void 0) {
|
|
4088
|
+
url.searchParams.set("domainId", request.domainId);
|
|
4089
|
+
}
|
|
4090
|
+
const response = await fetch(url);
|
|
4091
|
+
let responseData;
|
|
4092
|
+
try {
|
|
4093
|
+
responseData = await response.json();
|
|
4094
|
+
} catch {
|
|
4095
|
+
throw new Error("Malformed response data: invalid JSON");
|
|
4096
|
+
}
|
|
4097
|
+
if (!response.ok) {
|
|
4098
|
+
let errorResponse;
|
|
4099
|
+
try {
|
|
4100
|
+
errorResponse = deserializeErrorResponse(responseData);
|
|
4101
|
+
} catch {
|
|
4102
|
+
console.log("Name Tokens API: handling a known server error.");
|
|
4103
|
+
}
|
|
4104
|
+
if (typeof errorResponse !== "undefined") {
|
|
4105
|
+
throw new Error(`Fetching ENSNode Name Tokens Failed: ${errorResponse.message}`);
|
|
4106
|
+
}
|
|
4107
|
+
}
|
|
4108
|
+
return deserializedNameTokensResponse(responseData);
|
|
4109
|
+
}
|
|
4110
|
+
};
|
|
4111
|
+
|
|
4112
|
+
// src/identity/identity.ts
|
|
4113
|
+
import { getENSRootChainId as getENSRootChainId2 } from "@ensnode/datasources";
|
|
4114
|
+
|
|
4115
|
+
// src/identity/types.ts
|
|
4116
|
+
var ResolutionStatusIds = {
|
|
4117
|
+
/**
|
|
4118
|
+
* Represents that the `Identity` is not resolved yet.
|
|
4119
|
+
*/
|
|
4120
|
+
Unresolved: "unresolved",
|
|
4121
|
+
/**
|
|
4122
|
+
* Represents that resolution of the `Identity` resulted in a named identity.
|
|
4123
|
+
*/
|
|
4124
|
+
Named: "named",
|
|
4125
|
+
/**
|
|
4126
|
+
* Represents that resolution of the `Identity` resulted in an unnamed identity.
|
|
4127
|
+
*/
|
|
4128
|
+
Unnamed: "unnamed",
|
|
4129
|
+
/**
|
|
4130
|
+
* Represents that attempted resolution of the `Identity` resulted in an error
|
|
4131
|
+
* and therefore it is unknown if the `Identity` resolves to a named or unnamed identity.
|
|
4132
|
+
*/
|
|
4133
|
+
Unknown: "unknown"
|
|
4134
|
+
};
|
|
4135
|
+
|
|
4136
|
+
// src/identity/identity.ts
|
|
4137
|
+
function buildUnresolvedIdentity(address, namespaceId, chainId) {
|
|
4138
|
+
return {
|
|
4139
|
+
resolutionStatus: ResolutionStatusIds.Unresolved,
|
|
4140
|
+
chainId: chainId ?? getENSRootChainId2(namespaceId),
|
|
4141
|
+
address
|
|
4142
|
+
};
|
|
4143
|
+
}
|
|
4144
|
+
function isResolvedIdentity(identity) {
|
|
4145
|
+
return identity.resolutionStatus !== ResolutionStatusIds.Unresolved;
|
|
4146
|
+
}
|
|
4147
|
+
|
|
4148
|
+
// src/resolution/ensip19-chainid.ts
|
|
4149
|
+
import { mainnet } from "viem/chains";
|
|
4150
|
+
import { getENSRootChainId as getENSRootChainId3 } from "@ensnode/datasources";
|
|
4151
|
+
var getResolvePrimaryNameChainIdParam = (chainId, namespaceId) => {
|
|
4152
|
+
const ensRootChainId = getENSRootChainId3(namespaceId);
|
|
4153
|
+
return chainId === ensRootChainId ? mainnet.id : chainId;
|
|
4154
|
+
};
|
|
4155
|
+
var translateDefaultableChainIdToChainId = (chainId, namespaceId) => {
|
|
4156
|
+
return chainId === DEFAULT_EVM_CHAIN_ID ? getENSRootChainId3(namespaceId) : chainId;
|
|
4157
|
+
};
|
|
4158
|
+
|
|
4159
|
+
// src/resolution/resolver-records-selection.ts
|
|
4160
|
+
var isSelectionEmpty = (selection) => !selection.name && !selection.addresses?.length && !selection.texts?.length;
|
|
4161
|
+
|
|
4162
|
+
// src/tracing/ens-protocol-tracing.ts
|
|
4163
|
+
var PROTOCOL_ATTRIBUTE_PREFIX = "ens";
|
|
4164
|
+
var ATTR_PROTOCOL_NAME = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol`;
|
|
4165
|
+
var ATTR_PROTOCOL_STEP = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol.step`;
|
|
4166
|
+
var ATTR_PROTOCOL_STEP_RESULT = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol.step.result`;
|
|
4167
|
+
var TraceableENSProtocol = /* @__PURE__ */ ((TraceableENSProtocol2) => {
|
|
4168
|
+
TraceableENSProtocol2["ForwardResolution"] = "forward-resolution";
|
|
4169
|
+
TraceableENSProtocol2["ReverseResolution"] = "reverse-resolution";
|
|
4170
|
+
return TraceableENSProtocol2;
|
|
4171
|
+
})(TraceableENSProtocol || {});
|
|
4172
|
+
var ForwardResolutionProtocolStep = /* @__PURE__ */ ((ForwardResolutionProtocolStep2) => {
|
|
4173
|
+
ForwardResolutionProtocolStep2["Operation"] = "forward-resolution";
|
|
4174
|
+
ForwardResolutionProtocolStep2["FindResolver"] = "find-resolver";
|
|
4175
|
+
ForwardResolutionProtocolStep2["ActiveResolverExists"] = "active-resolver-exists";
|
|
4176
|
+
ForwardResolutionProtocolStep2["AccelerateENSIP19ReverseResolver"] = "accelerate-ensip-19-reverse-resolver";
|
|
4177
|
+
ForwardResolutionProtocolStep2["AccelerateKnownOffchainLookupResolver"] = "accelerate-known-offchain-lookup-resolver";
|
|
4178
|
+
ForwardResolutionProtocolStep2["AccelerateKnownOnchainStaticResolver"] = "accelerate-known-onchain-static-resolver";
|
|
4179
|
+
ForwardResolutionProtocolStep2["RequireResolver"] = "require-resolver";
|
|
4180
|
+
ForwardResolutionProtocolStep2["ExecuteResolveCalls"] = "execute-resolve-calls";
|
|
4181
|
+
return ForwardResolutionProtocolStep2;
|
|
4182
|
+
})(ForwardResolutionProtocolStep || {});
|
|
4183
|
+
var ReverseResolutionProtocolStep = /* @__PURE__ */ ((ReverseResolutionProtocolStep2) => {
|
|
4184
|
+
ReverseResolutionProtocolStep2["Operation"] = "reverse-resolution";
|
|
4185
|
+
ReverseResolutionProtocolStep2["ResolveReverseName"] = "resolve-reverse-name";
|
|
4186
|
+
ReverseResolutionProtocolStep2["NameRecordExists"] = "name-record-exists-check";
|
|
4187
|
+
ReverseResolutionProtocolStep2["ForwardResolveAddressRecord"] = "forward-resolve-address-record";
|
|
4188
|
+
ReverseResolutionProtocolStep2["VerifyResolvedAddressMatchesAddress"] = "verify-resolved-address-matches-address";
|
|
4189
|
+
return ReverseResolutionProtocolStep2;
|
|
4190
|
+
})(ReverseResolutionProtocolStep || {});
|
|
4191
|
+
export {
|
|
4192
|
+
ADDR_REVERSE_NODE,
|
|
4193
|
+
ATTR_PROTOCOL_NAME,
|
|
4194
|
+
ATTR_PROTOCOL_STEP,
|
|
4195
|
+
ATTR_PROTOCOL_STEP_RESULT,
|
|
4196
|
+
AssetNamespaces,
|
|
4197
|
+
BASENAMES_NODE,
|
|
4198
|
+
ChainIndexingConfigTypeIds,
|
|
4199
|
+
ChainIndexingStatusIds,
|
|
4200
|
+
ClientError,
|
|
4201
|
+
CrossChainIndexingStrategyIds,
|
|
4202
|
+
CurrencyIds,
|
|
4203
|
+
DEFAULT_EVM_CHAIN_ID,
|
|
4204
|
+
DEFAULT_EVM_COIN_TYPE,
|
|
4205
|
+
ENSNamespaceIds,
|
|
4206
|
+
ENSNodeClient,
|
|
4207
|
+
ENS_ROOT,
|
|
4208
|
+
ETH_COIN_TYPE,
|
|
4209
|
+
ETH_NODE,
|
|
4210
|
+
ForwardResolutionProtocolStep,
|
|
4211
|
+
IndexingStatusResponseCodes,
|
|
4212
|
+
LINEANAMES_NODE,
|
|
4213
|
+
LruCache,
|
|
4214
|
+
NFTMintStatuses,
|
|
4215
|
+
NFTTransferTypes,
|
|
4216
|
+
NameTokenOwnershipTypes,
|
|
4217
|
+
NameTokensResponseCodes,
|
|
4218
|
+
NameTokensResponseErrorCodes,
|
|
4219
|
+
OmnichainIndexingStatusIds,
|
|
4220
|
+
PROTOCOL_ATTRIBUTE_PREFIX,
|
|
4221
|
+
PluginName,
|
|
4222
|
+
RECORDS_PER_PAGE_DEFAULT,
|
|
4223
|
+
RECORDS_PER_PAGE_MAX,
|
|
4224
|
+
ROOT_NODE,
|
|
4225
|
+
ReferrerDetailResponseCodes,
|
|
4226
|
+
ReferrerLeaderboardPageResponseCodes,
|
|
4227
|
+
RegistrarActionTypes,
|
|
4228
|
+
RegistrarActionsFilterTypes,
|
|
4229
|
+
RegistrarActionsOrders,
|
|
4230
|
+
RegistrarActionsResponseCodes,
|
|
4231
|
+
ResolutionStatusIds,
|
|
4232
|
+
ReverseResolutionProtocolStep,
|
|
4233
|
+
SWRCache,
|
|
4234
|
+
TheGraphCannotFallbackReasonSchema,
|
|
4235
|
+
TheGraphFallbackSchema,
|
|
4236
|
+
TraceableENSProtocol,
|
|
4237
|
+
TtlCache,
|
|
4238
|
+
ZERO_ENCODED_REFERRER,
|
|
4239
|
+
accountIdEqual,
|
|
4240
|
+
addDuration,
|
|
4241
|
+
addPrices,
|
|
4242
|
+
addrReverseLabel,
|
|
4243
|
+
asLowerCaseAddress,
|
|
4244
|
+
beautifyName,
|
|
4245
|
+
bigIntToNumber,
|
|
4246
|
+
bigintToCoinType,
|
|
4247
|
+
buildAssetId,
|
|
4248
|
+
buildEnsRainbowClientLabelSet,
|
|
4249
|
+
buildLabelSetId,
|
|
4250
|
+
buildLabelSetVersion,
|
|
4251
|
+
buildPageContext,
|
|
4252
|
+
buildUnresolvedIdentity,
|
|
4253
|
+
checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill,
|
|
4254
|
+
checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted,
|
|
4255
|
+
checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing,
|
|
4256
|
+
checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted,
|
|
4257
|
+
coinTypeReverseLabel,
|
|
4258
|
+
coinTypeToEvmChainId,
|
|
4259
|
+
createIndexingConfig,
|
|
4260
|
+
createRealtimeIndexingStatusProjection,
|
|
4261
|
+
decodeDNSEncodedLiteralName,
|
|
4262
|
+
decodeDNSEncodedName,
|
|
4263
|
+
decodeEncodedReferrer,
|
|
4264
|
+
deserializeAssetId,
|
|
4265
|
+
deserializeBlockNumber,
|
|
4266
|
+
deserializeBlockRef,
|
|
4267
|
+
deserializeBlockrange,
|
|
4268
|
+
deserializeChainId,
|
|
4269
|
+
deserializeChainIndexingStatusSnapshot,
|
|
4270
|
+
deserializeConfigResponse,
|
|
4271
|
+
deserializeCrossChainIndexingStatusSnapshot,
|
|
4272
|
+
deserializeDatetime,
|
|
4273
|
+
deserializeDuration,
|
|
4274
|
+
deserializeENSApiPublicConfig,
|
|
4275
|
+
deserializeENSIndexerPublicConfig,
|
|
4276
|
+
deserializeErrorResponse,
|
|
4277
|
+
deserializeIndexingStatusResponse,
|
|
4278
|
+
deserializeOmnichainIndexingStatusSnapshot,
|
|
4279
|
+
deserializeRealtimeIndexingStatusProjection,
|
|
4280
|
+
deserializeReferrerDetailResponse,
|
|
4281
|
+
deserializeReferrerLeaderboardPageResponse,
|
|
4282
|
+
deserializeRegistrarActionsResponse,
|
|
4283
|
+
deserializeUnixTimestamp,
|
|
4284
|
+
deserializeUrl,
|
|
4285
|
+
deserializedNameTokensResponse,
|
|
4286
|
+
durationBetween,
|
|
4287
|
+
encodeLabelHash,
|
|
4288
|
+
evmChainIdToCoinType,
|
|
4289
|
+
formatAccountId,
|
|
4290
|
+
formatAssetId,
|
|
4291
|
+
formatNFTTransferEventMetadata,
|
|
4292
|
+
getBasenamesSubregistryId,
|
|
4293
|
+
getBasenamesSubregistryManagedName,
|
|
4294
|
+
getCurrencyInfo,
|
|
4295
|
+
getDatasourceContract,
|
|
4296
|
+
getENSRootChainId,
|
|
4297
|
+
getEthnamesSubregistryId,
|
|
4298
|
+
getEthnamesSubregistryManagedName,
|
|
4299
|
+
getLatestIndexedBlockRef,
|
|
4300
|
+
getLineanamesSubregistryId,
|
|
4301
|
+
getLineanamesSubregistryManagedName,
|
|
4302
|
+
getNFTTransferType,
|
|
4303
|
+
getNameHierarchy,
|
|
4304
|
+
getNameTokenOwnership,
|
|
4305
|
+
getNameWrapperAccounts,
|
|
4306
|
+
getOmnichainIndexingCursor,
|
|
4307
|
+
getOmnichainIndexingStatus,
|
|
4308
|
+
getParentNameFQDN,
|
|
4309
|
+
getResolvePrimaryNameChainIdParam,
|
|
4310
|
+
getTimestampForHighestOmnichainKnownBlock,
|
|
4311
|
+
getTimestampForLowestOmnichainStartBlock,
|
|
4312
|
+
hasNullByte,
|
|
4313
|
+
interpretedLabelsToInterpretedName,
|
|
4314
|
+
isEncodedLabelHash,
|
|
4315
|
+
isHttpProtocol,
|
|
4316
|
+
isLabelHash,
|
|
4317
|
+
isNormalizedLabel,
|
|
4318
|
+
isNormalizedName,
|
|
4319
|
+
isPriceCurrencyEqual,
|
|
4320
|
+
isPriceEqual,
|
|
4321
|
+
isRegistrarActionPricingAvailable,
|
|
4322
|
+
isRegistrarActionReferralAvailable,
|
|
4323
|
+
isResolvedIdentity,
|
|
4324
|
+
isSelectionEmpty,
|
|
4325
|
+
isSubgraphCompatible,
|
|
4326
|
+
isWebSocketProtocol,
|
|
4327
|
+
labelHashToBytes,
|
|
4328
|
+
labelhashLiteralLabel,
|
|
4329
|
+
literalLabelToInterpretedLabel,
|
|
4330
|
+
literalLabelsToInterpretedName,
|
|
4331
|
+
literalLabelsToLiteralName,
|
|
4332
|
+
makeENSApiPublicConfigSchema,
|
|
4333
|
+
makeSubdomainNode,
|
|
4334
|
+
maybeGetDatasourceContract,
|
|
4335
|
+
nameTokensPrerequisites,
|
|
4336
|
+
parseAccountId,
|
|
4337
|
+
parseAssetId,
|
|
4338
|
+
parseNonNegativeInteger,
|
|
4339
|
+
parseReverseName,
|
|
4340
|
+
priceDai,
|
|
4341
|
+
priceEth,
|
|
4342
|
+
priceUsdc,
|
|
4343
|
+
registrarActionsFilter,
|
|
4344
|
+
registrarActionsPrerequisites,
|
|
4345
|
+
reverseName,
|
|
4346
|
+
serializeAssetId,
|
|
4347
|
+
serializeChainId,
|
|
4348
|
+
serializeChainIndexingSnapshots,
|
|
4349
|
+
serializeConfigResponse,
|
|
4350
|
+
serializeCrossChainIndexingStatusSnapshotOmnichain,
|
|
4351
|
+
serializeDatetime,
|
|
4352
|
+
serializeDomainAssetId,
|
|
4353
|
+
serializeENSApiPublicConfig,
|
|
4354
|
+
serializeENSIndexerPublicConfig,
|
|
4355
|
+
serializeIndexedChainIds,
|
|
4356
|
+
serializeIndexingStatusResponse,
|
|
4357
|
+
serializeNameToken,
|
|
4358
|
+
serializeNameTokensResponse,
|
|
4359
|
+
serializeNamedRegistrarAction,
|
|
4360
|
+
serializeOmnichainIndexingStatusSnapshot,
|
|
4361
|
+
serializePrice,
|
|
4362
|
+
serializePriceEth,
|
|
4363
|
+
serializeRealtimeIndexingStatusProjection,
|
|
4364
|
+
serializeReferrerDetailResponse,
|
|
4365
|
+
serializeReferrerLeaderboardPageResponse,
|
|
4366
|
+
serializeRegisteredNameTokens,
|
|
4367
|
+
serializeRegistrarAction,
|
|
4368
|
+
serializeRegistrarActionPricing,
|
|
4369
|
+
serializeRegistrarActionsResponse,
|
|
4370
|
+
serializeUrl,
|
|
4371
|
+
sortChainStatusesByStartBlockAsc,
|
|
4372
|
+
stripNullBytes,
|
|
4373
|
+
translateDefaultableChainIdToChainId,
|
|
4374
|
+
uint256ToHex32,
|
|
4375
|
+
uniq,
|
|
4376
|
+
validateSupportedLabelSetAndVersion
|
|
4377
|
+
};
|
|
4378
|
+
//# sourceMappingURL=index.js.map
|