From e158f8b2506d53cb151e274bc4a7dfc0d8440792 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 18 May 2026 15:16:47 -0500 Subject: [PATCH 1/9] docs: prune stale reference pages, trim README, link follow-ups Per priority docs pass: - delete reference/{roadmap,what-is-ensnode,ensnode-v2-notes,mainnet-registered-subnames-of-subregistries} and integrate/migrate-from-subgraph (boss called these stale, lower-value, or "less is more") - remove their sidebar entries + the stale /ensnode/concepts/what-is-ensnode redirect - drop the now-dangling 'Skip to What is ENSNode?' LinkCard on reference/subgraph-legacy/what-is-the-ens-subgraph - drop the 'Coming Soon' panel from integrate/ai-llm (existing content is fine) - rewrite README around docs/quickstart links + an Omnigraph GraphQL example (inlined eth) sourced from examples/omnigraph-graphql-example - drop the stale 'docs/ensnode/src/content/docs/reference/mainnet-registered-subnames-of-subregistries.mdx' pointers in datasources comments (mainnet.ts, sepolia.ts) Follow-ups filed as sub-issues of #1360: - #2138 docs: write Migrate from ENS Subgraph guide - #2139 docs: capture mainnet-registered subnames of subregistries Co-Authored-By: Claude Opus 4.7 (1M context) --- README.md | 169 ++---------------- docs/ensnode.io/astro.config.mjs | 1 - .../starlight/sidebar-topics/integrate.ts | 4 - .../starlight/sidebar-topics/reference.ts | 16 -- .../content/docs/docs/integrate/ai-llm.mdx | 4 - .../docs/integrate/migrate-from-subgraph.mdx | 10 -- .../docs/docs/reference/ensnode-v2-notes.mdx | 105 ----------- ...t-registered-subnames-of-subregistries.mdx | 56 ------ .../content/docs/docs/reference/roadmap.mdx | 82 --------- .../what-is-the-ens-subgraph.mdx | 8 - .../docs/docs/reference/what-is-ensnode.mdx | 114 ------------ packages/datasources/src/mainnet.ts | 6 - packages/datasources/src/sepolia.ts | 6 - 13 files changed, 19 insertions(+), 562 deletions(-) delete mode 100644 docs/ensnode.io/src/content/docs/docs/integrate/migrate-from-subgraph.mdx delete mode 100644 docs/ensnode.io/src/content/docs/docs/reference/ensnode-v2-notes.mdx delete mode 100644 docs/ensnode.io/src/content/docs/docs/reference/mainnet-registered-subnames-of-subregistries.mdx delete mode 100644 docs/ensnode.io/src/content/docs/docs/reference/roadmap.mdx delete mode 100644 docs/ensnode.io/src/content/docs/docs/reference/what-is-ensnode.mdx diff --git a/README.md b/README.md index 721eb1bf79..c5030dce7b 100644 --- a/README.md +++ b/README.md @@ -19,75 +19,29 @@ # 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 multichain indexer for ENS, with first-class support for [ENSv2](https://roadmap.ens.domains/roadmap/). It exposes a unified GraphQL API — the **ENS Omnigraph** — over both ENSv1 and ENSv2. + +- 📚 **Docs:** [ensnode.io](https://ensnode.io) +- 🚀 **Quickstart:** [ensnode.io/docs/integrate](https://ensnode.io/docs/integrate) +- 💬 **Telegram:** [t.me/ensnode](https://t.me/ensnode) + +## Example: query a name via the Omnigraph ```graphql -# get all of a user's domains by address — not possible on-chain! -query Domains($adress: String!) { - domains(where: { owner: $address }) { - id - name - ... +query HelloWorld { + domain(by: { name: "eth" }) { + __typename + canonical { name { interpreted } } + owner { address } + subdomains(first: 20) { + totalCount + edges { node { __typename canonical { name { interpreted } } owner { address } } } + } } } ``` -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). - -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`). - -## Documentation - -Documentation for the ENSNode suite of apps is available at [ensnode.io](https://ensnode.io). +See [`examples/omnigraph-graphql-example`](examples/omnigraph-graphql-example) for the full runnable script, and the [Quickstart](https://ensnode.io/docs/integrate) for `enskit` (React), `enssdk` (TypeScript), and direct GraphQL integrations. ## Running with Docker @@ -97,9 +51,9 @@ docker compose -f docker/docker-compose.yml up -d See [`docker/README.md`](docker/README.md) for all use cases and commands. -## 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 +64,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..9a13484154 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": 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..eb4e37b5c7 100644 --- a/docs/ensnode.io/config/integrations/starlight/sidebar-topics/integrate.ts +++ b/docs/ensnode.io/config/integrations/starlight/sidebar-topics/integrate.ts @@ -153,10 +153,6 @@ export const integrateSidebarTopic = { }, ], }, - { - label: "Migrate from ENS Subgraph", - link: "/docs/integrate/migrate-from-subgraph", - }, { label: "Hosted Instances", link: "/docs/integrate/hosted-instances", 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 93f5a4c5fd..36919b1da7 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/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/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/reference/ensnode-v2-notes.mdx b/docs/ensnode.io/src/content/docs/docs/reference/ensnode-v2-notes.mdx deleted file mode 100644 index 7204c67834..0000000000 --- a/docs/ensnode.io/src/content/docs/docs/reference/ensnode-v2-notes.mdx +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: ENSNode V2 Notes ---- - -:::caution[Work in Progress] -This document contains implementation and architectural notes for the evolution of ENSNode. It is very much a work-in-progress and should not be considered definitive or indicative. -::: - -## Goals of ENSNode V2 - -The original architecture of the ENS Subgraph assumes a single-chain, on-chain namespace. The protocol and ecosystem has since evolved: the ENS namespace now exists across multiple chains and across many possible off-chain datasources. The primary goal of ENSNode v2 is to become a unified multichain & off-chain ENS indexer, capable of representing the full state of the protocol at a given time. - -Many of the ENS datasources are _dynamic_ in nature and capable of changing over time. For example, the normalization algorithm may change to produce newly normalized labels, additional labels may be healed over time, and the state of off-chain databases may change incredibly frequently. A new protocol-centric architecture & data structure - -Additionally, the original schema proposed in the ENS Subgraph isn't 1:1 with the protocol itself, increasing confusion, and will likely need to be updated in the future for and changes made in ENS Protocol V2. ENSNode v2 of course aims to perfectly support ENS v2 and Namechain as they release. - -## Proposed Architecture - -``` - ┌──────────────────────────────────────────┐ - │ API Server │ - └──────┬──────────────┬────────────────┬───┘ - │ │ │ -┌──────────▼─┐ ┌────────▼───┐ ┌────────▼────────┐ -│ Ponder │ │ ENSRainbow │ │ CCIP Read │ -└──────────┬─┘ └────────┬───┘ └──────────┬──────┘ - │ │ │ - ┌──────▼──────────────▼──────────────────▼─┐ - │ Postgres (Isolated Schemas) │ - └──────────────────────────────────────────┘ -``` - -At the top level, an API server that stitches the various datasources together at request-time, likely with lots of semantic caching involved. Likely HTTP-JSON based, perhaps GraphQL-based (but GraphQL comes with so many downsides, should be seriously evaluated). Large opportunity for ENS protocol semantic endpoints (i.e. every well-known query from ensjs and ens-app-v3 could/should be a dedicated endpoint given how specific and important that functionality seems to be). - -Each datasource persists its data to postgres, either a separate postgres instance or a separate schema in a shared postgres. No native joins are used to power queries, as that likely gets a little too far into the weeds of syncing ponder state with other tables in the same db between re-indexes, etc. - -## Ponder Indexer (currently ENSIndexer) - -ponder multichain-indexes all on-chain state and shoves it into the postgres database. our ensnode api server talks to ponder's postgres tables via shared drizzle schema. api server maintains some internal state to persist which ponder schema is 'active' and then talks to that specific schema. - -### Indexer Schema & Logic Improvements - -the 'empty' domains should be handled more accurately, depending on how important serving empty domains is for people. - -- `Domain#subdomainCount` could/should be a computed property by count(children of parent) - - removes need to recursively update parent records during domain delete - - removes need to increment during domain creation - - new impl likely needs to exclude 'empty' domains (see registry notes for context) - -domain createdAt should not update on re-registration, should be original createdAt - -various resources use both null and zeroAddress to indicate emptiness, this is horrible and creates numerous checks like [this](https://github.com/ensdomains/ensjs/blob/17ab314/packages/ensjs/src/functions/subgraph/getNamesForAddress.ts#L255) where they check for `!== NULL && !== zeroAddress` - -wrappedOwnerId should not be materialized onto domain, should just be resolved through wrappedDomain.owner - -### Registry - -- in `Registry:NewOwner`, the event emits `node` and `label`, `node` should be named `parent` and the computed subnode should be named `node` or `domain` -- empty domains aren't actually deleted from the index, but if a domain is empty the parent's subdomain count is reduced appropriately. options: - 1. if historical info not important (still available by blockheight queries), domains should be deleted, and `subdomainCount` computed with a simple count query - 2. if domain existance is necesssary, make `subdomainCount` computed with a where clause to exclude 'empty' domains - 3. if filters against subdomainCount are necessary, maybe the current logic works just fine - - -### Resolver - -- the local `Resolver` resource should be keyed by `CAIP-10 ID`, not pairwise ala subgraph, to match on-chain datamodel - - the handlers should persist all keys and values emitted by the resolver in `Records` - - the `Record` model stores (`node`, `key`, `value`) and is keyed by (`resolverId`, `node`, `key`) - - on active resolver change, simply point the domain's `resolverId` to the resolver's address - - any domain's records are computed through the current `resolverId` and querying - -any resolver that implements the CCIP Read standard will have to have its records implemented at the API layer which can stitch the indexed data with realtime offchain data via CCIP Reads. if we don't want to implement the CCIP Read proxy as part of this unified api, the api should know if a Resolver defers to CCIP and communicate that effectively in the response so that clients can do it themselves. - -in the subgraph implementation, resolver handlers must upsert resolvers because people can set records etc for a node that has not (yet) specified this resolver as active, meaning the create in `Registry:NewResolver` has yet to fire. - -resolvers should be keyed by `(chainId, address)` and manage a mapping of records for a node, to be more protocol-centric. `coinTypes` and `texts` keys & values should be fully indexed (if possible — intentionally ignored in the subgraph because of some historical reason...) - -> Yes, when it comes to all forms of key -> value pairs that comprise resolver records, the ENS Subgraph only indexes the keys and not the values. The motivation for this comes from a concern that some apps might improperly decide to use the ENS Subgraph as a source of truth for resolver record values, rather than ENS protocol standards for how resolver record values should be dynamically looked up. A naive implementation that considers the ENS Subgraph as a source of truth for these can cause a lot of problems. - -### Registrar - -the subgraph implements all of the BaseRegistrar, EthRegistrarController, and LegacyEthRegistrarController logic together - -## ENSRainbow - -ENSRainbow would be extended to handle all possible label healing data sources and provide a labelhash lookup api to the ensnode api service. In order to track on-chain datasources of healed labels (namely NameWrapper wraps [hah]), this service will likely run its own separate ponder indexer to track those events. It should also serve the existing legacy rainbow tables (`ens_names.sql`) along with tracking any other additional sources of healed labels. - -It should store all known labels, normalized, healed, or otherwise, and then over time (cron? on-demand?) attempt to normalize any yet-normalized labels and add them to the set of healed labels. This ensures that changes in unicode and the normalization algorithm are represented in real-time. - -It should also filter out any labels that are not indexable -- i.e. null byte https://ens.mirror.xyz/9GN77d-MqGvRypm72FcwgxlUnPSuKWhG3rWxddHhRwM -- or other invalid characters (see `isLabelIndexable`) - -In theory (and likely in practice) any normalized name will never become invalid, so once added to the set of healed labels it can live there forever. - -# ENSIP Ideas - -- unable to automatically identify subname registries via onchain event, CCIP standard dosn't include any info about data source, so we'll need to encode manually for now -- ENSIP - shared interface for subdomain registrars -- ENSIP — standard for how a resolver on L1 can (optionally) emit an event specifying contract on an L2 that it proxies records from - - optional, in the popular case of L2-managed subnames - - removes centralized dependency on the CCIP Gateway - - flaky test experience with .cb.id name gateway - - also helps indexer discovery diff --git a/docs/ensnode.io/src/content/docs/docs/reference/mainnet-registered-subnames-of-subregistries.mdx b/docs/ensnode.io/src/content/docs/docs/reference/mainnet-registered-subnames-of-subregistries.mdx deleted file mode 100644 index d3e5a6a635..0000000000 --- a/docs/ensnode.io/src/content/docs/docs/reference/mainnet-registered-subnames-of-subregistries.mdx +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: Mainnet-Registered Subnames of Subregistries -sidebar: - order: 4 ---- - -:::caution[Work in Progress] -This documentation is under active development. Some sections may be incomplete or out of date. -::: - -This reference discusses the situation in which a name is registered on multiple chains (ex. `example.base.eth` being registered on both the mainnet Registry and Basenames [**Shadow Registry**](/docs/reference/terminology#shadow-registry)). - -## ENSNode Architecture Background - -The current architecture ('v1') of ENSNode derives from that of the ENS Subgraph which was not architected with multi-chain multi-registry use in mind. When running ENSNode with a single-plugin enabled, only the subnames registered in the plugin's indexed subregistry are included in the index, as designed. - -When running ENSNode **with multiple plugins enabled**, however, the behavior of mainnet-registered subnames of subregistries managed by the additional plugins should be considered undefined. The specific names that are registered on mainnet for these subregistries as of a given date are listed below. - -## ENS Protocol Context - -Based on the ENSIP-10 (Wildcard Resolution) standard, any subnames of subregistries (i.e. `.base.eth`, `.linea.eth`) that exist in the ENS Registry on the mainnet ENS namespace will NOT have the forward resolution of their data delegated to the subregistry defined below. Instead their forward resolution will be managed according to the state defined in the ENS Registry. - -These subnames (and any others added beneath `base.eth` or `.linea.eth` in the mainnet ENS Registry) may or may not be properly represented during indexing until futher enhancements are made to ENSNode ('v2'). - -## Current Behavior - -Imagine the situation in which a name (i.e. `gov.base.eth`) is registered on both ETH Mainnet and Base and certain records are set for the name on each chain. - -ENSNode currently uses ponder in `omnichain` mode, processing all events across all chains in serial order by timestamp. This means that in that scenario the state of `gov.base.eth` in the resulting index will be determined by the order of the events in time, regardless which chain they occurred on. - -In the near future, ENSNode will operate in ponder's `multichain` mode, processing events in parallel by chain. With that same scenario, the state of `gov.base.eth` depends on the (unknown) order in which ponder processes backfill events, and could differ from expectations. - -v2 of ENSNode will handle this behavior accurately. - -## Mainnet-Registered Subnames of .base.eth - -As of 9-Feb-2025 a number of subnames of 'base.eth' exist in the ENS Registry on mainnet. - -This includes: -- gov.base.eth -- bootcamp.base.eth -- grants.base.eth -- bridge.base.eth -- portal.base.eth -- faucet.base.eth -- bonjour.base.eth -- gm.base.eth -- mint.base.eth - -## Mainnet-Registered Subnames of .linea.eth - -As of 9-Feb-2025 a number of subnames of 'linea.eth' exist in the ENS Registry on mainnet. - -This includes: -- bridge.linea.eth -- devconnect.linea.eth diff --git a/docs/ensnode.io/src/content/docs/docs/reference/roadmap.mdx b/docs/ensnode.io/src/content/docs/docs/reference/roadmap.mdx deleted file mode 100644 index 39a3554943..0000000000 --- a/docs/ensnode.io/src/content/docs/docs/reference/roadmap.mdx +++ /dev/null @@ -1,82 +0,0 @@ ---- -title: ENSNode Roadmap -sidebar: - order: 3 ---- - -## First-Class ENS v2 Support - -With the launch of [ENSv2](https://roadmap.ens.domains/roadmap/), ENS names will increasingly live across multiple chains and require at-request-time resolution via [CCIP-Read](https://docs.ens.domains/resolvers/ccip-read). The ENS Subgraph, which can only index a single chain and lacks support for resolution of offchain names, is unable to meet these emerging needs. - -Built on [Ponder](https://ponder.sh), ENSNode provides multichain indexing and at-request-time resolution capabilities that are essential for ENSv2. It maintains backwards compatibility with Subgraph queries while enabling support for [Namechain](https://app.ens.domains/ens-v2) and offchain names like `.uni.eth` and `.cb.id`. - -ENSNode will introduce an ENSv2-optimized schema and custom API endpoints specifically designed for common ENSjs operations. - -## Additional Chain / Integration Support - -- Offchain Names - - `.cb.id`, `.uni.id`, + more - - [NameStone](https://namestone.com/) Names - - [NameSpace](https://namespace.ninja/) Names - - [Justaname](https://www.justaname.id/) Names - -:::tip[Contribute] -Want support for a specific chain/integration? Contribute to this documentation by [opening a Pull Request](https://github.com/namehash/ensnode). -::: - -## ENS Protocol Accelerator - -ENSNode v2 could introduce a custom HTTP/JSON API layer that would allow for performing additional logic at request time, reducing client-side workload and latency, and accelerating common ENS protocol operations like name/record lookups. - -In particular, when records are indexed by ENSIndexer, ENSNode could directly query name records without relying on UniversalResolver or CCIP-Read, significantly reducing latency and avoiding unnecessary HTTP requests. For names that aren't directly indexed, ENSNode can implement CCIP-Read, ensuring clients only need a single lightweight HTTP/2 request to confidently resolve records for a given name. - -ENSNode could handle CCIP-Read logic internally, batch multiple requests to reduce RPC calls, and cache CCIP-Read and NFT metadata results. Utilizing HTTP/2 multiplexing and optional batch endpoints could ensure efficient server-side deduplication. To minimize latency in cases like lengthy CCIP-Read or NFT resolution, ENSNode could deliver partial JSON objects over Server-Sent Events (SSE), enabling immediate client updates for critical data like Primary Names while background tasks like avatar resolution complete. - -Besides dramatically decreasing latency for client applications, the Protocol Accelerator is also a key step forward in decentralization, away from reliance on centralized offchain gateway servers. This is a big win for the ENS protocol! - -## ENSDb CLI & Snapshots - -We're investing in [ENSDb](/docs/services/ensdb) as a first-class integration point - and the next big step is making it trivial *and inexpensive* to **operate** an ENSDb and to **share state** across instances. See the full teaser at [ensdb-cli & ENSDb snapshots](/docs/integrate/integration-options/ensdb-cli). - -Goals on this roadmap stream include: - -- **Snapshot creation & consumption** - publish a portable, versioned package of an ENSDb instance to a destination like Cloudflare R2, and pull it down to bootstrap a new ENSNode instance in minutes instead of waiting on a full historical backfill. Saves **both time and RPC cost** - consumers don't need to replay 9+ years of ENS history through their own RPC provider to catch up. -- **Snapshot metadata** - record which ENSIndexer config, version, and chains a snapshot was produced from, so consumers can pick the right one and trust it for their use case. -- **Snapshot diffing** - compare snapshots produced before and after an indexing change to confirm the change didn't unexpectedly alter indexed data. A powerful safety net for release reviews. -- **Operational ENSNode CLI** - list indexer instances tracked in an ENSDb, inspect their configuration and indexing status, and clean up schemas that are no longer in use. -- **Snapshot verification (exploratory)** - strategies for letting third parties confirm a snapshot's integrity, such as multi-publisher hash consensus or signed attestations. Open research, not a commitment. - -These capabilities will unlock dramatically faster - and cheaper - iteration for hackathon teams, self-hosters, marketplaces, and anyone building custom services on top of ENSDb. - -## ENS TokenScope: ENS NFT Marketplace Data API - -With Reservoir shutting down in the coming months, ENSNode aims to provide replacement infrastructure for tokenized ENS name market data. This includes: - -- past sales history -- active buy/sell orders (on-chain and off-chain) - -This capability could be implemented as an optional ENSNode service, providing free and open source infrastructure for marketplaces platforms that support the name market. - -By enabling robust secondary markets through this infrastructure, we aim to strengthen both secondary and primary markets for tokenized names, benefiting registrars and the broader ENS ecosystem. - -## Label Healing 'Protocol' - -ENSRainbow could establish a (decentralized?) protocol for sharing healed ENS labels, enabling community-driven expansion of the rainbow tables. This protocol would: - -- allow anyone to contribute newly healed labels to a shared dataset -- perhaps use a DHT-like peer-to-peer network for label distribution -- implement verification and validation of contributed labels -- enable automatic synchronization between ENSNode/ENSRainbow & other network participants - -By decentralizing label healing contributions, the protocol would accelerate the growth of available rainbow tables while maintaining data quality through consensus mechanisms. Participants could run lightweight nodes that selectively replicate subsets of the dataset based on their needs. Registration apps could submit healed values of registered names to the protocol, ensuring users' names show up correctly across web3. - -## ENS Protocol Inspector & Developer Tools - -ENSNode aims to build out the ENS Protocol Inspector and Developer PowerTools in [ENSAdmin](/ensadmin/), including: - -- Visual inspection tools for understanding ENS Protocol behavior -- Testing and debugging capabilities for protocol interactions -- Edge case exploration and documentation -- Best practices validation for ENS integrations - -Rather than relying solely on historical documentation, the Protocol Inspector will provide an interactive way to understand how the ENS Protocol handles various scenarios, helping developers build more robust integrations. diff --git a/docs/ensnode.io/src/content/docs/docs/reference/subgraph-legacy/what-is-the-ens-subgraph.mdx b/docs/ensnode.io/src/content/docs/docs/reference/subgraph-legacy/what-is-the-ens-subgraph.mdx index ca3bc97969..333603bffb 100644 --- a/docs/ensnode.io/src/content/docs/docs/reference/subgraph-legacy/what-is-the-ens-subgraph.mdx +++ b/docs/ensnode.io/src/content/docs/docs/reference/subgraph-legacy/what-is-the-ens-subgraph.mdx @@ -4,18 +4,10 @@ sidebar: order: 1 --- -import { LinkCard } from "@astrojs/starlight/components"; - :::note The following serves as background information regarding the ENS Subgraph and describes the ecosystem & context in which ENSNode was developed. It is not necessary for running ENSNode. ::: - - ## The Graph & Graph Node [The Graph](https://thegraph.com/) leads development of [Graph Node](https://thegraph.com/docs/en/indexing/tooling/graph-node/), an [open source software application](https://github.com/graphprotocol/graph-node) for indexing blockchain data. diff --git a/docs/ensnode.io/src/content/docs/docs/reference/what-is-ensnode.mdx b/docs/ensnode.io/src/content/docs/docs/reference/what-is-ensnode.mdx deleted file mode 100644 index 0764f9b9af..0000000000 --- a/docs/ensnode.io/src/content/docs/docs/reference/what-is-ensnode.mdx +++ /dev/null @@ -1,114 +0,0 @@ ---- -title: Understanding ENSNode V1 -sidebar: - order: 2 ---- - -import { LinkCard } from "@astrojs/starlight/components"; - -:::note -This document assumes general knowledge of the ENS protocol and the ENS Subgraph. -::: - -### What is ENSNode - -ENSNode is the new multichain indexer for ENS and ENSv2. It is built on [Ponder](https://ponder.sh/) and provides enhanced capabilities over the ENS Subgraph, as well as being more efficient, flexible, and maintainable. ENSNode's enhanced capabilities include multichain and multiregistrar indexing while maintaining backwards compatibility with existing ENS Subgraph APIs. - -### ENSNode Version 1 - -ENSNode version 1 (`V1`), discussed here, prioritizes equivalency with the [ENS Subgraph](/docs/reference/subgraph-legacy/what-is-the-ens-subgraph), which drove many architectural decisions. - - - -## Core Design Principles - -1. **Full Backwards Compatibility w/ ENS Subgraph** - - Full support for existing ENS Subgraph queries used by [`ensjs`](https://github.com/ensdomains/ensjs/) and [`ens-app-v3`](https://github.com/ensdomains/ens-app-v3) - - Drop-in replacement for applications using the ENS Subgraph - - Verified compatibility through extensive testing with [`ens-test-env`](https://github.com/namehash/ens-test-env/) and [ens-subgraph-transition-tools](https://github.com/namehash/ens-subgraph-transition-tools) (see [Subgraph Compatibility](/docs/reference/subgraph-legacy/what-is-the-ens-subgraph)) -2. **Multi-Registry Plugin Architecture** - - Support for indexing ENS data across multiple chains & subregistries (i.e. mainnet, Base, Linea) - - Plugins can be activated independently or in combination -3. **Built on Ponder** - - Improved indexing speed (>10x faster than ENS Subgraph) - - Isolated indexing schemas (supporting branches, staging environments) - - Access your indexed data directly from Postgres -4. **Self-hostable Decentralization Approach** - - Self-hostable infrastructure - - Bring-your-own Postgres - - Bring-your-own ENSRainbow - -## Execution Order - -ENSIndexer is a Ponder application, so its execution order is that of a Ponder application. First the `ponder.config.ts` is executed, and then `ponder.schema.ts` and finally all files in `src/` are executed in order to register indexing event handlers via `ponder.on`. - -We place all of our application code into the `src/` directory, so it's all eligible for hot-reloading, and event handler registration occurs in each plugin's `event-handlers.ts` file. - -## Plugins - -ENSIndexer implements the indexing logic for each plugin inside event handlers. Event handlers may optionally be shared across plugins. For example, see the shared event handler functions in `apps/ensindexer/src/handlers/*.ts` which are shared by multiple plugins such as the `subgraph`, `basenames`, and `lineanames` plugins. - -Each plugin requires two files: - -- `plugin.ts` defines the plugin's overall indexing configuration. See `apps/ensindexer/src/plugins/basenames/plugin.ts` and `apps/ensindexer/src/plugins/lineanames/plugin.ts` for examples. -- `event-handlers.ts` registers the event handler functions with Ponder at runtime. See `apps/ensindexer/src/plugins/basenames/event-handlers.ts` and `apps/ensindexer/src/plugins/lineanames/event-handlers.ts` for examples. - -### Plugin-Scoping - -Because plugins indexing subregistries use the shared handlers and may clobber entities created by the `subgraph` plugin—which didn't expect multichain or multi-source entities—, id-generating code is abstracted to be plugin-specific. See the helpers in `apps/ensindexer/src/lib/ids.ts`. In these cases, for the `subgraph` plugin, the original behavior is left un-modified to facilitate 1:1 responses from the subgraph-compatible api. - -This scoping also applies to the concept of a "Managed Name" (see `apps/ensindexer/src/lib/managed-names.ts`): some contracts (like Registrars and RegistrarControllers) operate in the context of a Managed Name (like 'eth', 'base.eth', or 'linea.eth'). In the original subgraph implementation, this was hardcoded for the .eth Registrar/RegistrarControllers as the `eth` name, but because ENSNode shares indexing logic between these similar contracts across `.eth` names, `.base.eth` names, etc, we introduce the concept of a contract's "Managed Name" within the context of which it operates. - -### Ponder Plugin Integration - -#### Contract Namespace - -Ponder, by default, does not have the concept of plugins — it assumes that a config is static and that all contract names are known at compile-time. In ENSIndexer, multiple plugins reference contracts of the same name, and further namespacing is required. We namespace plugin-specific contract definitions with a prefix (namely `PluginName`) to avoid collisions (see `apps/ensindexer/src/lib/plugin-helpers.ts` for reference). - -#### Contract & Event Typing - -Ponder uses the type information of contracts and their abis in the provided config to power the `ponder.on('MyContract:MyEvent', ...)` api, including inferred types for contract names, event names, and event arguments. - -In order to replicate this experience with plugins selected at runtime, we use some creative typing in `apps/ensindexer/src/plugins/index.ts` to merge the possible plugin types for Ponder. With this approach we have full type inference for contract and event names/args across the app regardless of which plugins are activated at runtime. - -#### Plugin Execution - -When ENSIndexer is run, the configs for all of the active plugins (those selected by the user) are merged and ponder runs in `omnichain` (perhaps later: `multichain`) mode to produce the resulting index. The relevant event handlers are attached in each plugin's `event-handlers.ts` which conditionally executes if the plugin is activated in the ENSIndexerConfig. - -## @ensnode/datasources - -This package provides configurations for each known ENS namespace. An ENS namespace represents a single, unified set of ENS names with a distinct onchain root Registry and the capability to span across multiple chains, subregistries, and offchain resources. - -Each namespace is logically independent - for instance, the Sepolia namespace is entirely separate from the canonical mainnet namespace. This package centralizes the contract addresses, start blocks, and other configuration needed to interact with each namespace. - -ENSIndexer uses `@ensnode/datasources` to configure its plugins and determine which are available for a given target namespace. - -See the [`@ensnode/datasources` README](https://github.com/namehash/ensnode/blob/main/packages/datasources/README.md) for more context on this package & its responsibilities. - -## General Execution Flow - -The subgraph's codebase is not exhaustively documented or trivially readable. In some cases we've decided to simplify the implementation (ensuring accuracy via [ens-subgraph-transition-tools](https://github.com/namehash/ens-subgraph-transition-tools)) and in others we've elected to match the subgraph's logic closer to 1:1. - -In general, however, each handler is written in a more ponder-native way, using ponder's drizzle-inspired entity CRUD apis, rather than the subgraph's active-record-inspired api. It uses minimial branched or nested logic, resulting in code that is much more readable. Along the way we've also documented the purpose of these handlers more exhaustively, which should promote understanding and readability. - -## API Layer - -ENSIndexer exposes the following API endpoint: - -- **Subgraph-Compatible GraphQL** (`/subgraph`) - - - Implements the ENS Subgraph schema and query patterns - - Enables gradual migration from existing Subgraph implementations - - Maintains compatibility with `ensjs` client library — just replace - -## Label Healing with ENSRainbow - -ENSIndexer depends on ENSRainbow at runtime to handle the healing of unknown labels. This parallels the ENS Subgraph's reliance on the graph-node's `ens.nameByHash` function. - -## Additional Notes in Comments - -Additional implementation & background context for certain decisions are included throughout the codebase where relevant, and we encourage curious readers to browse the comments and general structure of the shared handlers & helper libs for further background. diff --git a/packages/datasources/src/mainnet.ts b/packages/datasources/src/mainnet.ts index db9b385a31..70fa9b6de0 100644 --- a/packages/datasources/src/mainnet.ts +++ b/packages/datasources/src/mainnet.ts @@ -135,9 +135,6 @@ export default { * * The owner of 'base.eth' in the ENS Registry in the mainnet 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: base, contracts: { @@ -214,9 +211,6 @@ export default { * * The owner of 'linea.eth' in the ENS Registry in the mainnet 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: linea, contracts: { diff --git a/packages/datasources/src/sepolia.ts b/packages/datasources/src/sepolia.ts index ec6a8e44f2..b335100482 100644 --- a/packages/datasources/src/sepolia.ts +++ b/packages/datasources/src/sepolia.ts @@ -129,9 +129,6 @@ export default { * * 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: { @@ -190,9 +187,6 @@ export default { * * 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: { From 0748c7e849a4a9b56a017fbe5ece8ae9ca443511 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 18 May 2026 15:20:04 -0500 Subject: [PATCH 2/9] docs: rewrite why-ensnode for app-developer audience Lead with what ENSNode is for app developers (unified API, multichain, full-stack integration surfaces), not what it is for ENS-the-protocol. Keep the macro arguments (close infra gaps, decentralization) below the fold as supporting context. Drop the Coming Soon banner and the Season 2 video embed. Anchor the "Subgraph won't work for ENSv2" thesis without a feature-comparison table. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../docs/docs/integrate/why-ensnode.mdx | 111 +++++++++++++----- 1 file changed, 83 insertions(+), 28 deletions(-) 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..46d93f0f66 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,102 @@ 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://roadmap.ens.domains/roadmap/) 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 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 the ENSv1 nametree, the ENSv2 Namegraph, on mainnet, or on an L2 subregistry. + +![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 hides that split: your code asks for `domain(by: { name: "vitalik.eth" })` and gets a typed result, whether the underlying record is V1 or V2. -## 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 indexes the full ENS namespace across every chain that matters, all from one query: -