From 527cd5716bfce811a695c9f2df81160c1e7fc7bf Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 12 Jan 2026 15:51:24 -0800 Subject: [PATCH 01/10] feat: enable latest sepolia namespace with ensv2 --- packages/datasources/src/sepolia.ts | 73 +++++++++++++++-------------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/packages/datasources/src/sepolia.ts b/packages/datasources/src/sepolia.ts index 9f630f0f8..1b03c02fa 100644 --- a/packages/datasources/src/sepolia.ts +++ b/packages/datasources/src/sepolia.ts @@ -14,6 +14,7 @@ import { RegistrarController as base_RegistrarController } from "./abis/basename 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 { ETHRegistrar } from "./abis/ensv2/ETHRegistrar"; import { Registry } from "./abis/ensv2/Registry"; // ABIs for Lineanames Datasource import { BaseRegistrar as linea_BaseRegistrar } from "./abis/lineanames/BaseRegistrar"; @@ -105,53 +106,57 @@ export default { ETHRegistry: { abi: Registry, - address: "0x1291be112d480055dafd8a610b7d1e203891c274", - startBlock: 23794084, + address: "0x3f0920aa92c5f9bce54643c09955c5f241f1f763", + startBlock: 9771260, }, RootRegistry: { abi: Registry, - address: "0x8a791620dd6260079bf849dc5567adc3f2fdc318", - startBlock: 23794084, + address: "0x245de1984f9bb890c5db0b1fb839470c6a4c7e08", + startBlock: 9771022, + }, + UniversalResolverV2: { + abi: root_UniversalResolver, + address: "0x50168842c0f5c9992a34085d9a6dc5b0a4f306ce", + startBlock: 9771281, }, Registry: { abi: Registry, - startBlock: 23794084, + startBlock: 9770973, }, EnhancedAccessControl: { abi: EnhancedAccessControl, - startBlock: 23794084, + startBlock: 9770973, }, }, }, - // 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, - // }, - // }, - // }, + [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, + }, + }, + }, /** * Basenames Datasource From bbc43ccacb9602cc526836dde6d8bad2fb4b4ada Mon Sep 17 00:00:00 2001 From: shrugs Date: Tue, 13 Jan 2026 09:54:26 -0800 Subject: [PATCH 02/10] fix: move new spolia deployment to its own namespace --- .../src/lib/default-records-selection.ts | 4 + apps/ensadmin/src/lib/namespace-utils.ts | 2 + packages/datasources/src/lib/types.ts | 1 + packages/datasources/src/namespaces.ts | 3 + packages/datasources/src/sepolia-v2.ts | 435 ++++++++++++++++++ packages/datasources/src/sepolia.ts | 73 ++- .../src/registrars/basenames-subregistry.ts | 1 + .../src/registrars/ethnames-subregistry.ts | 1 + .../src/registrars/lineanames-subregistry.ts | 1 + 9 files changed, 482 insertions(+), 39 deletions(-) create mode 100644 packages/datasources/src/sepolia-v2.ts 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/ensadmin/src/lib/namespace-utils.ts b/apps/ensadmin/src/lib/namespace-utils.ts index fac3b09c5..ed040eafd 100644 --- a/apps/ensadmin/src/lib/namespace-utils.ts +++ b/apps/ensadmin/src/lib/namespace-utils.ts @@ -80,6 +80,7 @@ export function getEnsManagerAppUrl(namespaceId: ENSNamespaceId): URL | null { case ENSNamespaceIds.Mainnet: return new URL(`https://app.ens.domains/`); case ENSNamespaceIds.Sepolia: + case ENSNamespaceIds.SepoliaV2: return new URL(`https://sepolia.app.ens.domains/`); case ENSNamespaceIds.EnsTestEnv: // ens-test-env runs on a local chain and is not supported by app.ens.domains @@ -109,6 +110,7 @@ export function buildEnsMetadataServiceAvatarUrl( case ENSNamespaceIds.Mainnet: return new URL(name, `https://metadata.ens.domains/mainnet/avatar/`); case ENSNamespaceIds.Sepolia: + case ENSNamespaceIds.SepoliaV2: return new URL(name, `https://metadata.ens.domains/sepolia/avatar/`); case ENSNamespaceIds.EnsTestEnv: // ens-test-env runs on a local chain and is not supported by metadata.ens.domains diff --git a/packages/datasources/src/lib/types.ts b/packages/datasources/src/lib/types.ts index b87a5f59a..fe0eb6643 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; 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..85ace0a2e --- /dev/null +++ b/packages/datasources/src/sepolia-v2.ts @@ -0,0 +1,435 @@ +import { + arbitrumSepolia, + baseSepolia, + lineaSepolia, + optimismSepolia, + scrollSepolia, + sepolia, +} from "viem/chains"; + +// ABIs for Basenames Datasource +import { BaseRegistrar as base_BaseRegistrar } from "./abis/basenames/BaseRegistrar"; +import { EarlyAccessRegistrarController as base_EARegistrarController } from "./abis/basenames/EARegistrarController"; +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 { ETHRegistrar } from "./abis/ensv2/ETHRegistrar"; +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"; +import { NameWrapper as linea_NameWrapper } from "./abis/lineanames/NameWrapper"; +import { Registry as linea_Registry } from "./abis/lineanames/Registry"; +// ABIs for ENSRoot Datasource +import { BaseRegistrar as root_BaseRegistrar } from "./abis/root/BaseRegistrar"; +import { LegacyEthRegistrarController as root_LegacyEthRegistrarController } from "./abis/root/LegacyEthRegistrarController"; +import { NameWrapper as root_NameWrapper } from "./abis/root/NameWrapper"; +import { Registry as root_Registry } from "./abis/root/Registry"; +import { UniversalRegistrarRenewalWithReferrer as root_UniversalRegistrarRenewalWithReferrer } from "./abis/root/UniversalRegistrarRenewalWithReferrer"; +import { UniversalResolver as root_UniversalResolver } from "./abis/root/UniversalResolver"; +import { UnwrappedEthRegistrarController as root_UnwrappedEthRegistrarController } from "./abis/root/UnwrappedEthRegistrarController"; +import { WrappedEthRegistrarController as root_WrappedEthRegistrarController } from "./abis/root/WrappedEthRegistrarController"; +import { Seaport as Seaport1_5 } from "./abis/seaport/Seaport1.5"; +// Shared ABIs +import { StandaloneReverseRegistrar } from "./abis/shared/StandaloneReverseRegistrar"; +import { ResolverABI } from "./lib/ResolverABI"; +// Types +import { DatasourceNames, type ENSNamespace } from "./lib/types"; + +/** + * The Sepolia V2 ENSNamespace + * + * This represents the ENS V2 deployment on Sepolia, a separate namespace from the original Sepolia ENS deployment. + * + * NOTE: The Sepolia V2 ENS namespace does not support 3DNS. + */ +export default { + /** + * ENSRoot Datasource + * + * ENS V2 contracts deployed on Sepolia + */ + [DatasourceNames.ENSRoot]: { + chain: sepolia, + contracts: { + ENSv1RegistryOld: { + abi: root_Registry, // Registry was redeployed, same abi + address: "0x94f523b8261b815b87effcf4d18e6abef18d6e4b", + startBlock: 3702721, + }, + ENSv1Registry: { + abi: root_Registry, // Registry was redeployed, same abi + address: "0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e", + startBlock: 3702728, + }, + Resolver: { + abi: ResolverABI, + startBlock: 3702721, // ignores any Resolver events prior to `startBlock` of RegistryOld on Sepolia + }, + BaseRegistrar: { + abi: root_BaseRegistrar, + address: "0x57f1887a8bf19b14fc0df6fd9b2acc9af147ea85", + startBlock: 3702731, + }, + LegacyEthRegistrarController: { + abi: root_LegacyEthRegistrarController, + address: "0x7e02892cfc2bfd53a75275451d73cf620e793fc0", + startBlock: 3790197, + }, + WrappedEthRegistrarController: { + abi: root_WrappedEthRegistrarController, + address: "0xfed6a969aaa60e4961fcd3ebf1a2e8913ac65b72", + startBlock: 3790244, + }, + UnwrappedEthRegistrarController: { + abi: root_UnwrappedEthRegistrarController, + address: "0xfb3ce5d01e0f33f41dbb39035db9745962f1f968", + startBlock: 8579988, + }, + UniversalRegistrarRenewalWithReferrer: { + abi: root_UniversalRegistrarRenewalWithReferrer, + address: "0x7ab2947592c280542e680ba8f08a589009da8644", + startBlock: 9447519, + }, + NameWrapper: { + abi: root_NameWrapper, + address: "0x0635513f179d50a207757e05759cbd106d7dfce8", + startBlock: 3790153, + }, + UniversalResolver: { + abi: root_UniversalResolver, + address: "0xb7b7dadf4d42a08b3ec1d3a1079959dfbc8cffcc", + startBlock: 8515717, + }, + + // ENS V2 contracts + + ETHRegistry: { + abi: Registry, + address: "0x3f0920aa92c5f9bce54643c09955c5f241f1f763", + startBlock: 9771260, + }, + RootRegistry: { + abi: Registry, + address: "0x245de1984f9bb890c5db0b1fb839470c6a4c7e08", + startBlock: 9771022, + }, + UniversalResolverV2: { + abi: root_UniversalResolver, + address: "0x50168842c0f5c9992a34085d9a6dc5b0a4f306ce", + startBlock: 9771281, + }, + Registry: { + abi: Registry, + startBlock: 9770973, + }, + EnhancedAccessControl: { + abi: EnhancedAccessControl, + startBlock: 9770973, + }, + }, + }, + + [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, + }, + }, + }, + + /** + * Basenames Datasource + * + * Addresses and Start Blocks from Basenames + * https://github.com/base-org/basenames + */ + [DatasourceNames.Basenames]: { + /** + * As of 5-Jun-2025 the Resolver for 'basetest.eth' in the Sepolia ENS namespace is + * 0x084D10C07EfEecD9fFc73DEb38ecb72f9eEb65aB. + * + * This Resolver uses ENSIP-10 (Wildcard Resolution) and EIP-3668 (CCIP Read) to delegate + * the forward resolution of data associated with subnames of 'basetest.eth' to an offchain + * gateway server operated by Coinbase that uses the following subregistry contracts on + * Base Sepolia as its source of truth. + * + * The owner of 'basetest.eth' in the ENS Registry on the Sepolia ENS namespace + * (e.g. Coinbase) has the ability to change this configuration at any time. + * + * See the reference documentation for additional context: + * docs/ensnode/src/content/docs/reference/mainnet-registered-subnames-of-subregistries.mdx + */ + chain: baseSepolia, + contracts: { + Registry: { + abi: base_Registry, + address: "0x1493b2567056c2181630115660963e13a8e32735", + startBlock: 13012458, + }, + Resolver: { + abi: ResolverABI, + startBlock: 13012458, + }, + BaseRegistrar: { + abi: base_BaseRegistrar, + address: "0xa0c70ec36c010b55e3c434d6c6ebeec50c705794", + startBlock: 13012465, + }, + EARegistrarController: { + abi: base_EARegistrarController, + address: "0x3a0e8c2a0a28f396a5e5b69edb2e630311f1517a", + startBlock: 13041164, + }, + RegistrarController: { + abi: base_RegistrarController, + address: "0x49ae3cc2e3aa768b1e5654f5d3c6002144a59581", + startBlock: 13298580, + }, + /** + * This controller was added to BaseRegistrar contract + * with the following tx: + * https://sepolia.basescan.org/tx/0x648d984c1a379a6c300851b9561fe98a9b5282a26ca8c2c7660b11c53f0564bc + */ + UpgradeableRegistrarController: { + abi: base_UpgradeableRegistrarController, + address: "0x82c858cdf64b3d893fe54962680edfddc37e94c8", // a proxy contract + startBlock: 29896051, + }, + }, + }, + + /** + * Lineanames Datasource + * + * Addresses and Start Blocks from Lineanames + * https://github.com/Consensys/linea-ens + */ + [DatasourceNames.Lineanames]: { + /** + * As of 5-Jun-2025 the Resolver for 'linea-sepolia.eth' in the Sepolia ENS namespace is + * 0x64884ED06241c059497aEdB2C7A44CcaE6bc7937. + * + * This Resolver uses ENSIP-10 (Wildcard Resolution) and EIP-3668 (CCIP Read) to delegate + * the forward resolution of data associated with subnames of 'linea-sepolia.eth' to an offchain + * gateway server operated by Consensys that uses the following subregistry contracts on + * Linea Sepolia as its source of truth. + * + * The owner of 'linea-sepolia.eth' in the ENS Registry on the Sepolia ENS namespace + * (e.g. Consensys) has the ability to change this configuration at any time. + * + * See the reference documentation for additional context: + * docs/ensnode/src/content/docs/reference/mainnet-registered-subnames-of-subregistries.mdx + */ + chain: lineaSepolia, + contracts: { + Registry: { + abi: linea_Registry, + address: "0x5b2636f0f2137b4ae722c01dd5122d7d3e9541f7", + startBlock: 2395094, + }, + Resolver: { + abi: ResolverABI, + startBlock: 2395094, // based on startBlock of Registry on Linea Sepolia + }, + BaseRegistrar: { + abi: linea_BaseRegistrar, + address: "0x83475a84c0ea834f06c8e636a62631e7d2e07a44", + startBlock: 2395099, + }, + EthRegistrarController: { + abi: linea_EthRegistrarController, + address: "0x0f81e3b3a32dfe1b8a08d3c0061d852337a09338", + startBlock: 2395231, + }, + NameWrapper: { + abi: linea_NameWrapper, + address: "0xf127de9e039a789806fed4c6b1c0f3affea9425e", + startBlock: 2395202, + }, + }, + }, + + /** + * Contracts that power Reverse Resolution on the (Sepolia) ENS Root chain. + */ + [DatasourceNames.ReverseResolverRoot]: { + chain: sepolia, + contracts: { + DefaultReverseRegistrar: { + abi: StandaloneReverseRegistrar, + address: "0x4f382928805ba0e23b30cfb75fc9e848e82dfd47", + startBlock: 8579966, + }, + + DefaultReverseResolver1: { + abi: ResolverABI, + address: "0x8fade66b79cc9f707ab26799354482eb93a5b7dd", + startBlock: 3790251, + }, + DefaultReverseResolver2: { + abi: ResolverABI, + address: "0x8948458626811dd0c23eb25cc74291247077cc51", + startBlock: 7035086, + }, + DefaultReverseResolver3: { + abi: ResolverABI, + address: "0x9dc60e7bd81ccc96774c55214ff389d42ae5e9ac", + startBlock: 8580041, + }, + + DefaultPublicResolver3: { + abi: ResolverABI, + address: "0x8fade66b79cc9f707ab26799354482eb93a5b7dd", + startBlock: 3790251, + }, + DefaultPublicResolver4: { + abi: ResolverABI, + address: "0x8948458626811dd0c23eb25cc74291247077cc51", + startBlock: 7035086, + }, + DefaultPublicResolver5: { + abi: ResolverABI, + address: "0xe99638b40e4fff0129d56f03b55b6bbc4bbe49b5", + startBlock: 8580001, + }, + + BaseReverseResolver: { + abi: ResolverABI, + // https://adraffy.github.io/ens-normalize.js/test/resolver.html?sepolia#80014a34.reverse + address: "0xaf3b3f636be80b6709f5bd3a374d6ac0d0a7c7aa", + startBlock: 8580004, + }, + + LineaReverseResolver: { + abi: ResolverABI, + // https://adraffy.github.io/ens-normalize.js/test/resolver.html?sepolia#8000e705.reverse + address: "0x083da1dbc0f379ccda6ac81a934207c3d8a8a205", + startBlock: 8580005, + }, + + OptimismReverseResolver: { + abi: ResolverABI, + // https://adraffy.github.io/ens-normalize.js/test/resolver.html?sepolia#80aa37dc.reverse + address: "0xc9ae189772bd48e01410ab3be933637ee9d3aa5f", + startBlock: 8580026, + }, + + ArbitrumReverseResolver: { + abi: ResolverABI, + // https://adraffy.github.io/ens-normalize.js/test/resolver.html?sepolia#80066eee.reverse + address: "0x926f94d2adc77c86cb0050892097d49aadd02e8b", + startBlock: 8580003, + }, + + ScrollReverseResolver: { + abi: ResolverABI, + // https://adraffy.github.io/ens-normalize.js/test/resolver.html?sepolia#8008274f.reverse + address: "0x9fa59673e43f15bdb8722fdaf5c2107574b99062", + startBlock: 8580040, + }, + }, + }, + + /** + * Contracts that power Reverse Resolution on Base Sepolia. + */ + [DatasourceNames.ReverseResolverBase]: { + chain: baseSepolia, + contracts: { + L2ReverseRegistrar: { + abi: ResolverABI, + address: "0x00000beef055f7934784d6d81b6bc86665630dba", + startBlock: 21788010, + }, + }, + }, + + /** + * Contracts that power Reverse Resolution on Optimism Sepolia. + */ + [DatasourceNames.ReverseResolverOptimism]: { + chain: optimismSepolia, + contracts: { + L2ReverseRegistrar: { + abi: ResolverABI, + address: "0x00000beef055f7934784d6d81b6bc86665630dba", + startBlock: 23770766, + }, + }, + }, + + /** + * Contracts that power Reverse Resolution on Arbitrum Sepolia. + */ + [DatasourceNames.ReverseResolverArbitrum]: { + chain: arbitrumSepolia, + contracts: { + L2ReverseRegistrar: { + abi: ResolverABI, + address: "0x00000beef055f7934784d6d81b6bc86665630dba", + startBlock: 123142726, + }, + }, + }, + + /** + * Contracts that power Reverse Resolution on Scroll Sepolia. + */ + [DatasourceNames.ReverseResolverScroll]: { + chain: scrollSepolia, + contracts: { + L2ReverseRegistrar: { + abi: ResolverABI, + address: "0x00000beef055f7934784d6d81b6bc86665630dba", + startBlock: 8175276, + }, + }, + }, + + /** + * Contracts that power Reverse Resolution on Linea Sepolia. + */ + [DatasourceNames.ReverseResolverLinea]: { + chain: lineaSepolia, + contracts: { + L2ReverseRegistrar: { + abi: ResolverABI, + address: "0x00000beef055f7934784d6d81b6bc86665630dba", + startBlock: 9267966, + }, + }, + }, + + [DatasourceNames.Seaport]: { + chain: sepolia, + contracts: { + Seaport1_5: { + abi: Seaport1_5, // Seaport 1.5 + address: "0x00000000000000adc04c56bf30ac9d3c0aaf14dc", + startBlock: 3365529, + }, + }, + }, +} satisfies ENSNamespace; diff --git a/packages/datasources/src/sepolia.ts b/packages/datasources/src/sepolia.ts index 1b03c02fa..9f630f0f8 100644 --- a/packages/datasources/src/sepolia.ts +++ b/packages/datasources/src/sepolia.ts @@ -14,7 +14,6 @@ import { RegistrarController as base_RegistrarController } from "./abis/basename 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 { ETHRegistrar } from "./abis/ensv2/ETHRegistrar"; import { Registry } from "./abis/ensv2/Registry"; // ABIs for Lineanames Datasource import { BaseRegistrar as linea_BaseRegistrar } from "./abis/lineanames/BaseRegistrar"; @@ -106,57 +105,53 @@ export default { ETHRegistry: { abi: Registry, - address: "0x3f0920aa92c5f9bce54643c09955c5f241f1f763", - startBlock: 9771260, + address: "0x1291be112d480055dafd8a610b7d1e203891c274", + startBlock: 23794084, }, RootRegistry: { abi: Registry, - address: "0x245de1984f9bb890c5db0b1fb839470c6a4c7e08", - startBlock: 9771022, - }, - UniversalResolverV2: { - abi: root_UniversalResolver, - address: "0x50168842c0f5c9992a34085d9a6dc5b0a4f306ce", - startBlock: 9771281, + address: "0x8a791620dd6260079bf849dc5567adc3f2fdc318", + startBlock: 23794084, }, Registry: { abi: Registry, - startBlock: 9770973, + startBlock: 23794084, }, EnhancedAccessControl: { abi: EnhancedAccessControl, - startBlock: 9770973, + startBlock: 23794084, }, }, }, - [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, - }, - }, - }, + // 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( From 6c0e3409ef6cd638a1e9ff7ca6090e5c44fe5fac Mon Sep 17 00:00:00 2001 From: shrugs Date: Tue, 13 Jan 2026 10:09:02 -0800 Subject: [PATCH 03/10] cleanup --- packages/datasources/src/mainnet.ts | 53 ------ packages/datasources/src/sepolia-v2.ts | 234 +------------------------ packages/datasources/src/sepolia.ts | 52 ------ 3 files changed, 8 insertions(+), 331 deletions(-) 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/sepolia-v2.ts b/packages/datasources/src/sepolia-v2.ts index 85ace0a2e..d6b686c2f 100644 --- a/packages/datasources/src/sepolia-v2.ts +++ b/packages/datasources/src/sepolia-v2.ts @@ -1,26 +1,8 @@ -import { - arbitrumSepolia, - baseSepolia, - lineaSepolia, - optimismSepolia, - scrollSepolia, - sepolia, -} from "viem/chains"; +import { sepolia } from "viem/chains"; -// ABIs for Basenames Datasource -import { BaseRegistrar as base_BaseRegistrar } from "./abis/basenames/BaseRegistrar"; -import { EarlyAccessRegistrarController as base_EARegistrarController } from "./abis/basenames/EARegistrarController"; -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 { ETHRegistrar } from "./abis/ensv2/ETHRegistrar"; 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"; -import { NameWrapper as linea_NameWrapper } from "./abis/lineanames/NameWrapper"; -import { Registry as linea_Registry } from "./abis/lineanames/Registry"; // ABIs for ENSRoot Datasource import { BaseRegistrar as root_BaseRegistrar } from "./abis/root/BaseRegistrar"; import { LegacyEthRegistrarController as root_LegacyEthRegistrarController } from "./abis/root/LegacyEthRegistrarController"; @@ -30,7 +12,6 @@ import { UniversalRegistrarRenewalWithReferrer as root_UniversalRegistrarRenewal import { UniversalResolver as root_UniversalResolver } from "./abis/root/UniversalResolver"; import { UnwrappedEthRegistrarController as root_UnwrappedEthRegistrarController } from "./abis/root/UnwrappedEthRegistrarController"; import { WrappedEthRegistrarController as root_WrappedEthRegistrarController } from "./abis/root/WrappedEthRegistrarController"; -import { Seaport as Seaport1_5 } from "./abis/seaport/Seaport1.5"; // Shared ABIs import { StandaloneReverseRegistrar } from "./abis/shared/StandaloneReverseRegistrar"; import { ResolverABI } from "./lib/ResolverABI"; @@ -40,16 +21,10 @@ import { DatasourceNames, type ENSNamespace } from "./lib/types"; /** * The Sepolia V2 ENSNamespace * - * This represents the ENS V2 deployment on Sepolia, a separate namespace from the original Sepolia ENS deployment. - * - * NOTE: The Sepolia V2 ENS namespace does not support 3DNS. + * This represents the ENS V2 deployment on Sepolia, a separate namespace from the original Sepolia + * ENS deployment, used for testing ENSv2. */ export default { - /** - * ENSRoot Datasource - * - * ENS V2 contracts deployed on Sepolia - */ [DatasourceNames.ENSRoot]: { chain: sepolia, contracts: { @@ -105,11 +80,6 @@ export default { // ENS V2 contracts - ETHRegistry: { - abi: Registry, - address: "0x3f0920aa92c5f9bce54643c09955c5f241f1f763", - startBlock: 9771260, - }, RootRegistry: { abi: Registry, address: "0x245de1984f9bb890c5db0b1fb839470c6a4c7e08", @@ -120,6 +90,11 @@ export default { address: "0x50168842c0f5c9992a34085d9a6dc5b0a4f306ce", startBlock: 9771281, }, + ETHRegistry: { + abi: Registry, + address: "0x3f0920aa92c5f9bce54643c09955c5f241f1f763", + startBlock: 9771260, + }, Registry: { abi: Registry, startBlock: 9770973, @@ -159,118 +134,6 @@ export default { }, }, - /** - * Basenames Datasource - * - * Addresses and Start Blocks from Basenames - * https://github.com/base-org/basenames - */ - [DatasourceNames.Basenames]: { - /** - * As of 5-Jun-2025 the Resolver for 'basetest.eth' in the Sepolia ENS namespace is - * 0x084D10C07EfEecD9fFc73DEb38ecb72f9eEb65aB. - * - * This Resolver uses ENSIP-10 (Wildcard Resolution) and EIP-3668 (CCIP Read) to delegate - * the forward resolution of data associated with subnames of 'basetest.eth' to an offchain - * gateway server operated by Coinbase that uses the following subregistry contracts on - * Base Sepolia as its source of truth. - * - * The owner of 'basetest.eth' in the ENS Registry on the Sepolia ENS namespace - * (e.g. Coinbase) has the ability to change this configuration at any time. - * - * See the reference documentation for additional context: - * docs/ensnode/src/content/docs/reference/mainnet-registered-subnames-of-subregistries.mdx - */ - chain: baseSepolia, - contracts: { - Registry: { - abi: base_Registry, - address: "0x1493b2567056c2181630115660963e13a8e32735", - startBlock: 13012458, - }, - Resolver: { - abi: ResolverABI, - startBlock: 13012458, - }, - BaseRegistrar: { - abi: base_BaseRegistrar, - address: "0xa0c70ec36c010b55e3c434d6c6ebeec50c705794", - startBlock: 13012465, - }, - EARegistrarController: { - abi: base_EARegistrarController, - address: "0x3a0e8c2a0a28f396a5e5b69edb2e630311f1517a", - startBlock: 13041164, - }, - RegistrarController: { - abi: base_RegistrarController, - address: "0x49ae3cc2e3aa768b1e5654f5d3c6002144a59581", - startBlock: 13298580, - }, - /** - * This controller was added to BaseRegistrar contract - * with the following tx: - * https://sepolia.basescan.org/tx/0x648d984c1a379a6c300851b9561fe98a9b5282a26ca8c2c7660b11c53f0564bc - */ - UpgradeableRegistrarController: { - abi: base_UpgradeableRegistrarController, - address: "0x82c858cdf64b3d893fe54962680edfddc37e94c8", // a proxy contract - startBlock: 29896051, - }, - }, - }, - - /** - * Lineanames Datasource - * - * Addresses and Start Blocks from Lineanames - * https://github.com/Consensys/linea-ens - */ - [DatasourceNames.Lineanames]: { - /** - * As of 5-Jun-2025 the Resolver for 'linea-sepolia.eth' in the Sepolia ENS namespace is - * 0x64884ED06241c059497aEdB2C7A44CcaE6bc7937. - * - * This Resolver uses ENSIP-10 (Wildcard Resolution) and EIP-3668 (CCIP Read) to delegate - * the forward resolution of data associated with subnames of 'linea-sepolia.eth' to an offchain - * gateway server operated by Consensys that uses the following subregistry contracts on - * Linea Sepolia as its source of truth. - * - * The owner of 'linea-sepolia.eth' in the ENS Registry on the Sepolia ENS namespace - * (e.g. Consensys) has the ability to change this configuration at any time. - * - * See the reference documentation for additional context: - * docs/ensnode/src/content/docs/reference/mainnet-registered-subnames-of-subregistries.mdx - */ - chain: lineaSepolia, - contracts: { - Registry: { - abi: linea_Registry, - address: "0x5b2636f0f2137b4ae722c01dd5122d7d3e9541f7", - startBlock: 2395094, - }, - Resolver: { - abi: ResolverABI, - startBlock: 2395094, // based on startBlock of Registry on Linea Sepolia - }, - BaseRegistrar: { - abi: linea_BaseRegistrar, - address: "0x83475a84c0ea834f06c8e636a62631e7d2e07a44", - startBlock: 2395099, - }, - EthRegistrarController: { - abi: linea_EthRegistrarController, - address: "0x0f81e3b3a32dfe1b8a08d3c0061d852337a09338", - startBlock: 2395231, - }, - NameWrapper: { - abi: linea_NameWrapper, - address: "0xf127de9e039a789806fed4c6b1c0f3affea9425e", - startBlock: 2395202, - }, - }, - }, - /** * Contracts that power Reverse Resolution on the (Sepolia) ENS Root chain. */ @@ -351,85 +214,4 @@ export default { }, }, }, - - /** - * Contracts that power Reverse Resolution on Base Sepolia. - */ - [DatasourceNames.ReverseResolverBase]: { - chain: baseSepolia, - contracts: { - L2ReverseRegistrar: { - abi: ResolverABI, - address: "0x00000beef055f7934784d6d81b6bc86665630dba", - startBlock: 21788010, - }, - }, - }, - - /** - * Contracts that power Reverse Resolution on Optimism Sepolia. - */ - [DatasourceNames.ReverseResolverOptimism]: { - chain: optimismSepolia, - contracts: { - L2ReverseRegistrar: { - abi: ResolverABI, - address: "0x00000beef055f7934784d6d81b6bc86665630dba", - startBlock: 23770766, - }, - }, - }, - - /** - * Contracts that power Reverse Resolution on Arbitrum Sepolia. - */ - [DatasourceNames.ReverseResolverArbitrum]: { - chain: arbitrumSepolia, - contracts: { - L2ReverseRegistrar: { - abi: ResolverABI, - address: "0x00000beef055f7934784d6d81b6bc86665630dba", - startBlock: 123142726, - }, - }, - }, - - /** - * Contracts that power Reverse Resolution on Scroll Sepolia. - */ - [DatasourceNames.ReverseResolverScroll]: { - chain: scrollSepolia, - contracts: { - L2ReverseRegistrar: { - abi: ResolverABI, - address: "0x00000beef055f7934784d6d81b6bc86665630dba", - startBlock: 8175276, - }, - }, - }, - - /** - * Contracts that power Reverse Resolution on Linea Sepolia. - */ - [DatasourceNames.ReverseResolverLinea]: { - chain: lineaSepolia, - contracts: { - L2ReverseRegistrar: { - abi: ResolverABI, - address: "0x00000beef055f7934784d6d81b6bc86665630dba", - startBlock: 9267966, - }, - }, - }, - - [DatasourceNames.Seaport]: { - chain: sepolia, - contracts: { - Seaport1_5: { - abi: Seaport1_5, // Seaport 1.5 - address: "0x00000000000000adc04c56bf30ac9d3c0aaf14dc", - startBlock: 3365529, - }, - }, - }, } 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 * From 56fe65880ee0224948f279dfadffa41ebf46419d Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 26 Jan 2026 17:24:01 +0900 Subject: [PATCH 04/10] clean up some types and fix typechecks after merge --- .../src/graphql-api/lib/get-domain-by-fqdn.ts | 135 +++++++++------- apps/ensindexer/src/lib/ponder-helpers.ts | 13 +- apps/ensindexer/src/plugins/ensv2/plugin.ts | 29 ++-- .../plugins/protocol-acceleration/plugin.ts | 12 +- packages/datasources/src/lib/types.ts | 19 --- packages/datasources/src/sepolia-v2.ts | 149 +----------------- packages/ensnode-sdk/src/shared/thegraph.ts | 1 + packages/namehash-ui/src/utils/ensManager.ts | 1 + packages/namehash-ui/src/utils/ensMetadata.ts | 1 + 9 files changed, 112 insertions(+), 248 deletions(-) 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..16bc7d010 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 @@ -4,7 +4,7 @@ import { getUnixTime } from "date-fns"; import { Param, sql } from "drizzle-orm"; import { labelhash, namehash } from "viem"; -import { DatasourceNames, getDatasource, maybeGetDatasource } from "@ensnode/datasources"; +import { DatasourceNames, maybeGetDatasource } from "@ensnode/datasources"; import * as schema from "@ensnode/ensnode-schema"; import { type DomainId, @@ -22,24 +22,18 @@ 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); 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 +122,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}`); 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), - ); - console.log( - `ETHTLDResolver deferring '${nameWithoutTld}' to ENSv2 .eth Registry on Namechain...`, - ); + /////////////////////////// + + // 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; + + // 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 ENS_ROOT_V2_ETH_REGISTRY_ID = makeRegistryId(ENS_ROOT_V2_ETH_REGISTRY); + const NAMECHAIN_V2_ETH_REGISTRY_ID = makeRegistryId(NAMECHAIN_V2_ETH_REGISTRY); + + // if the path did not terminate at the .eth Registry, then it was not found + if (leaf.registry_id !== ENS_ROOT_V2_ETH_REGISTRY_ID) return null; + + console.log(name); + console.log(JSON.stringify(rows, null, 2)); - const NAMECHAIN_V2_ETH_REGISTRY_ID = makeRegistryId({ - chainId: namechain.chain.id, - address: namechain.contracts.ETHRegistry.address, - }); + // 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; - return v2_getDomainIdByFqdn(NAMECHAIN_V2_ETH_REGISTRY_ID, nameWithoutTld); + // Invariant: must be >= 2LD + if (labelHashPath.length < 2) { + throw new Error(`Invariant: Not >= 2LD??`); } - // finally, not found - return null; + // 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), + ); + console.log( + `ETHTLDResolver deferring '${nameWithoutTld}' to ENSv2 .eth Registry on Namechain...`, + ); + + return v2_getDomainIdByFqdn(NAMECHAIN_V2_ETH_REGISTRY_ID, nameWithoutTld); } diff --git a/apps/ensindexer/src/lib/ponder-helpers.ts b/apps/ensindexer/src/lib/ponder-helpers.ts index d8e48527b..1cf00ab4f 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/packages/datasources/src/lib/types.ts b/packages/datasources/src/lib/types.ts index fe0eb6643..72466e9d0 100644 --- a/packages/datasources/src/lib/types.ts +++ b/packages/datasources/src/lib/types.ts @@ -109,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/sepolia-v2.ts b/packages/datasources/src/sepolia-v2.ts index d6b686c2f..76c4ac58d 100644 --- a/packages/datasources/src/sepolia-v2.ts +++ b/packages/datasources/src/sepolia-v2.ts @@ -3,20 +3,11 @@ import { sepolia } from "viem/chains"; import { EnhancedAccessControl } from "./abis/ensv2/EnhancedAccessControl"; import { ETHRegistrar } from "./abis/ensv2/ETHRegistrar"; import { Registry } from "./abis/ensv2/Registry"; -// ABIs for ENSRoot Datasource -import { BaseRegistrar as root_BaseRegistrar } from "./abis/root/BaseRegistrar"; -import { LegacyEthRegistrarController as root_LegacyEthRegistrarController } from "./abis/root/LegacyEthRegistrarController"; -import { NameWrapper as root_NameWrapper } from "./abis/root/NameWrapper"; -import { Registry as root_Registry } from "./abis/root/Registry"; -import { UniversalRegistrarRenewalWithReferrer as root_UniversalRegistrarRenewalWithReferrer } from "./abis/root/UniversalRegistrarRenewalWithReferrer"; import { UniversalResolver as root_UniversalResolver } from "./abis/root/UniversalResolver"; -import { UnwrappedEthRegistrarController as root_UnwrappedEthRegistrarController } from "./abis/root/UnwrappedEthRegistrarController"; -import { WrappedEthRegistrarController as root_WrappedEthRegistrarController } from "./abis/root/WrappedEthRegistrarController"; -// Shared ABIs -import { StandaloneReverseRegistrar } from "./abis/shared/StandaloneReverseRegistrar"; import { ResolverABI } from "./lib/ResolverABI"; // Types import { DatasourceNames, type ENSNamespace } from "./lib/types"; +import SepoliaNamespace from "./sepolia"; /** * The Sepolia V2 ENSNamespace @@ -25,61 +16,15 @@ import { DatasourceNames, type ENSNamespace } from "./lib/types"; * ENS deployment, used for testing ENSv2. */ export default { + // Extends the existing Sepolia Namespace + ...SepoliaNamespace, + [DatasourceNames.ENSRoot]: { chain: sepolia, contracts: { - ENSv1RegistryOld: { - abi: root_Registry, // Registry was redeployed, same abi - address: "0x94f523b8261b815b87effcf4d18e6abef18d6e4b", - startBlock: 3702721, - }, - ENSv1Registry: { - abi: root_Registry, // Registry was redeployed, same abi - address: "0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e", - startBlock: 3702728, - }, - Resolver: { - abi: ResolverABI, - startBlock: 3702721, // ignores any Resolver events prior to `startBlock` of RegistryOld on Sepolia - }, - BaseRegistrar: { - abi: root_BaseRegistrar, - address: "0x57f1887a8bf19b14fc0df6fd9b2acc9af147ea85", - startBlock: 3702731, - }, - LegacyEthRegistrarController: { - abi: root_LegacyEthRegistrarController, - address: "0x7e02892cfc2bfd53a75275451d73cf620e793fc0", - startBlock: 3790197, - }, - WrappedEthRegistrarController: { - abi: root_WrappedEthRegistrarController, - address: "0xfed6a969aaa60e4961fcd3ebf1a2e8913ac65b72", - startBlock: 3790244, - }, - UnwrappedEthRegistrarController: { - abi: root_UnwrappedEthRegistrarController, - address: "0xfb3ce5d01e0f33f41dbb39035db9745962f1f968", - startBlock: 8579988, - }, - UniversalRegistrarRenewalWithReferrer: { - abi: root_UniversalRegistrarRenewalWithReferrer, - address: "0x7ab2947592c280542e680ba8f08a589009da8644", - startBlock: 9447519, - }, - NameWrapper: { - abi: root_NameWrapper, - address: "0x0635513f179d50a207757e05759cbd106d7dfce8", - startBlock: 3790153, - }, - UniversalResolver: { - abi: root_UniversalResolver, - address: "0xb7b7dadf4d42a08b3ec1d3a1079959dfbc8cffcc", - startBlock: 8515717, - }, - - // ENS V2 contracts + ...SepoliaNamespace[DatasourceNames.ENSRoot].contracts, + // add the ENS V2 contracts RootRegistry: { abi: Registry, address: "0x245de1984f9bb890c5db0b1fb839470c6a4c7e08", @@ -106,6 +51,7 @@ export default { }, }, + // add a namechain [DatasourceNames.Namechain]: { chain: sepolia, contracts: { @@ -133,85 +79,4 @@ export default { }, }, }, - - /** - * Contracts that power Reverse Resolution on the (Sepolia) ENS Root chain. - */ - [DatasourceNames.ReverseResolverRoot]: { - chain: sepolia, - contracts: { - DefaultReverseRegistrar: { - abi: StandaloneReverseRegistrar, - address: "0x4f382928805ba0e23b30cfb75fc9e848e82dfd47", - startBlock: 8579966, - }, - - DefaultReverseResolver1: { - abi: ResolverABI, - address: "0x8fade66b79cc9f707ab26799354482eb93a5b7dd", - startBlock: 3790251, - }, - DefaultReverseResolver2: { - abi: ResolverABI, - address: "0x8948458626811dd0c23eb25cc74291247077cc51", - startBlock: 7035086, - }, - DefaultReverseResolver3: { - abi: ResolverABI, - address: "0x9dc60e7bd81ccc96774c55214ff389d42ae5e9ac", - startBlock: 8580041, - }, - - DefaultPublicResolver3: { - abi: ResolverABI, - address: "0x8fade66b79cc9f707ab26799354482eb93a5b7dd", - startBlock: 3790251, - }, - DefaultPublicResolver4: { - abi: ResolverABI, - address: "0x8948458626811dd0c23eb25cc74291247077cc51", - startBlock: 7035086, - }, - DefaultPublicResolver5: { - abi: ResolverABI, - address: "0xe99638b40e4fff0129d56f03b55b6bbc4bbe49b5", - startBlock: 8580001, - }, - - BaseReverseResolver: { - abi: ResolverABI, - // https://adraffy.github.io/ens-normalize.js/test/resolver.html?sepolia#80014a34.reverse - address: "0xaf3b3f636be80b6709f5bd3a374d6ac0d0a7c7aa", - startBlock: 8580004, - }, - - LineaReverseResolver: { - abi: ResolverABI, - // https://adraffy.github.io/ens-normalize.js/test/resolver.html?sepolia#8000e705.reverse - address: "0x083da1dbc0f379ccda6ac81a934207c3d8a8a205", - startBlock: 8580005, - }, - - OptimismReverseResolver: { - abi: ResolverABI, - // https://adraffy.github.io/ens-normalize.js/test/resolver.html?sepolia#80aa37dc.reverse - address: "0xc9ae189772bd48e01410ab3be933637ee9d3aa5f", - startBlock: 8580026, - }, - - ArbitrumReverseResolver: { - abi: ResolverABI, - // https://adraffy.github.io/ens-normalize.js/test/resolver.html?sepolia#80066eee.reverse - address: "0x926f94d2adc77c86cb0050892097d49aadd02e8b", - startBlock: 8580003, - }, - - ScrollReverseResolver: { - abi: ResolverABI, - // https://adraffy.github.io/ens-normalize.js/test/resolver.html?sepolia#8008274f.reverse - address: "0x9fa59673e43f15bdb8722fdaf5c2107574b99062", - startBlock: 8580040, - }, - }, - }, } satisfies ENSNamespace; diff --git a/packages/ensnode-sdk/src/shared/thegraph.ts b/packages/ensnode-sdk/src/shared/thegraph.ts index 642811c4d..12179b320 100644 --- a/packages/ensnode-sdk/src/shared/thegraph.ts +++ b/packages/ensnode-sdk/src/shared/thegraph.ts @@ -43,6 +43,7 @@ const makeTheGraphSubgraphUrl = (namespace: ENSNamespaceId, apiKey: string) => { case ENSNamespaceIds.Mainnet: return `https://gateway.thegraph.com/api/${apiKey}/subgraphs/id/5XqPmWe6gjyrJtFn9cLy237i4cWw2j9HcUJEXsP5qGtH`; case ENSNamespaceIds.Sepolia: + case ENSNamespaceIds.SepoliaV2: return `https://gateway.thegraph.com/api/${apiKey}/subgraphs/id/G1SxZs317YUb9nQX3CC98hDyvxfMJNZH5pPRGpNrtvwN`; case ENSNamespaceIds.EnsTestEnv: return null; diff --git a/packages/namehash-ui/src/utils/ensManager.ts b/packages/namehash-ui/src/utils/ensManager.ts index bf0a310bf..37a2090f1 100644 --- a/packages/namehash-ui/src/utils/ensManager.ts +++ b/packages/namehash-ui/src/utils/ensManager.ts @@ -15,6 +15,7 @@ export function getEnsManagerUrl(namespaceId: ENSNamespaceId): URL | null { case ENSNamespaceIds.Mainnet: return new URL(`https://app.ens.domains/`); case ENSNamespaceIds.Sepolia: + case ENSNamespaceIds.SepoliaV2: return new URL(`https://sepolia.app.ens.domains/`); case ENSNamespaceIds.EnsTestEnv: // ens-test-env runs on a local chain and is not supported by app.ens.domains diff --git a/packages/namehash-ui/src/utils/ensMetadata.ts b/packages/namehash-ui/src/utils/ensMetadata.ts index 7b3a6ab99..a8b62d362 100644 --- a/packages/namehash-ui/src/utils/ensMetadata.ts +++ b/packages/namehash-ui/src/utils/ensMetadata.ts @@ -23,6 +23,7 @@ export function getEnsMetadataServiceAvatarUrl( case ENSNamespaceIds.Mainnet: return new URL(name, `https://metadata.ens.domains/mainnet/avatar/`); case ENSNamespaceIds.Sepolia: + case ENSNamespaceIds.SepoliaV2: return new URL(name, `https://metadata.ens.domains/sepolia/avatar/`); case ENSNamespaceIds.EnsTestEnv: // ens-test-env runs on a local chain and is not supported by metadata.ens.domains From 5c94b72c75cbde500c969d57b67fb8366252890d Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 26 Jan 2026 17:26:40 +0900 Subject: [PATCH 05/10] docs(changeset): 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 should be considered highly experimental and unstable. --- .changeset/short-cobras-bathe.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/short-cobras-bathe.md diff --git a/.changeset/short-cobras-bathe.md b/.changeset/short-cobras-bathe.md new file mode 100644 index 000000000..b702b29dd --- /dev/null +++ b/.changeset/short-cobras-bathe.md @@ -0,0 +1,5 @@ +--- +"@ensnode/datasources": minor +--- + +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 should be considered highly experimental and unstable. From 4d7670ae86dc803673a52645e9f590743744a902 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 26 Jan 2026 17:53:52 +0900 Subject: [PATCH 06/10] fic nits from bot --- .../src/graphql-api/lib/get-domain-by-fqdn.ts | 28 +++++++++++-------- packages/ensnode-sdk/src/shared/thegraph.ts | 2 +- 2 files changed, 17 insertions(+), 13 deletions(-) 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 16bc7d010..5a6f6aeec 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,7 +2,7 @@ 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, maybeGetDatasource } from "@ensnode/datasources"; import * as schema from "@ensnode/ensnode-schema"; @@ -28,6 +28,7 @@ import { import { getLatestRegistration } from "@/graphql-api/lib/get-latest-registration"; import { db } from "@/lib/db"; +import logger from "@/lib/logger"; const namechain = maybeGetDatasource(config.namespace, DatasourceNames.Namechain); @@ -127,7 +128,7 @@ async function v2_getDomainIdByFqdn( /////////////////////////// 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; } @@ -164,8 +165,7 @@ async function v2_getDomainIdByFqdn( // if the path did not terminate at the .eth Registry, then it was not found if (leaf.registry_id !== ENS_ROOT_V2_ETH_REGISTRY_ID) return null; - console.log(name); - console.log(JSON.stringify(rows, null, 2)); + logger.debug({ name, rows }); // 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 @@ -173,17 +173,21 @@ async function v2_getDomainIdByFqdn( // Invariant: must be >= 2LD if (labelHashPath.length < 2) { - throw new Error(`Invariant: Not >= 2LD??`); + throw new Error(`Invariant: '${name}' is not >= 2LD (has depth ${labelHashPath.length})!`); } - // Invariant: must be a .eth subname + // Invariant: LabelHashPath must originate at 'eth' if (labelHashPath[0] !== ETH_LABELHASH) { - throw new Error(`Invariant: Not .eth subname????`); + throw new Error( + `Invariant: '${name}' terminated at .eth Registry but the queried labelHashPath (${JSON.stringify(labelHashPath)}) does not originate with 'eth' (${ETH_LABELHASH}).`, + ); } - // Invariant: must be a .eth subname - if (leaf.label_hash !== labelhash("eth")) { - throw new Error(`Invariant: Not .eth subname??`); + // 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}).`, + ); } // construct the node of the 2ld @@ -194,7 +198,7 @@ async function v2_getDomainIdByFqdn( const registration = await getLatestRegistration(ensv1DomainId); if (registration && !isRegistrationFullyExpired(registration, now)) { - console.log( + logger.debug( `ETHTLDResolver deferring to actively registered name ${dotEth2LDNode} in ENSv1...`, ); return await v1_getDomainIdByFqdn(name); @@ -204,7 +208,7 @@ async function v2_getDomainIdByFqdn( const nameWithoutTld = interpretedLabelsToInterpretedName( interpretedNameToInterpretedLabels(name).slice(0, -1), ); - console.log( + logger.debug( `ETHTLDResolver deferring '${nameWithoutTld}' to ENSv2 .eth Registry on Namechain...`, ); diff --git a/packages/ensnode-sdk/src/shared/thegraph.ts b/packages/ensnode-sdk/src/shared/thegraph.ts index 12179b320..a67d7b5f3 100644 --- a/packages/ensnode-sdk/src/shared/thegraph.ts +++ b/packages/ensnode-sdk/src/shared/thegraph.ts @@ -43,8 +43,8 @@ const makeTheGraphSubgraphUrl = (namespace: ENSNamespaceId, apiKey: string) => { case ENSNamespaceIds.Mainnet: return `https://gateway.thegraph.com/api/${apiKey}/subgraphs/id/5XqPmWe6gjyrJtFn9cLy237i4cWw2j9HcUJEXsP5qGtH`; case ENSNamespaceIds.Sepolia: - case ENSNamespaceIds.SepoliaV2: return `https://gateway.thegraph.com/api/${apiKey}/subgraphs/id/G1SxZs317YUb9nQX3CC98hDyvxfMJNZH5pPRGpNrtvwN`; + case ENSNamespaceIds.SepoliaV2: case ENSNamespaceIds.EnsTestEnv: return null; default: From 0a149f8347644a16db1782df58d5d71091dd1d04 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 26 Jan 2026 17:57:01 +0900 Subject: [PATCH 07/10] deps: fix audit deps --- package.json | 4 +++- pnpm-lock.yaml | 38 ++++++++++++++++++++------------------ 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index c3fdba1de..1579c054e 100644 --- a/package.json +++ b/package.json @@ -40,7 +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.2": ">=7.5.3" + "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/pnpm-lock.yaml b/pnpm-lock.yaml index d7f19b0d1..8e4f7b15b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -92,7 +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.2: '>=7.5.3' + 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': @@ -6409,8 +6411,8 @@ packages: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} - lodash-es@4.17.21: - resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + lodash-es@4.17.23: + resolution: {integrity: sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==} lodash.camelcase@4.3.0: resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} @@ -6442,8 +6444,8 @@ packages: lodash.uniq@4.5.0: resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + lodash@4.17.23: + resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} long@5.3.2: resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} @@ -7968,8 +7970,8 @@ packages: resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} engines: {node: '>=6'} - tar@7.5.3: - resolution: {integrity: sha512-ENg5JUHUm2rDD7IvKNFGzyElLXNjachNLp6RaGf4+JOgxXHkqA+gq81ZAMCUmtMtqBsoU62lcp6S27g1LCYGGQ==} + tar@7.5.6: + resolution: {integrity: sha512-xqUeu2JAIJpXyvskvU3uvQW8PAmHrtXp2KDuMJwQqW8Sqq0CaZBAQ+dKS3RBXVhU4wC5NjAdKrmh84241gO9cA==} engines: {node: '>=18'} tdigest@0.1.2: @@ -9814,12 +9816,12 @@ snapshots: dependencies: '@chevrotain/gast': 11.0.3 '@chevrotain/types': 11.0.3 - lodash-es: 4.17.21 + lodash-es: 4.17.23 '@chevrotain/gast@11.0.3': dependencies: '@chevrotain/types': 11.0.3 - lodash-es: 4.17.21 + lodash-es: 4.17.23 '@chevrotain/regexp-to-ast@11.0.3': {} @@ -10504,7 +10506,7 @@ snapshots: local-pkg: 0.5.1 pathe: 1.1.2 svgo: 3.3.2 - tar: 7.5.3 + tar: 7.5.6 transitivePeerDependencies: - debug - supports-color @@ -13421,7 +13423,7 @@ snapshots: chevrotain-allstar@0.3.1(chevrotain@11.0.3): dependencies: chevrotain: 11.0.3 - lodash-es: 4.17.21 + lodash-es: 4.17.23 chevrotain@11.0.3: dependencies: @@ -13430,7 +13432,7 @@ snapshots: '@chevrotain/regexp-to-ast': 11.0.3 '@chevrotain/types': 11.0.3 '@chevrotain/utils': 11.0.3 - lodash-es: 4.17.21 + lodash-es: 4.17.23 chokidar@3.6.0: dependencies: @@ -13846,7 +13848,7 @@ snapshots: dagre-d3-es@7.0.13: dependencies: d3: 7.9.0 - lodash-es: 4.17.21 + lodash-es: 4.17.23 data-urls@6.0.0: dependencies: @@ -15092,7 +15094,7 @@ snapshots: dependencies: p-locate: 4.1.0 - lodash-es@4.17.21: {} + lodash-es@4.17.23: {} lodash.camelcase@4.3.0: {} @@ -15114,7 +15116,7 @@ snapshots: lodash.uniq@4.5.0: {} - lodash@4.17.21: {} + lodash@4.17.23: {} long@5.3.2: {} @@ -15379,7 +15381,7 @@ snapshots: dompurify: 3.3.0 katex: 0.16.25 khroma: 2.1.0 - lodash-es: 4.17.21 + lodash-es: 4.17.23 marked: 16.4.1 roughjs: 4.6.6 stylis: 4.3.6 @@ -17162,7 +17164,7 @@ snapshots: tapable@2.3.0: {} - tar@7.5.3: + tar@7.5.6: dependencies: '@isaacs/fs-minipass': 4.0.1 chownr: 3.0.0 @@ -17869,7 +17871,7 @@ snapshots: yaml-language-server@1.15.0: dependencies: ajv: 8.17.1 - lodash: 4.17.21 + lodash: 4.17.23 request-light: 0.5.8 vscode-json-languageservice: 4.1.8 vscode-languageserver: 7.0.0 From 9870dcff8b290a662ecff1f3f5e91566bebac1a9 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 26 Jan 2026 17:59:27 +0900 Subject: [PATCH 08/10] fix bot nit --- apps/ensapi/src/graphql-api/lib/get-domain-by-fqdn.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) 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 5a6f6aeec..406283eee 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 @@ -4,7 +4,7 @@ import { getUnixTime } from "date-fns"; import { Param, sql } from "drizzle-orm"; import { namehash } from "viem"; -import { DatasourceNames, maybeGetDatasource } from "@ensnode/datasources"; +import { DatasourceNames } from "@ensnode/datasources"; import * as schema from "@ensnode/ensnode-schema"; import { type DomainId, @@ -30,8 +30,6 @@ import { getLatestRegistration } from "@/graphql-api/lib/get-latest-registration import { db } from "@/lib/db"; import logger from "@/lib/logger"; -const namechain = maybeGetDatasource(config.namespace, DatasourceNames.Namechain); - const ETH_LABELHASH = labelhashLiteralLabel("eth" as LiteralLabel); const ROOT_REGISTRY_ID = getENSv2RootRegistryId(config.namespace); @@ -162,15 +160,11 @@ async function v2_getDomainIdByFqdn( const ENS_ROOT_V2_ETH_REGISTRY_ID = makeRegistryId(ENS_ROOT_V2_ETH_REGISTRY); const NAMECHAIN_V2_ETH_REGISTRY_ID = makeRegistryId(NAMECHAIN_V2_ETH_REGISTRY); - // if the path did not terminate at the .eth Registry, then it was not found + // 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 }); - // 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: '${name}' is not >= 2LD (has depth ${labelHashPath.length})!`); From b3680e029d302670042c45a860991670d6d53e49 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 26 Jan 2026 19:27:18 +0900 Subject: [PATCH 09/10] fix: bot nits --- .../src/graphql-api/lib/get-domain-by-fqdn.ts | 21 ++++++++++--------- package.json | 6 +++--- pnpm-lock.yaml | 6 +++--- 3 files changed, 17 insertions(+), 16 deletions(-) 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 406283eee..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 @@ -149,16 +149,7 @@ async function v2_getDomainIdByFqdn( ); if (!ENS_ROOT_V2_ETH_REGISTRY) return null; - // 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 ENS_ROOT_V2_ETH_REGISTRY_ID = makeRegistryId(ENS_ROOT_V2_ETH_REGISTRY); - const NAMECHAIN_V2_ETH_REGISTRY_ID = makeRegistryId(NAMECHAIN_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; @@ -199,6 +190,16 @@ async function v2_getDomainIdByFqdn( } // 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), ); @@ -206,5 +207,5 @@ async function v2_getDomainIdByFqdn( `ETHTLDResolver deferring '${nameWithoutTld}' to ENSv2 .eth Registry on Namechain...`, ); - return v2_getDomainIdByFqdn(NAMECHAIN_V2_ETH_REGISTRY_ID, nameWithoutTld); + return v2_getDomainIdByFqdn(NAMECHAIN_V2_ETH_REGISTRY_ID, nameWithoutTld, { now }); } diff --git a/package.json b/package.json index 1579c054e..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@<=4.17.22": ">=4.17.23", - "lodash-es@<=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/pnpm-lock.yaml b/pnpm-lock.yaml index 8e4f7b15b..390928c64 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@<=4.17.22: '>=4.17.23' - lodash-es@<=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': From 4e557d7194d59bf803e54abd7f1233e7cba4b668 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 26 Jan 2026 19:36:06 +0900 Subject: [PATCH 10/10] update changeset --- .changeset/short-cobras-bathe.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/short-cobras-bathe.md b/.changeset/short-cobras-bathe.md index b702b29dd..d5d0c3324 100644 --- a/.changeset/short-cobras-bathe.md +++ b/.changeset/short-cobras-bathe.md @@ -1,5 +1,5 @@ --- -"@ensnode/datasources": minor +"@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 should be considered highly experimental and unstable. +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.