diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2481304764..9f7f7c544c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,10 +4,7 @@ Thank you for your interest in contributing to ENSNode! We welcome contributions ## Documentation -For detailed contribution guidelines and setup instructions: - -- **ENSNode**: Visit [ENSNode Contributing Guide](https://ensnode.io/docs/contributing) -- **ENSRainbow**: Visit [ENSRainbow Contributing Guide](https://ensnode.io/ensrainbow/contributing) +For detailed setup instructions, visit the [ENSNode Contributing Guide](https://ensnode.io/docs/reference/contributing). ## Getting Help diff --git a/README.md b/README.md index 721eb1bf79..17fb7c5761 100644 --- a/README.md +++ b/README.md @@ -19,87 +19,37 @@ # ENSNode -ENSNode is the new multichain indexer for ENS, including [ENSv2](https://roadmap.ens.domains/roadmap/). - -Full Documentation ➡︎ ensnode.io - -[Join us on Telegram](https://t.me/ensnode) to get support, share ideas, and discuss the future of ENSNode. - -## The future of ENS indexing - -ENSNode provides enhanced ENS indexing capabilities beyond the ENS Subgraph, including faster indexing and simpler self-hosted deployments. Initial multichain capabilities include indexing mainnet, Basenames, Lineanames, 3DNS, and more, providing a unified multichain namespace via a subgraph-compatible GraphQL API. When exclusively activating our subgraph plugin, ENSNode has full data equivalency with the ENS Subgraph. - -- Multichain ENS Namespace - - flattened, unified, multichain and multiregistrar namespace via optional plugins - - ✅ All names added to the ENS Registry and the ENS NameWrapper - - ✅ All direct subnames of .eth - - ✅ [Basenames](https://www.base.org/names) (`.base.eth`) - - ✅ [Lineanames](https://names.linea.build/) (`.linea.eth`) - - ✅ [3DNS](https://3dns.box) Support (`.box`, `.xyz`, +more) - - 🚧 Offchain Names - - `.cb.id`, `.uni.id`, + more - - [NameStone](https://namestone.com/) Names - - [NameSpace](https://namespace.ninja/) Names - - [Justaname](https://www.justaname.id/) Names - - 🚧 + more -- Built on [Ponder](https://ponder.sh) - - ✅ Rapid Indexing & Backfill - - 10x faster than ENS Subgraph - - Mainnet Cached Backfill: **4.5 hours** on M1 Macbook Pro - - ✅ More efficient than ENS Subgraph - - 35x less disk space and 35% fewer RPC credits [[source]](https://ponder.sh/docs/why-ponder) - - ✅ End-to-end type safety - - ✅ Automatically reconciles chain reorganizations - - ✅ Deploy anywhere with Node.js & Docker -- Designed for web developers - - ✅ [use ENSNode with ENSjs](https://ensnode.io/docs/usage/with-ensjs) - - ✅ [GraphQL APIs](https://ensnode.io/docs/usage/api) - - ✅ Custom APIs for your app -- [1:1 Subgraph Compatibility](https://ensnode.io/docs/concepts/what-is-the-ens-subgraph) - - ✅ [100% data equivalency](https://github.com/namehash/ens-subgraph-transition-tools) as compared to Subgraph - - ✅ 100% ensjs test suites passing via [ens-test-env](https://github.com/namehash/ens-test-env) - - ✅ 100% ens-app-v3 test suites passing via [ens-test-env](https://github.com/namehash/ens-test-env) -- Own your ENSNode index - - ✅ [Deploy ENSNode to your own cloud](https://ensnode.io/docs/deploying) for controlling your own uptime guarantees and private queries - -## Why Index ENS? Why ENSNode? - -The ENS protocol enables resolution of names across multiple chains and, increasingly, offchain data sources. ENS smart contracts optimize for some operations, but not others: for example, if you wanted to list all of a user's owned names, there's no practical way to do this through ENS contracts, and an indexer like ENSNode _must_ be used. - -An indexer aggregates and reorganizes the representation of ENS's state to make important queries like that possible, efficient, and convenient: +[ENSNode](https://ensnode.io) is the full-stack development platform for [ENSv2](https://ens.domains/ensv2). Use ENSNode to achieve full ENSv2 readiness even before ENSv2 launches. -```graphql -# get all of a user's domains by address — not possible on-chain! -query Domains($adress: String!) { - domains(where: { owner: $address }) { - id - name - ... - } -} -``` - -Historically the ENS Subgraph has served this purpose, but the Subgraph's limitations are increasingly severe as the ENS protocol grows: the ENS Subgraph can only index a single chain at a time (ex: mainnet) and can't integrate with names or that require [CCIP-Read](https://docs.ens.domains/resolvers/ccip-read), which includes all names stored on L2 chains or offchain. - -Given how the majority of ENS names are now issued off of mainnet, only a small percentage of ENS names can be indexed by the ENS Subgraph. This issue will only grow more severe with the launch of [ENSv2](https://roadmap.ens.domains/roadmap/) and [Namechain](https://app.ens.domains/ens-v2). +The easiest way to get started is through the new **ENS Omnigraph API** — the world's first and only API to support querying the full state of both ENSv1 and ENSv2 in a single unified API. -ENSNode is a modern, multichain indexer for ENS. It supports backwards-compatible Subgraph queries and sets the stage for supporting [ENSv2](https://roadmap.ens.domains/roadmap/), in particular [Namechain](https://app.ens.domains/ens-v2) and the growing set of off-chain ENS names (like `.uni.eth` and `.cb.id`). +- 📚 **Docs:** [ensnode.io](https://ensnode.io) +- 🚀 **Quickstart:** [ensnode.io/docs/integrate](https://ensnode.io/docs/integrate) +- 💬 **Telegram:** [t.me/ensnode](https://t.me/ensnode) -## Documentation +## Example: query the subnames of '.eth' via the ENS Omnigraph API -Documentation for the ENSNode suite of apps is available at [ensnode.io](https://ensnode.io). +Note that substantial ENS data is not directly queryable through traditional smart contract RPC calls. Examples include: the subnames of a name, or the names owned by an address. ENSNode is the world's first and only solution that makes the full set of ENS data spanning both ENSv1 and ENSv2 accessible through a single unified API. -## Running with Docker - -```bash -docker compose -f docker/docker-compose.yml up -d +```graphql +query HelloWorld { + domain(by: { name: "eth" }) { + __typename + canonical { name { interpreted } } + owner { address } + subdomains(first: 20) { + totalCount + edges { node { __typename canonical { name { interpreted } } owner { address } } } + } + } +} ``` -See [`docker/README.md`](docker/README.md) for all use cases and commands. +To get started with ENSNode and the ENS Omnigraph API, follow the [Quickstart](https://ensnode.io/docs/integrate). -## Contributions +## Contributing -We welcome community contributions and feedback—please see [CONTRIBUTING.md](CONTRIBUTING.md) for more information. +See [CONTRIBUTING.md](CONTRIBUTING.md). ## Sponsors @@ -110,93 +60,8 @@ NameHash has received generous support from the [ENS DAO](https://ensdao.org/) a

-## Contact Us - -Visit our [website](https://namehashlabs.org/) to get in contact, or [join us on Telegram](https://t.me/ensnode). - ## License Licensed under the MIT License, Copyright © 2025-present [NameHash Labs](https://namehashlabs.org). See [LICENSE](./LICENSE) for more information. - -## Repo Overview - -The ENSNode monorepo contains multiple modules in the following subdirectories: - -- [`apps`](apps) executable applications. -- [`packages`](packages) for libraries that can be embedded into apps. -- [`docs`](docs) documentation sites. - -### [`apps/ensadmin`](apps/ensadmin) - - - - - - -
ENSadminENSAdmin
- -ENSAdmin is a dashboard for ENSNode and the ENS protocol. See the [ENSAdmin documentation](https://ensnode.io/ensadmin) for more details. - -### [`apps/ensindexer`](apps/ensindexer) - - - - - - -
ENSIndexerENSIndexer
- -ENSIndexer is a Ponder-powered indexer for ENS across multiple chains. See the [ENSIndexer documentation](https://ensnode.io/ensindexer) for more details. - -### [`apps/ensrainbow`](apps/ensrainbow) - - - - - - -
ENSRainbowENSRainbow
- -ENSRainbow heals unknown ENS names: it provides a simple API to recover labels from their labelHashes. See the [ENSRainbow documentation](https://ensnode.io/ensrainbow) for more details. - -## Packages - -### [`packages/ensdb-sdk`](packages/ensdb-sdk) - -Software Development Kit for interacting with data in ENSDb. - -### [`packages/ensnode-sdk`](packages/ensnode-sdk) - -Software Development Kit for interacting with ENSNode services and data. Includes common utilities used across ENSNode applications. - -### [`packages/datasources`](packages/datasources) - -Convenient catalog of ENSNode-related datasources including chain, contract addresses, start blocks, and event filters. - -### [`packages/ensrainbow-sdk`](packages/ensrainbow-sdk) - -TypeScript library for interacting with the [ENSRainbow API](apps/ensrainbow). - -### [`packages/ponder-sdk`](packages/ponder-sdk) - -A utility library for interacting with Ponder apps and data. - -### [`packages/ponder-subgraph`](packages/ponder-subgraph) - -Subgraph-compatible GraphQL API. - -### [`packages/shared-configs`](packages/shared-configs) - -Shared internal configuration files. - -## Docs - -### [`docs/ensnode.io`](docs/ensnode.io/) - -Astro/Starlight documentation app for ENSNode, ENSIndexer, ENSAdmin, and ENSRainbow. - -### [`docs/ensrainbow.io`](docs/ensrainbow.io/) - -Landing page for ENSRainbow. diff --git a/docs/ensnode.io/astro.config.mjs b/docs/ensnode.io/astro.config.mjs index 1b04ccc5d2..2631833bfd 100644 --- a/docs/ensnode.io/astro.config.mjs +++ b/docs/ensnode.io/astro.config.mjs @@ -36,7 +36,6 @@ export default defineConfig({ "/docs": "/docs/integrate", "/ensnode": "/docs/integrate", "/ensnode/deploying/railway": "/docs/services/ensrainbow/deploying/railway", - "/ensnode/concepts/what-is-ensnode": "/docs/reference/what-is-ensnode", "/ensnode/concepts/what-is-the-ens-subgraph": "/docs/reference/subgraph-legacy/what-is-the-ens-subgraph", "/docs/reference/what-is-the-ens-subgraph": @@ -53,6 +52,12 @@ export default defineConfig({ "/ensrainbow/concepts/label-sets-and-versioning": "/docs/services/ensrainbow/concepts/label-sets-and-versioning", "/docs/reference/rest-api": "/docs/services/ensapi/reference/api-reference", + "/docs/integrate/hosted-instances": "/docs/hosted-instances", + "/docs/integrate/migrate-from-subgraph": "/docs/integrate/ensv2-readiness", + "/docs/reference/ensnode-v2-notes": "/docs/integrate/ensv2-readiness", + "/docs/reference/mainnet-registered-subnames-of-subregistries": "/docs/integrate/omnigraph", + "/docs/reference/roadmap": "/docs/integrate/ensv2-readiness", + "/docs/reference/what-is-ensnode": "/docs/integrate/why-ensnode", }, env: { schema: { diff --git a/docs/ensnode.io/config/integrations/starlight/sidebar-topics/hosted-instances.ts b/docs/ensnode.io/config/integrations/starlight/sidebar-topics/hosted-instances.ts new file mode 100644 index 0000000000..9b40f1a6bd --- /dev/null +++ b/docs/ensnode.io/config/integrations/starlight/sidebar-topics/hosted-instances.ts @@ -0,0 +1,18 @@ +export const hostedInstancesSidebarTopic = { + label: "Hosted Instances", + link: "/docs/hosted-instances", + icon: "cloud-download", + items: [ + { + label: "Hosted Instances", + collapsed: false, + items: [ + { label: "v2 Sepolia", link: "/docs/hosted-instances#ensnode-v2-sepolia" }, + { label: "Alpha", link: "/docs/hosted-instances#ensnode-alpha" }, + { label: "Alpha-Sepolia", link: "/docs/hosted-instances#ensnode-alpha-sepolia" }, + { label: "Mainnet", link: "/docs/hosted-instances#ensnode-mainnet" }, + { label: "Sepolia", link: "/docs/hosted-instances#ensnode-sepolia" }, + ], + }, + ], +}; diff --git a/docs/ensnode.io/config/integrations/starlight/sidebar-topics/index.ts b/docs/ensnode.io/config/integrations/starlight/sidebar-topics/index.ts index 4a884cf3e3..e9d88537bf 100644 --- a/docs/ensnode.io/config/integrations/starlight/sidebar-topics/index.ts +++ b/docs/ensnode.io/config/integrations/starlight/sidebar-topics/index.ts @@ -1,5 +1,6 @@ import type { StarlightSidebarTopicsUserConfig } from "starlight-sidebar-topics"; +import { hostedInstancesSidebarTopic } from "./hosted-instances"; import { integrateSidebarTopic } from "./integrate"; import { servicesSidebarTopic } from "./services"; import { referenceSidebarTopic } from "./reference"; @@ -7,7 +8,8 @@ import { selfHostSidebarTopic } from "./self-host"; export const starlightSidebarTopicsConfig = [ integrateSidebarTopic, + hostedInstancesSidebarTopic, selfHostSidebarTopic, - referenceSidebarTopic, servicesSidebarTopic, + referenceSidebarTopic, ] satisfies StarlightSidebarTopicsUserConfig; diff --git a/docs/ensnode.io/config/integrations/starlight/sidebar-topics/integrate.ts b/docs/ensnode.io/config/integrations/starlight/sidebar-topics/integrate.ts index 01b66e1bd2..cdfb0044e2 100644 --- a/docs/ensnode.io/config/integrations/starlight/sidebar-topics/integrate.ts +++ b/docs/ensnode.io/config/integrations/starlight/sidebar-topics/integrate.ts @@ -29,7 +29,7 @@ export const integrateSidebarTopic = { }, { label: "Examples", - collapsed: false, + collapsed: true, items: [ { label: "Overview", @@ -153,14 +153,6 @@ export const integrateSidebarTopic = { }, ], }, - { - label: "Migrate from ENS Subgraph", - link: "/docs/integrate/migrate-from-subgraph", - }, - { - label: "Hosted Instances", - link: "/docs/integrate/hosted-instances", - }, { label: "AI / LLM Tooling", link: "/docs/integrate/ai-llm", diff --git a/docs/ensnode.io/config/integrations/starlight/sidebar-topics/reference.ts b/docs/ensnode.io/config/integrations/starlight/sidebar-topics/reference.ts index c281f98861..d4265bd527 100644 --- a/docs/ensnode.io/config/integrations/starlight/sidebar-topics/reference.ts +++ b/docs/ensnode.io/config/integrations/starlight/sidebar-topics/reference.ts @@ -11,22 +11,6 @@ export const referenceSidebarTopic = { label: "Terminology", link: "/docs/reference/terminology", }, - { - label: "Roadmap", - link: "/docs/reference/roadmap", - }, - { - label: "What is ENSNode?", - link: "/docs/reference/what-is-ensnode", - }, - { - label: "ENSNode V2 Notes", - link: "/docs/reference/ensnode-v2-notes", - }, - { - label: "Mainnet Subnames of Subregistries", - link: "/docs/reference/mainnet-registered-subnames-of-subregistries", - }, { label: "Subgraph API (Legacy)", collapsed: true, diff --git a/docs/ensnode.io/config/integrations/starlight/sidebar-topics/services.ts b/docs/ensnode.io/config/integrations/starlight/sidebar-topics/services.ts index f346f0cbbb..36e0861be0 100644 --- a/docs/ensnode.io/config/integrations/starlight/sidebar-topics/services.ts +++ b/docs/ensnode.io/config/integrations/starlight/sidebar-topics/services.ts @@ -5,42 +5,33 @@ export const servicesSidebarTopic = { items: [ { label: "Overview", link: "/docs/services" }, { - label: "ENSApi", - collapsed: true, - items: [ - { label: "Overview", link: "/docs/services/ensapi" }, - { label: "Configuration", link: "/docs/services/ensapi/usage/configuration" }, - { label: "API Reference", link: "/docs/services/ensapi/reference/api-reference" }, - { label: "Contributing", link: "/docs/services/ensapi/contributing" }, - ], - }, - { - label: "ENSIndexer", + label: "ENSAdmin", collapsed: true, items: [ - { label: "Overview", link: "/docs/services/ensindexer" }, - { label: "Startup Sequence", link: "/docs/services/ensindexer/concepts/startup-sequence" }, - { - label: "Usage", - collapsed: true, - items: [ - { label: "Configuration", link: "/docs/services/ensindexer/usage/configuration" }, - { label: "Management", link: "/docs/services/ensindexer/usage/management" }, - ], - }, + { label: "Overview", link: "/docs/services/ensadmin" }, { label: "Contributing", collapsed: true, items: [ - { label: "Overview", link: "/docs/services/ensindexer/contributing" }, + { label: "Overview", link: "/docs/services/ensadmin/contributing" }, { - label: "Creating a Plugin", - link: "/docs/services/ensindexer/contributing/creating-a-plugin", + label: "Using Docker", + link: "/docs/services/ensadmin/contributing/docker", }, ], }, ], }, + { + label: "ENSApi", + collapsed: true, + items: [ + { label: "Overview", link: "/docs/services/ensapi" }, + { label: "Configuration", link: "/docs/services/ensapi/usage/configuration" }, + { label: "API Reference", link: "/docs/services/ensapi/reference/api-reference" }, + { label: "Contributing", link: "/docs/services/ensapi/contributing" }, + ], + }, { label: "ENSDb", collapsed: true, @@ -80,6 +71,33 @@ export const servicesSidebarTopic = { }, ], }, + { + label: "ENSIndexer", + collapsed: true, + items: [ + { label: "Overview", link: "/docs/services/ensindexer" }, + { label: "Startup Sequence", link: "/docs/services/ensindexer/concepts/startup-sequence" }, + { + label: "Usage", + collapsed: true, + items: [ + { label: "Configuration", link: "/docs/services/ensindexer/usage/configuration" }, + { label: "Management", link: "/docs/services/ensindexer/usage/management" }, + ], + }, + { + label: "Contributing", + collapsed: true, + items: [ + { label: "Overview", link: "/docs/services/ensindexer/contributing" }, + { + label: "Creating a Plugin", + link: "/docs/services/ensindexer/contributing/creating-a-plugin", + }, + ], + }, + ], + }, { label: "ENSRainbow", collapsed: true, @@ -168,24 +186,6 @@ export const servicesSidebarTopic = { }, ], }, - { - label: "ENSAdmin", - collapsed: true, - items: [ - { label: "Overview", link: "/docs/services/ensadmin" }, - { - label: "Contributing", - collapsed: true, - items: [ - { label: "Overview", link: "/docs/services/ensadmin/contributing" }, - { - label: "Using Docker", - link: "/docs/services/ensadmin/contributing/docker", - }, - ], - }, - ], - }, { label: "ENSEngine", collapsed: true, diff --git a/docs/ensnode.io/src/components/molecules/IntegrateHostedEnsNodeTip.astro b/docs/ensnode.io/src/components/molecules/IntegrateHostedEnsNodeTip.astro index 99187a3479..4369656c3d 100644 --- a/docs/ensnode.io/src/components/molecules/IntegrateHostedEnsNodeTip.astro +++ b/docs/ensnode.io/src/components/molecules/IntegrateHostedEnsNodeTip.astro @@ -7,7 +7,7 @@ You don't need to run your own ENSNode to follow this guide — the steps below diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/hosted-instances.mdx b/docs/ensnode.io/src/content/docs/docs/hosted-instances.mdx similarity index 75% rename from docs/ensnode.io/src/content/docs/docs/integrate/hosted-instances.mdx rename to docs/ensnode.io/src/content/docs/docs/hosted-instances.mdx index a85a83e96e..4cdd5bb7d9 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/hosted-instances.mdx +++ b/docs/ensnode.io/src/content/docs/docs/hosted-instances.mdx @@ -1,10 +1,11 @@ --- -title: Using Hosted ENSNode Instances +title: Hosted ENSNode Instances sidebar: - label: Hosted ENSNode Instances + label: Overview order: 1 --- +import { LinkCard } from "@astrojs/starlight/components"; import HostedEnsNodeInstances from "@components/molecules/HostedEnsNodeInstances.astro"; ## Hosted Instances @@ -15,22 +16,26 @@ These instances are provided free of charge with no API key required, have no ra ### Available instance configurations -Each ENSNode hosted instance is configured for a specific ENS namespace and activated ENSNode plugins. The ENS namespace is the source of truth for the data indexed by the instance, and the activated ENSNode plugins determine the specific data model produced by indexing and available for querying. +Each ENSNode hosted instance is configured for a specific ENS **namespace** and activated ENSNode **plugins**. The ENS namespace identifies which ENS protocol deployment will be indexed by ENSNode (ex: mainnet or sepolia). The activated plugins determine the specific indexed data model ENSIndexer will produce in ENSDb and therefore which APIs ENSApi will make available to query. -Each ENS namespace is associated with a particular ENS root registry deployment, which may or may not have completed the transition from ENSv1 to ENSv2. Currently, ENSNode supports the following ENS namespaces: +Each ENS namespace is associated with a particular ENS Root Registry deployment, which may or may not have completed the transition from ENSv1 to ENSv2. Currently, ENSNode supports the following ENS namespaces: - `mainnet` (ENSv1) - `sepolia` (ENSv1) -- `sepolia-v2` (An independent deployment of ENS to Sepolia that is already upgraded to ENSv2) -- `ens-test-env` (A deployment of ENSv2 to a local Anvil chain for development and testing. For details see https://github.com/ensdomains/ens-test-env and https://github.com/ensdomains/contracts-v2) +- `sepolia-v2` (ENSv1+ENSv2 — An independent deployment of ENS to Sepolia that is already upgraded to ENSv2) +- `ens-test-env` (ENSv1+ENSv2 — A deployment of ENSv2 to a local Anvil chain for development and testing. For details see https://github.com/ensdomains/ens-test-env and https://github.com/ensdomains/contracts-v2) More details about ENS namespaces can be found inside [ENSNode's datasources package](https://github.com/namehash/ensnode/tree/main/packages/datasources). -### ENSv2 instances +### ENSv2 Instances These instances are associated with an ENS namespace that has upgraded to ENSv2 and demonstrate the latest ENSv2 support in ENSNode. #### ENSNode 'v2 Sepolia' +:::tip[v2 Sepolia] +The `sepolia-v2` namespace is undergoing active development by the ENS Labs team who is continuing to release updated ENSv2 contracts. It should be considered experimental. +::: + -## Endpoints +## Start building -For more details on how to use these instances, refer to the [ENSNode Quickstart](/docs/integrate). +Pick an instance above, then jump into the Quickstart for integration options to start making use of it. + + diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/ai-llm.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/ai-llm.mdx index 0b2ab17d1a..499b95d541 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/ai-llm.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/ai-llm.mdx @@ -5,10 +5,6 @@ description: AI and LLM tooling for building on ENSv2. import { LinkCard } from "@astrojs/starlight/components"; -:::caution[Coming Soon] -We're actively working on this page right now. Check back by May 18th for full content! -::: - AI and LLM tooling is a key priority for ENSNode, and we're building the infrastructure to make ENS a first-class citizen in the world of AI coding assistants and chat-based interfaces. Next on the roadmap for this space are [`enscli`](/docs/integrate/integration-options/enscli) and [`ensskills`](/docs/integrate/integration-options/ensskills) — the foundation for how developers and their AI agents will reach for ENS. diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/ensv2-readiness.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/ensv2-readiness.mdx index baf8a2b5ef..c48c180a75 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/ensv2-readiness.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/ensv2-readiness.mdx @@ -18,7 +18,7 @@ Full access to ENS data formerly required two separate data fetching strategies 1. **ENS resolution** — RPC calls with CCIP-read support for offchain data (e.g. via a popular package such as `viem` or `wagmi`) to perform forward or reverse ENS resolution. 2. **Indexed ENS data** — the [ENS Subgraph](/docs/reference/subgraph-legacy/what-is-the-ens-subgraph) for indexed ENS data, such as discovering names owned by an address and all other ENS state outside of ENS resolutions. -Neither system alone was complete. +Neither system alone was complete. - ENS resolution gives you resolver records, but no access to all the other state about ENS! ENS Resolutions as exposed through popular libraries such as `viem` and `wagmi` are also painfully "close to the metal", putting the burden on app developers to learn and carefully implement complex details about interpreting raw values returned by the ENS protocol. - The Subgraph gives you queryable indexed ENS data but has critical limitations, including: - The Subgraph is single-chain. @@ -31,15 +31,27 @@ In the past, apps building on ENS have had to live with these split fetching str ## How ENSNode solves this -[ENSIndexer](/docs/services/ensindexer) offers the `unigraph` plugin, which builds a **unified** polymorphic indexed data model in [ENSDb](/docs/services/ensdb) of multiple ENSv1 Nametrees (the ENSv1 onchain state model found in the ENS root registry, Basenames on Base, Lineanames on Linea, 3DNS on Optimism, etc.), and the ENSv2 Namegraph (the ENSv2 onchain state model that ENSv1 domains may optionally make a dynamic upgrade to, and may contain cycles, disjoint domains, and allows domains to dynamically reposition themselves across time within the ENSv2 Namegraph). +**The Unigraph Data Model** — [ENSIndexer](/docs/services/ensindexer) offers the `unigraph` plugin, which builds a **unified** polymorphic indexed data model in [ENSDb](/docs/services/ensdb) of multiple ENSv1 Nametrees (the ENSv1 onchain state model found in the ENS root registry, Basenames on Base, Lineanames on Linea, 3DNS on Optimism, etc.), and the ENSv2 Namegraph (the ENSv2 onchain state model that ENSv1 domains may optionally be upgraded to, which allows for dynamic reconfiguration of the name hierarchy, including possible cycles, disjoint domains, and infinite aliases). -The [ENS Omnigraph API](/docs/integrate/omnigraph) is delivered by the [ENSApi](/docs/services/ensapi) service which provides a highly tailored GraphQL API that builds upon and refines the "unigraph" indexed data model held in ENSDb to deliver all your ENS data access needs in a single API endpoint. The ENS Omnigraph API also understands ENS protocol implementation details including ENSIP-15 (ENS name normalization), ENSIP-10, ENSIP-19, and much more so that you can focus on building your app and not all the internal implementation complexities of the ENS protocol. +**The Omnigraph API** — The [ENS Omnigraph API](/docs/integrate/omnigraph) is delivered by [ENSApi](/docs/services/ensapi) and builds upon and refines the Unigraph data model held in [ENSDb](/docs/services/ensdb). The Omnigraph API provides a highly tailored, fully typed GraphQL API that understands ENS protocol implementation details—including ENSIP-10, ENSIP-15, ENSIP-19, and much more—so that you can focus on building your app (and not all the internal implementation complexities of the ENS protocol). -- **ENS Resolution** — The ENS Omnigraph API, through ENSApi, internally implements the ENS Universal Resolver on top of the indexed ENS Unigraph datamodel in ENSDb. We refer to this idea as "ENS Protocol Acceleration". For cases where ENS Resolution requires offchain data, ENSApi internally performs the CCIP-read operations on your behalf to ensure every resolution request accurately follows all ENS protocol standards. No need for any RPC calls in your app. Your ENS resolutions may now also be faster than ever! -- **Indexed ENS data** — Access the multichain indexed "unigraph" state model all within a single unified, polymorphic API-level state model that understands ENS protocol implementation details including ENSIP-15 (ENS name normalization), ENSIP-10, ENSIP-19, and much more so that you can focus on building your app and not all the internal implementation complexities of the ENS protocol. +**Accelerated ENS Resolution** — The ENS Omnigraph API, through ENSApi, internally implements the ENS Universal Resolver on top of the indexed ENS Unigraph data model in ENSDb. We refer to this idea as "ENS Protocol Acceleration". For cases where ENS Resolution requires offchain data, ENSApi internally performs the CCIP-read operations on your behalf to ensure every resolution request accurately follows all ENS protocol standards. No need for any RPC calls in your app, and your ENS resolutions for indexed names could speed up by an order of magnitude or more! -## What you need to do +## What You Need to Do + +**Resolving Records** — If you're exclusively interested in resolving ENS names, you need to ensure that your `resolve` RPC calls go to the new `UniversalResolverV2` contract or risk stale and incorrect results being returned. Depending on your situation, this update may be handled simply by updating `viem` or `wagmi`, but for many apps building on indexed ENS data or with more advanced requirements, additional upgrade actions may be required. + +For many, the simple solution for ENSv2 readiness will be to adopt the ENS Omnigraph API from ENSNode for all their ENS data needs (both ENSv1 and ENSv2). ENSNode also provides **ENS Protocol Acceleration**, dramatically reducing resolution latency for most names people use. + +**Querying ENS Data** — If you're querying ENS names via a legacy API such as the ENS Subgraph you need to update to an ENSv2-ready service like ENSNode; as soon as ENSv2 launches, data served by the Subgraph (and any ENSv1-only indexers) will be instantly unreliable for the true state of ENS. + +## Pick Your Integration + +ENSNode meets you wherever you are — drop-in React components, a typed TypeScript SDK, raw GraphQL, direct ENSDb access, CLI tooling, or AI agent integration. Pick the surface that fits your stack and ship ENSv2-ready code today. + + -:::caution[Coming Soon] -We're actively working on this page right now. Check back by May 18th for full content! -::: diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/index.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/index.mdx index f1fee67625..9e2be956d5 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/index.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/index.mdx @@ -11,7 +11,7 @@ import OmnigraphAPIExample from "@components/organisms/OmnigraphAPIExample.astro ## What is ENSv2? -[ENSv2](https://ens.domains/ensv2) is the next generation of the Ethereum Name Service — a protocol upgrade that fundamentally changes the onchain data model of ENS. +[ENSv2](https://ens.domains/ensv2) is the next generation of the [Ethereum Name Service](https://ens.domains) — a protocol upgrade that fundamentally changes how the ENS protocol works. :::tip[Prepare for ENSv2] The ENSv2 upgrade to the ENS protocol is coming **Summer 2026**! Your app, regardless of how it interacts with names, needs to be updated to avoid being left behind. @@ -23,15 +23,15 @@ The ENSv2 upgrade to the ENS protocol is coming **Summer 2026**! Your app, regar ## What is the ENS Omnigraph? -ENSNode fully supports ENSv2 via the [Omnigraph API](/docs/integrate/omnigraph), a _unified_ API over **both ENSv1 and ENSv2**. Note how when ENSv2 launches, ENSv1 continues to exist in parallel. ENSNode takes the guesswork out of building on ENS, whether you need to resolve up-to-date records, search all Domains, or see which Domains a user owns (and much, much more). +ENSNode fully supports ENSv2 via the [ENS Omnigraph API](/docs/integrate/omnigraph), the world's first and only _unified_ API over the full state of **both ENSv1 and ENSv2**. When ENSv2 launches in **Summer 2026**, ENSv1 continues to exist, and apps _must_ be updated to use the new protocol version. ENSNode takes the guesswork out of building on ENS, whether you need to resolve up-to-date records, search all Domains, or see which Domains a user owns (and much, much more). ![ENS Omnigraph diagram](/ens-omnigraph-diagram.png) -ENS Omnigraph supports both ENSv1 and ENSv2 **concurrently**. This means you can integrate today (before ENSv2 launches) and continue with full ENSv2 support when it goes live with zero downtime! +ENS Omnigraph supports both ENSv1 and ENSv2 **concurrently** within the **same unified data model**. This means you can integrate today (before ENSv2 launches) and continue with full ENSv2 support when it goes live, with zero downtime! ## ENSNode's Integration Options -ENSNode supports a full range of different integration options across the stack, whether you're using React, any JavaScript runtime, raw GraphQL, or looking to go deep and build a new and fully custom service on ENS data. +ENSNode supports a full range of different integration options across the stack, whether you're using React, any JavaScript runtime, raw GraphQL, or looking to go deep and build a fully custom service using indexed ENS data. +### 4. Further Integration Options + +Beyond `enskit`, `enssdk`, and the Omnigraph GraphQL API, ENSNode exposes a deeper set of integration surfaces for advanced use cases: + +- **ENSDb** — query the indexed ENS dataset directly over Postgres for custom analytics or your own service layer. +- **enscli** — (coming soon) script ENSNode operations from the command line. +- **ensskills** — (coming soon) AI agent tooling for working with ENS data. +- **ensdb-cli** — (coming soon) share and load point-in-time ENSDb snapshots. +- **ENSEngine** (coming soon) — subscribe to ENS-aware webhooks driven by changes in ENSDb. + - -:::tip[Coming soon: accelerated self-hosting] -Planning to self-host? We're building [**`ensdb-cli` & ENSDb snapshots**](/docs/integrate/integration-options/ensdb-cli) so you can stand up a fresh, nearly-current ENSDb in minutes instead of waiting days and spending big on RPC credits to complete a full historical backfill. -::: diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/enskit/index.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/enskit/index.mdx index 101dd4bec0..da1f58b86f 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/enskit/index.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/enskit/index.mdx @@ -81,7 +81,7 @@ import { StrictMode } from "react"; import { DomainView } from "./DomainView"; // you may use a NameHash Hosted ENSNode instance -// learn more at https://ensnode.io/docs/integrate/hosted-instances +// learn more at https://ensnode.io/docs/hosted-instances const ENSNODE_URL = import.meta.env.VITE_ENSNODE_URL! // create and extend an EnsNodeClient with Omnigraph support diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/enssdk/index.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/enssdk/index.mdx index 7d632d3600..5835f9e4ca 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/enssdk/index.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/enssdk/index.mdx @@ -98,7 +98,7 @@ import { createEnsNodeClient } from "enssdk/core"; import { omnigraph } from "enssdk/omnigraph"; // you may use a NameHash Hosted ENSNode instance -// learn more at https://ensnode.io/docs/integrate/hosted-instances +// learn more at https://ensnode.io/docs/hosted-instances const ENSNODE_URL = process.env.ENSNODE_URL!; // create and extend an EnsNodeClient with Omnigraph support @@ -222,7 +222,7 @@ import { createEnsNodeClient } from "enssdk/core"; import { type FragmentOf, graphql, omnigraph, readFragment } from "enssdk/omnigraph"; // you may use a NameHash Hosted ENSNode instance -// learn more at https://ensnode.io/docs/integrate/hosted-instances +// learn more at https://ensnode.io/docs/hosted-instances const ENSNODE_URL = process.env.ENSNODE_URL!; const client = createEnsNodeClient({ url: ENSNODE_URL }).extend(omnigraph); diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/omnigraph-graphql-api.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/omnigraph-graphql-api.mdx index 4978309b70..a328732829 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/omnigraph-graphql-api.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/omnigraph-graphql-api.mdx @@ -71,7 +71,7 @@ Create `src/index.ts`. The whole script is a single `fetch` against `/api/omnigr ```ts title="src/index.ts" // you may use a NameHash Hosted ENSNode instance -// learn more at https://ensnode.io/docs/integrate/hosted-instances +// learn more at https://ensnode.io/docs/hosted-instances const ENSNODE_URL = process.env.ENSNODE_URL!; const HELLO_WORLD_QUERY = /* GraphQL */ ` diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/migrate-from-subgraph.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/migrate-from-subgraph.mdx deleted file mode 100644 index db3086a6c8..0000000000 --- a/docs/ensnode.io/src/content/docs/docs/integrate/migrate-from-subgraph.mdx +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Migrate from ENS Subgraph -description: Migration guide for developers using the legacy ENS Subgraph. ---- - -:::caution[Coming Soon] -We're actively working on this page right now. Check back by May 18th for full content! -::: - -This page will provide a migration guide for developers currently using the legacy ENS Subgraph — why to migrate, query-shape mapping, and step-by-step instructions. diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/omnigraph/examples/index.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/omnigraph/examples/index.mdx index 3721ebbeb0..25dadbf6a8 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/omnigraph/examples/index.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/omnigraph/examples/index.mdx @@ -1,5 +1,5 @@ --- -title: ENS Omnigraph Queries Examples +title: ENS Omnigraph Example Queries description: Ready-to-run ENS Omnigraph GraphQL examples with variables, sample JSON, cURL, and ENSAdmin links. sidebar: order: 1 diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/omnigraph/index.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/omnigraph/index.mdx index ebf2f77f26..20a7524e0f 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/omnigraph/index.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/omnigraph/index.mdx @@ -1,10 +1,161 @@ --- title: ENS Omnigraph API -description: The ultimate ENSv2 API. +description: The world's first and only API providing unified access to the full state of ENSv1 and ENSv2. --- -:::caution[Coming Soon] -We're actively working on this page right now. Check back by May 18th for full content! -::: +import { LinkCard, CardGrid } from "@astrojs/starlight/components"; -This page will introduce the ENS Omnigraph API — the ultimate ENSv2 API. Includes schema overview, mental model, and how it differs from the legacy ENS Subgraph schema. +The **ENS Omnigraph API** is the world's first and only API providing unified access to the full state of ENSv1 and ENSv2. It's a single, polymorphic GraphQL API over **both ENSv1 and ENSv2** — write your query once and get correct, typed results regardless of which protocol version a given Domain lives in. + +![ENS Omnigraph diagram](/ens-omnigraph-diagram.png) + +The Omnigraph is delivered by [ENSApi](/docs/services/ensapi) on top of the indexed Unigraph in [ENSDb](/docs/services/ensdb). It follows the [Relay specification](https://relay.dev/graphql/connections.htm), abstracts away the most common ENS-protocol footguns, and exposes enough of the underlying protocol for builders who need to go deep. + +## One unified API over ENSv1 + ENSv2 + +When ENSv2 launches in **Summer 2026**, the two protocol versions coexist — and the Omnigraph keeps your app working against both, at the same time, with no code changes. Both ENSv1 and ENSv2 Domains are indexed concurrently and exposed through a unified schema. + +Addressing a Domain by name (`domain(by: { name: "vitalik.eth" })`) returns an ENSv2 Domain if the domain has been optionally upgraded by its owner to ENSv2, and returns an ENSv1 Domain otherwise. Set-returning queries (`domains(where: { name: ... })`) return both the ENSv1 and ENSv2 onchain representations of the same domain, unless explicitly filtered with `version: ENSv1` or `version: ENSv2`. + +## What is a Namegraph? + +A **Namegraph** is the native onchain data model of ENSv2: it represents names not as a flat mapping of namehashes in a Nametable (as in ENSv1), but as a graph of `Registry → Domain → Registry → Domain → …`. This graph may be cyclic, and within the ENSv2 protocol an unbounded number of _disjoint_ (not connected) Namegraphs will exist. Within the unified ENS protocol (v1+v2) there will exist many Namegraphs, at the very least those headed by the ENSv1 Root Registry, Basenames, Lineanames, 3DNS, and the ENSv2 Root Registry. + +## What is the Unigraph? + +The **Unigraph** is the entire collection of these disjoint ENSv2 Namegraphs and multiple ENSv1 Nametables, combined together into a single unified data model using ENS Resolution semantics. Navigating the Unigraph from `"eth"` down to `"vitalik.eth"` and beyond looks identical regardless of whether the underlying entities are ENSv1 or ENSv2. + +The [`unigraph` plugin](/docs/services/ensindexer) in ENSIndexer is what builds this unified model. It's also where multichain coverage lives: Basenames (`.base.eth`), Lineanames (`.linea.eth`), and 3DNS names (`.box`) are all materialized into the same Unigraph as mainnet `.eth`, so a single query covers all indexable names in one shot. + +## Canonicality + +Given that a Domain entity (say, the `sub` in `sub.example.eth`) can be reached by infinitely many aliases (for example, `sub.other.eth`), it becomes important to determine a _canonical_ reference to the Domain — this is the **Canonical Name**. Canonicality is also connected to nameability; if an ENSv2 Domain exists on-chain but isn't eventually connected to the Root Registry somehow, **it doesn't have a name!** + +Within the Omnigraph API the complexity of this is reduced, and all Canonical Domains (those with names) are queryable, searchable, and addressable by said name. Domains that are not canonical are _still_ referenceable by `id` (eg. `domain(by: { id: DomainId! })`). + +Canonical Domains have a `Domain.canonical` field hosting the canonicality-derived fields such as `name`, `node`, `depth` (i.e. 2 for `vitalik.eth`), and `path` from the ENS root (i.e. `[Domain("eth"), Domain("vitalik.eth")]`). + +## Stable IDs vs. Namegraph addressing + +Every entity in the Omnigraph has an `id` — a nominally-typed, stable reference to a specific on-chain entity (`DomainId`, `RegistryId`, `RegistrationId`, etc.). When you already know the entity you mean, address it by `id`: `domain(by: { id: "..." })` always returns the same on-chain Domain, even if its canonical name changes across time. + +Addressing a Domain by **name** is a different operation. It's **Unigraph forward traversal**: `domain(by: { name: "vitalik.eth" })` walks from the ENSv2 Root Registry → `"eth"` in that Registry → the Registry that `"eth"` points at (the EthRegistry) → `"vitalik"` in that Registry. The Domain returned is whichever on-chain entity (if any) that path currently resolves to. + +These two views are not interchangeable: + +- The `id` you receive from a name lookup _is_ the stable reference to the on-chain entity that the Namegraph currently resolves `"vitalik.eth"` to. +- But `"vitalik.eth"` is not a stable reference to that entity. The Namegraph can be re-parented or re-aliased — and tomorrow, `"vitalik.eth"` may resolve to an entirely different on-chain Domain. + +**Rule of thumb:** address by `name` when you're answering "which Domain would records come from if resolved right now"; address by `id` when you're answering "what's the latest state of this specific on-chain entity?". + +## Polymorphism via GraphQL interfaces + +`Domain`, `Registry`, and `Registration` are GraphQL **interfaces**, with concrete types implementing each: + +- `Domain` → `ENSv1Domain`, `ENSv2Domain` +- `Registry` → `ENSv1Registry`, `ENSv1VirtualRegistry`, `ENSv2Registry` +- `Registration` → `BaseRegistrarRegistration`, `NameWrapperRegistration`, `ThreeDNSRegistration`, `ENSv2RegistryRegistration`, `ENSv2RegistryReservation` + +Shared fields are available unconditionally on the interface. Protocol- or implementation-specific fields are reached via typed inline fragments — `... on ENSv1Domain { rootRegistryOwner }`, `... on ENSv2Domain { tokenId }`, `... on BaseRegistrarRegistration { wrapped { fuses } }`, `... on NameWrapperRegistration { fuses }`. The result is a single query that compiles, type-checks, and returns the right fields for whichever concrete type each record turns out to be. + +## Interpreted Names everywhere + +Every name and label crossing the Omnigraph surface is an **Interpreted Name** (or Interpreted Label). Each label in an Interpreted Name is either a normalized literal label or an Encoded LabelHash (`[abc123…]`) when the literal isn't known or is unnormalized. This eliminates one of the most common ENS UI footguns — unnormalized labels, unhealed hashes, and rendering surprises — at the schema layer, making UI rendering trivial. See [terminology](/docs/reference/terminology#interpreted-label) for the full definition. + +## Relay-spec connections + +Collection and paginated relationship fields in the schema follow the [Relay-spec Connection](https://relay.dev/graphql/connections.htm) pattern with `edges`, `pageInfo`, and `totalCount`. Cursor-based pagination is idiomatic in urql, Apollo, Relay, and most modern GraphQL clients — infinite scroll and stable pagination work out of the box, with no per-endpoint plumbing. + +## A complete audit log of ENS Events + +The Omnigraph indexes every onchain Event relevant to ENS and exposes it from the entities each Event relates to: + +- `Domain.events` — every Event for a specific Domain +- `Resolver.events` — every Event emitted by a specific Resolver +- `Account.events` — every Event for which an Account is the HCA-aware `sender` +- `Permissions.events`, `PermissionsUser.events` — Permission grant and revocation history + +Each `Event` carries chain, block, transaction, and log metadata, plus an HCA-aware `sender` field distinct from the raw `tx.from` for HCA-mediated transactions. + +## First-class Permissions + +Permissions are modeled as top-level entities. `Permissions` represents a contract that manages role grants; `PermissionsResource` is an addressable resource within that contract; `PermissionsUser` is a specific user's role bitmap on a specific resource. + +Registries, Resolvers, and ENSv2 Domains all expose their Permissions directly (`Registry.permissions`, `Resolver.permissions`, `ENSv2Domain.permissions`), and an `Account` can be queried for every Permission it's been granted (`Account.permissions`, `Account.registryPermissions`, `Account.resolverPermissions`). Access-aware UIs — "which Domains can this address manage?", "who can update this Registry?" — become a single query. + +## Example + +The polymorphism, Namegraph traversal, Canonical Name, Events, and version-specific fragments — all in one query: + +```graphql +query EthAndSubdomains { + domains(where: { name: { eq: "eth" } }) { + edges { + node { + __typename + id + canonical { + name { interpreted } + depth + } + events(first: 5) { + totalCount + edges { + node { + timestamp + transactionHash + } + } + } + subdomains(first: 10, order: { by: NAME }) { + totalCount + edges { + node { + __typename + id + canonical { name { interpreted } } + ... on ENSv1Domain { + rootRegistryOwner { address } + } + ... on ENSv2Domain { + tokenId + } + } + } + } + ... on ENSv1Domain { + rootRegistryOwner { address } + } + ... on ENSv2Domain { + tokenId + } + } + } + } +} +``` + +## Next steps + + + + + + + diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/why-ensnode.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/why-ensnode.mdx index b0d8b9560a..a88df80253 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/why-ensnode.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/why-ensnode.mdx @@ -2,47 +2,101 @@ title: Why ENSNode? description: Why ENSNode is the best way to build ENSv2 apps. --- + +import { LinkCard, CardGrid } from "@astrojs/starlight/components"; import LostENSNamesImage from "@workspace/docs/ensnode.io/src/components/atoms/images/astro/LostENSNamesImage.astro"; import ENSAdminImage from "@workspace/docs/ensnode.io/src/components/atoms/images/astro/ENSAdminImage.astro"; -:::caution[Coming Soon] -We're actively working on this page right now. Check back by May 18th for full content! -::: +ENSNode is the full-stack ENSv2 development platform — a single, unified API over **both ENSv1 and ENSv2**, with first-class multichain support and the integration surfaces (React, TypeScript, GraphQL, Postgres) you need to ship. + +## Built for ENSv2 from day one + +[ENSv2](https://ens.domains/ensv2) is a fundamental change to ENS's onchain data model. The legacy ENS Subgraph wasn't designed for it, and it never will be — single-chain, no resolution, no understanding of the new ENSv2 Namegraph. Apps that stay on the Subgraph will be left behind the moment ENSv2 launches. + +ENSNode is built around ENSv2 from the ground up. The same query works against an ENSv1 name today and an ENSv2 name the moment it goes live — with **zero downtime or code changes** in your app. + + + +## One unified API over ENSv1 + ENSv2 + +The [ENS Omnigraph](/docs/integrate/omnigraph) is a single GraphQL API that returns a polymorphic, unified view of every ENS Domain — regardless of whether it lives in an ENSv1 Nametree, the ENSv2 Namegraph, on mainnet, or on an L2 subregistry such as base.eth subnames on Base. + +![ENS Omnigraph diagram](/ens-omnigraph-diagram.png) -This page will explain why ENSNode is the best way to build ENSv2 applications — including ENSNode's ENSv2 readiness, multichain support, how it compares to the legacy ENS Subgraph, and much more. +ENSv1 and ENSv2 coexist after the ENSv2 launch. The Omnigraph simplifies that split: your code asks for `domain(by: { name: "vitalik.eth" })` and gets a typed result, regardless of whether the underlying domain is on ENSv1 or ENSv2. -## Why it's important for ENS? +## Multichain by default -ENSv2 introduces a completely new onchain data model we refer to as the ENS Namegraph. -Additionally, when ENSv2 launches, ENSv1 continues to exist in parallel. -The legacy ENS Subgraph cannot support ENSv2. -Apps building on ENSv2 need a simple and powerful solution for querying the full unified state of ENSv1 and ENSv2. -ENSNode delivers this as a full-stack of integration points for developers building on the future of ENS. -Learn more +ENSNode provides the world's best indexing coverage for ENS, spanning every chain that matters, including: -