@ensnode/ensnode-sdk 1.2.0 → 1.3.1

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 CHANGED
@@ -7,25 +7,6 @@ import { z as z3 } from "zod/v4";
7
7
  // src/ensindexer/config/zod-schemas.ts
8
8
  import z2 from "zod/v4";
9
9
 
10
- // src/ens/is-normalized.ts
11
- import { normalize } from "viem/ens";
12
- function isNormalizedName(name) {
13
- try {
14
- return name === normalize(name);
15
- } catch {
16
- return false;
17
- }
18
- }
19
- function isNormalizedLabel(label) {
20
- if (label === "") return false;
21
- if (label.includes(".")) return false;
22
- try {
23
- return label === normalize(label);
24
- } catch {
25
- return false;
26
- }
27
- }
28
-
29
10
  // src/shared/account-id.ts
30
11
  import { isAddressEqual } from "viem";
31
12
  var accountIdEqual = (a, b) => {
@@ -179,9 +160,39 @@ function isEncodedLabelHash(maybeEncodedLabelHash) {
179
160
  return expectedFormatting && includesLabelHash;
180
161
  }
181
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
182
  // src/ens/names.ts
183
183
  import { ens_beautify } from "@adraffy/ens-normalize";
184
+ var ENS_ROOT = "";
184
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
+ };
185
196
  var beautifyName = (name) => {
186
197
  const beautifiedLabels = name.split(".").map((label) => {
187
198
  if (isNormalizedLabel(label)) {
@@ -424,7 +435,7 @@ var makeAccountIdSchema = (valueLabel = "AccountId") => z.strictObject({
424
435
  chainId: makeChainIdSchema(`${valueLabel} chain ID`),
425
436
  address: makeLowercaseAddressSchema(`${valueLabel} address`)
426
437
  });
427
- var makeSerializedAccountIdSchema = (valueLabel = "Account ID") => z.coerce.string().transform((v) => {
438
+ var makeAccountIdStringSchema = (valueLabel = "Account ID String") => z.coerce.string().transform((v) => {
428
439
  const result = new CaipAccountId(v);
429
440
  return {
430
441
  chainId: Number(result.chainId.reference),
@@ -436,7 +447,7 @@ var makeHexStringSchema = (options, valueLabel = "String representation of bytes
436
447
  ctx.issues.push({
437
448
  code: "custom",
438
449
  input: ctx.value,
439
- message: `${valueLabel} must start with '0x'.`
450
+ message: `${valueLabel} must be a hexadecimal value which starts with '0x'.`
440
451
  });
441
452
  }
442
453
  }).transform((v) => v).check(function invariant_encodesRequiredBytesCount(ctx) {
@@ -546,8 +557,8 @@ ${prettifyError(parsed.error)}
546
557
  }
547
558
  return parsed.data;
548
559
  }
549
- function deserializeAccountId(maybeAccountId, valueLabel) {
550
- const schema = makeSerializedAccountIdSchema(valueLabel);
560
+ function parseAccountId(maybeAccountId, valueLabel) {
561
+ const schema = makeAccountIdStringSchema(valueLabel);
551
562
  const parsed = schema.safeParse(maybeAccountId);
552
563
  if (parsed.error) {
553
564
  throw new RangeError(`Cannot deserialize AccountId:
@@ -565,181 +576,65 @@ function addDuration(timestamp, duration) {
565
576
  return deserializeUnixTimestamp(timestamp + duration, "UnixTimestamp");
566
577
  }
567
578
 
568
- // src/shared/cache/background-revalidation-scheduler.ts
569
- var BackgroundRevalidationScheduler = class {
570
- activeSchedules = /* @__PURE__ */ new Map();
571
- /**
572
- * Schedule a revalidation function to run on a recurring interval.
573
- *
574
- * @param config Configuration object for the schedule
575
- * @returns The revalidate function that can be passed to `cancel()` to stop the schedule
576
- */
577
- schedule(config) {
578
- const { revalidate, interval, initialDelay = 0, onError } = config;
579
- if (this.activeSchedules.has(revalidate)) {
580
- return revalidate;
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
+ );
581
588
  }
582
- const metadata = {
583
- config,
584
- timeoutId: null,
585
- inProgress: false
586
- };
587
- this.activeSchedules.set(revalidate, metadata);
588
- const executeRevalidation = async () => {
589
- if (metadata.inProgress) return;
590
- metadata.inProgress = true;
591
- try {
592
- await revalidate();
593
- } catch (error) {
594
- onError?.(error);
595
- } finally {
596
- metadata.inProgress = false;
597
- }
598
- };
599
- const scheduleNext = () => {
600
- if (!this.activeSchedules.has(revalidate)) return;
601
- metadata.timeoutId = setTimeout(() => {
602
- if (this.activeSchedules.has(revalidate)) {
603
- executeRevalidation().then(() => scheduleNext());
604
- }
605
- }, interval);
606
- };
607
- if (initialDelay > 0) {
608
- metadata.timeoutId = setTimeout(() => {
609
- if (this.activeSchedules.has(revalidate)) {
610
- executeRevalidation().then(() => scheduleNext());
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
+ };
611
608
  }
612
- }, initialDelay);
613
- } else {
614
- scheduleNext();
609
+ }).finally(() => {
610
+ this.inProgressRevalidate = null;
611
+ });
615
612
  }
616
- return revalidate;
613
+ return this.inProgressRevalidate;
617
614
  }
618
615
  /**
619
- * Cancel a scheduled revalidation by its revalidate function.
616
+ * Read the most recently cached result from the `SWRCache`.
620
617
  *
621
- * @param revalidate The revalidation function returned from `schedule()`
622
- */
623
- cancel(revalidate) {
624
- const metadata = this.activeSchedules.get(revalidate);
625
- if (!metadata) return;
626
- if (metadata.timeoutId !== null) {
627
- clearTimeout(metadata.timeoutId);
628
- }
629
- this.activeSchedules.delete(revalidate);
630
- }
631
- /**
632
- * Cancel all active schedules.
618
+ * @returns a `ValueType` that was most recently successfully returned by `fn` or `Error` if `fn`
619
+ * has never successfully returned.
633
620
  */
634
- cancelAll() {
635
- for (const [, metadata] of this.activeSchedules) {
636
- if (metadata.timeoutId !== null) {
637
- clearTimeout(metadata.timeoutId);
638
- }
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();
639
626
  }
640
- this.activeSchedules.clear();
627
+ return this.cache.result;
641
628
  }
642
629
  /**
643
- * Get the count of active schedules.
644
- * Useful for debugging and monitoring.
645
- *
646
- * @returns The number of currently active schedules
647
- */
648
- getActiveScheduleCount() {
649
- return this.activeSchedules.size;
650
- }
651
- };
652
-
653
- // src/shared/cache/swr-cache.ts
654
- var bgRevalidationScheduler = new BackgroundRevalidationScheduler();
655
- var SWRCache = class _SWRCache {
656
- options;
657
- cache;
658
- /**
659
- * Optional promise of the current in-progress attempt to revalidate the `cache`.
660
- *
661
- * If null, no revalidation attempt is currently in progress.
662
- * If not null, identifies the revalidation attempt that is currently in progress.
663
- *
664
- * Used to enforce no concurrent revalidation attempts.
665
- */
666
- inProgressRevalidate;
667
- /**
668
- * The callback function being managed by `BackgroundRevalidationScheduler`.
669
- *
670
- * If null, no background revalidation is scheduled.
671
- * If not null, identifies the background revalidation that is currently scheduled.
672
- *
673
- * Used to enforce no concurrent background revalidation attempts.
674
- */
675
- scheduledBackgroundRevalidate;
676
- constructor(options) {
677
- this.cache = null;
678
- this.inProgressRevalidate = null;
679
- this.scheduledBackgroundRevalidate = null;
680
- this.options = options;
681
- }
682
- /**
683
- * Asynchronously create a new `SWRCache` instance.
684
- *
685
- * @param options - The {@link SWRCacheOptions} for the SWR cache.
686
- * @returns a new `SWRCache` instance.
630
+ * Destroys the background revalidation interval, if exists.
687
631
  */
688
- static async create(options) {
689
- const cache = new _SWRCache(options);
690
- if (cache.options.proactivelyInitialize) {
691
- cache.readCache();
632
+ destroy() {
633
+ if (this.backgroundInterval) {
634
+ clearInterval(this.backgroundInterval);
635
+ this.backgroundInterval = null;
692
636
  }
693
- return cache;
694
637
  }
695
- revalidate = async () => {
696
- if (this.inProgressRevalidate) {
697
- return this.inProgressRevalidate;
698
- }
699
- return this.options.fn().then((value) => {
700
- this.cache = {
701
- value,
702
- updatedAt: getUnixTime(/* @__PURE__ */ new Date())
703
- };
704
- return this.cache;
705
- }).catch(() => {
706
- return null;
707
- }).finally(() => {
708
- this.inProgressRevalidate = null;
709
- if (this.options.revalidationInterval === void 0) {
710
- return;
711
- }
712
- if (this.scheduledBackgroundRevalidate) {
713
- bgRevalidationScheduler.cancel(this.scheduledBackgroundRevalidate);
714
- }
715
- const backgroundRevalidate = async () => {
716
- this.revalidate();
717
- };
718
- this.scheduledBackgroundRevalidate = bgRevalidationScheduler.schedule({
719
- revalidate: backgroundRevalidate,
720
- interval: secondsToMilliseconds(this.options.revalidationInterval)
721
- });
722
- });
723
- };
724
- /**
725
- * Read the most recently cached `CachedValue` from the `SWRCache`.
726
- *
727
- * @returns a `CachedValue` holding a `value` of `ValueType` that was most recently successfully returned by `fn`
728
- * or `null` if `fn` has never successfully returned and has always thrown an error,
729
- */
730
- readCache = async () => {
731
- if (!this.cache) {
732
- this.inProgressRevalidate = this.revalidate();
733
- return this.inProgressRevalidate;
734
- }
735
- if (durationBetween(this.cache.updatedAt, getUnixTime(/* @__PURE__ */ new Date())) <= this.options.ttl) {
736
- return this.cache;
737
- }
738
- if (!this.inProgressRevalidate) {
739
- this.inProgressRevalidate = this.revalidate();
740
- }
741
- return this.cache;
742
- };
743
638
  };
744
639
 
745
640
  // src/shared/cache/ttl-cache.ts
@@ -810,6 +705,28 @@ var TtlCache = class {
810
705
  // src/shared/collections.ts
811
706
  var uniq = (arr) => [...new Set(arr)];
812
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
+
813
730
  // src/shared/labelhash.ts
814
731
  import { keccak256 as keccak2562, stringToBytes } from "viem";
815
732
  var labelhashLiteralLabel = (label) => keccak2562(stringToBytes(label));
@@ -868,7 +785,7 @@ function serializePrice(price) {
868
785
  function serializePriceEth(price) {
869
786
  return serializePrice(price);
870
787
  }
871
- function serializeAccountId(accountId) {
788
+ function formatAccountId(accountId) {
872
789
  return CaipAccountId2.format({
873
790
  chainId: { namespace: "eip155", reference: accountId.chainId.toString() },
874
791
  address: accountId.address
@@ -1844,152 +1761,748 @@ function serializeConfigResponse(response) {
1844
1761
  import { prettifyError as prettifyError5 } from "zod/v4";
1845
1762
 
1846
1763
  // src/api/indexing-status/zod-schemas.ts
1847
- import z11 from "zod/v4";
1848
-
1849
- // src/api/registrar-actions/zod-schemas.ts
1850
- import { namehash as namehash2 } from "viem/ens";
1851
- import z6 from "zod/v4";
1852
-
1853
- // src/api/shared/errors/zod-schemas.ts
1854
1764
  import z5 from "zod/v4";
1855
- var ErrorResponseSchema = z5.object({
1856
- message: z5.string(),
1857
- details: z5.optional(z5.unknown())
1858
- });
1859
1765
 
1860
- // src/api/registrar-actions/response.ts
1861
- var RegistrarActionsResponseCodes = {
1766
+ // src/api/indexing-status/response.ts
1767
+ var IndexingStatusResponseCodes = {
1862
1768
  /**
1863
- * Represents that Registrar Actions are available.
1769
+ * Represents that the indexing status is available.
1864
1770
  */
1865
1771
  Ok: "ok",
1866
1772
  /**
1867
- * Represents that Registrar Actions are unavailable.
1773
+ * Represents that the indexing status is unavailable.
1868
1774
  */
1869
1775
  Error: "error"
1870
1776
  };
1871
1777
 
1872
- // src/api/registrar-actions/zod-schemas.ts
1873
- function invariant_registrationLifecycleNodeMatchesName(ctx) {
1874
- const { name, action } = ctx.value;
1875
- const expectedNode = action.registrationLifecycle.node;
1876
- const actualNode = namehash2(name);
1877
- if (actualNode !== expectedNode) {
1878
- ctx.issues.push({
1879
- code: "custom",
1880
- input: ctx.value,
1881
- message: `The 'action.registrationLifecycle.node' must match namehash of 'name'`
1882
- });
1883
- }
1884
- }
1885
- var makeNamedRegistrarActionSchema = (valueLabel = "Named Registrar Action") => z6.object({
1886
- action: makeRegistrarActionSchema(valueLabel),
1887
- name: makeReinterpretedNameSchema(valueLabel)
1888
- }).check(invariant_registrationLifecycleNodeMatchesName);
1889
- var makeRegistrarActionsResponseOkSchema = (valueLabel = "Registrar Actions Response OK") => z6.strictObject({
1890
- responseCode: z6.literal(RegistrarActionsResponseCodes.Ok),
1891
- registrarActions: z6.array(makeNamedRegistrarActionSchema(valueLabel))
1778
+ // src/api/indexing-status/zod-schemas.ts
1779
+ var makeIndexingStatusResponseOkSchema = (valueLabel = "Indexing Status Response OK") => z5.strictObject({
1780
+ responseCode: z5.literal(IndexingStatusResponseCodes.Ok),
1781
+ realtimeProjection: makeRealtimeIndexingStatusProjectionSchema(valueLabel)
1892
1782
  });
1893
- var makeRegistrarActionsResponseErrorSchema = (_valueLabel = "Registrar Actions Response Error") => z6.strictObject({
1894
- responseCode: z6.literal(RegistrarActionsResponseCodes.Error),
1895
- error: ErrorResponseSchema
1783
+ var makeIndexingStatusResponseErrorSchema = (_valueLabel = "Indexing Status Response Error") => z5.strictObject({
1784
+ responseCode: z5.literal(IndexingStatusResponseCodes.Error)
1896
1785
  });
1897
- var makeRegistrarActionsResponseSchema = (valueLabel = "Registrar Actions Response") => z6.discriminatedUnion("responseCode", [
1898
- makeRegistrarActionsResponseOkSchema(valueLabel),
1899
- makeRegistrarActionsResponseErrorSchema(valueLabel)
1786
+ var makeIndexingStatusResponseSchema = (valueLabel = "Indexing Status Response") => z5.discriminatedUnion("responseCode", [
1787
+ makeIndexingStatusResponseOkSchema(valueLabel),
1788
+ makeIndexingStatusResponseErrorSchema(valueLabel)
1900
1789
  ]);
1901
1790
 
1902
- // src/api/shared/pagination/zod-schemas.ts
1903
- import z7 from "zod/v4";
1904
-
1905
- // src/api/shared/pagination/request.ts
1906
- var RECORDS_PER_PAGE_DEFAULT = 10;
1907
- var RECORDS_PER_PAGE_MAX = 100;
1908
-
1909
- // ../ens-referrals/src/address.ts
1910
- import { isAddress as isAddress3 } from "viem";
1911
-
1912
- // ../ens-referrals/src/encoding.ts
1913
- import { getAddress, pad, size as size2, slice, zeroAddress } from "viem";
1914
- var ENCODED_REFERRER_BYTE_OFFSET = 12;
1915
- var ENCODED_REFERRER_BYTE_LENGTH = 32;
1916
- var EXPECTED_ENCODED_REFERRER_PADDING = pad("0x", {
1917
- size: ENCODED_REFERRER_BYTE_OFFSET,
1918
- dir: "left"
1919
- });
1920
- var ZERO_ENCODED_REFERRER = pad("0x", {
1921
- size: ENCODED_REFERRER_BYTE_LENGTH,
1922
- dir: "left"
1923
- });
1924
- function decodeEncodedReferrer(encodedReferrer) {
1925
- if (size2(encodedReferrer) !== ENCODED_REFERRER_BYTE_LENGTH) {
1926
- throw new Error(
1927
- `Encoded referrer value must be represented by ${ENCODED_REFERRER_BYTE_LENGTH} bytes.`
1928
- );
1929
- }
1930
- const padding = slice(encodedReferrer, 0, ENCODED_REFERRER_BYTE_OFFSET);
1931
- if (padding !== EXPECTED_ENCODED_REFERRER_PADDING) {
1932
- return zeroAddress;
1791
+ // src/api/indexing-status/deserialize.ts
1792
+ function deserializeIndexingStatusResponse(maybeResponse) {
1793
+ const parsed = makeIndexingStatusResponseSchema().safeParse(maybeResponse);
1794
+ if (parsed.error) {
1795
+ throw new Error(`Cannot deserialize IndexingStatusResponse:
1796
+ ${prettifyError5(parsed.error)}
1797
+ `);
1933
1798
  }
1934
- const decodedReferrer = slice(encodedReferrer, ENCODED_REFERRER_BYTE_OFFSET);
1935
- try {
1936
- return getAddress(decodedReferrer);
1937
- } catch {
1938
- throw new Error(`Decoded referrer value must be a valid EVM address.`);
1799
+ return parsed.data;
1800
+ }
1801
+
1802
+ // src/api/indexing-status/serialize.ts
1803
+ function serializeIndexingStatusResponse(response) {
1804
+ switch (response.responseCode) {
1805
+ case IndexingStatusResponseCodes.Ok:
1806
+ return {
1807
+ responseCode: response.responseCode,
1808
+ realtimeProjection: serializeRealtimeIndexingStatusProjection(response.realtimeProjection)
1809
+ };
1810
+ case IndexingStatusResponseCodes.Error:
1811
+ return response;
1939
1812
  }
1940
1813
  }
1941
1814
 
1942
- // ../ens-referrals/src/leaderboard-page.ts
1943
- var REFERRERS_PER_LEADERBOARD_PAGE_MAX = 100;
1815
+ // src/api/name-tokens/deserialize.ts
1816
+ import { prettifyError as prettifyError7 } from "zod/v4";
1944
1817
 
1945
- // ../ens-referrals/src/link.ts
1946
- import { getAddress as getAddress2 } from "viem";
1818
+ // src/api/name-tokens/zod-schemas.ts
1819
+ import { namehash as namehash2 } from "viem";
1820
+ import z8 from "zod/v4";
1947
1821
 
1948
- // ../ens-referrals/src/referrer-detail.ts
1949
- var ReferrerDetailTypeIds = {
1822
+ // src/tokenscope/assets.ts
1823
+ import { AssetId as CaipAssetId2 } from "caip";
1824
+ import { isAddressEqual as isAddressEqual3, zeroAddress as zeroAddress3 } from "viem";
1825
+ import { prettifyError as prettifyError6 } from "zod/v4";
1826
+
1827
+ // src/tokenscope/zod-schemas.ts
1828
+ import { AssetId as CaipAssetId } from "caip";
1829
+ import { zeroAddress as zeroAddress2 } from "viem";
1830
+ import z6 from "zod/v4";
1831
+
1832
+ // src/tokenscope/name-token.ts
1833
+ import { isAddressEqual as isAddressEqual2, zeroAddress } from "viem";
1834
+ import { DatasourceNames } from "@ensnode/datasources";
1835
+ var NameTokenOwnershipTypes = {
1950
1836
  /**
1951
- * Represents a referrer who is ranked on the leaderboard.
1837
+ * Name Token is owned by NameWrapper account.
1952
1838
  */
1953
- Ranked: "ranked",
1839
+ NameWrapper: "namewrapper",
1954
1840
  /**
1955
- * Represents a referrer who is not ranked on the leaderboard.
1841
+ * Name Token is owned fully onchain.
1842
+ *
1843
+ * This ownership type can only apply to direct subnames of `.eth`
1956
1844
  */
1957
- Unranked: "unranked"
1845
+ FullyOnchain: "fully-onchain",
1846
+ /**
1847
+ * Name Token ownership has been transferred to the null address.
1848
+ */
1849
+ Burned: "burned",
1850
+ /**
1851
+ * Name Token ownership is unknown.
1852
+ */
1853
+ Unknown: "unknown"
1958
1854
  };
1959
-
1960
- // src/registrars/zod-schemas.ts
1961
- import z8 from "zod/v4";
1962
-
1963
- // src/registrars/subregistry.ts
1964
- function serializeSubregistry(subregistry) {
1855
+ function serializeNameToken(nameToken) {
1965
1856
  return {
1966
- subregistryId: serializeAccountId(subregistry.subregistryId),
1967
- node: subregistry.node
1857
+ token: serializeAssetId(nameToken.token),
1858
+ ownership: nameToken.ownership,
1859
+ mintStatus: nameToken.mintStatus
1968
1860
  };
1969
1861
  }
1970
-
1971
- // src/registrars/registration-lifecycle.ts
1972
- function serializeRegistrationLifecycle(registrationLifecycle) {
1862
+ function getNameWrapperAccounts(namespaceId) {
1863
+ const ethnamesNameWrapperAccount = getDatasourceContract(
1864
+ namespaceId,
1865
+ DatasourceNames.ENSRoot,
1866
+ "NameWrapper"
1867
+ );
1868
+ const lineanamesNameWrapperAccount = maybeGetDatasourceContract(
1869
+ namespaceId,
1870
+ DatasourceNames.Lineanames,
1871
+ "NameWrapper"
1872
+ );
1873
+ const nameWrapperAccounts = [
1874
+ // NameWrapper for direct subnames of .eth is defined for all ENS namespaces
1875
+ ethnamesNameWrapperAccount
1876
+ ];
1877
+ if (lineanamesNameWrapperAccount) {
1878
+ nameWrapperAccounts.push(lineanamesNameWrapperAccount);
1879
+ }
1880
+ return nameWrapperAccounts;
1881
+ }
1882
+ function getNameTokenOwnership(namespaceId, name, owner) {
1883
+ const nameWrapperAccounts = getNameWrapperAccounts(namespaceId);
1884
+ const hasNameWrapperOwnership = nameWrapperAccounts.some(
1885
+ (nameWrapperAccount) => accountIdEqual(owner, nameWrapperAccount)
1886
+ );
1887
+ if (hasNameWrapperOwnership) {
1888
+ return {
1889
+ ownershipType: NameTokenOwnershipTypes.NameWrapper,
1890
+ owner
1891
+ };
1892
+ }
1893
+ if (isAddressEqual2(owner.address, zeroAddress)) {
1894
+ return {
1895
+ ownershipType: NameTokenOwnershipTypes.Burned,
1896
+ owner
1897
+ };
1898
+ }
1899
+ const parentName = getParentNameFQDN(name);
1900
+ if (parentName === "eth") {
1901
+ return {
1902
+ ownershipType: NameTokenOwnershipTypes.FullyOnchain,
1903
+ owner
1904
+ };
1905
+ }
1973
1906
  return {
1974
- subregistry: serializeSubregistry(registrationLifecycle.subregistry),
1975
- node: registrationLifecycle.node,
1976
- expiresAt: registrationLifecycle.expiresAt
1907
+ ownershipType: NameTokenOwnershipTypes.Unknown,
1908
+ owner
1977
1909
  };
1978
1910
  }
1979
1911
 
1980
- // src/registrars/registrar-action.ts
1981
- var RegistrarActionTypes = {
1982
- Registration: "registration",
1983
- Renewal: "renewal"
1984
- };
1985
- function isRegistrarActionPricingAvailable(registrarActionPricing) {
1986
- const { baseCost, premium, total } = registrarActionPricing;
1987
- return baseCost !== null && premium !== null && total !== null;
1988
- }
1989
- function isRegistrarActionReferralAvailable(registrarActionReferral) {
1990
- const { encodedReferrer, decodedReferrer } = registrarActionReferral;
1991
- return encodedReferrer !== null && decodedReferrer !== null;
1992
- }
1912
+ // src/tokenscope/zod-schemas.ts
1913
+ var makeAssetIdSchema = (valueLabel = "Asset ID Schema") => z6.object({
1914
+ assetNamespace: z6.enum(AssetNamespaces),
1915
+ contract: makeAccountIdSchema(valueLabel),
1916
+ tokenId: z6.preprocess((v) => typeof v === "string" ? BigInt(v) : v, z6.bigint().positive())
1917
+ });
1918
+ var makeAssetIdStringSchema = (valueLabel = "Asset ID String Schema") => z6.preprocess((v) => {
1919
+ if (typeof v === "string") {
1920
+ const result = new CaipAssetId(v);
1921
+ return {
1922
+ assetNamespace: result.assetName.namespace,
1923
+ contract: {
1924
+ chainId: Number(result.chainId.reference),
1925
+ address: result.assetName.reference
1926
+ },
1927
+ tokenId: result.tokenId
1928
+ };
1929
+ }
1930
+ return v;
1931
+ }, makeAssetIdSchema(valueLabel));
1932
+ function invariant_nameTokenOwnershipHasNonZeroAddressOwner(ctx) {
1933
+ const ownership = ctx.value;
1934
+ if (ctx.value.owner.address === zeroAddress2) {
1935
+ ctx.issues.push({
1936
+ code: "custom",
1937
+ input: ctx.value,
1938
+ message: `Name Token Ownership with '${ownership.ownershipType}' must have 'address' other than the zero address.`
1939
+ });
1940
+ }
1941
+ }
1942
+ var makeNameTokenOwnershipNameWrapperSchema = (valueLabel = "Name Token Ownership NameWrapper") => z6.object({
1943
+ ownershipType: z6.literal(NameTokenOwnershipTypes.NameWrapper),
1944
+ owner: makeAccountIdSchema(`${valueLabel}.owner`)
1945
+ }).check(invariant_nameTokenOwnershipHasNonZeroAddressOwner);
1946
+ var makeNameTokenOwnershipFullyOnchainSchema = (valueLabel = "Name Token Ownership Fully Onchain") => z6.object({
1947
+ ownershipType: z6.literal(NameTokenOwnershipTypes.FullyOnchain),
1948
+ owner: makeAccountIdSchema(`${valueLabel}.owner`)
1949
+ }).check(invariant_nameTokenOwnershipHasNonZeroAddressOwner);
1950
+ var makeNameTokenOwnershipBurnedSchema = (valueLabel = "Name Token Ownership Burned") => z6.object({
1951
+ ownershipType: z6.literal(NameTokenOwnershipTypes.Burned),
1952
+ owner: makeAccountIdSchema(`${valueLabel}.owner`)
1953
+ }).check(invariant_nameTokenOwnershipHasZeroAddressOwner);
1954
+ var makeNameTokenOwnershipUnknownSchema = (valueLabel = "Name Token Ownership Unknown") => z6.object({
1955
+ ownershipType: z6.literal(NameTokenOwnershipTypes.Unknown),
1956
+ owner: makeAccountIdSchema(`${valueLabel}.owner`)
1957
+ }).check(invariant_nameTokenOwnershipHasNonZeroAddressOwner);
1958
+ function invariant_nameTokenOwnershipHasZeroAddressOwner(ctx) {
1959
+ const ownership = ctx.value;
1960
+ if (ctx.value.owner.address !== zeroAddress2) {
1961
+ ctx.issues.push({
1962
+ code: "custom",
1963
+ input: ctx.value,
1964
+ message: `Name Token Ownership with '${ownership.ownershipType}' must have 'address' set to the zero address.`
1965
+ });
1966
+ }
1967
+ }
1968
+ var makeNameTokenOwnershipSchema = (valueLabel = "Name Token Ownership") => z6.discriminatedUnion("ownershipType", [
1969
+ makeNameTokenOwnershipNameWrapperSchema(valueLabel),
1970
+ makeNameTokenOwnershipFullyOnchainSchema(valueLabel),
1971
+ makeNameTokenOwnershipBurnedSchema(valueLabel),
1972
+ makeNameTokenOwnershipUnknownSchema(valueLabel)
1973
+ ]);
1974
+ var makeNameTokenSchema = (valueLabel = "Name Token Schema") => z6.object({
1975
+ token: makeAssetIdSchema(`${valueLabel}.token`),
1976
+ ownership: makeNameTokenOwnershipSchema(`${valueLabel}.ownership`),
1977
+ mintStatus: z6.enum(NFTMintStatuses)
1978
+ });
1979
+
1980
+ // src/tokenscope/assets.ts
1981
+ var AssetNamespaces = {
1982
+ ERC721: "erc721",
1983
+ ERC1155: "erc1155"
1984
+ };
1985
+ function serializeAssetId(assetId) {
1986
+ return {
1987
+ assetNamespace: assetId.assetNamespace,
1988
+ contract: assetId.contract,
1989
+ tokenId: uint256ToHex32(assetId.tokenId)
1990
+ };
1991
+ }
1992
+ function deserializeAssetId(maybeAssetId, valueLabel) {
1993
+ const schema = makeAssetIdSchema(valueLabel);
1994
+ const parsed = schema.safeParse(maybeAssetId);
1995
+ if (parsed.error) {
1996
+ throw new RangeError(`Cannot deserialize AssetId:
1997
+ ${prettifyError6(parsed.error)}
1998
+ `);
1999
+ }
2000
+ return parsed.data;
2001
+ }
2002
+ function formatAssetId(assetId) {
2003
+ const { assetNamespace, contract, tokenId } = serializeAssetId(assetId);
2004
+ return CaipAssetId2.format({
2005
+ chainId: { namespace: "eip155", reference: contract.chainId.toString() },
2006
+ assetName: { namespace: assetNamespace, reference: contract.address },
2007
+ tokenId
2008
+ }).toLowerCase();
2009
+ }
2010
+ function parseAssetId(maybeAssetId, valueLabel) {
2011
+ const schema = makeAssetIdStringSchema(valueLabel);
2012
+ const parsed = schema.safeParse(maybeAssetId);
2013
+ if (parsed.error) {
2014
+ throw new RangeError(`Cannot parse AssetId:
2015
+ ${prettifyError6(parsed.error)}
2016
+ `);
2017
+ }
2018
+ return parsed.data;
2019
+ }
2020
+ var buildAssetId = (contract, tokenId, assetNamespace) => {
2021
+ return {
2022
+ assetNamespace,
2023
+ contract,
2024
+ tokenId
2025
+ };
2026
+ };
2027
+ function serializeDomainAssetId(domainAsset) {
2028
+ return {
2029
+ ...serializeAssetId(domainAsset),
2030
+ domainId: domainAsset.domainId
2031
+ };
2032
+ }
2033
+ var NFTMintStatuses = {
2034
+ Minted: "minted",
2035
+ Burned: "burned"
2036
+ };
2037
+ var formatNFTTransferEventMetadata = (metadata) => {
2038
+ const serializedAssetId = serializeAssetId(metadata.nft);
2039
+ return [
2040
+ `Event: ${metadata.eventHandlerName}`,
2041
+ `Chain ID: ${metadata.chainId}`,
2042
+ `Block Number: ${metadata.blockNumber}`,
2043
+ `Transaction Hash: ${metadata.transactionHash}`,
2044
+ `NFT: ${serializedAssetId}`
2045
+ ].map((line) => ` - ${line}`).join("\n");
2046
+ };
2047
+ var NFTTransferTypes = {
2048
+ /**
2049
+ * Initial transfer from zeroAddress to a non-zeroAddress
2050
+ * Can happen at most once to a NFT AssetId
2051
+ *
2052
+ * Invariants:
2053
+ * - NFT is not indexed and therefore has no previous mint status or owner
2054
+ * - new NFT mint status is `minted`
2055
+ * - new NFT owner is a non-zeroAddress
2056
+ */
2057
+ Mint: "mint",
2058
+ /**
2059
+ * Subsequent transfer from zeroAddress to a non-zeroAddress
2060
+ * Can happen any number of times to a NFT AssetId as it passes in a cycle from
2061
+ * mint -> burn -> remint -> burn -> remint -> ...
2062
+ *
2063
+ * Invariants:
2064
+ * - NFT is indexed
2065
+ * - previous NFT mint status was `burned`
2066
+ * - previous NFT owner is the zeroAddress
2067
+ * - new NFT mint status is `minted`
2068
+ * - new NFT owner is a non-zeroAddress
2069
+ */
2070
+ Remint: "remint",
2071
+ /**
2072
+ * Special transfer type for improperly implemented NFT contracts that allow a NFT
2073
+ * that is currently minted to be reminted before an intermediate burn.
2074
+ *
2075
+ * Transfer from zeroAddress to non-zeroAddress for an indexed NFT where the
2076
+ * previously indexed nft had status `minted` with a non-zeroAddress owner.
2077
+ *
2078
+ * Invariants:
2079
+ * - NFT is indexed
2080
+ * - previous NFT mint status was `minted`
2081
+ * - previous NFT owner was a non-zeroAddress
2082
+ * - new NFT mint status is `minted`
2083
+ * - new NFT owner is a non-zeroAddress
2084
+ */
2085
+ MintedRemint: "minted-remint",
2086
+ /**
2087
+ * Transfer from a non-zeroAddress to zeroAddress
2088
+ *
2089
+ * Invariants:
2090
+ * - NFT is indexed
2091
+ * - previous NFT mint status was `minted`
2092
+ * - previous NFT owner is a non-zeroAddress
2093
+ * - new NFT mint status is `burned`
2094
+ * - new NFT owner is the zeroAddress
2095
+ */
2096
+ Burn: "burn",
2097
+ /**
2098
+ * Transfer from a non-zeroAddress to a distinct non-zeroAddress
2099
+ *
2100
+ * Invariants:
2101
+ * - NFT is indexed
2102
+ * - previous and new NFT mint status is `minted`
2103
+ * - previous and new NFT owner are distinct non-zeroAddress
2104
+ */
2105
+ Transfer: "transfer",
2106
+ /**
2107
+ * Transfer from a non-zeroAddress to the same non-zeroAddress
2108
+ *
2109
+ * Invariants:
2110
+ * - NFT is indexed
2111
+ * - previous and new NFT mint status is `minted`
2112
+ * - previous and new NFT owner are equivalent non-zeroAddress
2113
+ */
2114
+ SelfTransfer: "self-transfer",
2115
+ /**
2116
+ * Transfer from zeroAddress to zeroAddress for an indexed NFT
2117
+ *
2118
+ * Invariants:
2119
+ * - NFT is indexed
2120
+ * - previous and new NFT mint status is `burned`
2121
+ * - previous and new NFT owner are zeroAddress
2122
+ */
2123
+ RemintBurn: "remint-burn",
2124
+ /**
2125
+ * Special transfer type for improperly implemented NFT contracts that allow a NFT
2126
+ * that is currently minted to be reminted again before an intermediate burn.
2127
+ *
2128
+ * Transfer from zeroAddress to zeroAddress for an indexed NFT where the
2129
+ * previously indexed nft had status `minted` with a non-zeroAddress owner.
2130
+ *
2131
+ * Invariants:
2132
+ * - NFT is indexed
2133
+ * - previous NFT mint status was `minted`
2134
+ * - previous NFT owner was a non-zeroAddress
2135
+ * - new NFT mint status is `burned`
2136
+ * - new NFT owner is the zeroAddress
2137
+ */
2138
+ MintedRemintBurn: "minted-remint-burn",
2139
+ /**
2140
+ * Transfer from zeroAddress to zeroAddress for an unindexed NFT
2141
+ *
2142
+ * Invariants:
2143
+ * - NFT is not indexed and therefore has no previous mint status or owner
2144
+ * - NFT should remain unindexed and without any mint status or owner
2145
+ */
2146
+ MintBurn: "mint-burn"
2147
+ };
2148
+ var getNFTTransferType = (from, to, allowMintedRemint, metadata, currentlyIndexedOwner) => {
2149
+ const isIndexed = currentlyIndexedOwner !== void 0;
2150
+ const isIndexedAsMinted = isIndexed && !isAddressEqual3(currentlyIndexedOwner, zeroAddress3);
2151
+ const isMint = isAddressEqual3(from, zeroAddress3);
2152
+ const isBurn = isAddressEqual3(to, zeroAddress3);
2153
+ const isSelfTransfer = isAddressEqual3(from, to);
2154
+ if (isIndexed && !isAddressEqual3(currentlyIndexedOwner, from)) {
2155
+ if (isMint && allowMintedRemint) {
2156
+ } else {
2157
+ throw new Error(
2158
+ `Error: Sending from ${from} conflicts with currently indexed owner ${currentlyIndexedOwner}.
2159
+ ${formatNFTTransferEventMetadata(metadata)}`
2160
+ );
2161
+ }
2162
+ }
2163
+ if (isSelfTransfer) {
2164
+ if (isMint) {
2165
+ if (!isIndexed) {
2166
+ return NFTTransferTypes.MintBurn;
2167
+ } else if (!isIndexedAsMinted) {
2168
+ return NFTTransferTypes.RemintBurn;
2169
+ } else if (allowMintedRemint) {
2170
+ return NFTTransferTypes.MintedRemintBurn;
2171
+ } else {
2172
+ throw new Error(
2173
+ `Error: Invalid state transition from minted -> remint-burn
2174
+ ${formatNFTTransferEventMetadata(metadata)}`
2175
+ );
2176
+ }
2177
+ } else {
2178
+ if (!isIndexed) {
2179
+ throw new Error(
2180
+ `Error: Invalid state transition from unindexed -> self-transfer
2181
+ ${formatNFTTransferEventMetadata(metadata)}`
2182
+ );
2183
+ } else if (!isIndexedAsMinted) {
2184
+ throw new Error(
2185
+ `Error: invalid state transition from burned -> self-transfer
2186
+ ${formatNFTTransferEventMetadata(metadata)}`
2187
+ );
2188
+ } else {
2189
+ return NFTTransferTypes.SelfTransfer;
2190
+ }
2191
+ }
2192
+ } else if (isMint) {
2193
+ if (!isIndexed) {
2194
+ return NFTTransferTypes.Mint;
2195
+ } else if (!isIndexedAsMinted) {
2196
+ return NFTTransferTypes.Remint;
2197
+ } else if (allowMintedRemint) {
2198
+ return NFTTransferTypes.MintedRemint;
2199
+ } else {
2200
+ throw new Error(
2201
+ `Error: Invalid state transition from minted -> mint
2202
+ ${formatNFTTransferEventMetadata(metadata)}`
2203
+ );
2204
+ }
2205
+ } else if (isBurn) {
2206
+ if (!isIndexed) {
2207
+ throw new Error(
2208
+ `Error: Invalid state transition from unindexed -> burn
2209
+ ${formatNFTTransferEventMetadata(metadata)}`
2210
+ );
2211
+ } else if (!isIndexedAsMinted) {
2212
+ throw new Error(
2213
+ `Error: Invalid state transition from burned -> burn
2214
+ ${formatNFTTransferEventMetadata(metadata)}`
2215
+ );
2216
+ } else {
2217
+ return NFTTransferTypes.Burn;
2218
+ }
2219
+ } else {
2220
+ if (!isIndexed) {
2221
+ throw new Error(
2222
+ `Error: Invalid state transition from unindexed -> transfer
2223
+ ${formatNFTTransferEventMetadata(metadata)}`
2224
+ );
2225
+ } else if (!isIndexedAsMinted) {
2226
+ throw new Error(
2227
+ `Error: Invalid state transition from burned -> transfer
2228
+ ${formatNFTTransferEventMetadata(metadata)}`
2229
+ );
2230
+ } else {
2231
+ return NFTTransferTypes.Transfer;
2232
+ }
2233
+ }
2234
+ };
2235
+
2236
+ // src/api/shared/errors/zod-schemas.ts
2237
+ import z7 from "zod/v4";
2238
+ var ErrorResponseSchema = z7.object({
2239
+ message: z7.string(),
2240
+ details: z7.optional(z7.unknown())
2241
+ });
2242
+
2243
+ // src/api/name-tokens/response.ts
2244
+ var NameTokensResponseCodes = {
2245
+ /**
2246
+ * Represents a response when Name Tokens API can respond with requested data.
2247
+ */
2248
+ Ok: "ok",
2249
+ /**
2250
+ * Represents a response when Name Tokens API could not respond with requested data.
2251
+ */
2252
+ Error: "error"
2253
+ };
2254
+ var NameTokensResponseErrorCodes = {
2255
+ /**
2256
+ * Name tokens not indexed
2257
+ *
2258
+ * Represents an error when tokens for the requested name are not indexed by
2259
+ * the ENSNode instance's configuration.
2260
+ */
2261
+ NameTokensNotIndexed: "name-tokens-not-indexed",
2262
+ /**
2263
+ * Unsupported ENSIndexer Config
2264
+ *
2265
+ * Represents a prerequisites error when connected ENSIndexer config lacks
2266
+ * params required to enable Name Tokens API.
2267
+ */
2268
+ EnsIndexerConfigUnsupported: "unsupported-ensindexer-config",
2269
+ /**
2270
+ * Unsupported Indexing Status
2271
+ *
2272
+ * Represents a prerequisites error when Indexing Status has not yet reached
2273
+ * status required to enable Name Tokens API.
2274
+ */
2275
+ IndexingStatusUnsupported: "unsupported-indexing-status"
2276
+ };
2277
+
2278
+ // src/api/name-tokens/zod-schemas.ts
2279
+ function invariant_nameIsAssociatedWithDomainId(ctx) {
2280
+ const { name, domainId } = ctx.value;
2281
+ if (namehash2(name) !== domainId) {
2282
+ ctx.issues.push({
2283
+ code: "custom",
2284
+ input: ctx.value,
2285
+ message: `'name' must be associated with 'domainId': ${domainId}`
2286
+ });
2287
+ }
2288
+ }
2289
+ function invariant_nameTokensOwnershipTypeNameWrapperRequiresOwnershipTypeFullyOnchainOrUnknown(ctx) {
2290
+ const { tokens } = ctx.value;
2291
+ const containsOwnershipNameWrapper = tokens.some(
2292
+ (t) => t.ownership.ownershipType === NameTokenOwnershipTypes.NameWrapper
2293
+ );
2294
+ const containsOwnershipFullyOnchainOrUnknown = tokens.some(
2295
+ (t) => t.ownership.ownershipType === NameTokenOwnershipTypes.FullyOnchain || t.ownership.ownershipType === NameTokenOwnershipTypes.Unknown
2296
+ );
2297
+ if (containsOwnershipNameWrapper && !containsOwnershipFullyOnchainOrUnknown) {
2298
+ ctx.issues.push({
2299
+ code: "custom",
2300
+ input: ctx.value,
2301
+ message: `'tokens' must contain name token with ownership type 'fully-onchain' or 'unknown' when name token with ownership type 'namewrapper' in listed`
2302
+ });
2303
+ }
2304
+ }
2305
+ function invariant_nameTokensContainAtMostOneWithOwnershipTypeEffective(ctx) {
2306
+ const { tokens } = ctx.value;
2307
+ const tokensCountWithOwnershipFullyOnchain = tokens.filter(
2308
+ (t) => t.ownership.ownershipType === NameTokenOwnershipTypes.FullyOnchain
2309
+ ).length;
2310
+ if (tokensCountWithOwnershipFullyOnchain > 1) {
2311
+ ctx.issues.push({
2312
+ code: "custom",
2313
+ input: ctx.value,
2314
+ message: `'tokens' must contain at most one name token with ownership type 'fully-onchain', current count: ${tokensCountWithOwnershipFullyOnchain}`
2315
+ });
2316
+ }
2317
+ }
2318
+ var makeRegisteredNameTokenSchema = (valueLabel = "Registered Name Token") => z8.object({
2319
+ domainId: makeNodeSchema(`${valueLabel}.domainId`),
2320
+ name: makeReinterpretedNameSchema(valueLabel),
2321
+ tokens: z8.array(makeNameTokenSchema(`${valueLabel}.tokens`)).nonempty(),
2322
+ expiresAt: makeUnixTimestampSchema(`${valueLabel}.expiresAt`),
2323
+ accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`)
2324
+ }).check(invariant_nameIsAssociatedWithDomainId).check(invariant_nameTokensContainAtMostOneWithOwnershipTypeEffective).check(invariant_nameTokensOwnershipTypeNameWrapperRequiresOwnershipTypeFullyOnchainOrUnknown);
2325
+ var makeNameTokensResponseOkSchema = (valueLabel = "Name Tokens Response OK") => z8.strictObject({
2326
+ responseCode: z8.literal(NameTokensResponseCodes.Ok),
2327
+ registeredNameTokens: makeRegisteredNameTokenSchema(`${valueLabel}.nameTokens`)
2328
+ });
2329
+ var makeNameTokensResponseErrorNameTokensNotIndexedSchema = (_valueLabel = "Name Tokens Response Error Name Not Indexed") => z8.strictObject({
2330
+ responseCode: z8.literal(NameTokensResponseCodes.Error),
2331
+ errorCode: z8.literal(NameTokensResponseErrorCodes.NameTokensNotIndexed),
2332
+ error: ErrorResponseSchema
2333
+ });
2334
+ var makeNameTokensResponseErrorEnsIndexerConfigUnsupported = (_valueLabel = "Name Tokens Response Error ENSIndexer Config Unsupported") => z8.strictObject({
2335
+ responseCode: z8.literal(NameTokensResponseCodes.Error),
2336
+ errorCode: z8.literal(NameTokensResponseErrorCodes.EnsIndexerConfigUnsupported),
2337
+ error: ErrorResponseSchema
2338
+ });
2339
+ var makeNameTokensResponseErrorNameIndexingStatusUnsupported = (_valueLabel = "Name Tokens Response Error Indexing Status Unsupported") => z8.strictObject({
2340
+ responseCode: z8.literal(NameTokensResponseCodes.Error),
2341
+ errorCode: z8.literal(NameTokensResponseErrorCodes.IndexingStatusUnsupported),
2342
+ error: ErrorResponseSchema
2343
+ });
2344
+ var makeNameTokensResponseErrorSchema = (valueLabel = "Name Tokens Response Error") => z8.discriminatedUnion("errorCode", [
2345
+ makeNameTokensResponseErrorNameTokensNotIndexedSchema(valueLabel),
2346
+ makeNameTokensResponseErrorEnsIndexerConfigUnsupported(valueLabel),
2347
+ makeNameTokensResponseErrorNameIndexingStatusUnsupported(valueLabel)
2348
+ ]);
2349
+ var makeNameTokensResponseSchema = (valueLabel = "Name Tokens Response") => z8.discriminatedUnion("responseCode", [
2350
+ makeNameTokensResponseOkSchema(valueLabel),
2351
+ makeNameTokensResponseErrorSchema(valueLabel)
2352
+ ]);
2353
+
2354
+ // src/api/name-tokens/deserialize.ts
2355
+ function deserializedNameTokensResponse(maybeResponse) {
2356
+ const parsed = makeNameTokensResponseSchema().safeParse(maybeResponse);
2357
+ if (parsed.error) {
2358
+ throw new Error(`Cannot deserialize NameTokensResponse:
2359
+ ${prettifyError7(parsed.error)}
2360
+ `);
2361
+ }
2362
+ return parsed.data;
2363
+ }
2364
+
2365
+ // src/api/name-tokens/prerequisites.ts
2366
+ var nameTokensPrerequisites = Object.freeze({
2367
+ /**
2368
+ * Required plugins to enable Name Tokens API routes.
2369
+ *
2370
+ * 1. `registrars` plugin is required so that data in the `registrationLifecycles`
2371
+ * table is populated.
2372
+ * 2. `tokenscope` plugin is required so that data in the `nameTokens`
2373
+ * table is populated.
2374
+ */
2375
+ requiredPlugins: ["registrars" /* Registrars */, "tokenscope" /* TokenScope */],
2376
+ /**
2377
+ * Check if provided ENSApiPublicConfig supports the Name Tokens API.
2378
+ */
2379
+ hasEnsIndexerConfigSupport(config) {
2380
+ return nameTokensPrerequisites.requiredPlugins.every(
2381
+ (plugin) => config.plugins.includes(plugin)
2382
+ );
2383
+ },
2384
+ /**
2385
+ * Required Indexing Status IDs
2386
+ *
2387
+ * Database indexes are created by the time the omnichain indexing status
2388
+ * is either `completed` or `following`.
2389
+ */
2390
+ supportedIndexingStatusIds: [
2391
+ OmnichainIndexingStatusIds.Completed,
2392
+ OmnichainIndexingStatusIds.Following
2393
+ ],
2394
+ /**
2395
+ * Check if provided indexing status supports the Name Tokens API.
2396
+ */
2397
+ hasIndexingStatusSupport(omnichainIndexingStatusId) {
2398
+ return nameTokensPrerequisites.supportedIndexingStatusIds.some(
2399
+ (supportedIndexingStatusId) => supportedIndexingStatusId === omnichainIndexingStatusId
2400
+ );
2401
+ }
2402
+ });
2403
+
2404
+ // src/api/name-tokens/serialize.ts
2405
+ function serializeRegisteredNameTokens({
2406
+ domainId,
2407
+ name,
2408
+ tokens,
2409
+ expiresAt,
2410
+ accurateAsOf
2411
+ }) {
2412
+ return {
2413
+ domainId,
2414
+ name,
2415
+ tokens: tokens.map(serializeNameToken),
2416
+ expiresAt,
2417
+ accurateAsOf
2418
+ };
2419
+ }
2420
+ function serializeNameTokensResponse(response) {
2421
+ switch (response.responseCode) {
2422
+ case NameTokensResponseCodes.Ok:
2423
+ return {
2424
+ responseCode: response.responseCode,
2425
+ registeredNameTokens: serializeRegisteredNameTokens(response.registeredNameTokens)
2426
+ };
2427
+ case NameTokensResponseCodes.Error:
2428
+ return response;
2429
+ }
2430
+ }
2431
+
2432
+ // src/api/registrar-actions/deserialize.ts
2433
+ import { prettifyError as prettifyError8 } from "zod/v4";
2434
+
2435
+ // src/api/registrar-actions/zod-schemas.ts
2436
+ import { namehash as namehash3 } from "viem/ens";
2437
+ import z11 from "zod/v4";
2438
+
2439
+ // ../ens-referrals/src/address.ts
2440
+ import { isAddress as isAddress3 } from "viem";
2441
+
2442
+ // ../ens-referrals/src/encoding.ts
2443
+ import { getAddress, pad, size as size2, slice, zeroAddress as zeroAddress4 } from "viem";
2444
+ var ENCODED_REFERRER_BYTE_OFFSET = 12;
2445
+ var ENCODED_REFERRER_BYTE_LENGTH = 32;
2446
+ var EXPECTED_ENCODED_REFERRER_PADDING = pad("0x", {
2447
+ size: ENCODED_REFERRER_BYTE_OFFSET,
2448
+ dir: "left"
2449
+ });
2450
+ var ZERO_ENCODED_REFERRER = pad("0x", {
2451
+ size: ENCODED_REFERRER_BYTE_LENGTH,
2452
+ dir: "left"
2453
+ });
2454
+ function decodeEncodedReferrer(encodedReferrer) {
2455
+ if (size2(encodedReferrer) !== ENCODED_REFERRER_BYTE_LENGTH) {
2456
+ throw new Error(
2457
+ `Encoded referrer value must be represented by ${ENCODED_REFERRER_BYTE_LENGTH} bytes.`
2458
+ );
2459
+ }
2460
+ const padding = slice(encodedReferrer, 0, ENCODED_REFERRER_BYTE_OFFSET);
2461
+ if (padding !== EXPECTED_ENCODED_REFERRER_PADDING) {
2462
+ return zeroAddress4;
2463
+ }
2464
+ const decodedReferrer = slice(encodedReferrer, ENCODED_REFERRER_BYTE_OFFSET);
2465
+ try {
2466
+ return getAddress(decodedReferrer);
2467
+ } catch {
2468
+ throw new Error(`Decoded referrer value must be a valid EVM address.`);
2469
+ }
2470
+ }
2471
+
2472
+ // ../ens-referrals/src/leaderboard-page.ts
2473
+ var REFERRERS_PER_LEADERBOARD_PAGE_MAX = 100;
2474
+
2475
+ // ../ens-referrals/src/link.ts
2476
+ import { getAddress as getAddress2 } from "viem";
2477
+
2478
+ // ../ens-referrals/src/referrer-detail.ts
2479
+ var ReferrerDetailTypeIds = {
2480
+ /**
2481
+ * Represents a referrer who is ranked on the leaderboard.
2482
+ */
2483
+ Ranked: "ranked",
2484
+ /**
2485
+ * Represents a referrer who is not ranked on the leaderboard.
2486
+ */
2487
+ Unranked: "unranked"
2488
+ };
2489
+
2490
+ // src/registrars/zod-schemas.ts
2491
+ import z9 from "zod/v4";
2492
+
2493
+ // src/registrars/registrar-action.ts
2494
+ var RegistrarActionTypes = {
2495
+ Registration: "registration",
2496
+ Renewal: "renewal"
2497
+ };
2498
+ function isRegistrarActionPricingAvailable(registrarActionPricing) {
2499
+ const { baseCost, premium, total } = registrarActionPricing;
2500
+ return baseCost !== null && premium !== null && total !== null;
2501
+ }
2502
+ function isRegistrarActionReferralAvailable(registrarActionReferral) {
2503
+ const { encodedReferrer, decodedReferrer } = registrarActionReferral;
2504
+ return encodedReferrer !== null && decodedReferrer !== null;
2505
+ }
1993
2506
  function serializeRegistrarActionPricing(pricing) {
1994
2507
  if (isRegistrarActionPricingAvailable(pricing)) {
1995
2508
  return {
@@ -2006,7 +2519,7 @@ function serializeRegistrarAction(registrarAction) {
2006
2519
  type: registrarAction.type,
2007
2520
  incrementalDuration: registrarAction.incrementalDuration,
2008
2521
  registrant: registrarAction.registrant,
2009
- registrationLifecycle: serializeRegistrationLifecycle(registrarAction.registrationLifecycle),
2522
+ registrationLifecycle: registrarAction.registrationLifecycle,
2010
2523
  pricing: serializeRegistrarActionPricing(registrarAction.pricing),
2011
2524
  referral: registrarAction.referral,
2012
2525
  block: registrarAction.block,
@@ -2016,11 +2529,11 @@ function serializeRegistrarAction(registrarAction) {
2016
2529
  }
2017
2530
 
2018
2531
  // src/registrars/zod-schemas.ts
2019
- var makeSubregistrySchema = (valueLabel = "Subregistry") => z8.object({
2020
- subregistryId: makeSerializedAccountIdSchema(`${valueLabel} Subregistry ID`),
2532
+ var makeSubregistrySchema = (valueLabel = "Subregistry") => z9.object({
2533
+ subregistryId: makeAccountIdSchema(`${valueLabel} Subregistry ID`),
2021
2534
  node: makeNodeSchema(`${valueLabel} Node`)
2022
2535
  });
2023
- var makeRegistrationLifecycleSchema = (valueLabel = "Registration Lifecycle") => z8.object({
2536
+ var makeRegistrationLifecycleSchema = (valueLabel = "Registration Lifecycle") => z9.object({
2024
2537
  subregistry: makeSubregistrySchema(`${valueLabel} Subregistry`),
2025
2538
  node: makeNodeSchema(`${valueLabel} Node`),
2026
2539
  expiresAt: makeUnixTimestampSchema(`${valueLabel} Expires at`)
@@ -2036,18 +2549,18 @@ function invariant_registrarActionPricingTotalIsSumOfBaseCostAndPremium(ctx) {
2036
2549
  });
2037
2550
  }
2038
2551
  }
2039
- var makeRegistrarActionPricingSchema = (valueLabel = "Registrar Action Pricing") => z8.union([
2552
+ var makeRegistrarActionPricingSchema = (valueLabel = "Registrar Action Pricing") => z9.union([
2040
2553
  // pricing available
2041
- z8.object({
2554
+ z9.object({
2042
2555
  baseCost: makePriceEthSchema(`${valueLabel} Base Cost`),
2043
2556
  premium: makePriceEthSchema(`${valueLabel} Premium`),
2044
2557
  total: makePriceEthSchema(`${valueLabel} Total`)
2045
2558
  }).check(invariant_registrarActionPricingTotalIsSumOfBaseCostAndPremium).transform((v) => v),
2046
2559
  // pricing unknown
2047
- z8.object({
2048
- baseCost: z8.null(),
2049
- premium: z8.null(),
2050
- total: z8.null()
2560
+ z9.object({
2561
+ baseCost: z9.null(),
2562
+ premium: z9.null(),
2563
+ total: z9.null()
2051
2564
  }).transform((v) => v)
2052
2565
  ]);
2053
2566
  function invariant_registrarActionDecodedReferrerBasedOnRawReferrer(ctx) {
@@ -2070,9 +2583,9 @@ function invariant_registrarActionDecodedReferrerBasedOnRawReferrer(ctx) {
2070
2583
  });
2071
2584
  }
2072
2585
  }
2073
- var makeRegistrarActionReferralSchema = (valueLabel = "Registrar Action Referral") => z8.union([
2586
+ var makeRegistrarActionReferralSchema = (valueLabel = "Registrar Action Referral") => z9.union([
2074
2587
  // referral available
2075
- z8.object({
2588
+ z9.object({
2076
2589
  encodedReferrer: makeHexStringSchema(
2077
2590
  { bytesCount: ENCODED_REFERRER_BYTE_LENGTH },
2078
2591
  `${valueLabel} Encoded Referrer`
@@ -2080,9 +2593,9 @@ var makeRegistrarActionReferralSchema = (valueLabel = "Registrar Action Referral
2080
2593
  decodedReferrer: makeLowercaseAddressSchema(`${valueLabel} Decoded Referrer`)
2081
2594
  }).check(invariant_registrarActionDecodedReferrerBasedOnRawReferrer),
2082
2595
  // referral not applicable
2083
- z8.object({
2084
- encodedReferrer: z8.null(),
2085
- decodedReferrer: z8.null()
2596
+ z9.object({
2597
+ encodedReferrer: z9.null(),
2598
+ decodedReferrer: z9.null()
2086
2599
  })
2087
2600
  ]);
2088
2601
  function invariant_eventIdsInitialElementIsTheActionId(ctx) {
@@ -2095,9 +2608,9 @@ function invariant_eventIdsInitialElementIsTheActionId(ctx) {
2095
2608
  });
2096
2609
  }
2097
2610
  }
2098
- var EventIdSchema = z8.string().nonempty();
2099
- var EventIdsSchema = z8.array(EventIdSchema).min(1).transform((v) => v);
2100
- var makeBaseRegistrarActionSchema = (valueLabel = "Base Registrar Action") => z8.object({
2611
+ var EventIdSchema = z9.string().nonempty();
2612
+ var EventIdsSchema = z9.array(EventIdSchema).min(1).transform((v) => v);
2613
+ var makeBaseRegistrarActionSchema = (valueLabel = "Base Registrar Action") => z9.object({
2101
2614
  id: EventIdSchema,
2102
2615
  incrementalDuration: makeDurationSchema(`${valueLabel} Incremental Duration`),
2103
2616
  registrant: makeLowercaseAddressSchema(`${valueLabel} Registrant`),
@@ -2111,168 +2624,135 @@ var makeBaseRegistrarActionSchema = (valueLabel = "Base Registrar Action") => z8
2111
2624
  eventIds: EventIdsSchema
2112
2625
  }).check(invariant_eventIdsInitialElementIsTheActionId);
2113
2626
  var makeRegistrarActionRegistrationSchema = (valueLabel = "Registration ") => makeBaseRegistrarActionSchema(valueLabel).extend({
2114
- type: z8.literal(RegistrarActionTypes.Registration)
2627
+ type: z9.literal(RegistrarActionTypes.Registration)
2115
2628
  });
2116
2629
  var makeRegistrarActionRenewalSchema = (valueLabel = "Renewal") => makeBaseRegistrarActionSchema(valueLabel).extend({
2117
- type: z8.literal(RegistrarActionTypes.Renewal)
2630
+ type: z9.literal(RegistrarActionTypes.Renewal)
2118
2631
  });
2119
- var makeRegistrarActionSchema = (valueLabel = "Registrar Action") => z8.discriminatedUnion("type", [
2632
+ var makeRegistrarActionSchema = (valueLabel = "Registrar Action") => z9.discriminatedUnion("type", [
2120
2633
  makeRegistrarActionRegistrationSchema(`${valueLabel} Registration`),
2121
2634
  makeRegistrarActionRenewalSchema(`${valueLabel} Renewal`)
2122
2635
  ]);
2123
2636
 
2124
- // src/shared/config/build-rpc-urls.ts
2125
- import {
2126
- arbitrum,
2127
- arbitrumSepolia,
2128
- base,
2129
- baseSepolia,
2130
- holesky,
2131
- linea,
2132
- lineaSepolia,
2133
- mainnet,
2134
- optimism,
2135
- optimismSepolia,
2136
- scroll,
2137
- scrollSepolia,
2138
- sepolia
2139
- } from "viem/chains";
2140
-
2141
- // src/shared/config/rpc-configs-from-env.ts
2142
- import { getENSNamespace } from "@ensnode/datasources";
2143
-
2144
- // src/shared/config/validatons.ts
2145
- import { getENSRootChainId as getENSRootChainId2 } from "@ensnode/datasources";
2146
- function invariant_rpcEndpointConfigIncludesAtLeastOneHTTPProtocolURL(ctx) {
2147
- const endpoints = ctx.value;
2148
- const httpEndpoints = endpoints.filter(isHttpProtocol);
2149
- if (httpEndpoints.length < 1) {
2637
+ // src/api/shared/pagination/zod-schemas.ts
2638
+ import z10 from "zod/v4";
2639
+
2640
+ // src/api/shared/pagination/request.ts
2641
+ var RECORDS_PER_PAGE_DEFAULT = 10;
2642
+ var RECORDS_PER_PAGE_MAX = 100;
2643
+
2644
+ // src/api/shared/pagination/zod-schemas.ts
2645
+ var makeRequestPageParamsSchema = (valueLabel = "RequestPageParams") => z10.object({
2646
+ page: makePositiveIntegerSchema(`${valueLabel}.page`),
2647
+ recordsPerPage: makePositiveIntegerSchema(`${valueLabel}.recordsPerPage`).max(
2648
+ RECORDS_PER_PAGE_MAX,
2649
+ `${valueLabel}.recordsPerPage must not exceed ${RECORDS_PER_PAGE_MAX}`
2650
+ )
2651
+ });
2652
+ var makeResponsePageContextSchemaWithNoRecords = (valueLabel = "ResponsePageContextWithNoRecords") => z10.object({
2653
+ totalRecords: z10.literal(0),
2654
+ totalPages: z10.literal(1),
2655
+ hasNext: z10.literal(false),
2656
+ hasPrev: z10.literal(false),
2657
+ startIndex: z10.undefined(),
2658
+ endIndex: z10.undefined()
2659
+ }).extend(makeRequestPageParamsSchema(valueLabel).shape);
2660
+ function invariant_responsePageWithRecordsIsCorrect(ctx) {
2661
+ const { hasNext, hasPrev, recordsPerPage, page, totalRecords, startIndex, endIndex } = ctx.value;
2662
+ const expectedHasNext = page * recordsPerPage < totalRecords;
2663
+ if (hasNext !== expectedHasNext) {
2150
2664
  ctx.issues.push({
2151
2665
  code: "custom",
2152
- input: endpoints,
2153
- message: `RPC endpoint configuration for a chain must include at least one http/https protocol URL.`
2666
+ input: ctx.value,
2667
+ message: `hasNext must be equal to '${expectedHasNext ? "true" : "false"}'`
2154
2668
  });
2155
2669
  }
2156
- }
2157
- function invariant_rpcEndpointConfigIncludesAtMostOneWebSocketsProtocolURL(ctx) {
2158
- const endpoints = ctx.value;
2159
- const wsEndpoints = endpoints.filter(isWebSocketProtocol);
2160
- if (wsEndpoints.length > 1) {
2670
+ const expectedHasPrev = page > 1;
2671
+ if (hasPrev !== expectedHasPrev) {
2161
2672
  ctx.issues.push({
2162
2673
  code: "custom",
2163
- input: endpoints,
2164
- message: `RPC endpoint configuration for a chain must include at most one websocket (ws/wss) protocol URL.`
2674
+ input: ctx.value,
2675
+ message: `hasPrev must be equal to '${expectedHasPrev ? "true" : "false"}'`
2165
2676
  });
2166
2677
  }
2167
- }
2168
-
2169
- // src/shared/config/zod-schemas.ts
2170
- import { z as z9 } from "zod/v4";
2171
- import { ENSNamespaceIds as ENSNamespaceIds3 } from "@ensnode/datasources";
2172
- var DatabaseSchemaNameSchema = z9.string({
2173
- error: "DATABASE_SCHEMA is required."
2174
- }).trim().min(1, {
2175
- error: "DATABASE_SCHEMA is required and cannot be an empty string."
2176
- });
2177
- var RpcConfigSchema = z9.string().transform((val) => val.split(",")).pipe(z9.array(makeUrlSchema("RPC URL"))).check(invariant_rpcEndpointConfigIncludesAtLeastOneHTTPProtocolURL).check(invariant_rpcEndpointConfigIncludesAtMostOneWebSocketsProtocolURL);
2178
- var RpcConfigsSchema = z9.record(makeChainIdStringSchema("RPC URL"), RpcConfigSchema, {
2179
- error: "Chains configuration must be an object mapping valid chain IDs to their configs."
2180
- }).transform((records) => {
2181
- const rpcConfigs = /* @__PURE__ */ new Map();
2182
- for (const [chainIdString, rpcConfig] of Object.entries(records)) {
2183
- const httpRPCs = rpcConfig.filter(isHttpProtocol);
2184
- const websocketRPC = rpcConfig.find(isWebSocketProtocol);
2185
- rpcConfigs.set(deserializeChainId(chainIdString), {
2186
- httpRPCs,
2187
- websocketRPC
2678
+ if (endIndex < startIndex) {
2679
+ ctx.issues.push({
2680
+ code: "custom",
2681
+ input: ctx.value,
2682
+ message: `endIndex must be greater than or equal to startIndex`
2188
2683
  });
2189
2684
  }
2190
- return rpcConfigs;
2191
- });
2192
- var EnsIndexerUrlSchema = makeUrlSchema("ENSINDEXER_URL");
2193
- var ENSNamespaceSchema = z9.enum(ENSNamespaceIds3, {
2194
- error: ({ input }) => `Invalid NAMESPACE. Got '${input}', but supported ENS namespaces are: ${Object.keys(ENSNamespaceIds3).join(", ")}`
2195
- });
2196
- var PortSchema = z9.coerce.number({ error: "PORT must be a number." }).min(1, { error: "PORT must be greater than 1." }).max(65535, { error: "PORT must be less than 65535" }).optional();
2197
- var TheGraphApiKeySchema = z9.string().optional();
2198
-
2199
- // src/shared/datasources-with-resolvers.ts
2200
- import {
2201
- DatasourceNames,
2202
- maybeGetDatasource
2203
- } from "@ensnode/datasources";
2204
- var DATASOURCE_NAMES_WITH_RESOLVERS = [
2205
- DatasourceNames.ENSRoot,
2206
- DatasourceNames.Basenames,
2207
- DatasourceNames.Lineanames,
2208
- DatasourceNames.ThreeDNSOptimism,
2209
- DatasourceNames.ThreeDNSBase
2210
- ];
2211
-
2212
- // src/shared/log-level.ts
2213
- import { z as z10 } from "zod/v4";
2214
- var LogLevelSchema = z10.enum(["fatal", "error", "warn", "info", "debug", "trace", "silent"]);
2215
-
2216
- // src/shared/protocol-acceleration/interpret-record-values.ts
2217
- import { isAddress as isAddress4, isAddressEqual as isAddressEqual2, zeroAddress as zeroAddress2 } from "viem";
2685
+ if (endIndex >= totalRecords) {
2686
+ ctx.issues.push({
2687
+ code: "custom",
2688
+ input: ctx.value,
2689
+ message: `endIndex must be lower than totalRecords`
2690
+ });
2691
+ }
2692
+ }
2693
+ var makeResponsePageContextSchemaWithRecords = (valueLabel = "ResponsePageContextWithRecords") => z10.object({
2694
+ totalRecords: makePositiveIntegerSchema(`${valueLabel}.totalRecords`),
2695
+ totalPages: makePositiveIntegerSchema(`${valueLabel}.totalPages`),
2696
+ hasNext: z10.boolean(),
2697
+ hasPrev: z10.boolean(),
2698
+ startIndex: makeNonNegativeIntegerSchema(`${valueLabel}.startIndex`),
2699
+ endIndex: makeNonNegativeIntegerSchema(`${valueLabel}.endIndex`)
2700
+ }).extend(makeRequestPageParamsSchema(valueLabel).shape).check(invariant_responsePageWithRecordsIsCorrect);
2701
+ var makeResponsePageContextSchema = (valueLabel = "ResponsePageContext") => z10.union([
2702
+ makeResponsePageContextSchemaWithNoRecords(valueLabel),
2703
+ makeResponsePageContextSchemaWithRecords(valueLabel)
2704
+ ]);
2218
2705
 
2219
- // src/api/indexing-status/response.ts
2220
- var IndexingStatusResponseCodes = {
2706
+ // src/api/registrar-actions/response.ts
2707
+ var RegistrarActionsResponseCodes = {
2221
2708
  /**
2222
- * Represents that the indexing status is available.
2709
+ * Represents that Registrar Actions are available.
2223
2710
  */
2224
2711
  Ok: "ok",
2225
2712
  /**
2226
- * Represents that the indexing status is unavailable.
2713
+ * Represents that Registrar Actions are unavailable.
2227
2714
  */
2228
2715
  Error: "error"
2229
2716
  };
2230
2717
 
2231
- // src/api/indexing-status/zod-schemas.ts
2232
- var makeIndexingStatusResponseOkSchema = (valueLabel = "Indexing Status Response OK") => z11.strictObject({
2233
- responseCode: z11.literal(IndexingStatusResponseCodes.Ok),
2234
- realtimeProjection: makeRealtimeIndexingStatusProjectionSchema(valueLabel)
2718
+ // src/api/registrar-actions/zod-schemas.ts
2719
+ function invariant_registrationLifecycleNodeMatchesName(ctx) {
2720
+ const { name, action } = ctx.value;
2721
+ const expectedNode = action.registrationLifecycle.node;
2722
+ const actualNode = namehash3(name);
2723
+ if (actualNode !== expectedNode) {
2724
+ ctx.issues.push({
2725
+ code: "custom",
2726
+ input: ctx.value,
2727
+ message: `The 'action.registrationLifecycle.node' must match namehash of 'name'`
2728
+ });
2729
+ }
2730
+ }
2731
+ var makeNamedRegistrarActionSchema = (valueLabel = "Named Registrar Action") => z11.object({
2732
+ action: makeRegistrarActionSchema(valueLabel),
2733
+ name: makeReinterpretedNameSchema(valueLabel)
2734
+ }).check(invariant_registrationLifecycleNodeMatchesName);
2735
+ var makeRegistrarActionsResponseOkSchema = (valueLabel = "Registrar Actions Response OK") => z11.strictObject({
2736
+ responseCode: z11.literal(RegistrarActionsResponseCodes.Ok),
2737
+ registrarActions: z11.array(makeNamedRegistrarActionSchema(valueLabel)),
2738
+ pageContext: makeResponsePageContextSchema(`${valueLabel}.pageContext`)
2235
2739
  });
2236
- var makeIndexingStatusResponseErrorSchema = (_valueLabel = "Indexing Status Response Error") => z11.strictObject({
2237
- responseCode: z11.literal(IndexingStatusResponseCodes.Error)
2740
+ var makeRegistrarActionsResponseErrorSchema = (_valueLabel = "Registrar Actions Response Error") => z11.strictObject({
2741
+ responseCode: z11.literal(RegistrarActionsResponseCodes.Error),
2742
+ error: ErrorResponseSchema
2238
2743
  });
2239
- var makeIndexingStatusResponseSchema = (valueLabel = "Indexing Status Response") => z11.discriminatedUnion("responseCode", [
2240
- makeIndexingStatusResponseOkSchema(valueLabel),
2241
- makeIndexingStatusResponseErrorSchema(valueLabel)
2744
+ var makeRegistrarActionsResponseSchema = (valueLabel = "Registrar Actions Response") => z11.discriminatedUnion("responseCode", [
2745
+ makeRegistrarActionsResponseOkSchema(valueLabel),
2746
+ makeRegistrarActionsResponseErrorSchema(valueLabel)
2242
2747
  ]);
2243
2748
 
2244
- // src/api/indexing-status/deserialize.ts
2245
- function deserializeIndexingStatusResponse(maybeResponse) {
2246
- const parsed = makeIndexingStatusResponseSchema().safeParse(maybeResponse);
2247
- if (parsed.error) {
2248
- throw new Error(`Cannot deserialize IndexingStatusResponse:
2249
- ${prettifyError5(parsed.error)}
2250
- `);
2251
- }
2252
- return parsed.data;
2253
- }
2254
-
2255
- // src/api/indexing-status/serialize.ts
2256
- function serializeIndexingStatusResponse(response) {
2257
- switch (response.responseCode) {
2258
- case IndexingStatusResponseCodes.Ok:
2259
- return {
2260
- responseCode: response.responseCode,
2261
- realtimeProjection: serializeRealtimeIndexingStatusProjection(response.realtimeProjection)
2262
- };
2263
- case IndexingStatusResponseCodes.Error:
2264
- return response;
2265
- }
2266
- }
2267
-
2268
2749
  // src/api/registrar-actions/deserialize.ts
2269
- import { prettifyError as prettifyError6 } from "zod/v4";
2270
2750
  function deserializeRegistrarActionsResponse(maybeResponse) {
2271
2751
  const parsed = makeRegistrarActionsResponseSchema().safeParse(maybeResponse);
2272
2752
  if (parsed.error) {
2273
2753
  throw new Error(
2274
2754
  `Cannot deserialize RegistrarActionsResponse:
2275
- ${prettifyError6(parsed.error)}
2755
+ ${prettifyError8(parsed.error)}
2276
2756
  `
2277
2757
  );
2278
2758
  }
@@ -2282,7 +2762,8 @@ ${prettifyError6(parsed.error)}
2282
2762
  // src/api/registrar-actions/request.ts
2283
2763
  var RegistrarActionsFilterTypes = {
2284
2764
  BySubregistryNode: "bySubregistryNode",
2285
- WithEncodedReferral: "withEncodedReferral"
2765
+ WithEncodedReferral: "withEncodedReferral",
2766
+ ByDecodedReferrer: "byDecodedReferrer"
2286
2767
  };
2287
2768
  var RegistrarActionsOrders = {
2288
2769
  LatestRegistrarActions: "orderBy[timestamp]=desc"
@@ -2306,9 +2787,19 @@ function withReferral(withReferral2) {
2306
2787
  filterType: RegistrarActionsFilterTypes.WithEncodedReferral
2307
2788
  };
2308
2789
  }
2790
+ function byDecodedReferrer(decodedReferrer) {
2791
+ if (typeof decodedReferrer === "undefined") {
2792
+ return void 0;
2793
+ }
2794
+ return {
2795
+ filterType: RegistrarActionsFilterTypes.ByDecodedReferrer,
2796
+ value: decodedReferrer
2797
+ };
2798
+ }
2309
2799
  var registrarActionsFilter = {
2310
2800
  byParentNode,
2311
- withReferral
2801
+ withReferral,
2802
+ byDecodedReferrer
2312
2803
  };
2313
2804
 
2314
2805
  // src/api/registrar-actions/prerequisites.ts
@@ -2361,12 +2852,50 @@ var registrarActionsPrerequisites = Object.freeze({
2361
2852
  }
2362
2853
  });
2363
2854
 
2855
+ // src/registrars/basenames-subregistry.ts
2856
+ import {
2857
+ DatasourceNames as DatasourceNames2,
2858
+ ENSNamespaceIds as ENSNamespaceIds3,
2859
+ maybeGetDatasource as maybeGetDatasource2
2860
+ } from "@ensnode/datasources";
2861
+ function getBasenamesSubregistryId(namespace) {
2862
+ const datasource = maybeGetDatasource2(namespace, DatasourceNames2.Basenames);
2863
+ if (!datasource) {
2864
+ throw new Error(`Datasource not found for ${namespace} ${DatasourceNames2.Basenames}`);
2865
+ }
2866
+ const address = datasource.contracts.BaseRegistrar?.address;
2867
+ if (address === void 0 || Array.isArray(address)) {
2868
+ throw new Error(`BaseRegistrar contract not found or has multiple addresses for ${namespace}`);
2869
+ }
2870
+ return {
2871
+ chainId: datasource.chain.id,
2872
+ address
2873
+ };
2874
+ }
2875
+ function getBasenamesSubregistryManagedName(namespaceId) {
2876
+ switch (namespaceId) {
2877
+ case ENSNamespaceIds3.Mainnet:
2878
+ return "base.eth";
2879
+ case ENSNamespaceIds3.Sepolia:
2880
+ return "basetest.eth";
2881
+ case ENSNamespaceIds3.Holesky:
2882
+ case ENSNamespaceIds3.EnsTestEnv:
2883
+ throw new Error(
2884
+ `No registrar managed name is known for the 'basenames' subregistry within the "${namespaceId}" namespace.`
2885
+ );
2886
+ }
2887
+ }
2888
+
2364
2889
  // src/registrars/ethnames-subregistry.ts
2365
- import { DatasourceNames as DatasourceNames2, maybeGetDatasource as maybeGetDatasource2 } from "@ensnode/datasources";
2890
+ import {
2891
+ DatasourceNames as DatasourceNames3,
2892
+ ENSNamespaceIds as ENSNamespaceIds4,
2893
+ maybeGetDatasource as maybeGetDatasource3
2894
+ } from "@ensnode/datasources";
2366
2895
  function getEthnamesSubregistryId(namespace) {
2367
- const datasource = maybeGetDatasource2(namespace, DatasourceNames2.ENSRoot);
2896
+ const datasource = maybeGetDatasource3(namespace, DatasourceNames3.ENSRoot);
2368
2897
  if (!datasource) {
2369
- throw new Error(`Datasource not found for ${namespace} ${DatasourceNames2.ENSRoot}`);
2898
+ throw new Error(`Datasource not found for ${namespace} ${DatasourceNames3.ENSRoot}`);
2370
2899
  }
2371
2900
  const address = datasource.contracts.BaseRegistrar?.address;
2372
2901
  if (address === void 0 || Array.isArray(address)) {
@@ -2377,6 +2906,49 @@ function getEthnamesSubregistryId(namespace) {
2377
2906
  address
2378
2907
  };
2379
2908
  }
2909
+ function getEthnamesSubregistryManagedName(namespaceId) {
2910
+ switch (namespaceId) {
2911
+ case ENSNamespaceIds4.Mainnet:
2912
+ case ENSNamespaceIds4.Sepolia:
2913
+ case ENSNamespaceIds4.Holesky:
2914
+ case ENSNamespaceIds4.EnsTestEnv:
2915
+ return "eth";
2916
+ }
2917
+ }
2918
+
2919
+ // src/registrars/lineanames-subregistry.ts
2920
+ import {
2921
+ DatasourceNames as DatasourceNames4,
2922
+ ENSNamespaceIds as ENSNamespaceIds5,
2923
+ maybeGetDatasource as maybeGetDatasource4
2924
+ } from "@ensnode/datasources";
2925
+ function getLineanamesSubregistryId(namespace) {
2926
+ const datasource = maybeGetDatasource4(namespace, DatasourceNames4.Lineanames);
2927
+ if (!datasource) {
2928
+ throw new Error(`Datasource not found for ${namespace} ${DatasourceNames4.Lineanames}`);
2929
+ }
2930
+ const address = datasource.contracts.BaseRegistrar?.address;
2931
+ if (address === void 0 || Array.isArray(address)) {
2932
+ throw new Error(`BaseRegistrar contract not found or has multiple addresses for ${namespace}`);
2933
+ }
2934
+ return {
2935
+ chainId: datasource.chain.id,
2936
+ address
2937
+ };
2938
+ }
2939
+ function getLineanamesSubregistryManagedName(namespaceId) {
2940
+ switch (namespaceId) {
2941
+ case ENSNamespaceIds5.Mainnet:
2942
+ return "linea.eth";
2943
+ case ENSNamespaceIds5.Sepolia:
2944
+ return "linea-sepolia.eth";
2945
+ case ENSNamespaceIds5.Holesky:
2946
+ case ENSNamespaceIds5.EnsTestEnv:
2947
+ throw new Error(
2948
+ `No registrar managed name is known for the 'Lineanames' subregistry within the "${namespaceId}" namespace.`
2949
+ );
2950
+ }
2951
+ }
2380
2952
 
2381
2953
  // src/api/registrar-actions/serialize.ts
2382
2954
  function serializeNamedRegistrarAction({
@@ -2393,7 +2965,8 @@ function serializeRegistrarActionsResponse(response) {
2393
2965
  case RegistrarActionsResponseCodes.Ok:
2394
2966
  return {
2395
2967
  responseCode: response.responseCode,
2396
- registrarActions: response.registrarActions.map(serializeNamedRegistrarAction)
2968
+ registrarActions: response.registrarActions.map(serializeNamedRegistrarAction),
2969
+ pageContext: response.pageContext
2397
2970
  };
2398
2971
  case RegistrarActionsResponseCodes.Error:
2399
2972
  return response;
@@ -2401,17 +2974,52 @@ function serializeRegistrarActionsResponse(response) {
2401
2974
  }
2402
2975
 
2403
2976
  // src/api/shared/errors/deserialize.ts
2404
- import { prettifyError as prettifyError7 } from "zod/v4";
2977
+ import { prettifyError as prettifyError9 } from "zod/v4";
2405
2978
  function deserializeErrorResponse(maybeErrorResponse) {
2406
2979
  const parsed = ErrorResponseSchema.safeParse(maybeErrorResponse);
2407
2980
  if (parsed.error) {
2408
2981
  throw new Error(`Cannot deserialize ErrorResponse:
2409
- ${prettifyError7(parsed.error)}
2982
+ ${prettifyError9(parsed.error)}
2410
2983
  `);
2411
2984
  }
2412
2985
  return parsed.data;
2413
2986
  }
2414
2987
 
2988
+ // src/api/shared/pagination/build-page-context.ts
2989
+ function buildPageContext(page, recordsPerPage, totalRecords) {
2990
+ const totalPages = Math.max(1, Math.ceil(totalRecords / recordsPerPage));
2991
+ if (page > totalPages) {
2992
+ throw new Error(`Invalid page: page ${page} exceeds total pages ${totalPages}.`);
2993
+ }
2994
+ if (totalRecords === 0) {
2995
+ return {
2996
+ page,
2997
+ recordsPerPage,
2998
+ totalRecords: 0,
2999
+ totalPages: 1,
3000
+ hasNext: false,
3001
+ hasPrev: false,
3002
+ startIndex: void 0,
3003
+ endIndex: void 0
3004
+ };
3005
+ }
3006
+ const startIndex = (page - 1) * recordsPerPage;
3007
+ const maxTheoreticalIndexOnPage = startIndex + (recordsPerPage - 1);
3008
+ const endIndex = Math.min(maxTheoreticalIndexOnPage, totalRecords - 1);
3009
+ const hasNext = maxTheoreticalIndexOnPage < totalRecords - 1;
3010
+ const hasPrev = page > 1;
3011
+ return {
3012
+ page,
3013
+ recordsPerPage,
3014
+ totalRecords,
3015
+ totalPages,
3016
+ hasNext,
3017
+ hasPrev,
3018
+ startIndex,
3019
+ endIndex
3020
+ };
3021
+ }
3022
+
2415
3023
  // src/client-error.ts
2416
3024
  var ClientError = class _ClientError extends Error {
2417
3025
  details;
@@ -2426,7 +3034,7 @@ var ClientError = class _ClientError extends Error {
2426
3034
  };
2427
3035
 
2428
3036
  // src/ensanalytics/deserialize.ts
2429
- import { prettifyError as prettifyError8 } from "zod/v4";
3037
+ import { prettifyError as prettifyError10 } from "zod/v4";
2430
3038
 
2431
3039
  // src/ensanalytics/zod-schemas.ts
2432
3040
  import z12 from "zod/v4";
@@ -2511,9 +3119,9 @@ var makeAggregatedReferrerMetricsSchema = (valueLabel = "AggregatedReferrerMetri
2511
3119
  });
2512
3120
  var makeReferrerLeaderboardPageContextSchema = (valueLabel = "ReferrerLeaderboardPageContext") => z12.object({
2513
3121
  page: makePositiveIntegerSchema(`${valueLabel}.page`),
2514
- itemsPerPage: makePositiveIntegerSchema(`${valueLabel}.itemsPerPage`).max(
3122
+ recordsPerPage: makePositiveIntegerSchema(`${valueLabel}.recordsPerPage`).max(
2515
3123
  REFERRERS_PER_LEADERBOARD_PAGE_MAX,
2516
- `${valueLabel}.itemsPerPage must not exceed ${REFERRERS_PER_LEADERBOARD_PAGE_MAX}`
3124
+ `${valueLabel}.recordsPerPage must not exceed ${REFERRERS_PER_LEADERBOARD_PAGE_MAX}`
2517
3125
  ),
2518
3126
  totalRecords: makeNonNegativeIntegerSchema(`${valueLabel}.totalRecords`),
2519
3127
  totalPages: makePositiveIntegerSchema(`${valueLabel}.totalPages`),
@@ -2524,9 +3132,9 @@ var makeReferrerLeaderboardPageContextSchema = (valueLabel = "ReferrerLeaderboar
2524
3132
  });
2525
3133
  var makeReferrerLeaderboardPageSchema = (valueLabel = "ReferrerLeaderboardPage") => z12.object({
2526
3134
  rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),
2527
- referrers: z12.array(makeAwardedReferrerMetricsSchema(`${valueLabel}.referrers[item]`)),
3135
+ referrers: z12.array(makeAwardedReferrerMetricsSchema(`${valueLabel}.referrers[record]`)),
2528
3136
  aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),
2529
- paginationContext: makeReferrerLeaderboardPageContextSchema(`${valueLabel}.paginationContext`),
3137
+ pageContext: makeReferrerLeaderboardPageContextSchema(`${valueLabel}.pageContext`),
2530
3138
  accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`)
2531
3139
  });
2532
3140
  var makeReferrerLeaderboardPageResponseOkSchema = (valueLabel = "ReferrerLeaderboardPageResponseOk") => z12.object({
@@ -2580,7 +3188,7 @@ function deserializeReferrerLeaderboardPageResponse(maybeResponse, valueLabel) {
2580
3188
  if (parsed.error) {
2581
3189
  throw new Error(
2582
3190
  `Cannot deserialize SerializedReferrerLeaderboardPageResponse:
2583
- ${prettifyError8(parsed.error)}
3191
+ ${prettifyError10(parsed.error)}
2584
3192
  `
2585
3193
  );
2586
3194
  }
@@ -2591,7 +3199,7 @@ function deserializeReferrerDetailResponse(maybeResponse, valueLabel) {
2591
3199
  const parsed = schema.safeParse(maybeResponse);
2592
3200
  if (parsed.error) {
2593
3201
  throw new Error(`Cannot deserialize ReferrerDetailResponse:
2594
- ${prettifyError8(parsed.error)}
3202
+ ${prettifyError10(parsed.error)}
2595
3203
  `);
2596
3204
  }
2597
3205
  return parsed.data;
@@ -2859,7 +3467,7 @@ var ENSNodeClient = class _ENSNodeClient {
2859
3467
  *
2860
3468
  * @param request - Pagination parameters
2861
3469
  * @param request.page - The page number to retrieve (1-indexed, default: 1)
2862
- * @param request.itemsPerPage - Number of items per page (default: 25, max: 100)
3470
+ * @param request.recordsPerPage - Number of records per page (default: 25, max: 100)
2863
3471
  * @returns {ReferrerLeaderboardPageResponse}
2864
3472
  *
2865
3473
  * @throws if the ENSNode request fails
@@ -2868,28 +3476,28 @@ var ENSNodeClient = class _ENSNodeClient {
2868
3476
  *
2869
3477
  * @example
2870
3478
  * ```typescript
2871
- * // Get first page with default page size (25 items)
3479
+ * // Get first page with default page size (25 records)
2872
3480
  * const response = await client.getReferrerLeaderboardPage();
2873
3481
  * if (response.responseCode === ReferrerLeaderboardPageResponseCodes.Ok) {
2874
3482
  * const {
2875
3483
  * aggregatedMetrics,
2876
3484
  * referrers,
2877
3485
  * rules,
2878
- * paginationContext,
3486
+ * pageContext,
2879
3487
  * updatedAt
2880
3488
  * } = response.data;
2881
3489
  * console.log(aggregatedMetrics);
2882
3490
  * console.log(referrers);
2883
3491
  * console.log(rules);
2884
3492
  * console.log(updatedAt);
2885
- * console.log(`Page ${paginationContext.page} of ${paginationContext.totalPages}`);
3493
+ * console.log(`Page ${pageContext.page} of ${pageContext.totalPages}`);
2886
3494
  * }
2887
3495
  * ```
2888
3496
  *
2889
3497
  * @example
2890
3498
  * ```typescript
2891
- * // Get second page with 50 items per page
2892
- * const response = await client.getReferrerLeaderboardPage({ page: 2, itemsPerPage: 50 });
3499
+ * // Get second page with 50 records per page
3500
+ * const response = await client.getReferrerLeaderboardPage({ page: 2, recordsPerPage: 50 });
2893
3501
  * ```
2894
3502
  *
2895
3503
  * @example
@@ -2906,8 +3514,8 @@ var ENSNodeClient = class _ENSNodeClient {
2906
3514
  async getReferrerLeaderboardPage(request) {
2907
3515
  const url = new URL(`/ensanalytics/referrers`, this.options.url);
2908
3516
  if (request?.page) url.searchParams.set("page", request.page.toString());
2909
- if (request?.itemsPerPage)
2910
- url.searchParams.set("itemsPerPage", request.itemsPerPage.toString());
3517
+ if (request?.recordsPerPage)
3518
+ url.searchParams.set("recordsPerPage", request.recordsPerPage.toString());
2911
3519
  const response = await fetch(url);
2912
3520
  let responseData;
2913
3521
  try {
@@ -3012,11 +3620,13 @@ var ENSNodeClient = class _ENSNodeClient {
3012
3620
  /**
3013
3621
  * Fetch ENSNode Registrar Actions
3014
3622
  *
3015
- * @param {RegistrarActionsRequestFilter} request.filter is
3016
- * an optional request filter configuration.
3017
- * @param {number} request.limit sets the maximum count of results in the response.
3018
- * @param {RegistrarActionsRequestOrder} request.order sets the order of
3019
- * results in the response by field and direction.
3623
+ * Retrieves a paginated list of registrar actions with optional filters.
3624
+ *
3625
+ * @param request is a request configuration.
3626
+ * @param request.page sets the page number to retrieve (1-indexed, default: 1)
3627
+ * @param request.recordsPerPage sets the number of records per page (default: 10, max: 100)
3628
+ * @param request.filters is an optional request filter configuration.
3629
+ * @param request.order sets the order of results in the response by field and direction.
3020
3630
  * @returns {RegistrarActionsResponse}
3021
3631
  *
3022
3632
  * @throws if the ENSNode request fails
@@ -3026,23 +3636,25 @@ var ENSNodeClient = class _ENSNodeClient {
3026
3636
  * @example
3027
3637
  * ```ts
3028
3638
  * import {
3029
- * registrarActionsFilter,,
3639
+ * registrarActionsFilter,
3030
3640
  * ENSNodeClient,
3031
3641
  * } from "@ensnode/ensnode-sdk";
3032
3642
  * import { namehash } from "viem/ens";
3033
3643
  *
3034
3644
  * const client: ENSNodeClient;
3035
3645
  *
3036
- * // get latest registrar action records across all indexed subregistries
3037
- * // NOTE: when no `limit` value is passed,
3038
- * // the default RESPONSE_ITEMS_PER_PAGE_DEFAULT applies.
3039
- * const registrarActions = await client.registrarActions();
3646
+ * // Get first page with default page size (10 records)
3647
+ * const response = await client.registrarActions();
3648
+ * if (response.responseCode === RegistrarActionsResponseCodes.Ok) {
3649
+ * const { registrarActions, pageContext } = response;
3650
+ * console.log(registrarActions);
3651
+ * console.log(`Page ${pageContext.page} of ${pageContext.totalPages}`);
3652
+ * }
3040
3653
  *
3041
- * // get latest 5 registrar action records across all indexed subregistries
3042
- * // NOTE: when a `limit` value is passed, it must be lower than or equal to
3043
- * // the RESPONSE_ITEMS_PER_PAGE_MAX value.
3044
- * const registrarActions = await client.registrarActions({
3045
- * limit: 5,
3654
+ * // Get second page with 25 records per page
3655
+ * const response = await client.registrarActions({
3656
+ * page: 2,
3657
+ * recordsPerPage: 25,
3046
3658
  * });
3047
3659
  *
3048
3660
  * // get latest registrar action records associated with
@@ -3056,11 +3668,16 @@ var ENSNodeClient = class _ENSNodeClient {
3056
3668
  * filters: [registrarActionsFilter.withReferral(true)],
3057
3669
  * });
3058
3670
  *
3671
+ * // get latest registrar action records for a specific decoded referrer
3672
+ * await client.registrarActions({
3673
+ * filters: [registrarActionsFilter.byDecodedReferrer("0x1234567890123456789012345678901234567890")],
3674
+ * });
3675
+ *
3059
3676
  * // get latest 10 registrar action records associated with
3060
3677
  * // subregistry managing `base.eth` name
3061
3678
  * await client.registrarActions({
3062
3679
  * filters: [registrarActionsFilter.byParentNode(namehash('base.eth'))],
3063
- * limit: 10
3680
+ * recordsPerPage: 10
3064
3681
  * });
3065
3682
  * ```
3066
3683
  */
@@ -3077,6 +3694,12 @@ var ENSNodeClient = class _ENSNodeClient {
3077
3694
  );
3078
3695
  return withReferralFilter ? { key: "withReferral", value: "true" } : null;
3079
3696
  };
3697
+ const buildDecodedReferrerArg = (filters) => {
3698
+ const decodedReferrerFilter = filters?.find(
3699
+ (f) => f.filterType === RegistrarActionsFilterTypes.ByDecodedReferrer
3700
+ );
3701
+ return decodedReferrerFilter ? { key: "decodedReferrer", value: decodedReferrerFilter.value } : null;
3702
+ };
3080
3703
  const buildOrderArg = (order) => {
3081
3704
  switch (order) {
3082
3705
  case RegistrarActionsOrders.LatestRegistrarActions: {
@@ -3093,13 +3716,76 @@ var ENSNodeClient = class _ENSNodeClient {
3093
3716
  const orderArgs = buildOrderArg(request.order);
3094
3717
  url.searchParams.set(orderArgs.key, orderArgs.value);
3095
3718
  }
3096
- if (request.itemsPerPage) {
3097
- url.searchParams.set("itemsPerPage", request.itemsPerPage.toString());
3719
+ if (request.page) {
3720
+ url.searchParams.set("page", request.page.toString());
3721
+ }
3722
+ if (request.recordsPerPage) {
3723
+ url.searchParams.set("recordsPerPage", request.recordsPerPage.toString());
3098
3724
  }
3099
3725
  const referralArg = buildWithReferralArg(request.filters);
3100
3726
  if (referralArg) {
3101
3727
  url.searchParams.set(referralArg.key, referralArg.value);
3102
3728
  }
3729
+ const decodedReferrerArg = buildDecodedReferrerArg(request.filters);
3730
+ if (decodedReferrerArg) {
3731
+ url.searchParams.set(decodedReferrerArg.key, decodedReferrerArg.value);
3732
+ }
3733
+ const response = await fetch(url);
3734
+ let responseData;
3735
+ try {
3736
+ responseData = await response.json();
3737
+ } catch {
3738
+ throw new Error("Malformed response data: invalid JSON");
3739
+ }
3740
+ if (!response.ok) {
3741
+ let errorResponse;
3742
+ try {
3743
+ errorResponse = deserializeErrorResponse(responseData);
3744
+ } catch {
3745
+ console.log("Registrar Actions API: handling a known server error.");
3746
+ }
3747
+ if (typeof errorResponse !== "undefined") {
3748
+ throw new Error(`Fetching ENSNode Registrar Actions Failed: ${errorResponse.message}`);
3749
+ }
3750
+ }
3751
+ return deserializeRegistrarActionsResponse(responseData);
3752
+ }
3753
+ /**
3754
+ * Fetch Name Tokens for requested name.
3755
+ *
3756
+ * @param request.name - Name for which Name Tokens will be fetched.
3757
+ * @returns {NameTokensResponse}
3758
+ *
3759
+ * @throws if the ENSNode request fails
3760
+ * @throws if the ENSNode API returns an error response
3761
+ * @throws if the ENSNode response breaks required invariants
3762
+ *
3763
+ * @example
3764
+ * ```ts
3765
+ * import {
3766
+ * ENSNodeClient,
3767
+ * } from "@ensnode/ensnode-sdk";
3768
+ * import { namehash } from "viem/ens";
3769
+ *
3770
+ * const client: ENSNodeClient;
3771
+ *
3772
+ * // get latest name token records from the indexed subregistry based on the requested name
3773
+ * const response = await client.nameTokens({
3774
+ * name: "vitalik.eth"
3775
+ * });
3776
+ *
3777
+ * const response = await client.nameTokens({
3778
+ * domainId: "0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835" // namehash('vitalik.eth')
3779
+ * })
3780
+ * ```
3781
+ */
3782
+ async nameTokens(request) {
3783
+ const url = new URL(`/api/name-tokens`, this.options.url);
3784
+ if (request.name !== void 0) {
3785
+ url.searchParams.set("name", request.name);
3786
+ } else {
3787
+ url.searchParams.set("domainId", request.domainId);
3788
+ }
3103
3789
  const response = await fetch(url);
3104
3790
  let responseData;
3105
3791
  try {
@@ -3112,18 +3798,18 @@ var ENSNodeClient = class _ENSNodeClient {
3112
3798
  try {
3113
3799
  errorResponse = deserializeErrorResponse(responseData);
3114
3800
  } catch {
3115
- console.log("Registrar Actions API: handling a known server error.");
3801
+ console.log("Name Tokens API: handling a known server error.");
3116
3802
  }
3117
3803
  if (typeof errorResponse !== "undefined") {
3118
- throw new Error(`Fetching ENSNode Registrar Actions Failed: ${errorResponse.message}`);
3804
+ throw new Error(`Fetching ENSNode Name Tokens Failed: ${errorResponse.message}`);
3119
3805
  }
3120
3806
  }
3121
- return deserializeRegistrarActionsResponse(responseData);
3807
+ return deserializedNameTokensResponse(responseData);
3122
3808
  }
3123
3809
  };
3124
3810
 
3125
3811
  // src/identity/identity.ts
3126
- import { getENSRootChainId as getENSRootChainId3 } from "@ensnode/datasources";
3812
+ import { getENSRootChainId as getENSRootChainId2 } from "@ensnode/datasources";
3127
3813
 
3128
3814
  // src/identity/types.ts
3129
3815
  var ResolutionStatusIds = {
@@ -3150,7 +3836,7 @@ var ResolutionStatusIds = {
3150
3836
  function buildUnresolvedIdentity(address, namespaceId, chainId) {
3151
3837
  return {
3152
3838
  resolutionStatus: ResolutionStatusIds.Unresolved,
3153
- chainId: chainId ?? getENSRootChainId3(namespaceId),
3839
+ chainId: chainId ?? getENSRootChainId2(namespaceId),
3154
3840
  address
3155
3841
  };
3156
3842
  }
@@ -3159,245 +3845,24 @@ function isResolvedIdentity(identity) {
3159
3845
  }
3160
3846
 
3161
3847
  // src/resolution/ensip19-chainid.ts
3162
- import { mainnet as mainnet2 } from "viem/chains";
3163
- import { getENSRootChainId as getENSRootChainId4 } from "@ensnode/datasources";
3848
+ import { mainnet } from "viem/chains";
3849
+ import { getENSRootChainId as getENSRootChainId3 } from "@ensnode/datasources";
3164
3850
  var getResolvePrimaryNameChainIdParam = (chainId, namespaceId) => {
3165
- const ensRootChainId = getENSRootChainId4(namespaceId);
3166
- return chainId === ensRootChainId ? mainnet2.id : chainId;
3851
+ const ensRootChainId = getENSRootChainId3(namespaceId);
3852
+ return chainId === ensRootChainId ? mainnet.id : chainId;
3167
3853
  };
3168
3854
  var translateDefaultableChainIdToChainId = (chainId, namespaceId) => {
3169
- return chainId === DEFAULT_EVM_CHAIN_ID ? getENSRootChainId4(namespaceId) : chainId;
3855
+ return chainId === DEFAULT_EVM_CHAIN_ID ? getENSRootChainId3(namespaceId) : chainId;
3170
3856
  };
3171
3857
 
3172
3858
  // src/resolution/resolver-records-selection.ts
3173
3859
  var isSelectionEmpty = (selection) => !selection.name && !selection.addresses?.length && !selection.texts?.length;
3174
3860
 
3175
- // src/tokenscope/assets.ts
3176
- import { AssetId as CaipAssetId } from "caip";
3177
- import { isAddressEqual as isAddressEqual3, zeroAddress as zeroAddress3 } from "viem";
3178
- var AssetNamespaces = {
3179
- ERC721: "erc721",
3180
- ERC1155: "erc1155"
3181
- };
3182
- function serializeAssetId(assetId) {
3183
- const { assetNamespace, contract, tokenId } = assetId;
3184
- return CaipAssetId.format({
3185
- chainId: { namespace: "eip155", reference: contract.chainId.toString() },
3186
- assetName: { namespace: assetNamespace, reference: contract.address },
3187
- tokenId: uint256ToHex32(tokenId)
3188
- }).toLowerCase();
3189
- }
3190
- var buildAssetId = (contract, tokenId, assetNamespace) => {
3191
- return {
3192
- assetNamespace,
3193
- contract,
3194
- tokenId
3195
- };
3196
- };
3197
- var NFTMintStatuses = {
3198
- Minted: "minted",
3199
- Burned: "burned"
3200
- };
3201
- var formatNFTTransferEventMetadata = (metadata) => {
3202
- const serializedAssetId = serializeAssetId(metadata.nft);
3203
- return [
3204
- `Event: ${metadata.eventHandlerName}`,
3205
- `Chain ID: ${metadata.chainId}`,
3206
- `Block Number: ${metadata.blockNumber}`,
3207
- `Transaction Hash: ${metadata.transactionHash}`,
3208
- `NFT: ${serializedAssetId}`
3209
- ].map((line) => ` - ${line}`).join("\n");
3210
- };
3211
- var NFTTransferTypes = {
3212
- /**
3213
- * Initial transfer from zeroAddress to a non-zeroAddress
3214
- * Can happen at most once to a NFT AssetId
3215
- *
3216
- * Invariants:
3217
- * - NFT is not indexed and therefore has no previous mint status or owner
3218
- * - new NFT mint status is `minted`
3219
- * - new NFT owner is a non-zeroAddress
3220
- */
3221
- Mint: "mint",
3222
- /**
3223
- * Subsequent transfer from zeroAddress to a non-zeroAddress
3224
- * Can happen any number of times to a NFT AssetId as it passes in a cycle from
3225
- * mint -> burn -> remint -> burn -> remint -> ...
3226
- *
3227
- * Invariants:
3228
- * - NFT is indexed
3229
- * - previous NFT mint status was `burned`
3230
- * - previous NFT owner is the zeroAddress
3231
- * - new NFT mint status is `minted`
3232
- * - new NFT owner is a non-zeroAddress
3233
- */
3234
- Remint: "remint",
3235
- /**
3236
- * Special transfer type for improperly implemented NFT contracts that allow a NFT
3237
- * that is currently minted to be reminted before an intermediate burn.
3238
- *
3239
- * Transfer from zeroAddress to non-zeroAddress for an indexed NFT where the
3240
- * previously indexed nft had status `minted` with a non-zeroAddress owner.
3241
- *
3242
- * Invariants:
3243
- * - NFT is indexed
3244
- * - previous NFT mint status was `minted`
3245
- * - previous NFT owner was a non-zeroAddress
3246
- * - new NFT mint status is `minted`
3247
- * - new NFT owner is a non-zeroAddress
3248
- */
3249
- MintedRemint: "minted-remint",
3250
- /**
3251
- * Transfer from a non-zeroAddress to zeroAddress
3252
- *
3253
- * Invariants:
3254
- * - NFT is indexed
3255
- * - previous NFT mint status was `minted`
3256
- * - previous NFT owner is a non-zeroAddress
3257
- * - new NFT mint status is `burned`
3258
- * - new NFT owner is the zeroAddress
3259
- */
3260
- Burn: "burn",
3261
- /**
3262
- * Transfer from a non-zeroAddress to a distinct non-zeroAddress
3263
- *
3264
- * Invariants:
3265
- * - NFT is indexed
3266
- * - previous and new NFT mint status is `minted`
3267
- * - previous and new NFT owner are distinct non-zeroAddress
3268
- */
3269
- Transfer: "transfer",
3270
- /**
3271
- * Transfer from a non-zeroAddress to the same non-zeroAddress
3272
- *
3273
- * Invariants:
3274
- * - NFT is indexed
3275
- * - previous and new NFT mint status is `minted`
3276
- * - previous and new NFT owner are equivalent non-zeroAddress
3277
- */
3278
- SelfTransfer: "self-transfer",
3279
- /**
3280
- * Transfer from zeroAddress to zeroAddress for an indexed NFT
3281
- *
3282
- * Invariants:
3283
- * - NFT is indexed
3284
- * - previous and new NFT mint status is `burned`
3285
- * - previous and new NFT owner are zeroAddress
3286
- */
3287
- RemintBurn: "remint-burn",
3288
- /**
3289
- * Special transfer type for improperly implemented NFT contracts that allow a NFT
3290
- * that is currently minted to be reminted again before an intermediate burn.
3291
- *
3292
- * Transfer from zeroAddress to zeroAddress for an indexed NFT where the
3293
- * previously indexed nft had status `minted` with a non-zeroAddress owner.
3294
- *
3295
- * Invariants:
3296
- * - NFT is indexed
3297
- * - previous NFT mint status was `minted`
3298
- * - previous NFT owner was a non-zeroAddress
3299
- * - new NFT mint status is `burned`
3300
- * - new NFT owner is the zeroAddress
3301
- */
3302
- MintedRemintBurn: "minted-remint-burn",
3303
- /**
3304
- * Transfer from zeroAddress to zeroAddress for an unindexed NFT
3305
- *
3306
- * Invariants:
3307
- * - NFT is not indexed and therefore has no previous mint status or owner
3308
- * - NFT should remain unindexed and without any mint status or owner
3309
- */
3310
- MintBurn: "mint-burn"
3311
- };
3312
- var getNFTTransferType = (from, to, allowMintedRemint, metadata, currentlyIndexedOwner) => {
3313
- const isIndexed = currentlyIndexedOwner !== void 0;
3314
- const isIndexedAsMinted = isIndexed && !isAddressEqual3(currentlyIndexedOwner, zeroAddress3);
3315
- const isMint = isAddressEqual3(from, zeroAddress3);
3316
- const isBurn = isAddressEqual3(to, zeroAddress3);
3317
- const isSelfTransfer = isAddressEqual3(from, to);
3318
- if (isIndexed && !isAddressEqual3(currentlyIndexedOwner, from)) {
3319
- if (isMint && allowMintedRemint) {
3320
- } else {
3321
- throw new Error(
3322
- `Error: Sending from ${from} conflicts with currently indexed owner ${currentlyIndexedOwner}.
3323
- ${formatNFTTransferEventMetadata(metadata)}`
3324
- );
3325
- }
3326
- }
3327
- if (isSelfTransfer) {
3328
- if (isMint) {
3329
- if (!isIndexed) {
3330
- return NFTTransferTypes.MintBurn;
3331
- } else if (!isIndexedAsMinted) {
3332
- return NFTTransferTypes.RemintBurn;
3333
- } else if (allowMintedRemint) {
3334
- return NFTTransferTypes.MintedRemintBurn;
3335
- } else {
3336
- throw new Error(
3337
- `Error: Invalid state transition from minted -> remint-burn
3338
- ${formatNFTTransferEventMetadata(metadata)}`
3339
- );
3340
- }
3341
- } else {
3342
- if (!isIndexed) {
3343
- throw new Error(
3344
- `Error: Invalid state transition from unindexed -> self-transfer
3345
- ${formatNFTTransferEventMetadata(metadata)}`
3346
- );
3347
- } else if (!isIndexedAsMinted) {
3348
- throw new Error(
3349
- `Error: invalid state transition from burned -> self-transfer
3350
- ${formatNFTTransferEventMetadata(metadata)}`
3351
- );
3352
- } else {
3353
- return NFTTransferTypes.SelfTransfer;
3354
- }
3355
- }
3356
- } else if (isMint) {
3357
- if (!isIndexed) {
3358
- return NFTTransferTypes.Mint;
3359
- } else if (!isIndexedAsMinted) {
3360
- return NFTTransferTypes.Remint;
3361
- } else if (allowMintedRemint) {
3362
- return NFTTransferTypes.MintedRemint;
3363
- } else {
3364
- throw new Error(
3365
- `Error: Invalid state transition from minted -> mint
3366
- ${formatNFTTransferEventMetadata(metadata)}`
3367
- );
3368
- }
3369
- } else if (isBurn) {
3370
- if (!isIndexed) {
3371
- throw new Error(
3372
- `Error: Invalid state transition from unindexed -> burn
3373
- ${formatNFTTransferEventMetadata(metadata)}`
3374
- );
3375
- } else if (!isIndexedAsMinted) {
3376
- throw new Error(
3377
- `Error: Invalid state transition from burned -> burn
3378
- ${formatNFTTransferEventMetadata(metadata)}`
3379
- );
3380
- } else {
3381
- return NFTTransferTypes.Burn;
3382
- }
3383
- } else {
3384
- if (!isIndexed) {
3385
- throw new Error(
3386
- `Error: Invalid state transition from unindexed -> transfer
3387
- ${formatNFTTransferEventMetadata(metadata)}`
3388
- );
3389
- } else if (!isIndexedAsMinted) {
3390
- throw new Error(
3391
- `Error: Invalid state transition from burned -> transfer
3392
- ${formatNFTTransferEventMetadata(metadata)}`
3393
- );
3394
- } else {
3395
- return NFTTransferTypes.Transfer;
3396
- }
3397
- }
3398
- };
3399
-
3400
- // src/tracing/index.ts
3861
+ // src/tracing/ens-protocol-tracing.ts
3862
+ var PROTOCOL_ATTRIBUTE_PREFIX = "ens";
3863
+ var ATTR_PROTOCOL_NAME = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol`;
3864
+ var ATTR_PROTOCOL_STEP = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol.step`;
3865
+ var ATTR_PROTOCOL_STEP_RESULT = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol.step.result`;
3401
3866
  var TraceableENSProtocol = /* @__PURE__ */ ((TraceableENSProtocol2) => {
3402
3867
  TraceableENSProtocol2["ForwardResolution"] = "forward-resolution";
3403
3868
  TraceableENSProtocol2["ReverseResolution"] = "reverse-resolution";
@@ -3422,10 +3887,6 @@ var ReverseResolutionProtocolStep = /* @__PURE__ */ ((ReverseResolutionProtocolS
3422
3887
  ReverseResolutionProtocolStep2["VerifyResolvedAddressMatchesAddress"] = "verify-resolved-address-matches-address";
3423
3888
  return ReverseResolutionProtocolStep2;
3424
3889
  })(ReverseResolutionProtocolStep || {});
3425
- var PROTOCOL_ATTRIBUTE_PREFIX = "ens";
3426
- var ATTR_PROTOCOL_NAME = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol`;
3427
- var ATTR_PROTOCOL_STEP = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol.step`;
3428
- var ATTR_PROTOCOL_STEP_RESULT = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol.step.result`;
3429
3890
  export {
3430
3891
  ADDR_REVERSE_NODE,
3431
3892
  ATTR_PROTOCOL_NAME,
@@ -3442,6 +3903,7 @@ export {
3442
3903
  DEFAULT_EVM_COIN_TYPE,
3443
3904
  ENSNamespaceIds,
3444
3905
  ENSNodeClient,
3906
+ ENS_ROOT,
3445
3907
  ETH_COIN_TYPE,
3446
3908
  ETH_NODE,
3447
3909
  ForwardResolutionProtocolStep,
@@ -3450,6 +3912,9 @@ export {
3450
3912
  LruCache,
3451
3913
  NFTMintStatuses,
3452
3914
  NFTTransferTypes,
3915
+ NameTokenOwnershipTypes,
3916
+ NameTokensResponseCodes,
3917
+ NameTokensResponseErrorCodes,
3453
3918
  OmnichainIndexingStatusIds,
3454
3919
  PROTOCOL_ATTRIBUTE_PREFIX,
3455
3920
  PluginName,
@@ -3482,6 +3947,7 @@ export {
3482
3947
  buildEnsRainbowClientLabelSet,
3483
3948
  buildLabelSetId,
3484
3949
  buildLabelSetVersion,
3950
+ buildPageContext,
3485
3951
  buildUnresolvedIdentity,
3486
3952
  checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill,
3487
3953
  checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted,
@@ -3494,7 +3960,7 @@ export {
3494
3960
  decodeDNSEncodedLiteralName,
3495
3961
  decodeDNSEncodedName,
3496
3962
  decodeEncodedReferrer,
3497
- deserializeAccountId,
3963
+ deserializeAssetId,
3498
3964
  deserializeBlockNumber,
3499
3965
  deserializeBlockRef,
3500
3966
  deserializeBlockrange,
@@ -3515,18 +3981,30 @@ export {
3515
3981
  deserializeRegistrarActionsResponse,
3516
3982
  deserializeUnixTimestamp,
3517
3983
  deserializeUrl,
3984
+ deserializedNameTokensResponse,
3518
3985
  durationBetween,
3519
3986
  encodeLabelHash,
3520
3987
  evmChainIdToCoinType,
3988
+ formatAccountId,
3989
+ formatAssetId,
3521
3990
  formatNFTTransferEventMetadata,
3991
+ getBasenamesSubregistryId,
3992
+ getBasenamesSubregistryManagedName,
3522
3993
  getCurrencyInfo,
3994
+ getDatasourceContract,
3523
3995
  getENSRootChainId,
3524
3996
  getEthnamesSubregistryId,
3997
+ getEthnamesSubregistryManagedName,
3525
3998
  getLatestIndexedBlockRef,
3999
+ getLineanamesSubregistryId,
4000
+ getLineanamesSubregistryManagedName,
3526
4001
  getNFTTransferType,
3527
4002
  getNameHierarchy,
4003
+ getNameTokenOwnership,
4004
+ getNameWrapperAccounts,
3528
4005
  getOmnichainIndexingCursor,
3529
4006
  getOmnichainIndexingStatus,
4007
+ getParentNameFQDN,
3530
4008
  getResolvePrimaryNameChainIdParam,
3531
4009
  getTimestampForHighestOmnichainKnownBlock,
3532
4010
  getTimestampForLowestOmnichainStartBlock,
@@ -3552,6 +4030,10 @@ export {
3552
4030
  literalLabelsToLiteralName,
3553
4031
  makeENSApiPublicConfigSchema,
3554
4032
  makeSubdomainNode,
4033
+ maybeGetDatasourceContract,
4034
+ nameTokensPrerequisites,
4035
+ parseAccountId,
4036
+ parseAssetId,
3555
4037
  parseNonNegativeInteger,
3556
4038
  parseReverseName,
3557
4039
  priceDai,
@@ -3560,17 +4042,19 @@ export {
3560
4042
  registrarActionsFilter,
3561
4043
  registrarActionsPrerequisites,
3562
4044
  reverseName,
3563
- serializeAccountId,
3564
4045
  serializeAssetId,
3565
4046
  serializeChainId,
3566
4047
  serializeChainIndexingSnapshots,
3567
4048
  serializeConfigResponse,
3568
4049
  serializeCrossChainIndexingStatusSnapshotOmnichain,
3569
4050
  serializeDatetime,
4051
+ serializeDomainAssetId,
3570
4052
  serializeENSApiPublicConfig,
3571
4053
  serializeENSIndexerPublicConfig,
3572
4054
  serializeIndexedChainIds,
3573
4055
  serializeIndexingStatusResponse,
4056
+ serializeNameToken,
4057
+ serializeNameTokensResponse,
3574
4058
  serializeNamedRegistrarAction,
3575
4059
  serializeOmnichainIndexingStatusSnapshot,
3576
4060
  serializePrice,
@@ -3578,11 +4062,10 @@ export {
3578
4062
  serializeRealtimeIndexingStatusProjection,
3579
4063
  serializeReferrerDetailResponse,
3580
4064
  serializeReferrerLeaderboardPageResponse,
4065
+ serializeRegisteredNameTokens,
3581
4066
  serializeRegistrarAction,
3582
4067
  serializeRegistrarActionPricing,
3583
4068
  serializeRegistrarActionsResponse,
3584
- serializeRegistrationLifecycle,
3585
- serializeSubregistry,
3586
4069
  serializeUrl,
3587
4070
  sortChainStatusesByStartBlockAsc,
3588
4071
  stripNullBytes,