From 38cbacefe76f016e0c0b4aec1fec391da6117738 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Tue, 24 Jun 2025 11:54:10 +0200 Subject: [PATCH 1/2] refactor(datasources): define ENSNamespaceId enum --- .../indexing-status/view-models.test.ts | 7 ++++--- apps/ensindexer/src/config/config.schema.ts | 6 +++--- apps/ensindexer/src/config/types.ts | 4 ++-- apps/ensindexer/src/lib/lib-config.ts | 3 ++- apps/ensindexer/src/lib/plugin-helpers.ts | 4 +++- .../basenames/lib/registrar-helpers.ts | 1 + .../lineanames/lib/registrar-helpers.ts | 1 + apps/ensindexer/test/dns-helpers.test.ts | 4 ++-- packages/datasources/src/lib/types.ts | 19 +++++++------------ 9 files changed, 25 insertions(+), 24 deletions(-) diff --git a/apps/ensadmin/src/components/indexing-status/view-models.test.ts b/apps/ensadmin/src/components/indexing-status/view-models.test.ts index eedc21dd2..e23474f09 100644 --- a/apps/ensadmin/src/components/indexing-status/view-models.test.ts +++ b/apps/ensadmin/src/components/indexing-status/view-models.test.ts @@ -1,3 +1,4 @@ +import { ENSNamespaceId } from "@ensnode/datasources"; import { PluginName } from "@ensnode/ensnode-sdk"; import { fromUnixTime } from "date-fns"; import { base, mainnet } from "viem/chains"; @@ -32,12 +33,12 @@ describe("View Models", () => { const result = ensNodeEnvViewModel({ ACTIVE_PLUGINS: [PluginName.Subgraph], DATABASE_SCHEMA: "public", - NAMESPACE: "ens-test-env", + NAMESPACE: ENSNamespaceId.EnsTestEnv, }); expect(result).toEqual([ { label: "Active Plugins", value: [PluginName.Subgraph] }, - { label: "ENS Namespace", value: "ens-test-env" }, + { label: "ENS Namespace", value: ENSNamespaceId.EnsTestEnv }, { label: "Database Schema", value: "public" }, ]); }); @@ -50,7 +51,7 @@ describe("View Models", () => { const mainnetStatus = ensNodeNetworkStatus[mainnet.id]; const baseStatus = ensNodeNetworkStatus[base.id]; - expect(globalIndexingStatusViewModel(ensNodeNetworkStatus, "mainnet")).toEqual({ + expect(globalIndexingStatusViewModel(ensNodeNetworkStatus, ENSNamespaceId.Mainnet)).toEqual({ networkStatuses: [ { name: "Ethereum", diff --git a/apps/ensindexer/src/config/config.schema.ts b/apps/ensindexer/src/config/config.schema.ts index 0d64e029e..ff8e61ff9 100644 --- a/apps/ensindexer/src/config/config.schema.ts +++ b/apps/ensindexer/src/config/config.schema.ts @@ -18,7 +18,7 @@ import { DEFAULT_RPC_RATE_LIMIT, } from "@/lib/lib-config"; import { uniq } from "@/lib/lib-helpers"; -import { ENSNamespaceIds } from "@ensnode/datasources"; +import { ENSNamespaceId } from "@ensnode/datasources"; import { PluginName } from "@ensnode/ensnode-sdk"; const chainIdSchema = z.number().int().min(1); @@ -56,9 +56,9 @@ const RpcConfigSchema = z.object({ }); const ENSNamespaceSchema = z - .enum(ENSNamespaceIds, { + .enum(ENSNamespaceId, { error: (issue) => { - return `Invalid NAMESPACE. Supported ENS namespaces are: ${Object.keys(ENSNamespaceIds).join(", ")}`; + return `Invalid NAMESPACE. Supported ENS namespaces are: ${Object.keys(ENSNamespaceId).join(", ")}`; }, }) .default(DEFAULT_NAMESPACE); diff --git a/apps/ensindexer/src/config/types.ts b/apps/ensindexer/src/config/types.ts index 5a03dddea..939b1717d 100644 --- a/apps/ensindexer/src/config/types.ts +++ b/apps/ensindexer/src/config/types.ts @@ -1,5 +1,5 @@ import { Blockrange } from "@/lib/types"; -import type { ENSNamespaceId, ENSNamespaceIds } from "@ensnode/datasources"; +import type { ENSNamespaceId } from "@ensnode/datasources"; import type { PluginName } from "@ensnode/ensnode-sdk"; /** @@ -32,7 +32,7 @@ export interface ENSIndexerConfig { /** * The ENS namespace that ENSNode operates in the context of, defaulting to 'mainnet' (DEFAULT_NAMESPACE). * - * See {@link ENSNamespaceIds} for available namespace identifiers. + * See {@link ENSNamespaceId} for available namespace identifiers. */ namespace: ENSNamespaceId; diff --git a/apps/ensindexer/src/lib/lib-config.ts b/apps/ensindexer/src/lib/lib-config.ts index eb1a9496a..1ae48ab52 100644 --- a/apps/ensindexer/src/lib/lib-config.ts +++ b/apps/ensindexer/src/lib/lib-config.ts @@ -1,11 +1,12 @@ import type { ENSIndexerConfig, RpcConfigEnvironment } from "@/config/types"; +import { ENSNamespaceId } from "@ensnode/datasources"; export const DEFAULT_RPC_RATE_LIMIT = 500; export const DEFAULT_ENSADMIN_URL = "https://admin.ensnode.io"; export const DEFAULT_PORT = 42069; export const DEFAULT_HEAL_REVERSE_ADDRESSES = true; export const DEFAULT_INDEX_ADDITIONAL_RESOLVER_RECORDS = true; -export const DEFAULT_NAMESPACE = "mainnet"; +export const DEFAULT_NAMESPACE = ENSNamespaceId.Mainnet; /** * Extracts dynamic chain configuration from environment variables. diff --git a/apps/ensindexer/src/lib/plugin-helpers.ts b/apps/ensindexer/src/lib/plugin-helpers.ts index 10c51d5b9..724e80b99 100644 --- a/apps/ensindexer/src/lib/plugin-helpers.ts +++ b/apps/ensindexer/src/lib/plugin-helpers.ts @@ -205,7 +205,9 @@ export function parseLabelAndNameFromOnChainMetadata(uri: string): [Label, Name] * those plugins pass the typechecker. ENSNode ensures that non-active plugins are not executed, * so the issue of type/value mismatch does not occur during execution. */ -type ENSNamespaceFullyDefinedAtCompileTime = ReturnType>; +type ENSNamespaceFullyDefinedAtCompileTime = ReturnType< + typeof getENSNamespace +>; /** * Returns the ENSNamespace for the provided `namespaceId`, cast to ENSNamespaceFullyDefinedAtCompileTime. diff --git a/apps/ensindexer/src/plugins/basenames/lib/registrar-helpers.ts b/apps/ensindexer/src/plugins/basenames/lib/registrar-helpers.ts index aa1ea52b4..830e99aca 100644 --- a/apps/ensindexer/src/plugins/basenames/lib/registrar-helpers.ts +++ b/apps/ensindexer/src/plugins/basenames/lib/registrar-helpers.ts @@ -17,6 +17,7 @@ export function getRegistrarManagedName(namespaceId: ENSNamespaceId): RegistrarM return "basetest.eth"; case "holesky": case "ens-test-env": + default: throw new Error( `No registrar managed name is known for the Basenames plugin within the "${namespaceId}" namespace.`, ); diff --git a/apps/ensindexer/src/plugins/lineanames/lib/registrar-helpers.ts b/apps/ensindexer/src/plugins/lineanames/lib/registrar-helpers.ts index 5062596ec..d6ccebea5 100644 --- a/apps/ensindexer/src/plugins/lineanames/lib/registrar-helpers.ts +++ b/apps/ensindexer/src/plugins/lineanames/lib/registrar-helpers.ts @@ -17,6 +17,7 @@ export function getRegistrarManagedName(namespaceId: ENSNamespaceId): RegistrarM return "linea-sepolia.eth"; case "holesky": case "ens-test-env": + default: throw new Error( `No registrar managed name is known for the Linea Names plugin within the "${namespaceId}" namespace.`, ); diff --git a/apps/ensindexer/test/dns-helpers.test.ts b/apps/ensindexer/test/dns-helpers.test.ts index 0f8178589..de5f81eb7 100644 --- a/apps/ensindexer/test/dns-helpers.test.ts +++ b/apps/ensindexer/test/dns-helpers.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from "vitest"; import { decodeDNSPacketBytes, decodeTXTData, parseRRSet } from "@/lib/dns-helpers"; -import { getDatasource } from "@ensnode/datasources"; +import { ENSNamespaceId, getDatasource } from "@ensnode/datasources"; import { TxtAnswer } from "dns-packet"; import { decodeEventLog, hexToBytes, toBytes, zeroHash } from "viem"; @@ -10,7 +10,7 @@ import { decodeEventLog, hexToBytes, toBytes, zeroHash } from "viem"; const { args: { record }, } = decodeEventLog({ - abi: getDatasource("mainnet", "threedns-base").contracts.Resolver.abi, + abi: getDatasource(ENSNamespaceId.Mainnet, "threedns-base").contracts.Resolver.abi, topics: [ "0xaaac3b4b3e6807b5b4585562beabaa2de9bd07db514a1eba2c11d1af5b9d9dc7", "0x6470e2677db6a5bb6c69e51fce7271aeeb5f2808ea7dfdf34b703749555b3e10", diff --git a/packages/datasources/src/lib/types.ts b/packages/datasources/src/lib/types.ts index 93fc7207e..639ba5686 100644 --- a/packages/datasources/src/lib/types.ts +++ b/packages/datasources/src/lib/types.ts @@ -1,7 +1,7 @@ import type { Abi, Address, Chain } from "viem"; /** - * ENSNamespaceIds encodes the set of identifiers for well-known ENS namespaces. + * ENSNamespaceId enum encodes the set of identifiers for well-known ENS namespaces. * * Each ENS namespace is a single, unified set of ENS names with a distinct onchain root * Registry (the ensroot Datasource) and the capability of spanning from that root Registry across @@ -26,17 +26,12 @@ import type { Abi, Address, Chain } from "viem"; * protocol changes, running deterministic test suites, and local development. * https://github.com/ensdomains/ens-test-env */ -export const ENSNamespaceIds = { - Mainnet: "mainnet", - Sepolia: "sepolia", - Holesky: "holesky", - EnsTestEnv: "ens-test-env", -} as const; - -/** - * ENSNamespaceId is the derived string union of possible ENS namespace identifiers. - */ -export type ENSNamespaceId = (typeof ENSNamespaceIds)[keyof typeof ENSNamespaceIds]; +export enum ENSNamespaceId { + Mainnet = "mainnet", + Sepolia = "sepolia", + Holesky = "holesky", + EnsTestEnv = "ens-test-env", +} /** * A Datasource describes a set of contracts on a given chain that interact with the ENS protocol. From 0b249603bedb26c02700d597d03fdecbd6b1a85a Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Tue, 24 Jun 2025 11:57:23 +0200 Subject: [PATCH 2/2] docs(changeset): Replace inline string literals with the `ENSNamespaceId` enum values. --- .changeset/icy-clubs-shave.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/icy-clubs-shave.md diff --git a/.changeset/icy-clubs-shave.md b/.changeset/icy-clubs-shave.md new file mode 100644 index 000000000..351600a0f --- /dev/null +++ b/.changeset/icy-clubs-shave.md @@ -0,0 +1,7 @@ +--- +"@ensnode/datasources": minor +"ensindexer": minor +"ensadmin": minor +--- + +Replace inline string literals with the `ENSNamespaceId` enum values.