@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/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