diff --git a/.changeset/short-cobras-bathe.md b/.changeset/short-cobras-bathe.md new file mode 100644 index 000000000..d5d0c3324 --- /dev/null +++ b/.changeset/short-cobras-bathe.md @@ -0,0 +1,5 @@ +--- +"@ensnode/datasources": patch +--- + +Introduces a temporary `sepolia-v2` ENS Namespace, intended for testing of ephemeral ENSv2 deployments to the Sepolia chain. This feature is intended for developers of the ENS protocol, and is highly experimental and should be considered unstable. diff --git a/apps/ensadmin/src/lib/default-records-selection.ts b/apps/ensadmin/src/lib/default-records-selection.ts index a73796121..6edfe8849 100644 --- a/apps/ensadmin/src/lib/default-records-selection.ts +++ b/apps/ensadmin/src/lib/default-records-selection.ts @@ -52,6 +52,10 @@ export const DefaultRecordsSelection = { addresses: getCommonCoinTypes(ENSNamespaceIds.Sepolia), texts: TEXTS, }, + [ENSNamespaceIds.SepoliaV2]: { + addresses: getCommonCoinTypes(ENSNamespaceIds.SepoliaV2), + texts: TEXTS, + }, [ENSNamespaceIds.EnsTestEnv]: { addresses: getCommonCoinTypes(ENSNamespaceIds.EnsTestEnv), texts: TEXTS, diff --git a/apps/ensapi/src/graphql-api/lib/get-domain-by-fqdn.ts b/apps/ensapi/src/graphql-api/lib/get-domain-by-fqdn.ts index 332244ee3..8db970a03 100644 --- a/apps/ensapi/src/graphql-api/lib/get-domain-by-fqdn.ts +++ b/apps/ensapi/src/graphql-api/lib/get-domain-by-fqdn.ts @@ -2,9 +2,9 @@ import config from "@/config"; import { getUnixTime } from "date-fns"; import { Param, sql } from "drizzle-orm"; -import { labelhash, namehash } from "viem"; +import { namehash } from "viem"; -import { DatasourceNames, getDatasource, maybeGetDatasource } from "@ensnode/datasources"; +import { DatasourceNames } from "@ensnode/datasources"; import * as schema from "@ensnode/ensnode-schema"; import { type DomainId, @@ -22,24 +22,17 @@ import { makeENSv1DomainId, makeRegistryId, makeSubdomainNode, + maybeGetDatasourceContract, type RegistryId, } from "@ensnode/ensnode-sdk"; import { getLatestRegistration } from "@/graphql-api/lib/get-latest-registration"; import { db } from "@/lib/db"; - -const ensroot = getDatasource(config.namespace, DatasourceNames.ENSRoot); -const namechain = maybeGetDatasource(config.namespace, DatasourceNames.Namechain); +import logger from "@/lib/logger"; const ETH_LABELHASH = labelhashLiteralLabel("eth" as LiteralLabel); - const ROOT_REGISTRY_ID = getENSv2RootRegistryId(config.namespace); -const ENS_ROOT_V2_ETH_REGISTRY_ID = makeRegistryId({ - chainId: ensroot.chain.id, - address: ensroot.contracts.ETHRegistry.address, -}); - /** * Gets the DomainId of the Domain addressed by `name`. */ @@ -128,72 +121,91 @@ async function v2_getDomainIdByFqdn( // biome-ignore lint/style/noNonNullAssertion: length check above const leaf = rows[rows.length - 1]!; - // we have an exact match within ENSv2 on the ENS Root Chain + /////////////////////////// + // An exact match was found for the Domain within ENSv2 on the ENS Root Chain. + /////////////////////////// const exact = rows.length === labelHashPath.length; if (exact) { - console.log(`Found '${name}' in ENSv2 from Registry ${registryId}`); + logger.debug(`Found '${name}' in ENSv2 from Registry ${registryId}`); return leaf.domain_id; } - console.log(name); - console.log(JSON.stringify(rows, null, 2)); - - // we did not find an exact match for the Domain within ENSv2 on the ENS Root Chain + /////////////////////////// + // 1. ETHTLDResolver // if the path terminates at the .eth Registry, we must implement the logic in ETHTLDResolver // TODO: we could add an additional invariant that the .eth v2 Registry does indeed have the ETHTLDResolver // set as its resolver, but that is unnecessary at the moment and incurs additional db requests or a join against // domain_resolver_relationships // TODO: generalize this into other future bridging resolvers depending on how basenames etc do it - if (leaf.registry_id === ENS_ROOT_V2_ETH_REGISTRY_ID) { - // TODO(ensv2): remove when all namspaces have Namechain datasource defined - // if namechain doesn't exist, we can't bridge the request to that Registry, so terminate - if (!namechain) return null; - - // Invariant: must be >= 2LD - if (labelHashPath.length < 2) { - throw new Error(`Invariant: Not >= 2LD??`); - } - - // Invariant: must be a .eth subname - if (labelHashPath[0] !== ETH_LABELHASH) { - throw new Error(`Invariant: Not .eth subname????`); - } - - // Invariant: must be a .eth subname - if (leaf.label_hash !== labelhash("eth")) { - throw new Error(`Invariant: Not .eth subname??`); - } - - // construct the node of the 2ld - const dotEth2LDNode = makeSubdomainNode(labelHashPath[1], ETH_NODE); - - // 1. if there's an active registration in ENSv1 for the .eth 2LD, then resolve from ENSv1 - const ensv1DomainId = makeENSv1DomainId(dotEth2LDNode); - const registration = await getLatestRegistration(ensv1DomainId); - - if (registration && !isRegistrationFullyExpired(registration, now)) { - console.log( - `ETHTLDResolver deferring to actively registered name ${dotEth2LDNode} in ENSv1...`, - ); - return await v1_getDomainIdByFqdn(name); - } - - // 2. otherwise, direct to Namechain ENSv2 .eth Registry - const nameWithoutTld = interpretedLabelsToInterpretedName( - interpretedNameToInterpretedLabels(name).slice(0, -1), + /////////////////////////// + + // TODO: can hoist these datasource lookups and registry id construction once ENSv2 is fully + // deployed in all namespaces, is for backwards-compatible behavior + // if there's no ENSv2 ETH Registry on the ENS Root Chain, the domain was not found + const ENS_ROOT_V2_ETH_REGISTRY = maybeGetDatasourceContract( + config.namespace, + DatasourceNames.ENSRoot, + "ETHRegistry", + ); + if (!ENS_ROOT_V2_ETH_REGISTRY) return null; + + const ENS_ROOT_V2_ETH_REGISTRY_ID = makeRegistryId(ENS_ROOT_V2_ETH_REGISTRY); + + // if the path did not terminate at the .eth Registry, then there's nothing to be done and the domain was not found + if (leaf.registry_id !== ENS_ROOT_V2_ETH_REGISTRY_ID) return null; + + logger.debug({ name, rows }); + + // Invariant: must be >= 2LD + if (labelHashPath.length < 2) { + throw new Error(`Invariant: '${name}' is not >= 2LD (has depth ${labelHashPath.length})!`); + } + + // Invariant: LabelHashPath must originate at 'eth' + if (labelHashPath[0] !== ETH_LABELHASH) { + throw new Error( + `Invariant: '${name}' terminated at .eth Registry but the queried labelHashPath (${JSON.stringify(labelHashPath)}) does not originate with 'eth' (${ETH_LABELHASH}).`, ); - console.log( - `ETHTLDResolver deferring '${nameWithoutTld}' to ENSv2 .eth Registry on Namechain...`, + } + + // Invariant: The path must terminate at 'eth' as well. + if (leaf.label_hash !== ETH_LABELHASH) { + throw new Error( + `Invariant: the leaf identified (${leaf.label_hash}) does not match 'eth' (${ETH_LABELHASH}).`, ); + } - const NAMECHAIN_V2_ETH_REGISTRY_ID = makeRegistryId({ - chainId: namechain.chain.id, - address: namechain.contracts.ETHRegistry.address, - }); + // construct the node of the 2ld + const dotEth2LDNode = makeSubdomainNode(labelHashPath[1], ETH_NODE); - return v2_getDomainIdByFqdn(NAMECHAIN_V2_ETH_REGISTRY_ID, nameWithoutTld); + // 1. if there's an active registration in ENSv1 for the .eth 2LD, then resolve from ENSv1 + const ensv1DomainId = makeENSv1DomainId(dotEth2LDNode); + const registration = await getLatestRegistration(ensv1DomainId); + + if (registration && !isRegistrationFullyExpired(registration, now)) { + logger.debug( + `ETHTLDResolver deferring to actively registered name ${dotEth2LDNode} in ENSv1...`, + ); + return await v1_getDomainIdByFqdn(name); } - // finally, not found - return null; + // 2. otherwise, direct to Namechain ENSv2 .eth Registry + // if there's no ETHRegistry on Namechain, the domain was not found + const NAMECHAIN_V2_ETH_REGISTRY = maybeGetDatasourceContract( + config.namespace, + DatasourceNames.Namechain, + "ETHRegistry", + ); + if (!NAMECHAIN_V2_ETH_REGISTRY) return null; + + const NAMECHAIN_V2_ETH_REGISTRY_ID = makeRegistryId(NAMECHAIN_V2_ETH_REGISTRY); + + const nameWithoutTld = interpretedLabelsToInterpretedName( + interpretedNameToInterpretedLabels(name).slice(0, -1), + ); + logger.debug( + `ETHTLDResolver deferring '${nameWithoutTld}' to ENSv2 .eth Registry on Namechain...`, + ); + + return v2_getDomainIdByFqdn(NAMECHAIN_V2_ETH_REGISTRY_ID, nameWithoutTld, { now }); } diff --git a/apps/ensindexer/src/lib/ponder-helpers.ts b/apps/ensindexer/src/lib/ponder-helpers.ts index 54eb2918a..50e1a6d64 100644 --- a/apps/ensindexer/src/lib/ponder-helpers.ts +++ b/apps/ensindexer/src/lib/ponder-helpers.ts @@ -305,16 +305,19 @@ export function chainsConnectionConfig( ); } + // NOTE: disable cache on local chains (e.g. ens-test-env, devnet) + const disableCache = + chainId === 31337 || + chainId === 1337 || + chainId === ensTestEnvL1Chain.id || + chainId === ensTestEnvL2Chain.id; + return { [chainId.toString()]: { id: chainId, rpc: rpcConfig.httpRPCs.map((httpRPC) => httpRPC.toString()), ws: rpcConfig.websocketRPC?.toString(), - // NOTE: disable cache on local chains (e.g. Anvil, Ganache) - ...((chainId === 31337 || - chainId === 1337 || - chainId === ensTestEnvL1Chain.id || - chainId === ensTestEnvL2Chain.id) && { disableCache: true }), + disableCache, } satisfies ChainConfig, }; } diff --git a/apps/ensindexer/src/plugins/ensv2/plugin.ts b/apps/ensindexer/src/plugins/ensv2/plugin.ts index 8e50d0041..a5c3a5d17 100644 --- a/apps/ensindexer/src/plugins/ensv2/plugin.ts +++ b/apps/ensindexer/src/plugins/ensv2/plugin.ts @@ -7,9 +7,6 @@ * - RequiredAndNotNull opposite type: RequiredToBeNull for constraining polymorphic entities in graphql schema * - re-asses NameWrapper expiry logic — compare to subgraph implementation & see if we can simplify * - indexes based on graphql queries, ask claude to compile recommendations - * - modify Registration schema to more closely match ENSv2, map v1 into it - * - Renewals (v1, v2) - * - include similar /latest / superceding logic, need to be able to reference latest renewal to upsert referrers * - ThreeDNS * - Migration * - need to understand migration pattern better @@ -21,11 +18,8 @@ * - Query.permissions(by: { contract: { } }) * - custom wrapper for resolveCursorConnection with typesafety that applies defaults and auto-decodes cursors to the indicated type * - Pothos envelop plugins (aliases, depth, tokens, whatever) - * - BEFORE MERGE: revert sepolia.ts namespace back to original, including ensv2 stubs * * PENDING ENS TEAM - * - DedicatedResolver moving to EAC - * - depends on: namechain --testNames script not crashing in commit >= 803a940 * - Domain.canonical/Domain.canonicalPath/Domain.fqdn depends on: * - depends on: Registry.canonicalName implementation + indexing * - Signal Pattern for Registry contracts @@ -105,17 +99,18 @@ export default createPlugin({ abi: RegistryABI, chain: [ensroot, namechain] .filter((ds) => !!ds) - .reduce( - (memo, datasource) => ({ + .reduce((memo, datasource) => { + // TODO(ensv2-coverage): remove once ENSv2 exists in all namespaces + if (!("Registry" in datasource.contracts)) return memo; + return { ...memo, ...chainConfigForContract( config.globalBlockrange, datasource.chain.id, datasource.contracts.Registry, ), - }), - {}, - ), + }; + }, {}), }, /////////////////////////////////// @@ -125,17 +120,19 @@ export default createPlugin({ abi: EnhancedAccessControlABI, chain: [ensroot, namechain] .filter((ds) => !!ds) - .reduce( - (memo, datasource) => ({ + .reduce((memo, datasource) => { + // TODO(ensv2-coverage): remove once ENSv2 exists in all namespaces + if (!("EnhancedAccessControl" in datasource.contracts)) return memo; + + return { ...memo, ...chainConfigForContract( config.globalBlockrange, datasource.chain.id, datasource.contracts.EnhancedAccessControl, ), - }), - {}, - ), + }; + }, {}), }, ////////////////////////// diff --git a/apps/ensindexer/src/plugins/protocol-acceleration/plugin.ts b/apps/ensindexer/src/plugins/protocol-acceleration/plugin.ts index 6ef2c8b29..a23d6a91f 100644 --- a/apps/ensindexer/src/plugins/protocol-acceleration/plugin.ts +++ b/apps/ensindexer/src/plugins/protocol-acceleration/plugin.ts @@ -144,11 +144,13 @@ export default createPlugin({ [namespaceContract(pluginName, "ENSv2Registry")]: { abi: RegistryABI, chain: { - ...chainConfigForContract( - config.globalBlockrange, - ensroot.chain.id, - ensroot.contracts.Registry, - ), + // TODO(ensv2-coverage): remove this conditional once ENSv2 exists in all namespaces + ...("Registry" in ensroot.contracts && + chainConfigForContract( + config.globalBlockrange, + ensroot.chain.id, + ensroot.contracts.Registry, + )), ...(namechain && chainConfigForContract( config.globalBlockrange, diff --git a/package.json b/package.json index ac8046588..953edc5fa 100644 --- a/package.json +++ b/package.json @@ -40,9 +40,9 @@ "undici@<6.23.0": ">=6.23.0", "devalue@>=5.3.0 <=5.6.1": ">=5.6.2", "h3@<=1.15.4": ">=1.15.5", - "tar@<=7.5.3": ">=7.5.4", - "lodash-es@>=4.0.0 <=4.17.22": ">=4.17.23", - "lodash@>=4.0.0 <=4.17.22": ">=4.17.23" + "tar@<=7.5.3": "^7.5.4", + "lodash@<=4.17.22": "^4.17.23", + "lodash-es@<=4.17.22": "^4.17.23" }, "ignoredBuiltDependencies": [ "bun" diff --git a/packages/datasources/src/lib/types.ts b/packages/datasources/src/lib/types.ts index b87a5f59a..72466e9d0 100644 --- a/packages/datasources/src/lib/types.ts +++ b/packages/datasources/src/lib/types.ts @@ -29,6 +29,7 @@ import type { Abi, Address, Chain } from "viem"; export const ENSNamespaceIds = { Mainnet: "mainnet", Sepolia: "sepolia", + SepoliaV2: "sepolia-v2", EnsTestEnv: "ens-test-env", } as const; @@ -108,25 +109,6 @@ export type ENSNamespace = { [DatasourceNames.ENSRoot]: Datasource; } & Partial, Datasource>>; -/** - * Helper type to merge multiple types into one. - */ -type MergedTypes = (T extends any ? (x: T) => void : never) extends (x: infer R) => void - ? R - : never; - -/** - * Preserves the chain union while merging contracts from multiple objects - */ -export type MergeNamespaces = T extends ENSNamespace - ? { - chain: T extends { chain: infer C } ? C : never; - contracts: T extends { [DatasourceNames.ENSRoot]: { contracts: infer C } } - ? MergedTypes - : never; - } - : never; - /** * Helper type to extract the datasource type for a specific datasource name across all namespaces. * Returns the union of all possible datasource types for that datasource name, or never if not found. diff --git a/packages/datasources/src/mainnet.ts b/packages/datasources/src/mainnet.ts index 7850a776f..961a40b24 100644 --- a/packages/datasources/src/mainnet.ts +++ b/packages/datasources/src/mainnet.ts @@ -6,9 +6,6 @@ import { EarlyAccessRegistrarController as base_EARegistrarController } from "./ import { RegistrarController as base_RegistrarController } from "./abis/basenames/RegistrarController"; import { Registry as base_Registry } from "./abis/basenames/Registry"; import { UpgradeableRegistrarController as base_UpgradeableRegistrarController } from "./abis/basenames/UpgradeableRegistrarController"; -// ABIs for Namechain -import { EnhancedAccessControl } from "./abis/ensv2/EnhancedAccessControl"; -import { Registry } from "./abis/ensv2/Registry"; // ABIs for Lineanames Datasource import { BaseRegistrar as linea_BaseRegistrar } from "./abis/lineanames/BaseRegistrar"; import { EthRegistrarController as linea_EthRegistrarController } from "./abis/lineanames/EthRegistrarController"; @@ -117,59 +114,9 @@ export default { address: "0xf58d55f06bb92f083e78bb5063a2dd3544f9b6a3", startBlock: 10170681, }, - - // - - ETHRegistry: { - abi: Registry, - address: "0x1291be112d480055dafd8a610b7d1e203891c274", - startBlock: 23794084, - }, - RootRegistry: { - abi: Registry, - address: "0x8a791620dd6260079bf849dc5567adc3f2fdc318", - startBlock: 23794084, - }, - Registry: { - abi: Registry, - startBlock: 23794084, - }, - EnhancedAccessControl: { - abi: EnhancedAccessControl, - startBlock: 23794084, - }, }, }, - // TODO(ensv2): reference Mainnet deployment - // [DatasourceNames.Namechain]: { - // chain: mainnet, - // contracts: { - // Resolver: { - // abi: ResolverABI, - // startBlock: 23794084, - // }, - // Registry: { - // abi: Registry, - // startBlock: 23794084, - // }, - // EnhancedAccessControl: { - // abi: EnhancedAccessControl, - // startBlock: 23794084, - // }, - // ETHRegistry: { - // abi: Registry, - // address: "0x5fc8d32690cc91d4c39d9d3abcbd16989f875707", - // startBlock: 23794084, - // }, - // ETHRegistrar: { - // abi: ETHRegistrar, - // address: "0xa513e6e4b8f2a923d98304ec87f64353c4d5c853", - // startBlock: 23794084, - // }, - // }, - // }, - /** * Basenames Datasource * diff --git a/packages/datasources/src/namespaces.ts b/packages/datasources/src/namespaces.ts index 19a999ba7..2eeba45f8 100644 --- a/packages/datasources/src/namespaces.ts +++ b/packages/datasources/src/namespaces.ts @@ -7,15 +7,18 @@ import { } from "./lib/types"; import mainnet from "./mainnet"; import sepolia from "./sepolia"; +import sepoliaV2 from "./sepolia-v2"; // internal map ENSNamespaceId -> ENSNamespace const ENSNamespacesById: { readonly mainnet: typeof mainnet; readonly sepolia: typeof sepolia; + readonly "sepolia-v2": typeof sepoliaV2; readonly "ens-test-env": typeof ensTestEnv; } = { mainnet, sepolia, + "sepolia-v2": sepoliaV2, "ens-test-env": ensTestEnv, } as const; diff --git a/packages/datasources/src/sepolia-v2.ts b/packages/datasources/src/sepolia-v2.ts new file mode 100644 index 000000000..76c4ac58d --- /dev/null +++ b/packages/datasources/src/sepolia-v2.ts @@ -0,0 +1,82 @@ +import { sepolia } from "viem/chains"; + +import { EnhancedAccessControl } from "./abis/ensv2/EnhancedAccessControl"; +import { ETHRegistrar } from "./abis/ensv2/ETHRegistrar"; +import { Registry } from "./abis/ensv2/Registry"; +import { UniversalResolver as root_UniversalResolver } from "./abis/root/UniversalResolver"; +import { ResolverABI } from "./lib/ResolverABI"; +// Types +import { DatasourceNames, type ENSNamespace } from "./lib/types"; +import SepoliaNamespace from "./sepolia"; + +/** + * The Sepolia V2 ENSNamespace + * + * This represents the ENS V2 deployment on Sepolia, a separate namespace from the original Sepolia + * ENS deployment, used for testing ENSv2. + */ +export default { + // Extends the existing Sepolia Namespace + ...SepoliaNamespace, + + [DatasourceNames.ENSRoot]: { + chain: sepolia, + contracts: { + ...SepoliaNamespace[DatasourceNames.ENSRoot].contracts, + + // add the ENS V2 contracts + RootRegistry: { + abi: Registry, + address: "0x245de1984f9bb890c5db0b1fb839470c6a4c7e08", + startBlock: 9771022, + }, + UniversalResolverV2: { + abi: root_UniversalResolver, + address: "0x50168842c0f5c9992a34085d9a6dc5b0a4f306ce", + startBlock: 9771281, + }, + ETHRegistry: { + abi: Registry, + address: "0x3f0920aa92c5f9bce54643c09955c5f241f1f763", + startBlock: 9771260, + }, + Registry: { + abi: Registry, + startBlock: 9770973, + }, + EnhancedAccessControl: { + abi: EnhancedAccessControl, + startBlock: 9770973, + }, + }, + }, + + // add a namechain + [DatasourceNames.Namechain]: { + chain: sepolia, + contracts: { + Resolver: { + abi: ResolverABI, + startBlock: 3702721, + }, + Registry: { + abi: Registry, + startBlock: 9770973, + }, + EnhancedAccessControl: { + abi: EnhancedAccessControl, + startBlock: 9770973, + }, + ETHRegistry: { + abi: Registry, + address: "0xf332544e6234f1ca149907d0d4658afd5feb6831", + startBlock: 9770973, + }, + ETHRegistrar: { + abi: ETHRegistrar, + address: "0xe37a1366c827d18dc0ad57f3767de4b3025ceac2", + startBlock: 9843689, + }, + }, + }, +} satisfies ENSNamespace; diff --git a/packages/datasources/src/sepolia.ts b/packages/datasources/src/sepolia.ts index 9f630f0f8..53b12100e 100644 --- a/packages/datasources/src/sepolia.ts +++ b/packages/datasources/src/sepolia.ts @@ -13,8 +13,6 @@ import { EarlyAccessRegistrarController as base_EARegistrarController } from "./ import { RegistrarController as base_RegistrarController } from "./abis/basenames/RegistrarController"; import { Registry as base_Registry } from "./abis/basenames/Registry"; import { UpgradeableRegistrarController as base_UpgradeableRegistrarController } from "./abis/basenames/UpgradeableRegistrarController"; -import { EnhancedAccessControl } from "./abis/ensv2/EnhancedAccessControl"; -import { Registry } from "./abis/ensv2/Registry"; // ABIs for Lineanames Datasource import { BaseRegistrar as linea_BaseRegistrar } from "./abis/lineanames/BaseRegistrar"; import { EthRegistrarController as linea_EthRegistrarController } from "./abis/lineanames/EthRegistrarController"; @@ -100,59 +98,9 @@ export default { address: "0xb7b7dadf4d42a08b3ec1d3a1079959dfbc8cffcc", startBlock: 8515717, }, - - // - - ETHRegistry: { - abi: Registry, - address: "0x1291be112d480055dafd8a610b7d1e203891c274", - startBlock: 23794084, - }, - RootRegistry: { - abi: Registry, - address: "0x8a791620dd6260079bf849dc5567adc3f2fdc318", - startBlock: 23794084, - }, - Registry: { - abi: Registry, - startBlock: 23794084, - }, - EnhancedAccessControl: { - abi: EnhancedAccessControl, - startBlock: 23794084, - }, }, }, - // TODO(ensv2): reference Sepolia deployment - // [DatasourceNames.Namechain]: { - // chain: sepolia, - // contracts: { - // Resolver: { - // abi: ResolverABI, - // startBlock: 23794084, - // }, - // Registry: { - // abi: Registry, - // startBlock: 23794084, - // }, - // EnhancedAccessControl: { - // abi: EnhancedAccessControl, - // startBlock: 23794084, - // }, - // ETHRegistry: { - // abi: Registry, - // address: "0x5fc8d32690cc91d4c39d9d3abcbd16989f875707", - // startBlock: 23794084, - // }, - // ETHRegistrar: { - // abi: ETHRegistrar, - // address: "0xa513e6e4b8f2a923d98304ec87f64353c4d5c853", - // startBlock: 23794084, - // }, - // }, - // }, - /** * Basenames Datasource * diff --git a/packages/ensnode-sdk/src/registrars/basenames-subregistry.ts b/packages/ensnode-sdk/src/registrars/basenames-subregistry.ts index 53522de22..35da5f6d8 100644 --- a/packages/ensnode-sdk/src/registrars/basenames-subregistry.ts +++ b/packages/ensnode-sdk/src/registrars/basenames-subregistry.ts @@ -45,6 +45,7 @@ export function getBasenamesSubregistryManagedName(namespaceId: ENSNamespaceId): case ENSNamespaceIds.Mainnet: return "base.eth"; case ENSNamespaceIds.Sepolia: + case ENSNamespaceIds.SepoliaV2: return "basetest.eth"; case ENSNamespaceIds.EnsTestEnv: throw new Error( diff --git a/packages/ensnode-sdk/src/registrars/ethnames-subregistry.ts b/packages/ensnode-sdk/src/registrars/ethnames-subregistry.ts index c084e4acf..70b1463a5 100644 --- a/packages/ensnode-sdk/src/registrars/ethnames-subregistry.ts +++ b/packages/ensnode-sdk/src/registrars/ethnames-subregistry.ts @@ -43,6 +43,7 @@ export function getEthnamesSubregistryManagedName(namespaceId: ENSNamespaceId): switch (namespaceId) { case ENSNamespaceIds.Mainnet: case ENSNamespaceIds.Sepolia: + case ENSNamespaceIds.SepoliaV2: case ENSNamespaceIds.EnsTestEnv: return "eth"; } diff --git a/packages/ensnode-sdk/src/registrars/lineanames-subregistry.ts b/packages/ensnode-sdk/src/registrars/lineanames-subregistry.ts index 520ada4a1..ef7f7626b 100644 --- a/packages/ensnode-sdk/src/registrars/lineanames-subregistry.ts +++ b/packages/ensnode-sdk/src/registrars/lineanames-subregistry.ts @@ -45,6 +45,7 @@ export function getLineanamesSubregistryManagedName(namespaceId: ENSNamespaceId) case ENSNamespaceIds.Mainnet: return "linea.eth"; case ENSNamespaceIds.Sepolia: + case ENSNamespaceIds.SepoliaV2: return "linea-sepolia.eth"; case ENSNamespaceIds.EnsTestEnv: throw new Error( diff --git a/packages/ensnode-sdk/src/shared/thegraph.ts b/packages/ensnode-sdk/src/shared/thegraph.ts index 642811c4d..a67d7b5f3 100644 --- a/packages/ensnode-sdk/src/shared/thegraph.ts +++ b/packages/ensnode-sdk/src/shared/thegraph.ts @@ -44,6 +44,7 @@ const makeTheGraphSubgraphUrl = (namespace: ENSNamespaceId, apiKey: string) => { return `https://gateway.thegraph.com/api/${apiKey}/subgraphs/id/5XqPmWe6gjyrJtFn9cLy237i4cWw2j9HcUJEXsP5qGtH`; case ENSNamespaceIds.Sepolia: return `https://gateway.thegraph.com/api/${apiKey}/subgraphs/id/G1SxZs317YUb9nQX3CC98hDyvxfMJNZH5pPRGpNrtvwN`; + case ENSNamespaceIds.SepoliaV2: case ENSNamespaceIds.EnsTestEnv: return null; default: diff --git a/packages/namehash-ui/src/utils/ensManager.ts b/packages/namehash-ui/src/utils/ensManager.ts index bf0a310bf..462965e09 100644 --- a/packages/namehash-ui/src/utils/ensManager.ts +++ b/packages/namehash-ui/src/utils/ensManager.ts @@ -16,6 +16,9 @@ export function getEnsManagerUrl(namespaceId: ENSNamespaceId): URL | null { return new URL(`https://app.ens.domains/`); case ENSNamespaceIds.Sepolia: return new URL(`https://sepolia.app.ens.domains/`); + case ENSNamespaceIds.SepoliaV2: + // sepolia-v2 is an ephemeral test deployment of ensv2 to sepolia and doesn't have a manager url + return null; case ENSNamespaceIds.EnsTestEnv: // ens-test-env runs on a local chain and is not supported by app.ens.domains return null; diff --git a/packages/namehash-ui/src/utils/ensMetadata.ts b/packages/namehash-ui/src/utils/ensMetadata.ts index 7b3a6ab99..9efbcb1a9 100644 --- a/packages/namehash-ui/src/utils/ensMetadata.ts +++ b/packages/namehash-ui/src/utils/ensMetadata.ts @@ -24,6 +24,9 @@ export function getEnsMetadataServiceAvatarUrl( return new URL(name, `https://metadata.ens.domains/mainnet/avatar/`); case ENSNamespaceIds.Sepolia: return new URL(name, `https://metadata.ens.domains/sepolia/avatar/`); + case ENSNamespaceIds.SepoliaV2: + // sepolia-v2 is an ephemeral test deployment of ensv2 to sepolia and doesn't have a metadata service + return null; case ENSNamespaceIds.EnsTestEnv: // ens-test-env runs on a local chain and is not supported by metadata.ens.domains // TODO: Above comment is not true. Details at https://github.com/namehash/ensnode/issues/1078 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b06c37341..0740623ed 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -92,9 +92,9 @@ overrides: undici@<6.23.0: '>=6.23.0' devalue@>=5.3.0 <=5.6.1: '>=5.6.2' h3@<=1.15.4: '>=1.15.5' - tar@<=7.5.3: '>=7.5.4' - lodash-es@>=4.0.0 <=4.17.22: '>=4.17.23' - lodash@>=4.0.0 <=4.17.22: '>=4.17.23' + tar@<=7.5.3: ^7.5.4 + lodash@<=4.17.22: ^4.17.23 + lodash-es@<=4.17.22: ^4.17.23 patchedDependencies: '@changesets/assemble-release-plan@6.0.9': @@ -4252,9 +4252,6 @@ packages: '@types/node@17.0.45': resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} - '@types/node@24.10.4': - resolution: {integrity: sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==} - '@types/node@24.10.9': resolution: {integrity: sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==} @@ -12670,7 +12667,7 @@ snapshots: '@types/fontkit@2.0.8': dependencies: - '@types/node': 24.10.4 + '@types/node': 24.10.9 '@types/geojson@7946.0.16': {} @@ -12702,10 +12699,6 @@ snapshots: '@types/node@17.0.45': {} - '@types/node@24.10.4': - dependencies: - undici-types: 7.16.0 - '@types/node@24.10.9': dependencies: undici-types: 7.16.0 @@ -12735,11 +12728,11 @@ snapshots: '@types/sax@1.2.7': dependencies: - '@types/node': 24.10.4 + '@types/node': 24.10.9 '@types/tar@6.1.13': dependencies: - '@types/node': 24.10.4 + '@types/node': 24.10.9 minipass: 4.2.8 '@types/trusted-types@2.0.7': @@ -12757,7 +12750,7 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 24.10.4 + '@types/node': 24.10.9 optional: true '@ungap/structured-clone@1.3.0': {} @@ -15841,7 +15834,7 @@ snapshots: dependencies: destr: 2.0.5 node-fetch-native: 1.6.7 - ufo: 1.6.1 + ufo: 1.6.3 ohash@2.0.11: {} @@ -17549,7 +17542,7 @@ snapshots: lru-cache: 10.4.3 node-fetch-native: 1.6.7 ofetch: 1.5.0 - ufo: 1.6.1 + ufo: 1.6.3 update-browserslist-db@1.1.4(browserslist@4.27.0): dependencies: