From 82781f3568079ee18e353bcd5d47b39ef58692b0 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Fri, 5 Jun 2026 15:17:58 +0200 Subject: [PATCH 01/12] Apply feedback from Slack and PR 2227 --- .../src/components/molecules/EnsDbReaderIntro.astro | 2 +- docs/ensnode.io/src/content/docs/docs/integrate/index.mdx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/ensnode.io/src/components/molecules/EnsDbReaderIntro.astro b/docs/ensnode.io/src/components/molecules/EnsDbReaderIntro.astro index d1119a101..fa1781b67 100644 --- a/docs/ensnode.io/src/components/molecules/EnsDbReaderIntro.astro +++ b/docs/ensnode.io/src/components/molecules/EnsDbReaderIntro.astro @@ -7,5 +7,5 @@ import { Aside } from "@astrojs/starlight/components"; href="/docs/services/ensdb/concepts/glossary#ensdb-writer-schema" >ensIndexerSchema schema definition in the Connect section if you haven't already. + > in the Connect example if you haven't already. 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 f6b7ad883..6f96a9eb0 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/index.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/index.mdx @@ -155,9 +155,9 @@ The ENS Omnigraph API is a GraphQL API following the Relay specification, so you Beyond [`enssdk`](/docs/integrate/integration-options/enssdk), [`enskit`](/docs/integrate/integration-options/enskit), and the [Omnigraph GraphQL API](/docs/integrate/integration-options/omnigraph-graphql-api), ENSNode exposes a deeper set of integration surfaces for advanced use cases: - **[ENSDb (SQL)](/docs/integrate/integration-options/ensdb)** — query the indexed ENSv1 and ENSv2 datasets directly via SQL for custom analytics or your own service layer, from any language with a Postgres driver. -- **[ENSDb Writers (Indexers)](/docs/integrate/integration-options/ensdb-writers)** — build your own ENSDb Writer to index ENS data into your own ENSDb instance. -- **[ENSDb Readers](/docs/integrate/integration-options/ensdb-readers)** — build your own ENSDb Reader to query your own ENSDb instance through any interface of your choice. -- **[ENSNode Plugins](/docs/integrate/integration-options/ensnode-plugins)** — define how onchain data should be indexed into ENSDb. +- **[ENSDb Writers (Indexers)](/docs/integrate/integration-options/ensdb-writers)** — enable all other layers of the ENSNode stack to build on your custom indexing engine. +- **[ENSDb Readers (Custom APIs)](/docs/integrate/integration-options/ensdb-readers)** — build your own custom APIs and services on top of ENSDb using any programming language or framework. +- **[ENSNode Plugins (Indexed Data Models)](/docs/integrate/integration-options/ensnode-plugins)** — define how onchain data should be indexed into ENSDb. - **[enscli (CLI)](/docs/integrate/integration-options/enscli)** — resolve names, look up records, and run ad-hoc Omnigraph queries from the terminal — built for humans and AI agents alike. - **[ensskills (AI agents)](/docs/integrate/integration-options/ensskills)** — a curated set of skills that gives AI coding agents a well-defined contract for working with ENS. - **[ensdb-cli (ENSDb Snapshots)](/docs/integrate/integration-options/ensdb-cli)** — bootstrap a fresh ENSDb in minutes from portable, versioned snapshots instead of waiting days on a full historical backfill. From a309cb7c6549f4b3865396019a7e4969c227b3cc Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Fri, 5 Jun 2026 15:18:11 +0200 Subject: [PATCH 02/12] Setup ENS Unigraph exmaple files --- .../starlight/sidebar-topics/integrate.ts | 28 ++- .../unigraph/examples/account-domains.mdx | 32 ++-- .../unigraph/examples/account-permissions.mdx | 55 ++++++ .../unigraph/examples/domain-by-name.mdx | 51 +---- .../unigraph/examples/domain-events.mdx | 72 +++++++ .../examples/domains-fuzzy-search-by-name.mdx | 55 ++++++ .../examples/expiring-registrations.mdx | 55 ++++++ .../unigraph/examples/indexing-status.mdx | 2 +- .../examples/latest-registrations.mdx | 55 ++++++ .../examples/subdomains-by-parent-name.mdx | 25 +++ .../data/unigraph-examples/domain-by-name.ts | 56 ++++++ .../domains-fuzzy-search-by-name.ts | 56 ++++++ .../subdomains-by-parent-name.ts | 175 ++++++++++++++++++ .../src/data/unigraph-examples/types.ts | 9 + 14 files changed, 660 insertions(+), 66 deletions(-) create mode 100644 docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-permissions.mdx create mode 100644 docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domain-events.mdx create mode 100644 docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domains-fuzzy-search-by-name.mdx create mode 100644 docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/expiring-registrations.mdx create mode 100644 docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/latest-registrations.mdx create mode 100644 docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/subdomains-by-parent-name.mdx create mode 100644 docs/ensnode.io/src/data/unigraph-examples/domain-by-name.ts create mode 100644 docs/ensnode.io/src/data/unigraph-examples/domains-fuzzy-search-by-name.ts create mode 100644 docs/ensnode.io/src/data/unigraph-examples/subdomains-by-parent-name.ts create mode 100644 docs/ensnode.io/src/data/unigraph-examples/types.ts 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 18b7500aa..9a40dcf4c 100644 --- a/docs/ensnode.io/config/integrations/starlight/sidebar-topics/integrate.ts +++ b/docs/ensnode.io/config/integrations/starlight/sidebar-topics/integrate.ts @@ -175,17 +175,41 @@ export const integrateSidebarTopic = { collapsed: true, items: [ { - label: "Overview", + label: "Connect", link: "/docs/integrate/unigraph/examples", }, { label: "Domain by Name", link: "/docs/integrate/unigraph/examples/domain-by-name", }, + { + label: "Domain Fuzzy Search", + link: "/docs/integrate/unigraph/examples/domains-fuzzy-search-by-name", + }, + { + label: "Domain Events", + link: "/docs/integrate/unigraph/examples/domain-events", + }, + { + label: "Subdomains", + link: "/docs/integrate/unigraph/examples/subdomains-by-parent-name", + }, { label: "Account Domains", link: "/docs/integrate/unigraph/examples/account-domains", }, + { + label: "Account Permissions", + link: "/docs/integrate/unigraph/examples/account-permissions", + }, + { + label: "Latest Registrations", + link: "/docs/integrate/unigraph/examples/latest-registrations", + }, + { + label: "Exipring Registrations", + link: "/docs/integrate/unigraph/examples/expiring-registrations", + }, { label: "Indexing Status", link: "/docs/integrate/unigraph/examples/indexing-status", @@ -231,7 +255,7 @@ export const integrateSidebarTopic = { link: "/docs/integrate/integration-options/ensdb-readers", }, { - label: "ENSNode Plugins (data models)", + label: "ENSNode Plugins (Data Models)", link: "/docs/integrate/integration-options/ensnode-plugins", }, { diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-domains.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-domains.mdx index c157b6595..aea543fd2 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-domains.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-domains.mdx @@ -20,19 +20,25 @@ export const resultJson = [ } ]; -export const sqlExampleSnippet = `SELECT type, count(*) FROM ensindexer_0.domains +export const sqlExample = { + codeSnippet: `SELECT type, count(*) FROM ensindexer_0.domains WHERE owner_id = '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' GROUP BY type; -`; +`, + result: resultJson, +}; -export const tsExampleSnippet = `import { count, eq } from "drizzle-orm"; +export const tsExample = { + codeSnippet: `import { count, eq } from "drizzle-orm"; const counts = await ensDb -\t.select({ type: ensIndexerSchema.domain.type, count: count() }) -\t.from(ensIndexerSchema.domain) -\t.where(eq(ensIndexerSchema.domain.ownerId, "0x70997970c51812dc3a010c7d01b50e0d17dc79c8")) -\t.groupBy(ensIndexerSchema.domain.type); -` +.select({ type: ensIndexerSchema.domain.type, count: count() }) +.from(ensIndexerSchema.domain) +.where(eq(ensIndexerSchema.domain.ownerId, "0x70997970c51812dc3a010c7d01b50e0d17dc79c8")) +.groupBy(ensIndexerSchema.domain.type); +`, +result: resultJson, +}; :::caution[`unigraph` plugin required] Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` plugin activated in your ENSNode instance. [Learn more](/docs/services/ensindexer/usage/configuration) @@ -41,14 +47,8 @@ Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` Count the Domains owned by an address, grouped by Domain `type` (`ENSv1Domain` vs `ENSv2Domain`) — a single query spanning both protocol versions. See [Connect](/docs/integrate/unigraph/examples) for setup. diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-permissions.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-permissions.mdx new file mode 100644 index 000000000..dae2c7e60 --- /dev/null +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-permissions.mdx @@ -0,0 +1,55 @@ +--- +title: Fuzzy Search for ENS Names +description: Perform a fuzzy search for ENS names. +sidebar: + label: Fuzzy Search +--- + +import UnigraphStaticExample from "@components/molecules/unigraph-static-example/UnigraphStaticExample.astro"; +import EnsDbWriterSchemaIntro from "@components/molecules/EnsDbWriterSchemaIntro.astro"; +import EnsDbReaderIntro from "@components/molecules/EnsDbReaderIntro.astro"; + +export const resultJson = [ + { + type: "ENSv1Domain", + count: 2 + }, + { + type: "ENSv2Domain", + count: 14 + } +]; + +export const sqlExampleSnippet = `SELECT type, count(*) FROM ensindexer_0.domains +WHERE owner_id = '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' +GROUP BY type; +`; + +export const tsExampleSnippet = `import { count, eq } from "drizzle-orm"; + +const counts = await ensDb +\t.select({ type: ensIndexerSchema.domain.type, count: count() }) +\t.from(ensIndexerSchema.domain) +\t.where(eq(ensIndexerSchema.domain.ownerId, "0x70997970c51812dc3a010c7d01b50e0d17dc79c8")) +\t.groupBy(ensIndexerSchema.domain.type); +` + +:::caution[`unigraph` plugin required] +Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` plugin activated in your ENSNode instance. [Learn more](/docs/services/ensindexer/usage/configuration) +::: + +Count the Domains owned by an address, grouped by Domain `type` (`ENSv1Domain` vs `ENSv2Domain`) — a single query spanning both protocol versions. See [Connect](/docs/integrate/unigraph/examples) for setup. + + + + + diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domain-by-name.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domain-by-name.mdx index 5590b6083..05b445a49 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domain-by-name.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domain-by-name.mdx @@ -8,50 +8,7 @@ sidebar: import UnigraphStaticExample from "@components/molecules/unigraph-static-example/UnigraphStaticExample.astro"; import EnsDbWriterSchemaIntro from "@components/molecules/EnsDbWriterSchemaIntro.astro"; import EnsDbReaderIntro from "@components/molecules/EnsDbReaderIntro.astro"; - -export const unigraphSqlResultJson = [ - { - id: "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", - type: "ENSv1Domain", - canonical_name: "vitalik.eth", - canonical_node: "0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", - owner_id: "0x220866b1a2219f40e72f5c628b65d54268ca3a9d", - }, -]; - -export const ensDbSdkResultJson = [ - { - id: "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", - type: "ENSv1Domain", - canonicalName: "vitalik.eth", - canonicalNode: "0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", - ownerId: "0x220866b1a2219f40e72f5c628b65d54268ca3a9d", - }, -]; - -export const sqlExampleSnippet = `SELECT - id, - type, - canonical_name, - canonical_node, - owner_id -FROM ensindexer_0.domains -WHERE canonical_name = 'vitalik.eth';` - -export const tsExampleSnippet = `import { eq } from "drizzle-orm"; - -const [vitalik] = await ensDb -\t.select({ -\t\tid: ensIndexerSchema.domain.id, -\t\ttype: ensIndexerSchema.domain.type, -\t\tcanonicalName: ensIndexerSchema.domain.canonicalName, -\t\tcanonicalNode: ensIndexerSchema.domain.canonicalNode, -\t\townerId: ensIndexerSchema.domain.ownerId, -\t}) -\t.from(ensIndexerSchema.domain) -\t.where(eq(ensIndexerSchema.domain.canonicalName, "vitalik.eth")); - -console.log(vitalik);` +import { exampleDomainByName } from "@data/unigraph-examples/domain-by-name"; :::caution[`unigraph` plugin required] Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` plugin activated in your ENSNode instance. [Learn more](/docs/services/ensindexer/usage/configuration) @@ -64,9 +21,9 @@ Canonical fields are populated on every Domain reachable from the canonical root ::: - + diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domain-events.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domain-events.mdx new file mode 100644 index 000000000..5590b6083 --- /dev/null +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domain-events.mdx @@ -0,0 +1,72 @@ +--- +title: Domain by Name +description: Fetch a Domain from the ENS Unigraph by its canonical name. +sidebar: + label: Domain by Name +--- + +import UnigraphStaticExample from "@components/molecules/unigraph-static-example/UnigraphStaticExample.astro"; +import EnsDbWriterSchemaIntro from "@components/molecules/EnsDbWriterSchemaIntro.astro"; +import EnsDbReaderIntro from "@components/molecules/EnsDbReaderIntro.astro"; + +export const unigraphSqlResultJson = [ + { + id: "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + type: "ENSv1Domain", + canonical_name: "vitalik.eth", + canonical_node: "0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + owner_id: "0x220866b1a2219f40e72f5c628b65d54268ca3a9d", + }, +]; + +export const ensDbSdkResultJson = [ + { + id: "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + type: "ENSv1Domain", + canonicalName: "vitalik.eth", + canonicalNode: "0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + ownerId: "0x220866b1a2219f40e72f5c628b65d54268ca3a9d", + }, +]; + +export const sqlExampleSnippet = `SELECT + id, + type, + canonical_name, + canonical_node, + owner_id +FROM ensindexer_0.domains +WHERE canonical_name = 'vitalik.eth';` + +export const tsExampleSnippet = `import { eq } from "drizzle-orm"; + +const [vitalik] = await ensDb +\t.select({ +\t\tid: ensIndexerSchema.domain.id, +\t\ttype: ensIndexerSchema.domain.type, +\t\tcanonicalName: ensIndexerSchema.domain.canonicalName, +\t\tcanonicalNode: ensIndexerSchema.domain.canonicalNode, +\t\townerId: ensIndexerSchema.domain.ownerId, +\t}) +\t.from(ensIndexerSchema.domain) +\t.where(eq(ensIndexerSchema.domain.canonicalName, "vitalik.eth")); + +console.log(vitalik);` + +:::caution[`unigraph` plugin required] +Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` plugin activated in your ENSNode instance. [Learn more](/docs/services/ensindexer/usage/configuration) +::: + +Fetch a Domain by its canonical name. Because `canonical_name` is materialized across both ENSv1 and ENSv2, the same lookup works regardless of protocol version. See [Connect](/docs/integrate/unigraph/examples) for setup. + +:::note[Canonical fields] +Canonical fields are populated on every Domain reachable from the canonical root, across both ENSv1 and ENSv2 — query them uniformly without branching by `type`. In SQL, these columns are `canonical_name`, `canonical_path`, `canonical_node`, and `canonical_depth`; in `ensdb-sdk`, the corresponding fields are `canonicalName`, `canonicalPath`, `canonicalNode`, and `canonicalDepth`. +::: + + + + + diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domains-fuzzy-search-by-name.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domains-fuzzy-search-by-name.mdx new file mode 100644 index 000000000..dae2c7e60 --- /dev/null +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domains-fuzzy-search-by-name.mdx @@ -0,0 +1,55 @@ +--- +title: Fuzzy Search for ENS Names +description: Perform a fuzzy search for ENS names. +sidebar: + label: Fuzzy Search +--- + +import UnigraphStaticExample from "@components/molecules/unigraph-static-example/UnigraphStaticExample.astro"; +import EnsDbWriterSchemaIntro from "@components/molecules/EnsDbWriterSchemaIntro.astro"; +import EnsDbReaderIntro from "@components/molecules/EnsDbReaderIntro.astro"; + +export const resultJson = [ + { + type: "ENSv1Domain", + count: 2 + }, + { + type: "ENSv2Domain", + count: 14 + } +]; + +export const sqlExampleSnippet = `SELECT type, count(*) FROM ensindexer_0.domains +WHERE owner_id = '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' +GROUP BY type; +`; + +export const tsExampleSnippet = `import { count, eq } from "drizzle-orm"; + +const counts = await ensDb +\t.select({ type: ensIndexerSchema.domain.type, count: count() }) +\t.from(ensIndexerSchema.domain) +\t.where(eq(ensIndexerSchema.domain.ownerId, "0x70997970c51812dc3a010c7d01b50e0d17dc79c8")) +\t.groupBy(ensIndexerSchema.domain.type); +` + +:::caution[`unigraph` plugin required] +Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` plugin activated in your ENSNode instance. [Learn more](/docs/services/ensindexer/usage/configuration) +::: + +Count the Domains owned by an address, grouped by Domain `type` (`ENSv1Domain` vs `ENSv2Domain`) — a single query spanning both protocol versions. See [Connect](/docs/integrate/unigraph/examples) for setup. + + + + + diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/expiring-registrations.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/expiring-registrations.mdx new file mode 100644 index 000000000..dae2c7e60 --- /dev/null +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/expiring-registrations.mdx @@ -0,0 +1,55 @@ +--- +title: Fuzzy Search for ENS Names +description: Perform a fuzzy search for ENS names. +sidebar: + label: Fuzzy Search +--- + +import UnigraphStaticExample from "@components/molecules/unigraph-static-example/UnigraphStaticExample.astro"; +import EnsDbWriterSchemaIntro from "@components/molecules/EnsDbWriterSchemaIntro.astro"; +import EnsDbReaderIntro from "@components/molecules/EnsDbReaderIntro.astro"; + +export const resultJson = [ + { + type: "ENSv1Domain", + count: 2 + }, + { + type: "ENSv2Domain", + count: 14 + } +]; + +export const sqlExampleSnippet = `SELECT type, count(*) FROM ensindexer_0.domains +WHERE owner_id = '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' +GROUP BY type; +`; + +export const tsExampleSnippet = `import { count, eq } from "drizzle-orm"; + +const counts = await ensDb +\t.select({ type: ensIndexerSchema.domain.type, count: count() }) +\t.from(ensIndexerSchema.domain) +\t.where(eq(ensIndexerSchema.domain.ownerId, "0x70997970c51812dc3a010c7d01b50e0d17dc79c8")) +\t.groupBy(ensIndexerSchema.domain.type); +` + +:::caution[`unigraph` plugin required] +Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` plugin activated in your ENSNode instance. [Learn more](/docs/services/ensindexer/usage/configuration) +::: + +Count the Domains owned by an address, grouped by Domain `type` (`ENSv1Domain` vs `ENSv2Domain`) — a single query spanning both protocol versions. See [Connect](/docs/integrate/unigraph/examples) for setup. + + + + + diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/indexing-status.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/indexing-status.mdx index 000984ac8..4a6085234 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/indexing-status.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/indexing-status.mdx @@ -121,7 +121,7 @@ export const unigraphSqlResultJson = { export const sqlExampleSnippet = `-- Indexing status snapshot for the \`ensindexer_0\` ENSIndexer Schema SELECT value -> 'indexingStatus' as indexing_status_snapshot -FROM ensnode.metadata +FROM "ensnode".metadata WHERE ens_indexer_schema_name = 'ensindexer_0' AND key = 'indexing_metadata_context'; `; diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/latest-registrations.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/latest-registrations.mdx new file mode 100644 index 000000000..dae2c7e60 --- /dev/null +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/latest-registrations.mdx @@ -0,0 +1,55 @@ +--- +title: Fuzzy Search for ENS Names +description: Perform a fuzzy search for ENS names. +sidebar: + label: Fuzzy Search +--- + +import UnigraphStaticExample from "@components/molecules/unigraph-static-example/UnigraphStaticExample.astro"; +import EnsDbWriterSchemaIntro from "@components/molecules/EnsDbWriterSchemaIntro.astro"; +import EnsDbReaderIntro from "@components/molecules/EnsDbReaderIntro.astro"; + +export const resultJson = [ + { + type: "ENSv1Domain", + count: 2 + }, + { + type: "ENSv2Domain", + count: 14 + } +]; + +export const sqlExampleSnippet = `SELECT type, count(*) FROM ensindexer_0.domains +WHERE owner_id = '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' +GROUP BY type; +`; + +export const tsExampleSnippet = `import { count, eq } from "drizzle-orm"; + +const counts = await ensDb +\t.select({ type: ensIndexerSchema.domain.type, count: count() }) +\t.from(ensIndexerSchema.domain) +\t.where(eq(ensIndexerSchema.domain.ownerId, "0x70997970c51812dc3a010c7d01b50e0d17dc79c8")) +\t.groupBy(ensIndexerSchema.domain.type); +` + +:::caution[`unigraph` plugin required] +Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` plugin activated in your ENSNode instance. [Learn more](/docs/services/ensindexer/usage/configuration) +::: + +Count the Domains owned by an address, grouped by Domain `type` (`ENSv1Domain` vs `ENSv2Domain`) — a single query spanning both protocol versions. See [Connect](/docs/integrate/unigraph/examples) for setup. + + + + + diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/subdomains-by-parent-name.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/subdomains-by-parent-name.mdx new file mode 100644 index 000000000..e323095f2 --- /dev/null +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/subdomains-by-parent-name.mdx @@ -0,0 +1,25 @@ +--- +title: Subdomains +description: Subdomains under an ENS name. +sidebar: + label: Subdomains +--- + +import UnigraphStaticExample from "@components/molecules/unigraph-static-example/UnigraphStaticExample.astro"; +import EnsDbWriterSchemaIntro from "@components/molecules/EnsDbWriterSchemaIntro.astro"; +import EnsDbReaderIntro from "@components/molecules/EnsDbReaderIntro.astro"; +import { exampleSubdomainsByParentName } from "@data/unigraph-examples/subdomains-by-parent-name"; + +:::caution[`unigraph` plugin required] +Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` plugin activated in your ENSNode instance. [Learn more](/docs/services/ensindexer/usage/configuration) +::: + +Get a list of subdomains for the `eth` domain, including their Domain `type` (`ENSv1Domain` vs `ENSv2Domain`) — a single query spanning both protocol versions. See [Connect](/docs/integrate/unigraph/examples) for setup. + + + + + diff --git a/docs/ensnode.io/src/data/unigraph-examples/domain-by-name.ts b/docs/ensnode.io/src/data/unigraph-examples/domain-by-name.ts new file mode 100644 index 000000000..fb179ea6a --- /dev/null +++ b/docs/ensnode.io/src/data/unigraph-examples/domain-by-name.ts @@ -0,0 +1,56 @@ +import type { QueryExample } from "./types"; + +/** + * Example query for fetching a Domain by its canonical name, + * demonstrating the use of canonical fields to query across both ENSv1 and + * ENSv2 domains without branching by protocol version. + */ +export const exampleDomainByName = { + sql: { + codeSnippet: `SELECT + id, + type, + canonical_name, + canonical_node, + owner_id +FROM ensindexer_0.domains +WHERE canonical_name = 'vitalik.eth'; +`, + result: [ + { + id: "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + type: "ENSv1Domain", + canonical_name: "vitalik.eth", + canonical_node: "0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + owner_id: "0x220866b1a2219f40e72f5c628b65d54268ca3a9d", + }, + ], + }, + sdk: { + codeSnippet: `import { eq } from "drizzle-orm"; + +const [vitalik] = await ensDb + .select({ + id: ensIndexerSchema.domain.id, + type: ensIndexerSchema.domain.type, + canonicalName: ensIndexerSchema.domain.canonicalName, + canonicalNode: ensIndexerSchema.domain.canonicalNode, + ownerId: ensIndexerSchema.domain.ownerId, + }) + .from(ensIndexerSchema.domain) + .where( + eq(ensIndexerSchema.domain.canonicalName, "vitalik.eth") + ); + +console.log(vitalik);`, + result: [ + { + id: "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + type: "ENSv1Domain", + canonicalName: "vitalik.eth", + canonicalNode: "0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + ownerId: "0x220866b1a2219f40e72f5c628b65d54268ca3a9d", + }, + ], + }, +} satisfies QueryExample; diff --git a/docs/ensnode.io/src/data/unigraph-examples/domains-fuzzy-search-by-name.ts b/docs/ensnode.io/src/data/unigraph-examples/domains-fuzzy-search-by-name.ts new file mode 100644 index 000000000..fb179ea6a --- /dev/null +++ b/docs/ensnode.io/src/data/unigraph-examples/domains-fuzzy-search-by-name.ts @@ -0,0 +1,56 @@ +import type { QueryExample } from "./types"; + +/** + * Example query for fetching a Domain by its canonical name, + * demonstrating the use of canonical fields to query across both ENSv1 and + * ENSv2 domains without branching by protocol version. + */ +export const exampleDomainByName = { + sql: { + codeSnippet: `SELECT + id, + type, + canonical_name, + canonical_node, + owner_id +FROM ensindexer_0.domains +WHERE canonical_name = 'vitalik.eth'; +`, + result: [ + { + id: "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + type: "ENSv1Domain", + canonical_name: "vitalik.eth", + canonical_node: "0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + owner_id: "0x220866b1a2219f40e72f5c628b65d54268ca3a9d", + }, + ], + }, + sdk: { + codeSnippet: `import { eq } from "drizzle-orm"; + +const [vitalik] = await ensDb + .select({ + id: ensIndexerSchema.domain.id, + type: ensIndexerSchema.domain.type, + canonicalName: ensIndexerSchema.domain.canonicalName, + canonicalNode: ensIndexerSchema.domain.canonicalNode, + ownerId: ensIndexerSchema.domain.ownerId, + }) + .from(ensIndexerSchema.domain) + .where( + eq(ensIndexerSchema.domain.canonicalName, "vitalik.eth") + ); + +console.log(vitalik);`, + result: [ + { + id: "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + type: "ENSv1Domain", + canonicalName: "vitalik.eth", + canonicalNode: "0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + ownerId: "0x220866b1a2219f40e72f5c628b65d54268ca3a9d", + }, + ], + }, +} satisfies QueryExample; diff --git a/docs/ensnode.io/src/data/unigraph-examples/subdomains-by-parent-name.ts b/docs/ensnode.io/src/data/unigraph-examples/subdomains-by-parent-name.ts new file mode 100644 index 000000000..2040f8e2a --- /dev/null +++ b/docs/ensnode.io/src/data/unigraph-examples/subdomains-by-parent-name.ts @@ -0,0 +1,175 @@ +import type { QueryExample } from "./types"; + +/** + * Example query for fetching subdomains by their canonical name of the parent domain. + */ +export const exampleSubdomainsByParentName = { + sql: { + codeSnippet: `WITH parent AS ( + SELECT subregistry_id + FROM "ensindexer_0".domains + WHERE canonical_name = 'eth' + AND canonical = true +) +SELECT + d.type, + d.canonical_name, + d.canonical_node, + d.id +FROM "ensindexer_0".domains d +JOIN parent p ON d.registry_id = p.subregistry_id +WHERE d.canonical = true +ORDER BY d.canonical_name +LIMIT 10; +`, + result: [ + { + type: "ENSv1Domain", + canonical_name: "[52602a50858115661619fb28cf543ee766c182e0be6743c72d5bd674b3d12686].eth", + canonical_node: "0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", + }, + { + type: "ENSv1Domain", + canonical_name: "[d90db363b8bc1371f7d738d264ff7294bfc5636f907c467adf68321a3c6d8188].eth", + canonical_node: "0x08c0f01c419a8971af6b3eefe2a8bba1556cccf1163df60b1cdbcab632c8ab48", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x08c0f01c419a8971af6b3eefe2a8bba1556cccf1163df60b1cdbcab632c8ab48", + }, + { + type: "ENSv2Domain", + canonical_name: "katrenpadu.eth", + canonical_node: "0xf8ae81127bcd7ff99828b3dbd982a943d6dd961ee3f1a6ca707aa0eea913328e", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-112554048520345018269255786667391470421317806528110367240542760381540064034816", + }, + { + type: "ENSv2Domain", + canonical_name: "roppp.eth", + canonical_node: "0x39095c3dfb872d6441c95547f88591e7fb97014eef30cabe3df12a9b2a64dbe8", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-88275407146030613359050872632052369891139576190404928761656352489271755538432", + }, + { + type: "ENSv1Domain", + canonical_name: "sfmpfv44d0mig.eth", + canonical_node: "0x9b365136312d7ee6e232e3c98e459bc8667ec818c47fbbc55bb5e23d0a21e8cc", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x9b365136312d7ee6e232e3c98e459bc8667ec818c47fbbc55bb5e23d0a21e8cc", + }, + { + type: "ENSv2Domain", + canonical_name: "sfmpfv44d0mig.eth", + canonical_node: "0x9b365136312d7ee6e232e3c98e459bc8667ec818c47fbbc55bb5e23d0a21e8cc", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-30078755955643454526763071980293195785165410039216352470119925106082295316480", + }, + { + type: "ENSv2Domain", + canonical_name: "sfmpfv44d0res.eth", + canonical_node: "0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-37259562946248504018379781627254217478007643438678910837598068740925220192256", + }, + { + type: "ENSv2Domain", + canonical_name: "sfmpfvtoicv2ok.eth", + canonical_node: "0x7d0c27336cf9d51c3fc8f29ef4ef69df9cd4a8ec983e3e17d457a8de6013f3c5", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-49509597771493908415463190501045916291230588437784211605615168713991762477056", + }, + { + type: "ENSv2Domain", + canonical_name: "wrapnation.eth", + canonical_node: "0xc7da9e9ef214b62959a64ba9967cb33a2545a5c0f217d2716474ad1e85fa51fd", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-68387108911874305622019956908914347119991166106996198835225265868637904830464", + }, + ], + }, + sdk: { + codeSnippet: `import { and, eq, asc } from "drizzle-orm"; + +// Two-step: +// 1) find parent domain, +// 2) query children by parent domain's subregistryId. +const [parentDomain] = await ensDb + .select({ subregistryId: ensIndexerSchema.domain.subregistryId }) + .from(ensIndexerSchema.domain) + .where( + and( + eq(ensIndexerSchema.domain.canonicalName, "eth"), + eq(ensIndexerSchema.domain.canonical, true), + ) +); + +if (parentDomain?.subregistryId) { + const subdomains = await ensDb + .select({ + type: ensIndexerSchema.domain.type, + canonicalName: ensIndexerSchema.domain.canonicalName, + canonicalNode: ensIndexerSchema.domain.canonicalNode, + id: ensIndexerSchema.domain.id, + }) + .from(ensIndexerSchema.domain) + .where( + and( + eq(ensIndexerSchema.domain.registryId, parentDomain.subregistryId), + eq(ensIndexerSchema.domain.canonical, true), + ) + ) + .orderBy(asc(ensIndexerSchema.domain.canonicalName)) + .limit(limit); + + console.log(subdomains); +}`, + result: [ + { + type: "ENSv1Domain", + canonicalName: "[52602a50858115661619fb28cf543ee766c182e0be6743c72d5bd674b3d12686].eth", + canonicalNode: "0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", + }, + { + type: "ENSv1Domain", + canonicalName: "[d90db363b8bc1371f7d738d264ff7294bfc5636f907c467adf68321a3c6d8188].eth", + canonicalNode: "0x08c0f01c419a8971af6b3eefe2a8bba1556cccf1163df60b1cdbcab632c8ab48", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x08c0f01c419a8971af6b3eefe2a8bba1556cccf1163df60b1cdbcab632c8ab48", + }, + { + type: "ENSv2Domain", + canonicalName: "katrenpadu.eth", + canonicalNode: "0xf8ae81127bcd7ff99828b3dbd982a943d6dd961ee3f1a6ca707aa0eea913328e", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-112554048520345018269255786667391470421317806528110367240542760381540064034816", + }, + { + type: "ENSv2Domain", + canonicalName: "roppp.eth", + canonicalNode: "0x39095c3dfb872d6441c95547f88591e7fb97014eef30cabe3df12a9b2a64dbe8", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-88275407146030613359050872632052369891139576190404928761656352489271755538432", + }, + { + type: "ENSv1Domain", + canonicalName: "sfmpfv44d0mig.eth", + canonicalNode: "0x9b365136312d7ee6e232e3c98e459bc8667ec818c47fbbc55bb5e23d0a21e8cc", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x9b365136312d7ee6e232e3c98e459bc8667ec818c47fbbc55bb5e23d0a21e8cc", + }, + { + type: "ENSv2Domain", + canonicalName: "sfmpfv44d0mig.eth", + canonicalNode: "0x9b365136312d7ee6e232e3c98e459bc8667ec818c47fbbc55bb5e23d0a21e8cc", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-30078755955643454526763071980293195785165410039216352470119925106082295316480", + }, + { + type: "ENSv2Domain", + canonicalName: "sfmpfv44d0res.eth", + canonicalNode: "0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-37259562946248504018379781627254217478007643438678910837598068740925220192256", + }, + { + type: "ENSv2Domain", + canonicalName: "sfmpfvtoicv2ok.eth", + canonicalNode: "0x7d0c27336cf9d51c3fc8f29ef4ef69df9cd4a8ec983e3e17d457a8de6013f3c5", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-49509597771493908415463190501045916291230588437784211605615168713991762477056", + }, + { + type: "ENSv2Domain", + canonicalName: "wrapnation.eth", + canonicalNode: "0xc7da9e9ef214b62959a64ba9967cb33a2545a5c0f217d2716474ad1e85fa51fd", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-68387108911874305622019956908914347119991166106996198835225265868637904830464", + }, + ], + }, +} satisfies QueryExample; diff --git a/docs/ensnode.io/src/data/unigraph-examples/types.ts b/docs/ensnode.io/src/data/unigraph-examples/types.ts new file mode 100644 index 000000000..31605aa9a --- /dev/null +++ b/docs/ensnode.io/src/data/unigraph-examples/types.ts @@ -0,0 +1,9 @@ +export interface CodeExample { + codeSnippet: string; + result: unknown; +} + +export interface QueryExample { + sql: CodeExample; + sdk: CodeExample; +} From d4e91df415482090053bb2b1e3932eb0774e825d Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Fri, 5 Jun 2026 16:47:49 +0200 Subject: [PATCH 03/12] Extend ENS Unigraph examples --- .../starlight/sidebar-topics/integrate.ts | 4 - .../unigraph/examples/account-domains.mdx | 36 +--- .../unigraph/examples/account-permissions.mdx | 55 ----- .../unigraph/examples/domain-events.mdx | 59 +----- .../examples/domains-fuzzy-search-by-name.mdx | 38 +--- .../examples/expiring-registrations.mdx | 44 +--- .../unigraph/examples/indexing-status.mdx | 132 +----------- .../examples/latest-registrations.mdx | 44 +--- .../data/unigraph-examples/account-domains.ts | 198 ++++++++++++++++++ .../data/unigraph-examples/domain-by-name.ts | 12 +- .../data/unigraph-examples/domain-events.ts | 168 +++++++++++++++ .../domains-fuzzy-search-by-name.ts | 124 ++++++++--- .../expiring-registrations.ts | 168 +++++++++++++++ .../data/unigraph-examples/indexing-status.ts | 132 ++++++++++++ .../unigraph-examples/latest-registrations.ts | 179 ++++++++++++++++ .../subdomains-by-parent-name.ts | 123 ++++------- 16 files changed, 1024 insertions(+), 492 deletions(-) delete mode 100644 docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-permissions.mdx create mode 100644 docs/ensnode.io/src/data/unigraph-examples/account-domains.ts create mode 100644 docs/ensnode.io/src/data/unigraph-examples/domain-events.ts create mode 100644 docs/ensnode.io/src/data/unigraph-examples/expiring-registrations.ts create mode 100644 docs/ensnode.io/src/data/unigraph-examples/indexing-status.ts create mode 100644 docs/ensnode.io/src/data/unigraph-examples/latest-registrations.ts 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 9a40dcf4c..60af43d51 100644 --- a/docs/ensnode.io/config/integrations/starlight/sidebar-topics/integrate.ts +++ b/docs/ensnode.io/config/integrations/starlight/sidebar-topics/integrate.ts @@ -198,10 +198,6 @@ export const integrateSidebarTopic = { label: "Account Domains", link: "/docs/integrate/unigraph/examples/account-domains", }, - { - label: "Account Permissions", - link: "/docs/integrate/unigraph/examples/account-permissions", - }, { label: "Latest Registrations", link: "/docs/integrate/unigraph/examples/latest-registrations", diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-domains.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-domains.mdx index aea543fd2..65dfe167e 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-domains.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-domains.mdx @@ -8,37 +8,7 @@ sidebar: import UnigraphStaticExample from "@components/molecules/unigraph-static-example/UnigraphStaticExample.astro"; import EnsDbWriterSchemaIntro from "@components/molecules/EnsDbWriterSchemaIntro.astro"; import EnsDbReaderIntro from "@components/molecules/EnsDbReaderIntro.astro"; - -export const resultJson = [ - { - type: "ENSv1Domain", - count: 2 - }, - { - type: "ENSv2Domain", - count: 14 - } -]; - -export const sqlExample = { - codeSnippet: `SELECT type, count(*) FROM ensindexer_0.domains -WHERE owner_id = '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' -GROUP BY type; -`, - result: resultJson, -}; - -export const tsExample = { - codeSnippet: `import { count, eq } from "drizzle-orm"; - -const counts = await ensDb -.select({ type: ensIndexerSchema.domain.type, count: count() }) -.from(ensIndexerSchema.domain) -.where(eq(ensIndexerSchema.domain.ownerId, "0x70997970c51812dc3a010c7d01b50e0d17dc79c8")) -.groupBy(ensIndexerSchema.domain.type); -`, -result: resultJson, -}; +import { exampleAccountDomains } from "@data/unigraph-examples/account-domains"; :::caution[`unigraph` plugin required] Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` plugin activated in your ENSNode instance. [Learn more](/docs/services/ensindexer/usage/configuration) @@ -47,8 +17,8 @@ Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` Count the Domains owned by an address, grouped by Domain `type` (`ENSv1Domain` vs `ENSv2Domain`) — a single query spanning both protocol versions. See [Connect](/docs/integrate/unigraph/examples) for setup. diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-permissions.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-permissions.mdx deleted file mode 100644 index dae2c7e60..000000000 --- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-permissions.mdx +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Fuzzy Search for ENS Names -description: Perform a fuzzy search for ENS names. -sidebar: - label: Fuzzy Search ---- - -import UnigraphStaticExample from "@components/molecules/unigraph-static-example/UnigraphStaticExample.astro"; -import EnsDbWriterSchemaIntro from "@components/molecules/EnsDbWriterSchemaIntro.astro"; -import EnsDbReaderIntro from "@components/molecules/EnsDbReaderIntro.astro"; - -export const resultJson = [ - { - type: "ENSv1Domain", - count: 2 - }, - { - type: "ENSv2Domain", - count: 14 - } -]; - -export const sqlExampleSnippet = `SELECT type, count(*) FROM ensindexer_0.domains -WHERE owner_id = '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' -GROUP BY type; -`; - -export const tsExampleSnippet = `import { count, eq } from "drizzle-orm"; - -const counts = await ensDb -\t.select({ type: ensIndexerSchema.domain.type, count: count() }) -\t.from(ensIndexerSchema.domain) -\t.where(eq(ensIndexerSchema.domain.ownerId, "0x70997970c51812dc3a010c7d01b50e0d17dc79c8")) -\t.groupBy(ensIndexerSchema.domain.type); -` - -:::caution[`unigraph` plugin required] -Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` plugin activated in your ENSNode instance. [Learn more](/docs/services/ensindexer/usage/configuration) -::: - -Count the Domains owned by an address, grouped by Domain `type` (`ENSv1Domain` vs `ENSv2Domain`) — a single query spanning both protocol versions. See [Connect](/docs/integrate/unigraph/examples) for setup. - - - - - diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domain-events.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domain-events.mdx index 5590b6083..3ce2a33e8 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domain-events.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domain-events.mdx @@ -1,72 +1,29 @@ --- -title: Domain by Name -description: Fetch a Domain from the ENS Unigraph by its canonical name. +title: Domain Events +description: Fetch recent events for a Domain from the ENS Unigraph by its canonical name. sidebar: - label: Domain by Name + label: Domain Events --- import UnigraphStaticExample from "@components/molecules/unigraph-static-example/UnigraphStaticExample.astro"; import EnsDbWriterSchemaIntro from "@components/molecules/EnsDbWriterSchemaIntro.astro"; import EnsDbReaderIntro from "@components/molecules/EnsDbReaderIntro.astro"; - -export const unigraphSqlResultJson = [ - { - id: "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", - type: "ENSv1Domain", - canonical_name: "vitalik.eth", - canonical_node: "0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", - owner_id: "0x220866b1a2219f40e72f5c628b65d54268ca3a9d", - }, -]; - -export const ensDbSdkResultJson = [ - { - id: "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", - type: "ENSv1Domain", - canonicalName: "vitalik.eth", - canonicalNode: "0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", - ownerId: "0x220866b1a2219f40e72f5c628b65d54268ca3a9d", - }, -]; - -export const sqlExampleSnippet = `SELECT - id, - type, - canonical_name, - canonical_node, - owner_id -FROM ensindexer_0.domains -WHERE canonical_name = 'vitalik.eth';` - -export const tsExampleSnippet = `import { eq } from "drizzle-orm"; - -const [vitalik] = await ensDb -\t.select({ -\t\tid: ensIndexerSchema.domain.id, -\t\ttype: ensIndexerSchema.domain.type, -\t\tcanonicalName: ensIndexerSchema.domain.canonicalName, -\t\tcanonicalNode: ensIndexerSchema.domain.canonicalNode, -\t\townerId: ensIndexerSchema.domain.ownerId, -\t}) -\t.from(ensIndexerSchema.domain) -\t.where(eq(ensIndexerSchema.domain.canonicalName, "vitalik.eth")); - -console.log(vitalik);` +import { exampleDomainEvents } from "@data/unigraph-examples/domain-events"; :::caution[`unigraph` plugin required] Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` plugin activated in your ENSNode instance. [Learn more](/docs/services/ensindexer/usage/configuration) ::: -Fetch a Domain by its canonical name. Because `canonical_name` is materialized across both ENSv1 and ENSv2, the same lookup works regardless of protocol version. See [Connect](/docs/integrate/unigraph/examples) for setup. +Fetch recent events for a Domain by its canonical name. This example joins the `events`, `domain_events`, and `domains` tables to retrieve domain events associated with the `vitalik.eth` name. :::note[Canonical fields] Canonical fields are populated on every Domain reachable from the canonical root, across both ENSv1 and ENSv2 — query them uniformly without branching by `type`. In SQL, these columns are `canonical_name`, `canonical_path`, `canonical_node`, and `canonical_depth`; in `ensdb-sdk`, the corresponding fields are `canonicalName`, `canonicalPath`, `canonicalNode`, and `canonicalDepth`. ::: - + diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domains-fuzzy-search-by-name.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domains-fuzzy-search-by-name.mdx index dae2c7e60..2d7eacbd3 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domains-fuzzy-search-by-name.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domains-fuzzy-search-by-name.mdx @@ -8,47 +8,17 @@ sidebar: import UnigraphStaticExample from "@components/molecules/unigraph-static-example/UnigraphStaticExample.astro"; import EnsDbWriterSchemaIntro from "@components/molecules/EnsDbWriterSchemaIntro.astro"; import EnsDbReaderIntro from "@components/molecules/EnsDbReaderIntro.astro"; - -export const resultJson = [ - { - type: "ENSv1Domain", - count: 2 - }, - { - type: "ENSv2Domain", - count: 14 - } -]; - -export const sqlExampleSnippet = `SELECT type, count(*) FROM ensindexer_0.domains -WHERE owner_id = '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' -GROUP BY type; -`; - -export const tsExampleSnippet = `import { count, eq } from "drizzle-orm"; - -const counts = await ensDb -\t.select({ type: ensIndexerSchema.domain.type, count: count() }) -\t.from(ensIndexerSchema.domain) -\t.where(eq(ensIndexerSchema.domain.ownerId, "0x70997970c51812dc3a010c7d01b50e0d17dc79c8")) -\t.groupBy(ensIndexerSchema.domain.type); -` +import { exampleDomainsFuzzySearchByName } from "@data/unigraph-examples/domains-fuzzy-search-by-name"; :::caution[`unigraph` plugin required] Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` plugin activated in your ENSNode instance. [Learn more](/docs/services/ensindexer/usage/configuration) ::: -Count the Domains owned by an address, grouped by Domain `type` (`ENSv1Domain` vs `ENSv2Domain`) — a single query spanning both protocol versions. See [Connect](/docs/integrate/unigraph/examples) for setup. +Fetch Domains with names similar to a query string, ranked by similarity. This example uses PostgreSQL's `pg_trgm` extension, which provides the `%` operator for fuzzy matching and the `similarity()` function for ranking results. See [Connect](/docs/integrate/unigraph/examples) for setup. diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/expiring-registrations.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/expiring-registrations.mdx index dae2c7e60..c5e59dea9 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/expiring-registrations.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/expiring-registrations.mdx @@ -1,54 +1,24 @@ --- -title: Fuzzy Search for ENS Names -description: Perform a fuzzy search for ENS names. +title: Expiring ENS Registrations +description: Fetch ENS registrations that are about to expire. sidebar: - label: Fuzzy Search + label: Expiring Registrations --- import UnigraphStaticExample from "@components/molecules/unigraph-static-example/UnigraphStaticExample.astro"; import EnsDbWriterSchemaIntro from "@components/molecules/EnsDbWriterSchemaIntro.astro"; import EnsDbReaderIntro from "@components/molecules/EnsDbReaderIntro.astro"; - -export const resultJson = [ - { - type: "ENSv1Domain", - count: 2 - }, - { - type: "ENSv2Domain", - count: 14 - } -]; - -export const sqlExampleSnippet = `SELECT type, count(*) FROM ensindexer_0.domains -WHERE owner_id = '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' -GROUP BY type; -`; - -export const tsExampleSnippet = `import { count, eq } from "drizzle-orm"; - -const counts = await ensDb -\t.select({ type: ensIndexerSchema.domain.type, count: count() }) -\t.from(ensIndexerSchema.domain) -\t.where(eq(ensIndexerSchema.domain.ownerId, "0x70997970c51812dc3a010c7d01b50e0d17dc79c8")) -\t.groupBy(ensIndexerSchema.domain.type); -` +import { exampleExpiringRegistrations } from "@data/unigraph-examples/expiring-registrations"; :::caution[`unigraph` plugin required] Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` plugin activated in your ENSNode instance. [Learn more](/docs/services/ensindexer/usage/configuration) ::: -Count the Domains owned by an address, grouped by Domain `type` (`ENSv1Domain` vs `ENSv2Domain`) — a single query spanning both protocol versions. See [Connect](/docs/integrate/unigraph/examples) for setup. +Fetch Domains with registrations expiring within a certain timeframe. This example uses a simple `WHERE` clause to filter for Domains with `expiry_date` between the current time and a specified future time (e.g., 3 days from now). See [Connect](/docs/integrate/unigraph/examples) for setup. diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/indexing-status.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/indexing-status.mdx index 4a6085234..09a77e5d6 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/indexing-status.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/indexing-status.mdx @@ -8,141 +8,17 @@ sidebar: import UnigraphStaticExample from "@components/molecules/unigraph-static-example/UnigraphStaticExample.astro"; import EnsNodeSchemaIntro from "@components/molecules/EnsNodeSchemaIntro.astro"; import EnsDbReaderIntro from "@components/molecules/EnsDbReaderIntro.astro"; - -export const ensDbSdkResultJson = { - indexingStatus: { - strategy: "omnichain", - snapshotTime: 1779795066, - omnichainSnapshot: { - chains: { - 1: { - config: { - rangeType: "left-bounded", - startBlock: { - number: 3327417, - timestamp: 1489165544, - }, - }, - chainStatus: "chain-backfill", - backfillEndBlock: { - number: 25171597, - timestamp: 1779703391, - }, - latestIndexedBlock: { - number: 21224717, - timestamp: 1732054691, - }, - }, - 10: { - config: { - rangeType: "left-bounded", - startBlock: { - number: 110393959, - timestamp: 1696386695, - }, - }, - chainStatus: "chain-backfill", - backfillEndBlock: { - number: 152052671, - timestamp: 1779704119, - }, - latestIndexedBlock: { - number: 128226309, - timestamp: 1732051395, - }, - }, - 8453: { - config: { - rangeType: "left-bounded", - startBlock: { - number: 17522624, - timestamp: 1721834595, - }, - }, - chainStatus: "chain-backfill", - backfillEndBlock: { - number: 46457386, - timestamp: 1779704119, - }, - latestIndexedBlock: { - number: 22632818, - timestamp: 1732054983, - }, - }, - 42161: { - config: { - rangeType: "left-bounded", - startBlock: { - number: 349263357, - timestamp: 1750406457, - }, - }, - chainStatus: "chain-queued", - }, - 59144: { - config: { - rangeType: "left-bounded", - startBlock: { - number: 6682888, - timestamp: 1720768992, - }, - }, - chainStatus: "chain-backfill", - backfillEndBlock: { - number: 30774477, - timestamp: 1779703911, - }, - latestIndexedBlock: { - number: 12280006, - timestamp: 1732054967, - }, - }, - 534352: { - config: { - rangeType: "left-bounded", - startBlock: { - number: 16604272, - timestamp: 1750406415, - }, - }, - chainStatus: "chain-queued", - }, - }, - omnichainStatus: "omnichain-backfill", - omnichainIndexingCursor: 1732054983, - }, - slowestChainIndexingCursor: 1732054983, - } -} - -export const unigraphSqlResultJson = { - indexing_status_snapshot: ensDbSdkResultJson.indexingStatus, -}; - -export const sqlExampleSnippet = `-- Indexing status snapshot for the \`ensindexer_0\` ENSIndexer Schema -SELECT value -> 'indexingStatus' as indexing_status_snapshot -FROM "ensnode".metadata -WHERE ens_indexer_schema_name = 'ensindexer_0' -AND key = 'indexing_metadata_context'; -`; - -export const tsExampleSnippet = `import { IndexingMetadataContextStatusCodes } from "@ensnode/ensdb-sdk"; - -const indexingMetadataContext = await ensDbReader.getIndexingMetadataContext(); -if (indexingMetadataContext.statusCode === IndexingMetadataContextStatusCodes.Initialized) { -\tconst { indexingStatus } = indexingMetadataContext; -\tconsole.log({ indexingStatus }); -}`; +import { exampleIndexingStatus } from "@data/unigraph-examples/indexing-status"; :::caution[`unigraph` plugin required] Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` plugin activated in your ENSNode instance. [Learn more](/docs/services/ensindexer/usage/configuration) ::: -Read the indexing status snapshot for an ENSIndexer instance from the shared `ensnode.metadata` table. See [Connect](/docs/integrate/unigraph/examples) for setup. +Read the indexing status snapshot for an ENSDb Writer instance from the shared `ensnode.metadata` table. See [Connect](/docs/integrate/unigraph/examples) for setup. diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/latest-registrations.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/latest-registrations.mdx index dae2c7e60..167336fe2 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/latest-registrations.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/latest-registrations.mdx @@ -1,54 +1,24 @@ --- -title: Fuzzy Search for ENS Names -description: Perform a fuzzy search for ENS names. +title: Latest ENS Registrations +description: Fetch the latest ENS registrations. sidebar: - label: Fuzzy Search + label: Latest Registrations --- import UnigraphStaticExample from "@components/molecules/unigraph-static-example/UnigraphStaticExample.astro"; import EnsDbWriterSchemaIntro from "@components/molecules/EnsDbWriterSchemaIntro.astro"; import EnsDbReaderIntro from "@components/molecules/EnsDbReaderIntro.astro"; - -export const resultJson = [ - { - type: "ENSv1Domain", - count: 2 - }, - { - type: "ENSv2Domain", - count: 14 - } -]; - -export const sqlExampleSnippet = `SELECT type, count(*) FROM ensindexer_0.domains -WHERE owner_id = '0x70997970c51812dc3a010c7d01b50e0d17dc79c8' -GROUP BY type; -`; - -export const tsExampleSnippet = `import { count, eq } from "drizzle-orm"; - -const counts = await ensDb -\t.select({ type: ensIndexerSchema.domain.type, count: count() }) -\t.from(ensIndexerSchema.domain) -\t.where(eq(ensIndexerSchema.domain.ownerId, "0x70997970c51812dc3a010c7d01b50e0d17dc79c8")) -\t.groupBy(ensIndexerSchema.domain.type); -` +import { exampleLatestRegistrations } from "@data/unigraph-examples/latest-registrations"; :::caution[`unigraph` plugin required] Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` plugin activated in your ENSNode instance. [Learn more](/docs/services/ensindexer/usage/configuration) ::: -Count the Domains owned by an address, grouped by Domain `type` (`ENSv1Domain` vs `ENSv2Domain`) — a single query spanning both protocol versions. See [Connect](/docs/integrate/unigraph/examples) for setup. +Fetch the latest registrations and their associated Domains. See [Connect](/docs/integrate/unigraph/examples) for setup. diff --git a/docs/ensnode.io/src/data/unigraph-examples/account-domains.ts b/docs/ensnode.io/src/data/unigraph-examples/account-domains.ts new file mode 100644 index 000000000..f70b6a900 --- /dev/null +++ b/docs/ensnode.io/src/data/unigraph-examples/account-domains.ts @@ -0,0 +1,198 @@ +import type { QueryExample } from "./types"; + +/** + * Example query for fetching Domains by their owner's address, + * demonstrating the use of canonical fields to query across both ENSv1 and + * ENSv2 domains without branching by protocol version. + */ +export const exampleAccountDomains = { + sql: { + codeSnippet: `SELECT + d.type, + d.canonical_name, + d.canonical_node, + d.id, + d.owner_id +FROM "ensindexer_0".domains d +WHERE d.canonical = true +AND d.owner_id = '0xffffffffff52d316b7bd028358089bc8066b8f80' +ORDER BY d.canonical_name +LIMIT 10;`, + result: [ + { + type: "ENSv1Domain", + canonical_name: + "[3ad05e2a5922916840bc1e5e6039f00b27cbabf8d0428abce062aa2011307374].addr.reverse", + canonical_node: "0xd3947f90d04d7f41f973f09ad7dbdb34cb7463359369e6cf1663bbf928d66e53", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0xd3947f90d04d7f41f973f09ad7dbdb34cb7463359369e6cf1663bbf928d66e53", + owner_id: "0xffffffffff52d316b7bd028358089bc8066b8f80", + }, + { + type: "ENSv1Domain", + canonical_name: "[52602a50858115661619fb28cf543ee766c182e0be6743c72d5bd674b3d12686].eth", + canonical_node: "0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", + owner_id: "0xffffffffff52d316b7bd028358089bc8066b8f80", + }, + { + type: "ENSv1Domain", + canonical_name: + "[8268685e13ae6bbfa54901f2954f9fcf80839ffa102fe7146b930623ce9bd7f0].addr.reverse", + canonical_node: "0x21c356e778799bfddf59a5683c04f6b08710d7c198fef466cc697563b2210785", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x21c356e778799bfddf59a5683c04f6b08710d7c198fef466cc697563b2210785", + owner_id: "0xffffffffff52d316b7bd028358089bc8066b8f80", + }, + { + type: "ENSv1Domain", + canonical_name: "[d90db363b8bc1371f7d738d264ff7294bfc5636f907c467adf68321a3c6d8188].eth", + canonical_node: "0x08c0f01c419a8971af6b3eefe2a8bba1556cccf1163df60b1cdbcab632c8ab48", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x08c0f01c419a8971af6b3eefe2a8bba1556cccf1163df60b1cdbcab632c8ab48", + owner_id: "0xffffffffff52d316b7bd028358089bc8066b8f80", + }, + { + type: "ENSv1Domain", + canonical_name: + "[d99fc3d8237200c7122431276a337421cf793f51276873df5a54cc482fdbe685].addr.reverse", + canonical_node: "0x4fc87044c0adc4a0c996b9dafe3a4889e72fe0745fc76f18151b81ed73582218", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x4fc87044c0adc4a0c996b9dafe3a4889e72fe0745fc76f18151b81ed73582218", + owner_id: "0xffffffffff52d316b7bd028358089bc8066b8f80", + }, + { + type: "ENSv2Domain", + canonical_name: "eth", + canonical_node: "0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae", + id: "11155111-0x835f0b284e78cd3f358bcf6cba3b53809f09b79e-35894389512221139346028120028875095598761990588366713962827482865183915769856", + owner_id: "0xffffffffff52d316b7bd028358089bc8066b8f80", + }, + { + type: "ENSv2Domain", + canonical_name: "reverse", + canonical_node: "0xa097f6721ce401e757d1223a763fef49b8b5f90bb18567ddb86fd205dff71d34", + id: "11155111-0x835f0b284e78cd3f358bcf6cba3b53809f09b79e-100753657518907091865523951670693454610893379027273088370152078482136467767296", + owner_id: "0xffffffffff52d316b7bd028358089bc8066b8f80", + }, + { + type: "ENSv1Domain", + canonical_name: "reverse", + canonical_node: "0xa097f6721ce401e757d1223a763fef49b8b5f90bb18567ddb86fd205dff71d34", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0xa097f6721ce401e757d1223a763fef49b8b5f90bb18567ddb86fd205dff71d34", + owner_id: "0xffffffffff52d316b7bd028358089bc8066b8f80", + }, + { + type: "ENSv2Domain", + canonical_name: "sfmpfv44d0mig.eth", + canonical_node: "0x9b365136312d7ee6e232e3c98e459bc8667ec818c47fbbc55bb5e23d0a21e8cc", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-30078755955643454526763071980293195785165410039216352470119925106082295316480", + owner_id: "0xffffffffff52d316b7bd028358089bc8066b8f80", + }, + { + type: "ENSv2Domain", + canonical_name: "sfmpfvtoicv2ok.eth", + canonical_node: "0x7d0c27336cf9d51c3fc8f29ef4ef69df9cd4a8ec983e3e17d457a8de6013f3c5", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-49509597771493908415463190501045916291230588437784211605615168713991762477056", + owner_id: "0xffffffffff52d316b7bd028358089bc8066b8f80", + }, + ], + }, + sdk: { + codeSnippet: `import { and, eq } from "drizzle-orm"; + +const owner = "0xffffffffff52d316b7bd028358089bc8066b8f80"; +const limit = 10; + +const accountDomains = await ensDb + .select({ + canonicalName: ensIndexerSchema.domain.canonicalName, + canonicalNode: ensIndexerSchema.domain.canonicalNode, + type: ensIndexerSchema.domain.type, + id: ensIndexerSchema.domain.id, + ownerId: ensIndexerSchema.domain.ownerId, + }) + .from(ensIndexerSchema.domain) + .where( + and( + eq(ensIndexerSchema.domain.ownerId, owner), + eq(ensIndexerSchema.domain.canonical, true), + ), + ) + .orderBy(asc(ensIndexerSchema.domain.canonicalName)) + .limit(limit); + +console.log(accountDomains);`, + result: [ + { + type: "ENSv1Domain", + canonicalName: + "[3ad05e2a5922916840bc1e5e6039f00b27cbabf8d0428abce062aa2011307374].addr.reverse", + canonicalNode: "0xd3947f90d04d7f41f973f09ad7dbdb34cb7463359369e6cf1663bbf928d66e53", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0xd3947f90d04d7f41f973f09ad7dbdb34cb7463359369e6cf1663bbf928d66e53", + ownerId: "0xffffffffff52d316b7bd028358089bc8066b8f80", + }, + { + type: "ENSv1Domain", + canonicalName: "[52602a50858115661619fb28cf543ee766c182e0be6743c72d5bd674b3d12686].eth", + canonicalNode: "0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", + ownerId: "0xffffffffff52d316b7bd028358089bc8066b8f80", + }, + { + type: "ENSv1Domain", + canonicalName: + "[8268685e13ae6bbfa54901f2954f9fcf80839ffa102fe7146b930623ce9bd7f0].addr.reverse", + canonicalNode: "0x21c356e778799bfddf59a5683c04f6b08710d7c198fef466cc697563b2210785", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x21c356e778799bfddf59a5683c04f6b08710d7c198fef466cc697563b2210785", + ownerId: "0xffffffffff52d316b7bd028358089bc8066b8f80", + }, + { + type: "ENSv1Domain", + canonicalName: "[d90db363b8bc1371f7d738d264ff7294bfc5636f907c467adf68321a3c6d8188].eth", + canonicalNode: "0x08c0f01c419a8971af6b3eefe2a8bba1556cccf1163df60b1cdbcab632c8ab48", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x08c0f01c419a8971af6b3eefe2a8bba1556cccf1163df60b1cdbcab632c8ab48", + ownerId: "0xffffffffff52d316b7bd028358089bc8066b8f80", + }, + { + type: "ENSv1Domain", + canonicalName: + "[d99fc3d8237200c7122431276a337421cf793f51276873df5a54cc482fdbe685].addr.reverse", + canonicalNode: "0x4fc87044c0adc4a0c996b9dafe3a4889e72fe0745fc76f18151b81ed73582218", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x4fc87044c0adc4a0c996b9dafe3a4889e72fe0745fc76f18151b81ed73582218", + ownerId: "0xffffffffff52d316b7bd028358089bc8066b8f80", + }, + { + type: "ENSv2Domain", + canonicalName: "eth", + canonicalNode: "0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae", + id: "11155111-0x835f0b284e78cd3f358bcf6cba3b53809f09b79e-35894389512221139346028120028875095598761990588366713962827482865183915769856", + ownerId: "0xffffffffff52d316b7bd028358089bc8066b8f80", + }, + { + type: "ENSv2Domain", + canonicalName: "reverse", + canonicalNode: "0xa097f6721ce401e757d1223a763fef49b8b5f90bb18567ddb86fd205dff71d34", + id: "11155111-0x835f0b284e78cd3f358bcf6cba3b53809f09b79e-100753657518907091865523951670693454610893379027273088370152078482136467767296", + ownerId: "0xffffffffff52d316b7bd028358089bc8066b8f80", + }, + { + type: "ENSv1Domain", + canonicalName: "reverse", + canonicalNode: "0xa097f6721ce401e757d1223a763fef49b8b5f90bb18567ddb86fd205dff71d34", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0xa097f6721ce401e757d1223a763fef49b8b5f90bb18567ddb86fd205dff71d34", + ownerId: "0xffffffffff52d316b7bd028358089bc8066b8f80", + }, + { + type: "ENSv2Domain", + canonicalName: "sfmpfv44d0mig.eth", + canonicalNode: "0x9b365136312d7ee6e232e3c98e459bc8667ec818c47fbbc55bb5e23d0a21e8cc", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-30078755955643454526763071980293195785165410039216352470119925106082295316480", + ownerId: "0xffffffffff52d316b7bd028358089bc8066b8f80", + }, + { + type: "ENSv2Domain", + canonicalName: "sfmpfvtoicv2ok.eth", + canonicalNode: "0x7d0c27336cf9d51c3fc8f29ef4ef69df9cd4a8ec983e3e17d457a8de6013f3c5", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-49509597771493908415463190501045916291230588437784211605615168713991762477056", + ownerId: "0xffffffffff52d316b7bd028358089bc8066b8f80", + }, + ], + }, +} satisfies QueryExample; diff --git a/docs/ensnode.io/src/data/unigraph-examples/domain-by-name.ts b/docs/ensnode.io/src/data/unigraph-examples/domain-by-name.ts index fb179ea6a..5fc624f93 100644 --- a/docs/ensnode.io/src/data/unigraph-examples/domain-by-name.ts +++ b/docs/ensnode.io/src/data/unigraph-examples/domain-by-name.ts @@ -13,8 +13,9 @@ export const exampleDomainByName = { canonical_name, canonical_node, owner_id -FROM ensindexer_0.domains -WHERE canonical_name = 'vitalik.eth'; +FROM "ensindexer_0".domains +WHERE canonical_name = 'vitalik.eth' +AND canonical = true; `, result: [ { @@ -27,7 +28,7 @@ WHERE canonical_name = 'vitalik.eth'; ], }, sdk: { - codeSnippet: `import { eq } from "drizzle-orm"; + codeSnippet: `import { and, eq } from "drizzle-orm"; const [vitalik] = await ensDb .select({ @@ -39,7 +40,10 @@ const [vitalik] = await ensDb }) .from(ensIndexerSchema.domain) .where( - eq(ensIndexerSchema.domain.canonicalName, "vitalik.eth") + and( + eq(ensIndexerSchema.domain.canonicalName, "vitalik.eth"), + eq(ensIndexerSchema.domain.canonical, true) + ) ); console.log(vitalik);`, diff --git a/docs/ensnode.io/src/data/unigraph-examples/domain-events.ts b/docs/ensnode.io/src/data/unigraph-examples/domain-events.ts new file mode 100644 index 000000000..82bbdec47 --- /dev/null +++ b/docs/ensnode.io/src/data/unigraph-examples/domain-events.ts @@ -0,0 +1,168 @@ +import type { QueryExample } from "./types"; + +/** + * Example query for fetching recent events for a Domain by its canonical name. + */ +export const exampleDomainEvents = { + sql: { + codeSnippet: `SELECT + e.chain_id, + e.block_number, + e.transaction_hash, + e.log_index, + e.address as contract_address, + e.sender, + d.id as domain_id +FROM "ensindexer_0".events e +JOIN "ensindexer_0".domain_events de ON e.id = de.event_id +JOIN "ensindexer_0".domains d ON de.domain_id = d.id +WHERE d.canonical_name = 'vitalik.eth' +AND d.canonical = true +ORDER BY e.block_number DESC, e.log_index DESC +LIMIT 5; +`, + result: [ + { + chain_id: "11155111", + block_number: "6023942", + transaction_hash: "0x6206e95dc5ba5fc8d0804283498f17bac18081437b4198c824b62ee851622ba5", + log_index: 194, + contract_address: "0xfed6a969aaa60e4961fcd3ebf1a2e8913ac65b72", + sender: "0x225f137127d9067788314bc7fcc1f36746a3c3b5", + domain_id: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + }, + { + chain_id: "11155111", + block_number: "6023942", + transaction_hash: "0x6206e95dc5ba5fc8d0804283498f17bac18081437b4198c824b62ee851622ba5", + log_index: 193, + contract_address: "0x57f1887a8bf19b14fc0df6fd9b2acc9af147ea85", + sender: "0x225f137127d9067788314bc7fcc1f36746a3c3b5", + domain_id: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + }, + { + chain_id: "11155111", + block_number: "4107392", + transaction_hash: "0xf143118eb4100361f040b1ae5627562125f0cf1717073a8204befe5e512c80d4", + log_index: 22, + contract_address: "0x0635513f179d50a207757e05759cbd106d7dfce8", + sender: "0x179a862703a4adfb29896552df9e307980d19285", + domain_id: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + }, + { + chain_id: "11155111", + block_number: "4107386", + transaction_hash: "0x6410de03e9a2f12543e491d1048209e5638d702948cf23d48a63d96a50efd20d", + log_index: 19, + contract_address: "0xfed6a969aaa60e4961fcd3ebf1a2e8913ac65b72", + sender: "0x179a862703a4adfb29896552df9e307980d19285", + domain_id: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + }, + { + chain_id: "11155111", + block_number: "4107386", + transaction_hash: "0x6410de03e9a2f12543e491d1048209e5638d702948cf23d48a63d96a50efd20d", + log_index: 16, + contract_address: "0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e", + sender: "0x179a862703a4adfb29896552df9e307980d19285", + domain_id: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + }, + ], + }, + sdk: { + codeSnippet: `import { and, desc, eq } from "drizzle-orm"; + +const name = "vitalik.eth"; +const limit = 5; + +const domainEvents = await ensDb + .select({ + chainId: ensIndexerSchema.event.chainId, + blockNumber: ensIndexerSchema.event.blockNumber, + transactionHash: ensIndexerSchema.event.transactionHash, + logIndex: ensIndexerSchema.event.logIndex, + contractAddress: ensIndexerSchema.event.address, + sender: ensIndexerSchema.event.sender, + domainId: ensIndexerSchema.domain.id, + }) + .from(ensIndexerSchema.event) + .innerJoin( + ensIndexerSchema.domainEvent, + eq(ensIndexerSchema.event.id, ensIndexerSchema.domainEvent.eventId), + ) + .innerJoin( + ensIndexerSchema.domain, + eq(ensIndexerSchema.domainEvent.domainId, ensIndexerSchema.domain.id), + ) + .where( + and( + eq(ensIndexerSchema.domain.canonicalName, name), + eq(ensIndexerSchema.domain.canonical, true), + ), + ) + .orderBy( + desc(ensIndexerSchema.event.blockNumber), + desc(ensIndexerSchema.event.logIndex), + ) + .limit(limit); + +console.log(domainEvents);`, + result: [ + { + chainId: 11155111, + blockNumber: "6023942", + transactionHash: "0x6206e95dc5ba5fc8d0804283498f17bac18081437b4198c824b62ee851622ba5", + logIndex: 194, + contractAddress: "0xfed6a969aaa60e4961fcd3ebf1a2e8913ac65b72", + sender: "0x225f137127d9067788314bc7fcc1f36746a3c3b5", + domainId: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + }, + { + chainId: 11155111, + blockNumber: "6023942", + transactionHash: "0x6206e95dc5ba5fc8d0804283498f17bac18081437b4198c824b62ee851622ba5", + logIndex: 193, + contractAddress: "0x57f1887a8bf19b14fc0df6fd9b2acc9af147ea85", + sender: "0x225f137127d9067788314bc7fcc1f36746a3c3b5", + domainId: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + }, + { + chainId: 11155111, + blockNumber: "4107392", + transactionHash: "0xf143118eb4100361f040b1ae5627562125f0cf1717073a8204befe5e512c80d4", + logIndex: 22, + contractAddress: "0x0635513f179d50a207757e05759cbd106d7dfce8", + sender: "0x179a862703a4adfb29896552df9e307980d19285", + domainId: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + }, + { + chainId: 11155111, + blockNumber: "4107386", + transactionHash: "0x6410de03e9a2f12543e491d1048209e5638d702948cf23d48a63d96a50efd20d", + logIndex: 19, + contractAddress: "0xfed6a969aaa60e4961fcd3ebf1a2e8913ac65b72", + sender: "0x179a862703a4adfb29896552df9e307980d19285", + domainId: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + }, + { + chainId: 11155111, + blockNumber: "4107386", + transactionHash: "0x6410de03e9a2f12543e491d1048209e5638d702948cf23d48a63d96a50efd20d", + logIndex: 16, + contractAddress: "0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e", + sender: "0x179a862703a4adfb29896552df9e307980d19285", + domainId: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + }, + ], + }, +} satisfies QueryExample; diff --git a/docs/ensnode.io/src/data/unigraph-examples/domains-fuzzy-search-by-name.ts b/docs/ensnode.io/src/data/unigraph-examples/domains-fuzzy-search-by-name.ts index fb179ea6a..bd33a75c2 100644 --- a/docs/ensnode.io/src/data/unigraph-examples/domains-fuzzy-search-by-name.ts +++ b/docs/ensnode.io/src/data/unigraph-examples/domains-fuzzy-search-by-name.ts @@ -1,55 +1,129 @@ import type { QueryExample } from "./types"; /** - * Example query for fetching a Domain by its canonical name, - * demonstrating the use of canonical fields to query across both ENSv1 and - * ENSv2 domains without branching by protocol version. + * Example query for fetching Domains by a fuzzy search on their canonical name. */ -export const exampleDomainByName = { +export const exampleDomainsFuzzySearchByName = { sql: { codeSnippet: `SELECT - id, - type, - canonical_name, - canonical_node, - owner_id -FROM ensindexer_0.domains -WHERE canonical_name = 'vitalik.eth'; + type, + canonical_name, + canonical_node, + owner_id, + similarity(canonical_name, 'vitalik') as name_similarity, + id +FROM "ensindexer_0".domains +-- Use the pg_trgm similarity operator (%) for fuzzy matching on canonical_name +WHERE canonical_name % 'vitalik' +AND canonical = true +ORDER BY name_similarity DESC +LIMIT 5; `, result: [ { - id: "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", type: "ENSv1Domain", canonical_name: "vitalik.eth", canonical_node: "0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", - owner_id: "0x220866b1a2219f40e72f5c628b65d54268ca3a9d", + owner_id: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", + name_similarity: 0.6666667, + }, + { + id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x278adcf079fceb551531f1593deae8891d83bf4708b935d54eda7f8db51ce797", + type: "ENSv1Domain", + canonical_name: "vitalikkk.eth", + canonical_node: "0x278adcf079fceb551531f1593deae8891d83bf4708b935d54eda7f8db51ce797", + owner_id: "0x588f6b3169f60176c1143f8bab47bcf3deebecdc", + name_similarity: 0.46666667, + }, + { + id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x55e83f7d37d7cf1f87c40a6bd5fc8e62e8898b327c5a09776596f6efe547349a", + type: "ENSv1Domain", + canonical_name: "vitalik.taars.eth", + canonical_node: "0x55e83f7d37d7cf1f87c40a6bd5fc8e62e8898b327c5a09776596f6efe547349a", + owner_id: "0x5a09e3ec3efdd91205cbb097142a4f4dcefc7f02", + name_similarity: 0.44444445, + }, + { + id: "84532-0x1493b2567056c2181630115660963e13a8e32735-0x97fa42e69feb1d407361108d79ddad705707a16392d7823f8b21b44dabfc4a9d", + type: "ENSv1Domain", + canonical_name: "vitalik.basetest.eth", + canonical_node: "0x97fa42e69feb1d407361108d79ddad705707a16392d7823f8b21b44dabfc4a9d", + owner_id: "0x15378e401f9c3243639c7c3250be0f396a758e40", + name_similarity: 0.3809524, + }, + { + id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x117e485acf1ebff586d1382b7689201ce23f7142ae92f4c397849f4b01e6a1cc", + type: "ENSv1Domain", + canonical_name: "vitalikbuterin.eth", + canonical_node: "0x117e485acf1ebff586d1382b7689201ce23f7142ae92f4c397849f4b01e6a1cc", + owner_id: "0x16ecc228f185b084cb884be2d65544f5ca4dd761", + name_similarity: 0.35, }, ], }, sdk: { - codeSnippet: `import { eq } from "drizzle-orm"; + codeSnippet: `import { and, asc, eq, sql } from "drizzle-orm"; -const [vitalik] = await ensDb +const q = "vitalik"; +const limit = 5; + +const domains = await ensDb .select({ - id: ensIndexerSchema.domain.id, - type: ensIndexerSchema.domain.type, canonicalName: ensIndexerSchema.domain.canonicalName, - canonicalNode: ensIndexerSchema.domain.canonicalNode, + canonicalDepth: ensIndexerSchema.domain.canonicalDepth, ownerId: ensIndexerSchema.domain.ownerId, + nameSimilarity: sql\`similarity(\${ensIndexerSchema.domain.canonicalName}, \${q})\`.as( + "name_similarity", + ), + id: ensIndexerSchema.domain.id, }) .from(ensIndexerSchema.domain) .where( - eq(ensIndexerSchema.domain.canonicalName, "vitalik.eth") - ); + and( + sql\`\${ensIndexerSchema.domain.canonicalName} % \${q}\`, + eq(ensIndexerSchema.domain.canonical, true), + ), + ) + .orderBy(sql\`name_similarity DESC\`) + .limit(limit); -console.log(vitalik);`, +console.log(domains);`, result: [ { - id: "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", - type: "ENSv1Domain", canonicalName: "vitalik.eth", - canonicalNode: "0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", - ownerId: "0x220866b1a2219f40e72f5c628b65d54268ca3a9d", + canonicalDepth: 2, + ownerId: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", + nameSimilarity: 0.6666667, + id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + }, + { + canonicalName: "vitalikkk.eth", + canonicalDepth: 2, + ownerId: "0x588f6b3169f60176c1143f8bab47bcf3deebecdc", + nameSimilarity: 0.46666667, + id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x278adcf079fceb551531f1593deae8891d83bf4708b935d54eda7f8db51ce797", + }, + { + canonicalName: "vitalik.taars.eth", + canonicalDepth: 3, + ownerId: "0x5a09e3ec3efdd91205cbb097142a4f4dcefc7f02", + nameSimilarity: 0.44444445, + id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x55e83f7d37d7cf1f87c40a6bd5fc8e62e8898b327c5a09776596f6efe547349a", + }, + { + canonicalName: "vitalik.basetest.eth", + canonicalDepth: 3, + ownerId: "0x15378e401f9c3243639c7c3250be0f396a758e40", + nameSimilarity: 0.3809524, + id: "84532-0x1493b2567056c2181630115660963e13a8e32735-0x97fa42e69feb1d407361108d79ddad705707a16392d7823f8b21b44dabfc4a9d", + }, + { + canonicalName: "vitalikbuterin.eth", + canonicalDepth: 2, + ownerId: "0x16ecc228f185b084cb884be2d65544f5ca4dd761", + nameSimilarity: 0.35, + id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x117e485acf1ebff586d1382b7689201ce23f7142ae92f4c397849f4b01e6a1cc", }, ], }, diff --git a/docs/ensnode.io/src/data/unigraph-examples/expiring-registrations.ts b/docs/ensnode.io/src/data/unigraph-examples/expiring-registrations.ts new file mode 100644 index 000000000..fb13a57db --- /dev/null +++ b/docs/ensnode.io/src/data/unigraph-examples/expiring-registrations.ts @@ -0,0 +1,168 @@ +import type { QueryExample } from "./types"; + +/** + * Example query for fetching recent events for a Domain by its canonical name. + */ +export const exampleExpiringRegistrations = { + sql: { + codeSnippet: `SELECT + d.canonical_name, + r.start, + r.expiry, + r.grace_period, + d.owner_id, + d.id as domain_id +FROM "ensindexer_0".registrations r +JOIN "ensindexer_0".latest_registration_index lri + ON r.domain_id = lri.domain_id + AND r.registration_index = lri.registration_index +JOIN "ensindexer_0".domains d ON r.domain_id = d.id +WHERE r.expiry >= EXTRACT(EPOCH FROM NOW()) + AND r.expiry <= EXTRACT(EPOCH FROM NOW() + INTERVAL '3 days') + AND d.canonical = true +ORDER BY r.expiry ASC +LIMIT 5; +`, + result: [ + { + canonical_name: "block-land.eth", + start: "1717602456", + expiry: "1780674456", + grace_period: "7776000", + owner_id: "0x95e488ed0d3497f8cf2392e35c9eb81812ef863c", + domain_id: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x4263eab7cb93cb3161f613e59357fce5de6646c9dab3682c388938231ca16fe6", + }, + { + canonical_name: "hagemz.eth", + start: "1749139932", + expiry: "1780675932", + grace_period: "7776000", + owner_id: "0xeb4bde48fb4ad1ab104eb1ef978fdd24e11d6a28", + domain_id: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x7886dc1e5b637005edf606d9e0f5cee78bd86a57e1378e1c76c3fa7557847659", + }, + { + canonical_name: "leogomez.eth", + start: "1749152664", + expiry: "1780688664", + grace_period: "7776000", + owner_id: "0x2f7970674b6410f90b8bc43d8188ef35ab3f1a9b", + domain_id: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x6c577a69aa94e39ee0ff1beedbd3385f405506bc35d88f47284056c1ceba5759", + }, + { + canonical_name: "ilanklein.eth", + start: "1749156780", + expiry: "1780692780", + grace_period: "7776000", + owner_id: "0x99969df2da9bf780cfd62d7cc22f77e5bdb332df", + domain_id: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x94877f55b294b34b0ac4952ad746f1c163a7e1aba16c41d113c558cd4f2bdff5", + }, + { + canonical_name: "iwms.eth", + start: "1749157272", + expiry: "1780693272", + grace_period: "7776000", + owner_id: "0xa098364308d3e400e2f1199675ac765adac4810f", + domain_id: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x13403c49bb9d168c7f18b830b5dd86f562e3e203fe2fc545927e5f609e3e6417", + }, + ], + }, + sdk: { + codeSnippet: `import { and, asc, eq, gte, lte, sql } from "drizzle-orm"; + +const limit = 5; + +const expiringRegistrations = await ensDb + .select({ + canonicalName: ensIndexerSchema.domain.canonicalName, + expiry: ensIndexerSchema.registration.expiry, + start: ensIndexerSchema.registration.start, + gracePeriod: ensIndexerSchema.registration.gracePeriod, + ownerId: ensIndexerSchema.domain.ownerId, + domainId: ensIndexerSchema.domain.id, + }) + .from(ensIndexerSchema.registration) + .innerJoin( + ensIndexerSchema.latestRegistrationIndex, + and( + eq( + ensIndexerSchema.registration.domainId, + ensIndexerSchema.latestRegistrationIndex.domainId, + ), + eq( + ensIndexerSchema.registration.registrationIndex, + ensIndexerSchema.latestRegistrationIndex.registrationIndex, + ), + ), + ) + .innerJoin( + ensIndexerSchema.domain, + eq(ensIndexerSchema.registration.domainId, ensIndexerSchema.domain.id), + ) + .where( + and( + gte(ensIndexerSchema.registration.expiry, sql\`EXTRACT(EPOCH FROM NOW())\`), + lte( + ensIndexerSchema.registration.expiry, + sql\`EXTRACT(EPOCH FROM NOW() + INTERVAL '3 days')\`, + ), + eq(ensIndexerSchema.domain.canonical, true), + ), + ) + .orderBy(asc(ensIndexerSchema.registration.expiry)) + .limit(limit); + +console.log(expiringRegistrations);`, + result: [ + { + canonicalName: "block-land.eth", + expiry: "1780674456", + start: "1717602456", + gracePeriod: "7776000", + ownerId: "0x95e488ed0d3497f8cf2392e35c9eb81812ef863c", + domainId: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x4263eab7cb93cb3161f613e59357fce5de6646c9dab3682c388938231ca16fe6", + }, + { + canonicalName: "hagemz.eth", + expiry: "1780675932", + start: "1749139932", + gracePeriod: "7776000", + ownerId: "0xeb4bde48fb4ad1ab104eb1ef978fdd24e11d6a28", + domainId: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x7886dc1e5b637005edf606d9e0f5cee78bd86a57e1378e1c76c3fa7557847659", + }, + { + canonicalName: "leogomez.eth", + expiry: "1780688664", + start: "1749152664", + gracePeriod: "7776000", + ownerId: "0x2f7970674b6410f90b8bc43d8188ef35ab3f1a9b", + domainId: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x6c577a69aa94e39ee0ff1beedbd3385f405506bc35d88f47284056c1ceba5759", + }, + { + canonicalName: "ilanklein.eth", + expiry: "1780692780", + start: "1749156780", + gracePeriod: "7776000", + ownerId: "0x99969df2da9bf780cfd62d7cc22f77e5bdb332df", + domainId: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x94877f55b294b34b0ac4952ad746f1c163a7e1aba16c41d113c558cd4f2bdff5", + }, + { + canonicalName: "iwms.eth", + expiry: "1780693272", + start: "1749157272", + gracePeriod: "7776000", + ownerId: "0xa098364308d3e400e2f1199675ac765adac4810f", + domainId: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x13403c49bb9d168c7f18b830b5dd86f562e3e203fe2fc545927e5f609e3e6417", + }, + ], + }, +} satisfies QueryExample; diff --git a/docs/ensnode.io/src/data/unigraph-examples/indexing-status.ts b/docs/ensnode.io/src/data/unigraph-examples/indexing-status.ts new file mode 100644 index 000000000..174dbd085 --- /dev/null +++ b/docs/ensnode.io/src/data/unigraph-examples/indexing-status.ts @@ -0,0 +1,132 @@ +import type { QueryExample } from "./types"; + +const indexingStatusSnapshot = { + indexingStatus: { + strategy: "omnichain", + snapshotTime: 1779795066, + omnichainSnapshot: { + chains: { + 1: { + config: { + rangeType: "left-bounded", + startBlock: { + number: 3327417, + timestamp: 1489165544, + }, + }, + chainStatus: "chain-backfill", + backfillEndBlock: { + number: 25171597, + timestamp: 1779703391, + }, + latestIndexedBlock: { + number: 21224717, + timestamp: 1732054691, + }, + }, + 10: { + config: { + rangeType: "left-bounded", + startBlock: { + number: 110393959, + timestamp: 1696386695, + }, + }, + chainStatus: "chain-backfill", + backfillEndBlock: { + number: 152052671, + timestamp: 1779704119, + }, + latestIndexedBlock: { + number: 128226309, + timestamp: 1732051395, + }, + }, + 8453: { + config: { + rangeType: "left-bounded", + startBlock: { + number: 17522624, + timestamp: 1721834595, + }, + }, + chainStatus: "chain-backfill", + backfillEndBlock: { + number: 46457386, + timestamp: 1779704119, + }, + latestIndexedBlock: { + number: 22632818, + timestamp: 1732054983, + }, + }, + 42161: { + config: { + rangeType: "left-bounded", + startBlock: { + number: 349263357, + timestamp: 1750406457, + }, + }, + chainStatus: "chain-queued", + }, + 59144: { + config: { + rangeType: "left-bounded", + startBlock: { + number: 6682888, + timestamp: 1720768992, + }, + }, + chainStatus: "chain-backfill", + backfillEndBlock: { + number: 30774477, + timestamp: 1779703911, + }, + latestIndexedBlock: { + number: 12280006, + timestamp: 1732054967, + }, + }, + 534352: { + config: { + rangeType: "left-bounded", + startBlock: { + number: 16604272, + timestamp: 1750406415, + }, + }, + chainStatus: "chain-queued", + }, + }, + omnichainStatus: "omnichain-backfill", + omnichainIndexingCursor: 1732054983, + }, + slowestChainIndexingCursor: 1732054983, + }, +} as const; + +/** + * Example query for fetching the indexing status snapshot of an ENSDb Writer + */ +export const exampleIndexingStatus = { + sql: { + codeSnippet: `SELECT value -> 'indexingStatus' as indexing_status_snapshot +FROM "ensnode".metadata +WHERE ens_indexer_schema_name = 'ensindexer_0' +AND key = 'indexing_metadata_context'; +`, + result: { indexing_status_snapshot: indexingStatusSnapshot }, + }, + sdk: { + codeSnippet: `import { IndexingMetadataContextStatusCodes } from "@ensnode/ensdb-sdk"; + +const indexingMetadataContext = await ensDbReader.getIndexingMetadataContext(); + +if (indexingMetadataContext.statusCode === IndexingMetadataContextStatusCodes.Initialized) { + const { indexingStatus } = indexingMetadataContext; + console.log({ indexingStatus }); +}`, + result: { indexingStatus: indexingStatusSnapshot }, + }, +} satisfies QueryExample; diff --git a/docs/ensnode.io/src/data/unigraph-examples/latest-registrations.ts b/docs/ensnode.io/src/data/unigraph-examples/latest-registrations.ts new file mode 100644 index 000000000..1c59c783a --- /dev/null +++ b/docs/ensnode.io/src/data/unigraph-examples/latest-registrations.ts @@ -0,0 +1,179 @@ +import type { QueryExample } from "./types"; + +/** + * Example query for fetching the latest registrations for a Domain by its canonical name. + */ +export const exampleLatestRegistrations = { + sql: { + codeSnippet: `SELECT + d.canonical_name, + r.start, + r.expiry, + d.owner_id, + d.id as domain_id +FROM "ensindexer_0".registrations r +JOIN "ensindexer_0".latest_registration_index lri + ON r.domain_id = lri.domain_id + AND r.registration_index = lri.registration_index +JOIN "ensindexer_0".domains d ON r.domain_id = d.id +WHERE r.start <= EXTRACT(EPOCH FROM NOW()) + AND d.canonical = true + AND r.type <> 'NameWrapper' +ORDER BY r.start DESC +LIMIT 15; +`, + result: [ + { + canonical_name: "[67f53c740a0051f85075dc2383fb83a7b48d2984fc9ed9db56b334ca96d1d309].eth", + start: "1779816216", + expiry: "1811352216", + grace_period: "7776000", + base: "3125000000003490", + premium: "0", + registration_type: "BaseRegistrar", + owner_id: "0x205d2686da3bf33f64c17f21462c51b5ead462cf", + domain_id: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x085bfc7f3695efa2e9d3f9717214d85474f40b4b3ef902b67d2bb49654679fa1", + }, + { + canonical_name: "coolorg.eth", + start: "1779794160", + expiry: "1811330160", + grace_period: "7776000", + base: "3125000000003490", + premium: "0", + registration_type: "BaseRegistrar", + owner_id: "0x5f71c6074141d41d0e769689dc9830388a5c7e3e", + domain_id: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xe2a76df5554592c08c28946f750aad17d0c2bb3553c6dd2f0298e0f2fe873be3", + }, + { + canonical_name: "[1d79e56219bd305bbd3fa8ab125997beceebe63b8f6e12d0b6cb956e955549ca].eth", + start: "1779785856", + expiry: "1906016256", + grace_period: "7776000", + base: "12508561643849586", + premium: "0", + registration_type: "BaseRegistrar", + owner_id: "0x07a811c0bd3f46733822df66d7e2d723e6f73fd6", + domain_id: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x8f9e9956842380910d836aa4ac85bc50bee0999824ea8b54412d02bc56d57c6c", + }, + { + canonical_name: "kevin-af.eth", + start: "1779768924", + expiry: "1874463324", + grace_period: "7776000", + base: "9383561643846096", + premium: "0", + registration_type: "BaseRegistrar", + owner_id: "0x6a89280251f72918b6b143817201008b3d99d96e", + domain_id: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x49c87057b1dbe6a6bdfdcf9cc9b2bc12544bc3cd9fd01aa6ea8efb7dab89ca7e", + }, + { + canonical_name: "executor1.eth", + start: "1779743592", + expiry: "1937509992", + grace_period: "7776000", + base: "15633561643853076", + premium: "0", + registration_type: "BaseRegistrar", + owner_id: "0xbb0274908a353d7c37a97ea1ea099352ee39734e", + domain_id: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x56fc11b057812d300b43fd13136ee7e656fa9081e5a3063ed011224302b3658f", + }, + ], + }, + sdk: { + codeSnippet: `import { and, asc, eq, ne, lte, sql } from "drizzle-orm"; + +const limit = 5; + +const recentRegistrations = await ensDb + .select({ + canonicalName: ensIndexerSchema.domain.canonicalName, + expiry: ensIndexerSchema.registration.expiry, + start: ensIndexerSchema.registration.start, + registrationType: ensIndexerSchema.registration.type, + ownerId: ensIndexerSchema.domain.ownerId, + domainId: ensIndexerSchema.domain.id, + }) + .from(ensIndexerSchema.registration) + .innerJoin( + ensIndexerSchema.latestRegistrationIndex, + and( + eq( + ensIndexerSchema.registration.domainId, + ensIndexerSchema.latestRegistrationIndex.domainId, + ), + eq( + ensIndexerSchema.registration.registrationIndex, + ensIndexerSchema.latestRegistrationIndex.registrationIndex, + ), + ), + ) + .innerJoin( + ensIndexerSchema.domain, + eq(ensIndexerSchema.registration.domainId, ensIndexerSchema.domain.id), + ) + .where( + and( + lte(ensIndexerSchema.registration.start, sql\`EXTRACT(EPOCH FROM NOW())\`), + eq(ensIndexerSchema.domain.canonical, true), + ne(ensIndexerSchema.registration.type, "NameWrapper"), + ), + ) + .orderBy(desc(ensIndexerSchema.registration.start)) + .limit(limit); + +console.log(recentRegistrations);`, + result: [ + { + canonicalName: "[67f53c740a0051f85075dc2383fb83a7b48d2984fc9ed9db56b334ca96d1d309].eth", + expiry: "1811352216", + start: "1779816216", + registrationType: "BaseRegistrar", + ownerId: "0x205d2686da3bf33f64c17f21462c51b5ead462cf", + domainId: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x085bfc7f3695efa2e9d3f9717214d85474f40b4b3ef902b67d2bb49654679fa1", + }, + { + canonicalName: "coolorg.eth", + expiry: "1811330160", + start: "1779794160", + registrationType: "BaseRegistrar", + ownerId: "0x5f71c6074141d41d0e769689dc9830388a5c7e3e", + domainId: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xe2a76df5554592c08c28946f750aad17d0c2bb3553c6dd2f0298e0f2fe873be3", + }, + { + canonicalName: "[1d79e56219bd305bbd3fa8ab125997beceebe63b8f6e12d0b6cb956e955549ca].eth", + expiry: "1906016256", + start: "1779785856", + registrationType: "BaseRegistrar", + ownerId: "0x07a811c0bd3f46733822df66d7e2d723e6f73fd6", + domainId: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x8f9e9956842380910d836aa4ac85bc50bee0999824ea8b54412d02bc56d57c6c", + }, + { + canonicalName: "kevin-af.eth", + expiry: "1874463324", + start: "1779768924", + registrationType: "BaseRegistrar", + ownerId: "0x6a89280251f72918b6b143817201008b3d99d96e", + domainId: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x49c87057b1dbe6a6bdfdcf9cc9b2bc12544bc3cd9fd01aa6ea8efb7dab89ca7e", + }, + { + canonicalName: "executor1.eth", + expiry: "1937509992", + start: "1779743592", + registrationType: "BaseRegistrar", + ownerId: "0xbb0274908a353d7c37a97ea1ea099352ee39734e", + domainId: + "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x56fc11b057812d300b43fd13136ee7e656fa9081e5a3063ed011224302b3658f", + }, + ], + }, +} satisfies QueryExample; diff --git a/docs/ensnode.io/src/data/unigraph-examples/subdomains-by-parent-name.ts b/docs/ensnode.io/src/data/unigraph-examples/subdomains-by-parent-name.ts index 2040f8e2a..0344f4759 100644 --- a/docs/ensnode.io/src/data/unigraph-examples/subdomains-by-parent-name.ts +++ b/docs/ensnode.io/src/data/unigraph-examples/subdomains-by-parent-name.ts @@ -20,68 +20,47 @@ FROM "ensindexer_0".domains d JOIN parent p ON d.registry_id = p.subregistry_id WHERE d.canonical = true ORDER BY d.canonical_name -LIMIT 10; +LIMIT 5; `, result: [ { type: "ENSv1Domain", - canonical_name: "[52602a50858115661619fb28cf543ee766c182e0be6743c72d5bd674b3d12686].eth", - canonical_node: "0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", - id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", + canonical_name: "$2442.eth", + canonical_node: "0x89c28481de9640822dd25f821e341b0304640b9363d419e10b9d6b99f049fc8c", + id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x89c28481de9640822dd25f821e341b0304640b9363d419e10b9d6b99f049fc8c", }, { type: "ENSv1Domain", - canonical_name: "[d90db363b8bc1371f7d738d264ff7294bfc5636f907c467adf68321a3c6d8188].eth", - canonical_node: "0x08c0f01c419a8971af6b3eefe2a8bba1556cccf1163df60b1cdbcab632c8ab48", - id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x08c0f01c419a8971af6b3eefe2a8bba1556cccf1163df60b1cdbcab632c8ab48", - }, - { - type: "ENSv2Domain", - canonical_name: "katrenpadu.eth", - canonical_node: "0xf8ae81127bcd7ff99828b3dbd982a943d6dd961ee3f1a6ca707aa0eea913328e", - id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-112554048520345018269255786667391470421317806528110367240542760381540064034816", - }, - { - type: "ENSv2Domain", - canonical_name: "roppp.eth", - canonical_node: "0x39095c3dfb872d6441c95547f88591e7fb97014eef30cabe3df12a9b2a64dbe8", - id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-88275407146030613359050872632052369891139576190404928761656352489271755538432", + canonical_name: "$bless.eth", + canonical_node: "0xfca869315283e0747c929ff17f57d6712cf76b372395eef8b770595d393902ea", + id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xfca869315283e0747c929ff17f57d6712cf76b372395eef8b770595d393902ea", }, { type: "ENSv1Domain", - canonical_name: "sfmpfv44d0mig.eth", - canonical_node: "0x9b365136312d7ee6e232e3c98e459bc8667ec818c47fbbc55bb5e23d0a21e8cc", - id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x9b365136312d7ee6e232e3c98e459bc8667ec818c47fbbc55bb5e23d0a21e8cc", - }, - { - type: "ENSv2Domain", - canonical_name: "sfmpfv44d0mig.eth", - canonical_node: "0x9b365136312d7ee6e232e3c98e459bc8667ec818c47fbbc55bb5e23d0a21e8cc", - id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-30078755955643454526763071980293195785165410039216352470119925106082295316480", + canonical_name: "$pauly.eth", + canonical_node: "0x8254e524ac45f21ce3a3483e52dbedf1aa7bc5d5cff69d4a189df5e369f6eacf", + id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x8254e524ac45f21ce3a3483e52dbedf1aa7bc5d5cff69d4a189df5e369f6eacf", }, { - type: "ENSv2Domain", - canonical_name: "sfmpfv44d0res.eth", - canonical_node: "0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", - id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-37259562946248504018379781627254217478007643438678910837598068740925220192256", - }, - { - type: "ENSv2Domain", - canonical_name: "sfmpfvtoicv2ok.eth", - canonical_node: "0x7d0c27336cf9d51c3fc8f29ef4ef69df9cd4a8ec983e3e17d457a8de6013f3c5", - id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-49509597771493908415463190501045916291230588437784211605615168713991762477056", + type: "ENSv1Domain", + canonical_name: "$vince.eth", + canonical_node: "0x1630be8a50ed7d79c1a5510ca7aaf3d6a483596affcc81c2dbaad17262619dcc", + id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x1630be8a50ed7d79c1a5510ca7aaf3d6a483596affcc81c2dbaad17262619dcc", }, { - type: "ENSv2Domain", - canonical_name: "wrapnation.eth", - canonical_node: "0xc7da9e9ef214b62959a64ba9967cb33a2545a5c0f217d2716474ad1e85fa51fd", - id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-68387108911874305622019956908914347119991166106996198835225265868637904830464", + type: "ENSv1Domain", + canonical_name: "0000000000000000000000000000000000000000.eth", + canonical_node: "0xc13733debbac0dd0143dddcbfe8fcede7c3405033357f034d8b0779ad85802e1", + id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xc13733debbac0dd0143dddcbfe8fcede7c3405033357f034d8b0779ad85802e1", }, ], }, sdk: { codeSnippet: `import { and, eq, asc } from "drizzle-orm"; +const name = "eth"; +const limit = 5; + // Two-step: // 1) find parent domain, // 2) query children by parent domain's subregistryId. @@ -90,7 +69,7 @@ const [parentDomain] = await ensDb .from(ensIndexerSchema.domain) .where( and( - eq(ensIndexerSchema.domain.canonicalName, "eth"), + eq(ensIndexerSchema.domain.canonicalName, name), eq(ensIndexerSchema.domain.canonical, true), ) ); @@ -118,57 +97,33 @@ if (parentDomain?.subregistryId) { result: [ { type: "ENSv1Domain", - canonicalName: "[52602a50858115661619fb28cf543ee766c182e0be6743c72d5bd674b3d12686].eth", - canonicalNode: "0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", - id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", + canonicalName: "$2442.eth", + canonicalNode: "0x89c28481de9640822dd25f821e341b0304640b9363d419e10b9d6b99f049fc8c", + id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x89c28481de9640822dd25f821e341b0304640b9363d419e10b9d6b99f049fc8c", }, { type: "ENSv1Domain", - canonicalName: "[d90db363b8bc1371f7d738d264ff7294bfc5636f907c467adf68321a3c6d8188].eth", - canonicalNode: "0x08c0f01c419a8971af6b3eefe2a8bba1556cccf1163df60b1cdbcab632c8ab48", - id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x08c0f01c419a8971af6b3eefe2a8bba1556cccf1163df60b1cdbcab632c8ab48", - }, - { - type: "ENSv2Domain", - canonicalName: "katrenpadu.eth", - canonicalNode: "0xf8ae81127bcd7ff99828b3dbd982a943d6dd961ee3f1a6ca707aa0eea913328e", - id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-112554048520345018269255786667391470421317806528110367240542760381540064034816", - }, - { - type: "ENSv2Domain", - canonicalName: "roppp.eth", - canonicalNode: "0x39095c3dfb872d6441c95547f88591e7fb97014eef30cabe3df12a9b2a64dbe8", - id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-88275407146030613359050872632052369891139576190404928761656352489271755538432", + canonicalName: "$bless.eth", + canonicalNode: "0xfca869315283e0747c929ff17f57d6712cf76b372395eef8b770595d393902ea", + id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xfca869315283e0747c929ff17f57d6712cf76b372395eef8b770595d393902ea", }, { type: "ENSv1Domain", - canonicalName: "sfmpfv44d0mig.eth", - canonicalNode: "0x9b365136312d7ee6e232e3c98e459bc8667ec818c47fbbc55bb5e23d0a21e8cc", - id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x9b365136312d7ee6e232e3c98e459bc8667ec818c47fbbc55bb5e23d0a21e8cc", - }, - { - type: "ENSv2Domain", - canonicalName: "sfmpfv44d0mig.eth", - canonicalNode: "0x9b365136312d7ee6e232e3c98e459bc8667ec818c47fbbc55bb5e23d0a21e8cc", - id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-30078755955643454526763071980293195785165410039216352470119925106082295316480", - }, - { - type: "ENSv2Domain", - canonicalName: "sfmpfv44d0res.eth", - canonicalNode: "0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", - id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-37259562946248504018379781627254217478007643438678910837598068740925220192256", + canonicalName: "$pauly.eth", + canonicalNode: "0x8254e524ac45f21ce3a3483e52dbedf1aa7bc5d5cff69d4a189df5e369f6eacf", + id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x8254e524ac45f21ce3a3483e52dbedf1aa7bc5d5cff69d4a189df5e369f6eacf", }, { - type: "ENSv2Domain", - canonicalName: "sfmpfvtoicv2ok.eth", - canonicalNode: "0x7d0c27336cf9d51c3fc8f29ef4ef69df9cd4a8ec983e3e17d457a8de6013f3c5", - id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-49509597771493908415463190501045916291230588437784211605615168713991762477056", + type: "ENSv1Domain", + canonicalName: "$vince.eth", + canonicalNode: "0x1630be8a50ed7d79c1a5510ca7aaf3d6a483596affcc81c2dbaad17262619dcc", + id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x1630be8a50ed7d79c1a5510ca7aaf3d6a483596affcc81c2dbaad17262619dcc", }, { - type: "ENSv2Domain", - canonicalName: "wrapnation.eth", - canonicalNode: "0xc7da9e9ef214b62959a64ba9967cb33a2545a5c0f217d2716474ad1e85fa51fd", - id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-68387108911874305622019956908914347119991166106996198835225265868637904830464", + type: "ENSv1Domain", + canonicalName: "0000000000000000000000000000000000000000.eth", + canonicalNode: "0xc13733debbac0dd0143dddcbfe8fcede7c3405033357f034d8b0779ad85802e1", + id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xc13733debbac0dd0143dddcbfe8fcede7c3405033357f034d8b0779ad85802e1", }, ], }, From 2b41753cafa6c338fcf08ef2950de4ed66e2e588 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Fri, 5 Jun 2026 19:54:58 +0200 Subject: [PATCH 04/12] Apply AI PR feedback --- .../integrations/starlight/sidebar-topics/integrate.ts | 2 +- .../integrate/unigraph/examples/account-domains.mdx | 2 +- .../docs/integrate/unigraph/examples/domain-events.mdx | 2 +- .../unigraph/examples/expiring-registrations.mdx | 2 +- .../src/data/unigraph-examples/account-domains.ts | 2 +- .../data/unigraph-examples/expiring-registrations.ts | 2 +- .../src/data/unigraph-examples/indexing-status.ts | 6 +++--- .../src/data/unigraph-examples/latest-registrations.ts | 10 +++++++--- 8 files changed, 16 insertions(+), 12 deletions(-) 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 60af43d51..c28584288 100644 --- a/docs/ensnode.io/config/integrations/starlight/sidebar-topics/integrate.ts +++ b/docs/ensnode.io/config/integrations/starlight/sidebar-topics/integrate.ts @@ -203,7 +203,7 @@ export const integrateSidebarTopic = { link: "/docs/integrate/unigraph/examples/latest-registrations", }, { - label: "Exipring Registrations", + label: "Expiring Registrations", link: "/docs/integrate/unigraph/examples/expiring-registrations", }, { diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-domains.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-domains.mdx index 65dfe167e..a721b5ccf 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-domains.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-domains.mdx @@ -14,7 +14,7 @@ import { exampleAccountDomains } from "@data/unigraph-examples/account-domains"; Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` plugin activated in your ENSNode instance. [Learn more](/docs/services/ensindexer/usage/configuration) ::: -Count the Domains owned by an address, grouped by Domain `type` (`ENSv1Domain` vs `ENSv2Domain`) — a single query spanning both protocol versions. See [Connect](/docs/integrate/unigraph/examples) for setup. +Fetch the Domains owned by an address (across both ENSv1 and ENSv2), including each Domain's `type` (`ENSv1Domain` vs `ENSv2Domain`). See [Connect](/docs/integrate/unigraph/examples) for setup. 'NameWrapper' ORDER BY r.start DESC -LIMIT 15; +LIMIT 5; `, result: [ { @@ -86,7 +90,7 @@ LIMIT 15; ], }, sdk: { - codeSnippet: `import { and, asc, eq, ne, lte, sql } from "drizzle-orm"; + codeSnippet: `import { and, desc, eq, ne, lte, sql } from "drizzle-orm"; const limit = 5; From 8b2ce94ec2b49d3e22ee5607800ba8a459c45de3 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Fri, 5 Jun 2026 21:11:51 +0200 Subject: [PATCH 05/12] Make examples to use latest indexed columns in domains table --- .../UnigraphStaticExample.astro | 6 +- .../data/unigraph-examples/account-domains.ts | 5 + .../data/unigraph-examples/domain-by-name.ts | 47 ++++-- .../data/unigraph-examples/domain-events.ts | 121 +++++--------- .../domains-fuzzy-search-by-name.ts | 150 ++++++++---------- .../expiring-registrations.ts | 5 + .../data/unigraph-examples/indexing-status.ts | 11 +- .../unigraph-examples/latest-registrations.ts | 5 + .../subdomains-by-parent-name.ts | 98 ++++++------ .../src/data/unigraph-examples/types.ts | 1 + .../src/data/unigraph-examples/utils.ts | 2 + 11 files changed, 222 insertions(+), 229 deletions(-) create mode 100644 docs/ensnode.io/src/data/unigraph-examples/utils.ts diff --git a/docs/ensnode.io/src/components/molecules/unigraph-static-example/UnigraphStaticExample.astro b/docs/ensnode.io/src/components/molecules/unigraph-static-example/UnigraphStaticExample.astro index a4663d928..093a7e1f6 100644 --- a/docs/ensnode.io/src/components/molecules/unigraph-static-example/UnigraphStaticExample.astro +++ b/docs/ensnode.io/src/components/molecules/unigraph-static-example/UnigraphStaticExample.astro @@ -38,7 +38,7 @@ const defaultResultNote = - {sql.resultNote ?? defaultResultNote} + @@ -54,8 +54,6 @@ const defaultResultNote = - - {ensDbSdk.resultNote ?? defaultResultNote} - + diff --git a/docs/ensnode.io/src/data/unigraph-examples/account-domains.ts b/docs/ensnode.io/src/data/unigraph-examples/account-domains.ts index 8aa10a7b8..27347cc06 100644 --- a/docs/ensnode.io/src/data/unigraph-examples/account-domains.ts +++ b/docs/ensnode.io/src/data/unigraph-examples/account-domains.ts @@ -1,5 +1,8 @@ +import { outputSource } from "./utils"; import type { QueryExample } from "./types"; +const resultNote = outputSource("V2 Sepolia"); + /** * Example query for fetching Domains by their owner's address, * demonstrating the use of canonical fields to query across both ENSv1 and @@ -93,6 +96,7 @@ LIMIT 10;`, owner_id: "0xffffffffff52d316b7bd028358089bc8066b8f80", }, ], + resultNote, }, sdk: { codeSnippet: `import { and, eq, asc } from "drizzle-orm"; @@ -194,5 +198,6 @@ console.log(accountDomains);`, ownerId: "0xffffffffff52d316b7bd028358089bc8066b8f80", }, ], + resultNote, }, } satisfies QueryExample; diff --git a/docs/ensnode.io/src/data/unigraph-examples/domain-by-name.ts b/docs/ensnode.io/src/data/unigraph-examples/domain-by-name.ts index 5fc624f93..46ef0ee76 100644 --- a/docs/ensnode.io/src/data/unigraph-examples/domain-by-name.ts +++ b/docs/ensnode.io/src/data/unigraph-examples/domain-by-name.ts @@ -1,7 +1,10 @@ +import { outputSource } from "./utils"; import type { QueryExample } from "./types"; +const resultNote = outputSource("V2 Sepolia"); + /** - * Example query for fetching a Domain by its canonical name, + * Example query for fetching Domains by a canonical name, * demonstrating the use of canonical fields to query across both ENSv1 and * ENSv2 domains without branching by protocol version. */ @@ -14,23 +17,33 @@ export const exampleDomainByName = { canonical_node, owner_id FROM "ensindexer_0".domains -WHERE canonical_name = 'vitalik.eth' +WHERE canonical_name = 'eth' AND canonical = true; `, result: [ { - id: "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae", type: "ENSv1Domain", - canonical_name: "vitalik.eth", - canonical_node: "0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", - owner_id: "0x220866b1a2219f40e72f5c628b65d54268ca3a9d", + canonical_name: "eth", + canonical_node: "0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae", + owner_id: "0xa51c9e6efe589407c72984e93b45e35a71a398ec", + }, + { + id: "11155111-0x835f0b284e78cd3f358bcf6cba3b53809f09b79e-35894389512221139346028120028875095598761990588366713962827482865183915769856", + type: "ENSv2Domain", + canonical_name: "eth", + canonical_node: "0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae", + owner_id: "0xffffffffff52d316b7bd028358089bc8066b8f80", }, ], + resultNote, }, sdk: { codeSnippet: `import { and, eq } from "drizzle-orm"; -const [vitalik] = await ensDb +const name = "eth"; + +const domains = await ensDb .select({ id: ensIndexerSchema.domain.id, type: ensIndexerSchema.domain.type, @@ -41,20 +54,28 @@ const [vitalik] = await ensDb .from(ensIndexerSchema.domain) .where( and( - eq(ensIndexerSchema.domain.canonicalName, "vitalik.eth"), + eq(ensIndexerSchema.domain.canonicalName, name), eq(ensIndexerSchema.domain.canonical, true) ) ); -console.log(vitalik);`, +console.log(domains);`, result: [ { - id: "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae", type: "ENSv1Domain", - canonicalName: "vitalik.eth", - canonicalNode: "0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", - ownerId: "0x220866b1a2219f40e72f5c628b65d54268ca3a9d", + canonicalName: "eth", + canonicalNode: "0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae", + ownerId: "0xa51c9e6efe589407c72984e93b45e35a71a398ec", + }, + { + id: "11155111-0x835f0b284e78cd3f358bcf6cba3b53809f09b79e-35894389512221139346028120028875095598761990588366713962827482865183915769856", + type: "ENSv2Domain", + canonicalName: "eth", + canonicalNode: "0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae", + ownerId: "0xffffffffff52d316b7bd028358089bc8066b8f80", }, ], + resultNote, }, } satisfies QueryExample; diff --git a/docs/ensnode.io/src/data/unigraph-examples/domain-events.ts b/docs/ensnode.io/src/data/unigraph-examples/domain-events.ts index 82bbdec47..af585abed 100644 --- a/docs/ensnode.io/src/data/unigraph-examples/domain-events.ts +++ b/docs/ensnode.io/src/data/unigraph-examples/domain-events.ts @@ -1,5 +1,8 @@ +import { outputSource } from "./utils"; import type { QueryExample } from "./types"; +const resultNote = outputSource("V2 Sepolia"); + /** * Example query for fetching recent events for a Domain by its canonical name. */ @@ -16,7 +19,7 @@ export const exampleDomainEvents = { FROM "ensindexer_0".events e JOIN "ensindexer_0".domain_events de ON e.id = de.event_id JOIN "ensindexer_0".domains d ON de.domain_id = d.id -WHERE d.canonical_name = 'vitalik.eth' +WHERE d.canonical_name = 'wrapnation.eth' AND d.canonical = true ORDER BY e.block_number DESC, e.log_index DESC LIMIT 5; @@ -24,60 +27,41 @@ LIMIT 5; result: [ { chain_id: "11155111", - block_number: "6023942", - transaction_hash: "0x6206e95dc5ba5fc8d0804283498f17bac18081437b4198c824b62ee851622ba5", - log_index: 194, - contract_address: "0xfed6a969aaa60e4961fcd3ebf1a2e8913ac65b72", - sender: "0x225f137127d9067788314bc7fcc1f36746a3c3b5", - domain_id: - "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", - }, - { - chain_id: "11155111", - block_number: "6023942", - transaction_hash: "0x6206e95dc5ba5fc8d0804283498f17bac18081437b4198c824b62ee851622ba5", - log_index: 193, - contract_address: "0x57f1887a8bf19b14fc0df6fd9b2acc9af147ea85", - sender: "0x225f137127d9067788314bc7fcc1f36746a3c3b5", - domain_id: - "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", - }, - { - chain_id: "11155111", - block_number: "4107392", - transaction_hash: "0xf143118eb4100361f040b1ae5627562125f0cf1717073a8204befe5e512c80d4", - log_index: 22, - contract_address: "0x0635513f179d50a207757e05759cbd106d7dfce8", - sender: "0x179a862703a4adfb29896552df9e307980d19285", + block_number: "10918673", + transaction_hash: "0xca5e111932f0b26e1d458c690c5dfe8b2b8165ee2a937c04e4021e93a71954e4", + log_index: 42, + contract_address: "0xb68e594a47fe057bd31e7a8229ffcfd85b2e28af", + sender: "0x801d2e48d378f161dba7ad7ad002ad557714c191", domain_id: - "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-68387108911874305622019956908914347119991166106996198835225265868637904830464", }, { chain_id: "11155111", - block_number: "4107386", - transaction_hash: "0x6410de03e9a2f12543e491d1048209e5638d702948cf23d48a63d96a50efd20d", - log_index: 19, - contract_address: "0xfed6a969aaa60e4961fcd3ebf1a2e8913ac65b72", - sender: "0x179a862703a4adfb29896552df9e307980d19285", + block_number: "10918673", + transaction_hash: "0xca5e111932f0b26e1d458c690c5dfe8b2b8165ee2a937c04e4021e93a71954e4", + log_index: 38, + contract_address: "0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1", + sender: "0xb68e594a47fe057bd31e7a8229ffcfd85b2e28af", domain_id: - "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-68387108911874305622019956908914347119991166106996198835225265868637904830464", }, { chain_id: "11155111", - block_number: "4107386", - transaction_hash: "0x6410de03e9a2f12543e491d1048209e5638d702948cf23d48a63d96a50efd20d", - log_index: 16, - contract_address: "0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e", - sender: "0x179a862703a4adfb29896552df9e307980d19285", + block_number: "10918673", + transaction_hash: "0xca5e111932f0b26e1d458c690c5dfe8b2b8165ee2a937c04e4021e93a71954e4", + log_index: 37, + contract_address: "0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1", + sender: "0xb68e594a47fe057bd31e7a8229ffcfd85b2e28af", domain_id: - "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-68387108911874305622019956908914347119991166106996198835225265868637904830464", }, ], + resultNote, }, sdk: { codeSnippet: `import { and, desc, eq } from "drizzle-orm"; -const name = "vitalik.eth"; +const name = "wrapnation.eth"; const limit = 5; const domainEvents = await ensDb @@ -115,54 +99,35 @@ console.log(domainEvents);`, result: [ { chainId: 11155111, - blockNumber: "6023942", - transactionHash: "0x6206e95dc5ba5fc8d0804283498f17bac18081437b4198c824b62ee851622ba5", - logIndex: 194, - contractAddress: "0xfed6a969aaa60e4961fcd3ebf1a2e8913ac65b72", - sender: "0x225f137127d9067788314bc7fcc1f36746a3c3b5", - domainId: - "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", - }, - { - chainId: 11155111, - blockNumber: "6023942", - transactionHash: "0x6206e95dc5ba5fc8d0804283498f17bac18081437b4198c824b62ee851622ba5", - logIndex: 193, - contractAddress: "0x57f1887a8bf19b14fc0df6fd9b2acc9af147ea85", - sender: "0x225f137127d9067788314bc7fcc1f36746a3c3b5", - domainId: - "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", - }, - { - chainId: 11155111, - blockNumber: "4107392", - transactionHash: "0xf143118eb4100361f040b1ae5627562125f0cf1717073a8204befe5e512c80d4", - logIndex: 22, - contractAddress: "0x0635513f179d50a207757e05759cbd106d7dfce8", - sender: "0x179a862703a4adfb29896552df9e307980d19285", + blockNumber: "10918673", + transactionHash: "0xca5e111932f0b26e1d458c690c5dfe8b2b8165ee2a937c04e4021e93a71954e4", + logIndex: 42, + contractAddress: "0xb68e594a47fe057bd31e7a8229ffcfd85b2e28af", + sender: "0x801d2e48d378f161dba7ad7ad002ad557714c191", domainId: - "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-68387108911874305622019956908914347119991166106996198835225265868637904830464", }, { chainId: 11155111, - blockNumber: "4107386", - transactionHash: "0x6410de03e9a2f12543e491d1048209e5638d702948cf23d48a63d96a50efd20d", - logIndex: 19, - contractAddress: "0xfed6a969aaa60e4961fcd3ebf1a2e8913ac65b72", - sender: "0x179a862703a4adfb29896552df9e307980d19285", + blockNumber: "10918673", + transactionHash: "0xca5e111932f0b26e1d458c690c5dfe8b2b8165ee2a937c04e4021e93a71954e4", + logIndex: 38, + contractAddress: "0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1", + sender: "0xb68e594a47fe057bd31e7a8229ffcfd85b2e28af", domainId: - "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-68387108911874305622019956908914347119991166106996198835225265868637904830464", }, { chainId: 11155111, - blockNumber: "4107386", - transactionHash: "0x6410de03e9a2f12543e491d1048209e5638d702948cf23d48a63d96a50efd20d", - logIndex: 16, - contractAddress: "0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e", - sender: "0x179a862703a4adfb29896552df9e307980d19285", + blockNumber: "10918673", + transactionHash: "0xca5e111932f0b26e1d458c690c5dfe8b2b8165ee2a937c04e4021e93a71954e4", + logIndex: 37, + contractAddress: "0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1", + sender: "0xb68e594a47fe057bd31e7a8229ffcfd85b2e28af", domainId: - "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", + "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-68387108911874305622019956908914347119991166106996198835225265868637904830464", }, ], + resultNote, }, } satisfies QueryExample; diff --git a/docs/ensnode.io/src/data/unigraph-examples/domains-fuzzy-search-by-name.ts b/docs/ensnode.io/src/data/unigraph-examples/domains-fuzzy-search-by-name.ts index bd33a75c2..f88aaebe6 100644 --- a/docs/ensnode.io/src/data/unigraph-examples/domains-fuzzy-search-by-name.ts +++ b/docs/ensnode.io/src/data/unigraph-examples/domains-fuzzy-search-by-name.ts @@ -1,66 +1,53 @@ +import { outputSource } from "./utils"; import type { QueryExample } from "./types"; +const resultNote = outputSource("V2 Sepolia"); + /** * Example query for fetching Domains by a fuzzy search on their canonical name. */ export const exampleDomainsFuzzySearchByName = { sql: { codeSnippet: `SELECT - type, - canonical_name, - canonical_node, - owner_id, - similarity(canonical_name, 'vitalik') as name_similarity, - id + type, + canonical_name, + canonical_node, + owner_id, + similarity(canonical_name, 'reverse') as name_similarity, + id FROM "ensindexer_0".domains --- Use the pg_trgm similarity operator (%) for fuzzy matching on canonical_name -WHERE canonical_name % 'vitalik' +WHERE __canonicalNamePrefix % 'reverse' AND canonical = true ORDER BY name_similarity DESC LIMIT 5; `, result: [ { - id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", - type: "ENSv1Domain", - canonical_name: "vitalik.eth", - canonical_node: "0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", - owner_id: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", - name_similarity: 0.6666667, - }, - { - id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x278adcf079fceb551531f1593deae8891d83bf4708b935d54eda7f8db51ce797", - type: "ENSv1Domain", - canonical_name: "vitalikkk.eth", - canonical_node: "0x278adcf079fceb551531f1593deae8891d83bf4708b935d54eda7f8db51ce797", - owner_id: "0x588f6b3169f60176c1143f8bab47bcf3deebecdc", - name_similarity: 0.46666667, - }, - { - id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x55e83f7d37d7cf1f87c40a6bd5fc8e62e8898b327c5a09776596f6efe547349a", type: "ENSv1Domain", - canonical_name: "vitalik.taars.eth", - canonical_node: "0x55e83f7d37d7cf1f87c40a6bd5fc8e62e8898b327c5a09776596f6efe547349a", - owner_id: "0x5a09e3ec3efdd91205cbb097142a4f4dcefc7f02", - name_similarity: 0.44444445, + canonical_name: "reverse", + canonical_node: "0xa097f6721ce401e757d1223a763fef49b8b5f90bb18567ddb86fd205dff71d34", + owner_id: "0xffffffffff52d316b7bd028358089bc8066b8f80", + name_similarity: 1, + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0xa097f6721ce401e757d1223a763fef49b8b5f90bb18567ddb86fd205dff71d34", }, { - id: "84532-0x1493b2567056c2181630115660963e13a8e32735-0x97fa42e69feb1d407361108d79ddad705707a16392d7823f8b21b44dabfc4a9d", - type: "ENSv1Domain", - canonical_name: "vitalik.basetest.eth", - canonical_node: "0x97fa42e69feb1d407361108d79ddad705707a16392d7823f8b21b44dabfc4a9d", - owner_id: "0x15378e401f9c3243639c7c3250be0f396a758e40", - name_similarity: 0.3809524, + type: "ENSv2Domain", + canonical_name: "reverse", + canonical_node: "0xa097f6721ce401e757d1223a763fef49b8b5f90bb18567ddb86fd205dff71d34", + owner_id: "0xffffffffff52d316b7bd028358089bc8066b8f80", + name_similarity: 1, + id: "11155111-0x835f0b284e78cd3f358bcf6cba3b53809f09b79e-100753657518907091865523951670693454610893379027273088370152078482136467767296", }, { - id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x117e485acf1ebff586d1382b7689201ce23f7142ae92f4c397849f4b01e6a1cc", type: "ENSv1Domain", - canonical_name: "vitalikbuterin.eth", - canonical_node: "0x117e485acf1ebff586d1382b7689201ce23f7142ae92f4c397849f4b01e6a1cc", - owner_id: "0x16ecc228f185b084cb884be2d65544f5ca4dd761", - name_similarity: 0.35, + canonical_name: "addr.reverse", + canonical_node: "0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2", + owner_id: "0x26e5e80e8f36607ef401443fb34eea363c86e8f7", + name_similarity: 0.61538464, + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2", }, ], + resultNote, }, sdk: { codeSnippet: `import { and, asc, eq, sql } from "drizzle-orm"; @@ -70,61 +57,52 @@ const limit = 5; const domains = await ensDb .select({ - canonicalName: ensIndexerSchema.domain.canonicalName, - canonicalDepth: ensIndexerSchema.domain.canonicalDepth, - ownerId: ensIndexerSchema.domain.ownerId, - nameSimilarity: sql\`similarity(\${ensIndexerSchema.domain.canonicalName}, \${q})\`.as( - "name_similarity", - ), - id: ensIndexerSchema.domain.id, - }) - .from(ensIndexerSchema.domain) - .where( - and( - sql\`\${ensIndexerSchema.domain.canonicalName} % \${q}\`, - eq(ensIndexerSchema.domain.canonical, true), - ), - ) - .orderBy(sql\`name_similarity DESC\`) - .limit(limit); + type: ensIndexerSchema.domain.type, + canonicalName: ensIndexerSchema.domain.canonicalName, + canonicalNode: ensIndexerSchema.domain.canonicalNode, + ownerId: ensIndexerSchema.domain.ownerId, + nameSimilarity: sql\`similarity(\${ensIndexerSchema.domain.canonicalName}, \${q})\`.as( + "name_similarity", + ), + id: ensIndexerSchema.domain.id, + }) + .from(ensIndexerSchema.domain) + .where( + and( + sql\`\${ensIndexerSchema.domain.__canonicalNamePrefix} % \${q}\`, + eq(ensIndexerSchema.domain.canonical, true), + ), + ) + .orderBy(sql\`name_similarity DESC\`) + .limit(limit); console.log(domains);`, result: [ { - canonicalName: "vitalik.eth", - canonicalDepth: 2, - ownerId: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", - nameSimilarity: 0.6666667, - id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835", - }, - { - canonicalName: "vitalikkk.eth", - canonicalDepth: 2, - ownerId: "0x588f6b3169f60176c1143f8bab47bcf3deebecdc", - nameSimilarity: 0.46666667, - id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x278adcf079fceb551531f1593deae8891d83bf4708b935d54eda7f8db51ce797", - }, - { - canonicalName: "vitalik.taars.eth", - canonicalDepth: 3, - ownerId: "0x5a09e3ec3efdd91205cbb097142a4f4dcefc7f02", - nameSimilarity: 0.44444445, - id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x55e83f7d37d7cf1f87c40a6bd5fc8e62e8898b327c5a09776596f6efe547349a", + type: "ENSv1Domain", + canonicalName: "reverse", + canonicalNode: "0xa097f6721ce401e757d1223a763fef49b8b5f90bb18567ddb86fd205dff71d34", + ownerId: "0xffffffffff52d316b7bd028358089bc8066b8f80", + nameSimilarity: 1, + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0xa097f6721ce401e757d1223a763fef49b8b5f90bb18567ddb86fd205dff71d34", }, { - canonicalName: "vitalik.basetest.eth", - canonicalDepth: 3, - ownerId: "0x15378e401f9c3243639c7c3250be0f396a758e40", - nameSimilarity: 0.3809524, - id: "84532-0x1493b2567056c2181630115660963e13a8e32735-0x97fa42e69feb1d407361108d79ddad705707a16392d7823f8b21b44dabfc4a9d", + type: "ENSv2Domain", + canonicalName: "reverse", + canonicalNode: "0xa097f6721ce401e757d1223a763fef49b8b5f90bb18567ddb86fd205dff71d34", + ownerId: "0xffffffffff52d316b7bd028358089bc8066b8f80", + nameSimilarity: 1, + id: "11155111-0x835f0b284e78cd3f358bcf6cba3b53809f09b79e-100753657518907091865523951670693454610893379027273088370152078482136467767296", }, { - canonicalName: "vitalikbuterin.eth", - canonicalDepth: 2, - ownerId: "0x16ecc228f185b084cb884be2d65544f5ca4dd761", - nameSimilarity: 0.35, - id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x117e485acf1ebff586d1382b7689201ce23f7142ae92f4c397849f4b01e6a1cc", + type: "ENSv1Domain", + canonicalName: "addr.reverse", + canonicalNode: "0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2", + ownerId: "0x26e5e80e8f36607ef401443fb34eea363c86e8f7", + nameSimilarity: 0.61538464, + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2", }, ], + resultNote, }, } satisfies QueryExample; diff --git a/docs/ensnode.io/src/data/unigraph-examples/expiring-registrations.ts b/docs/ensnode.io/src/data/unigraph-examples/expiring-registrations.ts index b924914ce..fbc3d15c5 100644 --- a/docs/ensnode.io/src/data/unigraph-examples/expiring-registrations.ts +++ b/docs/ensnode.io/src/data/unigraph-examples/expiring-registrations.ts @@ -1,5 +1,8 @@ +import { outputSource } from "./utils"; import type { QueryExample } from "./types"; +const resultNote = outputSource("Alpha Sepolia"); + /** * Example query for fetching ENS registrations that are expiring soon. */ @@ -70,6 +73,7 @@ LIMIT 5; "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x13403c49bb9d168c7f18b830b5dd86f562e3e203fe2fc545927e5f609e3e6417", }, ], + resultNote, }, sdk: { codeSnippet: `import { and, asc, eq, gte, lte, sql } from "drizzle-orm"; @@ -164,5 +168,6 @@ console.log(expiringRegistrations);`, "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x13403c49bb9d168c7f18b830b5dd86f562e3e203fe2fc545927e5f609e3e6417", }, ], + resultNote, }, } satisfies QueryExample; diff --git a/docs/ensnode.io/src/data/unigraph-examples/indexing-status.ts b/docs/ensnode.io/src/data/unigraph-examples/indexing-status.ts index 9e1526228..a8aee98fe 100644 --- a/docs/ensnode.io/src/data/unigraph-examples/indexing-status.ts +++ b/docs/ensnode.io/src/data/unigraph-examples/indexing-status.ts @@ -1,6 +1,9 @@ +import { outputSource } from "@data/unigraph-examples/utils"; import type { QueryExample } from "./types"; -const result = { +const resultNote = outputSource("Alpha"); + +const indexingMetadataContextPartial = { indexingStatus: { strategy: "omnichain", snapshotTime: 1779795066, @@ -116,7 +119,8 @@ FROM "ensnode".metadata WHERE ens_indexer_schema_name = 'ensindexer_0' AND key = 'indexing_metadata_context'; `, - result: { indexing_status_snapshot: result.indexingStatus }, + result: { indexing_status_snapshot: indexingMetadataContextPartial.indexingStatus }, + resultNote, }, sdk: { codeSnippet: `import { IndexingMetadataContextStatusCodes } from "@ensnode/ensdb-sdk"; @@ -127,6 +131,7 @@ if (indexingMetadataContext.statusCode === IndexingMetadataContextStatusCodes.In const { indexingStatus } = indexingMetadataContext; console.log({ indexingStatus }); }`, - result: { indexingStatus: result.indexingStatus }, + result: { indexingStatus: indexingMetadataContextPartial.indexingStatus }, + resultNote, }, } satisfies QueryExample; diff --git a/docs/ensnode.io/src/data/unigraph-examples/latest-registrations.ts b/docs/ensnode.io/src/data/unigraph-examples/latest-registrations.ts index 786d79433..1e21d43da 100644 --- a/docs/ensnode.io/src/data/unigraph-examples/latest-registrations.ts +++ b/docs/ensnode.io/src/data/unigraph-examples/latest-registrations.ts @@ -1,5 +1,8 @@ +import { outputSource } from "./utils"; import type { QueryExample } from "./types"; +const resultNote = outputSource("Alpha Sepolia"); + /** * Example query for fetching the latest registrations across all Domains. */ @@ -88,6 +91,7 @@ LIMIT 5; "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x56fc11b057812d300b43fd13136ee7e656fa9081e5a3063ed011224302b3658f", }, ], + resultNote, }, sdk: { codeSnippet: `import { and, desc, eq, ne, lte, sql } from "drizzle-orm"; @@ -179,5 +183,6 @@ console.log(recentRegistrations);`, "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x56fc11b057812d300b43fd13136ee7e656fa9081e5a3063ed011224302b3658f", }, ], + resultNote, }, } satisfies QueryExample; diff --git a/docs/ensnode.io/src/data/unigraph-examples/subdomains-by-parent-name.ts b/docs/ensnode.io/src/data/unigraph-examples/subdomains-by-parent-name.ts index 0344f4759..b3b2a28d6 100644 --- a/docs/ensnode.io/src/data/unigraph-examples/subdomains-by-parent-name.ts +++ b/docs/ensnode.io/src/data/unigraph-examples/subdomains-by-parent-name.ts @@ -1,5 +1,8 @@ +import { outputSource } from "./utils"; import type { QueryExample } from "./types"; +const resultNote = outputSource("V2 Sepolia"); + /** * Example query for fetching subdomains by their canonical name of the parent domain. */ @@ -25,56 +28,57 @@ LIMIT 5; result: [ { type: "ENSv1Domain", - canonical_name: "$2442.eth", - canonical_node: "0x89c28481de9640822dd25f821e341b0304640b9363d419e10b9d6b99f049fc8c", - id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x89c28481de9640822dd25f821e341b0304640b9363d419e10b9d6b99f049fc8c", + canonical_name: "[52602a50858115661619fb28cf543ee766c182e0be6743c72d5bd674b3d12686].eth", + canonical_node: "0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", }, { type: "ENSv1Domain", - canonical_name: "$bless.eth", - canonical_node: "0xfca869315283e0747c929ff17f57d6712cf76b372395eef8b770595d393902ea", - id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xfca869315283e0747c929ff17f57d6712cf76b372395eef8b770595d393902ea", + canonical_name: "[d90db363b8bc1371f7d738d264ff7294bfc5636f907c467adf68321a3c6d8188].eth", + canonical_node: "0x08c0f01c419a8971af6b3eefe2a8bba1556cccf1163df60b1cdbcab632c8ab48", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x08c0f01c419a8971af6b3eefe2a8bba1556cccf1163df60b1cdbcab632c8ab48", }, { - type: "ENSv1Domain", - canonical_name: "$pauly.eth", - canonical_node: "0x8254e524ac45f21ce3a3483e52dbedf1aa7bc5d5cff69d4a189df5e369f6eacf", - id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x8254e524ac45f21ce3a3483e52dbedf1aa7bc5d5cff69d4a189df5e369f6eacf", + type: "ENSv2Domain", + canonical_name: "katrenpadu.eth", + canonical_node: "0xf8ae81127bcd7ff99828b3dbd982a943d6dd961ee3f1a6ca707aa0eea913328e", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-112554048520345018269255786667391470421317806528110367240542760381540064034816", }, { - type: "ENSv1Domain", - canonical_name: "$vince.eth", - canonical_node: "0x1630be8a50ed7d79c1a5510ca7aaf3d6a483596affcc81c2dbaad17262619dcc", - id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x1630be8a50ed7d79c1a5510ca7aaf3d6a483596affcc81c2dbaad17262619dcc", + type: "ENSv2Domain", + canonical_name: "roppp.eth", + canonical_node: "0x39095c3dfb872d6441c95547f88591e7fb97014eef30cabe3df12a9b2a64dbe8", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-88275407146030613359050872632052369891139576190404928761656352489271755538432", }, { type: "ENSv1Domain", - canonical_name: "0000000000000000000000000000000000000000.eth", - canonical_node: "0xc13733debbac0dd0143dddcbfe8fcede7c3405033357f034d8b0779ad85802e1", - id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xc13733debbac0dd0143dddcbfe8fcede7c3405033357f034d8b0779ad85802e1", + canonical_name: "sfmpfv44d0mig.eth", + canonical_node: "0x9b365136312d7ee6e232e3c98e459bc8667ec818c47fbbc55bb5e23d0a21e8cc", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x9b365136312d7ee6e232e3c98e459bc8667ec818c47fbbc55bb5e23d0a21e8cc", }, ], + resultNote, }, sdk: { - codeSnippet: `import { and, eq, asc } from "drizzle-orm"; + codeSnippet: `import { and, eq, inArray, asc } from "drizzle-orm"; const name = "eth"; const limit = 5; // Two-step: -// 1) find parent domain, -// 2) query children by parent domain's subregistryId. -const [parentDomain] = await ensDb +// 1) find parent domains +// 2) query children by each parent domain's subregistryId. +const parentDomains = await ensDb .select({ subregistryId: ensIndexerSchema.domain.subregistryId }) .from(ensIndexerSchema.domain) .where( and( eq(ensIndexerSchema.domain.canonicalName, name), eq(ensIndexerSchema.domain.canonical, true), - ) -); + ), + ); -if (parentDomain?.subregistryId) { +if (parentDomains.length > 0) { const subdomains = await ensDb .select({ type: ensIndexerSchema.domain.type, @@ -85,11 +89,14 @@ if (parentDomain?.subregistryId) { .from(ensIndexerSchema.domain) .where( and( - eq(ensIndexerSchema.domain.registryId, parentDomain.subregistryId), + inArray( + ensIndexerSchema.domain.registryId, + parentDomains.map((d) => d.subregistryId), + ), eq(ensIndexerSchema.domain.canonical, true), - ) + ), ) - .orderBy(asc(ensIndexerSchema.domain.canonicalName)) + .orderBy(asc(ensIndexerSchema.domain.__canonicalNamePrefix)) .limit(limit); console.log(subdomains); @@ -97,34 +104,35 @@ if (parentDomain?.subregistryId) { result: [ { type: "ENSv1Domain", - canonicalName: "$2442.eth", - canonicalNode: "0x89c28481de9640822dd25f821e341b0304640b9363d419e10b9d6b99f049fc8c", - id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x89c28481de9640822dd25f821e341b0304640b9363d419e10b9d6b99f049fc8c", + canonicalName: "[52602a50858115661619fb28cf543ee766c182e0be6743c72d5bd674b3d12686].eth", + canonicalNode: "0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", }, { type: "ENSv1Domain", - canonicalName: "$bless.eth", - canonicalNode: "0xfca869315283e0747c929ff17f57d6712cf76b372395eef8b770595d393902ea", - id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xfca869315283e0747c929ff17f57d6712cf76b372395eef8b770595d393902ea", + canonicalName: "[d90db363b8bc1371f7d738d264ff7294bfc5636f907c467adf68321a3c6d8188].eth", + canonicalNode: "0x08c0f01c419a8971af6b3eefe2a8bba1556cccf1163df60b1cdbcab632c8ab48", + id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x08c0f01c419a8971af6b3eefe2a8bba1556cccf1163df60b1cdbcab632c8ab48", }, { - type: "ENSv1Domain", - canonicalName: "$pauly.eth", - canonicalNode: "0x8254e524ac45f21ce3a3483e52dbedf1aa7bc5d5cff69d4a189df5e369f6eacf", - id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x8254e524ac45f21ce3a3483e52dbedf1aa7bc5d5cff69d4a189df5e369f6eacf", + type: "ENSv2Domain", + canonicalName: "katrenpadu.eth", + canonicalNode: "0xf8ae81127bcd7ff99828b3dbd982a943d6dd961ee3f1a6ca707aa0eea913328e", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-112554048520345018269255786667391470421317806528110367240542760381540064034816", }, { - type: "ENSv1Domain", - canonicalName: "$vince.eth", - canonicalNode: "0x1630be8a50ed7d79c1a5510ca7aaf3d6a483596affcc81c2dbaad17262619dcc", - id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x1630be8a50ed7d79c1a5510ca7aaf3d6a483596affcc81c2dbaad17262619dcc", + type: "ENSv2Domain", + canonicalName: "roppp.eth", + canonicalNode: "0x39095c3dfb872d6441c95547f88591e7fb97014eef30cabe3df12a9b2a64dbe8", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-88275407146030613359050872632052369891139576190404928761656352489271755538432", }, { - type: "ENSv1Domain", - canonicalName: "0000000000000000000000000000000000000000.eth", - canonicalNode: "0xc13733debbac0dd0143dddcbfe8fcede7c3405033357f034d8b0779ad85802e1", - id: "11155111-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xc13733debbac0dd0143dddcbfe8fcede7c3405033357f034d8b0779ad85802e1", + type: "ENSv2Domain", + canonicalName: "sfmpfv44d0mig.eth", + canonicalNode: "0x9b365136312d7ee6e232e3c98e459bc8667ec818c47fbbc55bb5e23d0a21e8cc", + id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-30078755955643454526763071980293195785165410039216352470119925106082295316480", }, ], + resultNote, }, } satisfies QueryExample; diff --git a/docs/ensnode.io/src/data/unigraph-examples/types.ts b/docs/ensnode.io/src/data/unigraph-examples/types.ts index 31605aa9a..56aebb586 100644 --- a/docs/ensnode.io/src/data/unigraph-examples/types.ts +++ b/docs/ensnode.io/src/data/unigraph-examples/types.ts @@ -1,6 +1,7 @@ export interface CodeExample { codeSnippet: string; result: unknown; + resultNote?: string; } export interface QueryExample { diff --git a/docs/ensnode.io/src/data/unigraph-examples/utils.ts b/docs/ensnode.io/src/data/unigraph-examples/utils.ts new file mode 100644 index 000000000..9935d4e66 --- /dev/null +++ b/docs/ensnode.io/src/data/unigraph-examples/utils.ts @@ -0,0 +1,2 @@ +export const outputSource = (source: "V2 Sepolia" | "Alpha" | "Alpha Sepolia") => + `Output matches a point in time snapshot of ENSDb result from our "${source}" Hosted ENSNode instance. Live output depends on the configuration of your ENSNode instance and also changes that may have happened in ENS since this point in time snapshot example response was captured.`; From 131bc366bea510a9b7f4d6217b19171f6760f26c Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Fri, 5 Jun 2026 21:13:34 +0200 Subject: [PATCH 06/12] Apply AI PR feedback --- .../docs/docs/integrate/unigraph/examples/indexing-status.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/indexing-status.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/indexing-status.mdx index 09a77e5d6..791e9bca6 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/indexing-status.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/indexing-status.mdx @@ -1,6 +1,6 @@ --- title: Indexing Status -description: Read the indexing status snapshot for an ENSIndexer instance from ENSDb. +description: Read the indexing status snapshot for an ENSDb Writer instance from ENSDb. sidebar: label: Indexing Status --- From 0a0b6f24d42dd9b7e05513ca59c32d9f2d2826b4 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Fri, 5 Jun 2026 21:16:00 +0200 Subject: [PATCH 07/12] Apply AI PR feedback --- .../src/data/unigraph-examples/domains-fuzzy-search-by-name.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ensnode.io/src/data/unigraph-examples/domains-fuzzy-search-by-name.ts b/docs/ensnode.io/src/data/unigraph-examples/domains-fuzzy-search-by-name.ts index f88aaebe6..1440e9f42 100644 --- a/docs/ensnode.io/src/data/unigraph-examples/domains-fuzzy-search-by-name.ts +++ b/docs/ensnode.io/src/data/unigraph-examples/domains-fuzzy-search-by-name.ts @@ -50,7 +50,7 @@ LIMIT 5; resultNote, }, sdk: { - codeSnippet: `import { and, asc, eq, sql } from "drizzle-orm"; + codeSnippet: `import { and, eq, sql } from "drizzle-orm"; const q = "vitalik"; const limit = 5; From d55072a5a71baca2aa6e2b37eb3459d2eed5835c Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Mon, 8 Jun 2026 12:25:10 +0200 Subject: [PATCH 08/12] Improve ENS Unigraph examples --- .../unigraph/examples/domain-events.mdx | 2 +- .../data/unigraph-examples/account-domains.ts | 4 +-- .../domains-fuzzy-search-by-name.ts | 4 +-- .../subdomains-by-parent-name.ts | 2 +- .../src/data/unigraph-examples/utils.ts | 31 +++++++++++++++++-- docs/ensnode.io/src/styles/starlight.css | 11 +++++++ 6 files changed, 46 insertions(+), 8 deletions(-) diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domain-events.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domain-events.mdx index 47a0838e7..861af34ad 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domain-events.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domain-events.mdx @@ -14,7 +14,7 @@ import { exampleDomainEvents } from "@data/unigraph-examples/domain-events"; Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` plugin activated in your ENSNode instance. [Learn more](/docs/services/ensindexer/usage/configuration) ::: -Fetch recent events for a Domain by its canonical name. This example joins the `events`, `domain_events`, and `domains` tables to retrieve domain events associated with the `vitalik.eth` name. See [Connect](/docs/integrate/unigraph/examples) for setup. +Fetch recent events for a Domain by its canonical name. This example joins the `events`, `domain_events`, and `domains` tables to retrieve domain events associated with the `wrapnation.eth` name. See [Connect](/docs/integrate/unigraph/examples) for setup. :::note[Canonical fields] Canonical fields are populated on every Domain reachable from the canonical root, across both ENSv1 and ENSv2 — query them uniformly without branching by `type`. In SQL, these columns are `canonical_name`, `canonical_path`, `canonical_node`, and `canonical_depth`; in `ensdb-sdk`, the corresponding fields are `canonicalName`, `canonicalPath`, `canonicalNode`, and `canonicalDepth`. diff --git a/docs/ensnode.io/src/data/unigraph-examples/account-domains.ts b/docs/ensnode.io/src/data/unigraph-examples/account-domains.ts index 27347cc06..98bde8756 100644 --- a/docs/ensnode.io/src/data/unigraph-examples/account-domains.ts +++ b/docs/ensnode.io/src/data/unigraph-examples/account-domains.ts @@ -19,7 +19,7 @@ export const exampleAccountDomains = { FROM "ensindexer_0".domains d WHERE d.canonical = true AND d.owner_id = '0xffffffffff52d316b7bd028358089bc8066b8f80' -ORDER BY d.canonical_name +ORDER BY d.__canonical_name_prefix ASC LIMIT 10;`, result: [ { @@ -119,7 +119,7 @@ const accountDomains = await ensDb eq(ensIndexerSchema.domain.canonical, true), ), ) - .orderBy(asc(ensIndexerSchema.domain.canonicalName)) + .orderBy(asc(ensIndexerSchema.domain.__canonicalNamePrefix)) .limit(limit); console.log(accountDomains);`, diff --git a/docs/ensnode.io/src/data/unigraph-examples/domains-fuzzy-search-by-name.ts b/docs/ensnode.io/src/data/unigraph-examples/domains-fuzzy-search-by-name.ts index 1440e9f42..3353360f2 100644 --- a/docs/ensnode.io/src/data/unigraph-examples/domains-fuzzy-search-by-name.ts +++ b/docs/ensnode.io/src/data/unigraph-examples/domains-fuzzy-search-by-name.ts @@ -16,7 +16,7 @@ export const exampleDomainsFuzzySearchByName = { similarity(canonical_name, 'reverse') as name_similarity, id FROM "ensindexer_0".domains -WHERE __canonicalNamePrefix % 'reverse' +WHERE __canonical_name_prefix % 'reverse' AND canonical = true ORDER BY name_similarity DESC LIMIT 5; @@ -52,7 +52,7 @@ LIMIT 5; sdk: { codeSnippet: `import { and, eq, sql } from "drizzle-orm"; -const q = "vitalik"; +const q = "reverse"; const limit = 5; const domains = await ensDb diff --git a/docs/ensnode.io/src/data/unigraph-examples/subdomains-by-parent-name.ts b/docs/ensnode.io/src/data/unigraph-examples/subdomains-by-parent-name.ts index b3b2a28d6..77f6623bd 100644 --- a/docs/ensnode.io/src/data/unigraph-examples/subdomains-by-parent-name.ts +++ b/docs/ensnode.io/src/data/unigraph-examples/subdomains-by-parent-name.ts @@ -22,7 +22,7 @@ SELECT FROM "ensindexer_0".domains d JOIN parent p ON d.registry_id = p.subregistry_id WHERE d.canonical = true -ORDER BY d.canonical_name +ORDER BY d.__canonical_name_prefix ASC LIMIT 5; `, result: [ diff --git a/docs/ensnode.io/src/data/unigraph-examples/utils.ts b/docs/ensnode.io/src/data/unigraph-examples/utils.ts index 9935d4e66..9fd47e5e5 100644 --- a/docs/ensnode.io/src/data/unigraph-examples/utils.ts +++ b/docs/ensnode.io/src/data/unigraph-examples/utils.ts @@ -1,2 +1,29 @@ -export const outputSource = (source: "V2 Sepolia" | "Alpha" | "Alpha Sepolia") => - `Output matches a point in time snapshot of ENSDb result from our "${source}" Hosted ENSNode instance. Live output depends on the configuration of your ENSNode instance and also changes that may have happened in ENS since this point in time snapshot example response was captured.`; +export const EnsNodeInstances = { + V2Sepolia: "V2 Sepolia", + Alpha: "Alpha", + AlphaSepolia: "Alpha Sepolia", + Mainnet: "Mainnet", + Sepolia: "Sepolia", +} as const; + +export type EnsNodeInstance = (typeof EnsNodeInstances)[keyof typeof EnsNodeInstances]; + +export const outputSource = (ensNodeInstance: EnsNodeInstance) => + `Output matches a point in time snapshot of ENSDb result from our ${ensNodeInstance} Hosted ENSNode instance. Live output depends on the configuration of your ENSNode instance and also changes that may have happened in ENS since this point in time snapshot example response was captured.`; + +const ensNodeInstanceDocUrl = (instance: EnsNodeInstance) => { + const hostedInstancesPath = "/docs/hosted-instances#ensnode-"; + + switch (instance) { + case EnsNodeInstances.V2Sepolia: + return `${hostedInstancesPath}v2-sepolia`; + case EnsNodeInstances.Alpha: + return `${hostedInstancesPath}alpha`; + case EnsNodeInstances.AlphaSepolia: + return `${hostedInstancesPath}alpha-sepolia`; + case EnsNodeInstances.Mainnet: + return `${hostedInstancesPath}mainnet`; + case EnsNodeInstances.Sepolia: + return `${hostedInstancesPath}sepolia`; + } +}; diff --git a/docs/ensnode.io/src/styles/starlight.css b/docs/ensnode.io/src/styles/starlight.css index 71e62eb38..4e93b132e 100644 --- a/docs/ensnode.io/src/styles/starlight.css +++ b/docs/ensnode.io/src/styles/starlight.css @@ -928,3 +928,14 @@ starlight-tabs ul[role="tablist"] { padding: 0.125rem 0.375rem; font-size: var(--sl-text-code-sm); } + +.static-example p a { + color: var(--sl-color-text-accent); + text-decoration: underline; + text-underline-offset: 4px; + transition: text-underline-offset 0.2s ease-in-out; + + &:hover { + text-underline-offset: 2px; + } +} From 97c53025ae13546c88ec59d126b95a27fd881bc2 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Tue, 9 Jun 2026 17:47:11 +0200 Subject: [PATCH 09/12] Improve ENS Unigraph examples --- .../starlight/sidebar-topics/integrate.ts | 4 + .../molecules/EnsUnigraphIntro.astro | 9 + .../docs/docs/integrate/unigraph/concepts.mdx | 49 ++++ .../unigraph/examples/account-domains.mdx | 4 - .../unigraph/examples/domain-by-name.mdx | 22 -- .../unigraph/examples/domain-events.mdx | 10 +- .../examples/domains-fuzzy-search-by-name.mdx | 4 - .../examples/expiring-registrations.mdx | 4 - .../integrate/unigraph/examples/index.mdx | 24 +- .../unigraph/examples/indexing-status.mdx | 4 - .../examples/latest-registrations.mdx | 4 - .../examples/subdomains-by-parent-name.mdx | 4 - .../docs/docs/integrate/unigraph/index.mdx | 33 +-- .../data/unigraph-examples/account-domains.ts | 190 ++++++++------- .../data/unigraph-examples/domain-by-name.ts | 36 +-- .../data/unigraph-examples/domain-events.ts | 220 ++++++++++++++---- .../domains-fuzzy-search-by-name.ts | 113 +++++---- .../expiring-registrations.ts | 102 ++++---- .../unigraph-examples/latest-registrations.ts | 120 +++++----- .../subdomains-by-parent-name.ts | 186 +++++++++++---- 20 files changed, 698 insertions(+), 444 deletions(-) create mode 100644 docs/ensnode.io/src/components/molecules/EnsUnigraphIntro.astro create mode 100644 docs/ensnode.io/src/content/docs/docs/integrate/unigraph/concepts.mdx 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 7c2955e1d..858db3b4e 100644 --- a/docs/ensnode.io/config/integrations/starlight/sidebar-topics/integrate.ts +++ b/docs/ensnode.io/config/integrations/starlight/sidebar-topics/integrate.ts @@ -119,6 +119,10 @@ export const integrateSidebarTopic = { label: "Overview", link: "/docs/integrate/unigraph", }, + { + label: "Core Concepts", + link: "/docs/integrate/unigraph/concepts", + }, { label: "Examples", collapsed: true, diff --git a/docs/ensnode.io/src/components/molecules/EnsUnigraphIntro.astro b/docs/ensnode.io/src/components/molecules/EnsUnigraphIntro.astro new file mode 100644 index 000000000..fd0e58a15 --- /dev/null +++ b/docs/ensnode.io/src/components/molecules/EnsUnigraphIntro.astro @@ -0,0 +1,9 @@ +--- +import { Aside } from "@astrojs/starlight/components" +--- + + diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/concepts.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/concepts.mdx new file mode 100644 index 000000000..dc91ad5db --- /dev/null +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/concepts.mdx @@ -0,0 +1,49 @@ +--- +title: ENS Unigraph Core Concepts +description: The core concepts behind the ENS Unigraph indexed data model. +--- + +import { CardGrid, LinkCard, Aside } from "@astrojs/starlight/components" + +## Indexed Data Model + +The ENS Unigraph indexed data model is available only when the [`unigraph` plugin](/docs/integrate/integration-options/ensnode-plugins#existing-plugins) is activated in your ENSNode instance. + +:::caution[`unigraph` plugin required] +Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` plugin activated in your ENSNode instance. [Learn more](/docs/services/ensindexer/usage/configuration) about activating [ENSNode Plugins](/docs/integrate/integration-options/ensnode-plugins). +::: + +## Canonical Nametree + +The **Canonical Nametree** is the set of all Domains that have an inferrable **Canonical Name** — materialized from the namegraph. For every Domain in it, the canonical fields are populated — `canonical_name`, `canonical_path`, `canonical_node`, and `canonical_depth` — across both ENSv1 and ENSv2. That means you can look a name up by `canonical_name = 'vitalik.eth'`, order by `canonical_depth`, or walk a name's path **without branching by `type` on protocol version** and without traversing the namegraph yourself. + +Multichain coverage is part of the same model: Basenames (`.base.eth`), Lineanames (`.linea.eth`), and 3DNS names (`.box`) are materialized into the same Unigraph as mainnet `.eth`, so a single query spans every indexable name. + +:::danger[Not a substitute for ENS Resolution] +The Unigraph mirrors onchain state; ENS's resolution-time behavior is applied _on top_ of it by +[ENSApi](/docs/services/ensapi). A direct SQL read of resolver records is therefore **not** +ENSIP-10 / CCIP-Read compliant and **cannot** be used as a source of truth for name resolution. +For correct resolution, use the [ENS Omnigraph API](/docs/integrate/omnigraph) (which adds ENS +Protocol Acceleration on top of the Unigraph). Use Unigraph SQL for analytics, discovery, and +custom indexing. +::: + +## Query optimizations + +### Domains + +A `canonical_name` can be very long, as it's the full, correct name. Due to limitations in Postgres btree indexes, the `domains` table has the `canonical_name` column and also the `__canonical_name_prefix` column (the first 64 code points of `canonical_name`, backed by a GIN trigram index). + +:::tip[Searching vs. displaying] +Always **select and display `canonical_name`**. When you need to **search** by prefix (`ILIKE 'vit%'`, case-insensitive to match the Omnigraph `starts_with` filter), match against the materialized `__canonical_name_prefix` column (the first 64 code points of `canonical_name`, backed by a GIN trigram index) so the `ILIKE` filter is index-backed: + +```sql +SELECT id, type, canonical_name, canonical_node, owner_id +FROM ensindexer_0.domains +WHERE __canonical_name_prefix ILIKE 'vit%' +ORDER BY __canonical_name_prefix +LIMIT 10; +``` + +The `SELECT` still returns `canonical_name`; only the `ILIKE` / `ORDER BY` use the prefix. The GIN trigram index backs the `ILIKE` filter; the `ORDER BY` then sorts the matched set (cheap under a small `LIMIT`) — scope the query by `registry_id` to use the `(registry_id, __canonical_name_prefix, id)` btree for fully index-backed ordering. For exact matches, use `canonical_name` directly (`canonical_name = 'vitalik.eth'`). +::: diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-domains.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-domains.mdx index a721b5ccf..5df936b4b 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-domains.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-domains.mdx @@ -10,10 +10,6 @@ import EnsDbWriterSchemaIntro from "@components/molecules/EnsDbWriterSchemaIntro import EnsDbReaderIntro from "@components/molecules/EnsDbReaderIntro.astro"; import { exampleAccountDomains } from "@data/unigraph-examples/account-domains"; -:::caution[`unigraph` plugin required] -Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` plugin activated in your ENSNode instance. [Learn more](/docs/services/ensindexer/usage/configuration) -::: - Fetch the Domains owned by an address (across both ENSv1 and ENSv2), including each Domain's `type` (`ENSv1Domain` vs `ENSv2Domain`). See [Connect](/docs/integrate/unigraph/examples) for setup. ## Connect -The Unigraph lives in [ENSDb](/docs/services/ensdb), a PostgreSQL database. Each [ENSDb Writer](/docs/services/ensdb/concepts/glossary#ensdb-writer) instance writes to its own **ENSDb Writer Schema** (e.g. `ensindexer_0`). Each instance of [ENSDb Metadata Writer](/docs/services/ensdb/concepts/glossary#ensdb-metadata-writer) writes to a shared operational [metadata table](/docs/services/ensdb/concepts/glossary#ensnode-metadata-table) in the [`ensnode` schema](/docs/services/ensdb/concepts/glossary#ensnode-schema). +The ENS Unigraph lives in [ENSDb](/docs/services/ensdb), a PostgreSQL database. Each [ENSDb Writer](/docs/services/ensdb/concepts/glossary#ensdb-writer) instance writes to its own **ENSDb Writer Schema** (e.g. `ensindexer_0`). Each instance of [ENSDb Metadata Writer](/docs/services/ensdb/concepts/glossary#ensdb-metadata-writer) writes to a shared operational [metadata table](/docs/services/ensdb/concepts/glossary#ensnode-metadata-table) in the [`ensnode` schema](/docs/services/ensdb/concepts/glossary#ensnode-schema). @@ -103,6 +100,13 @@ The Unigraph lives in [ENSDb](/docs/services/ensdb), a PostgreSQL database. Each ## Examples - - - +Here are some example queries to get you started. Each example is available in raw SQL and with the `ensdb-sdk` for TypeScript projects. + +See each example's page for details on the query and how to run it against your ENSDb instance. + + + + + + + diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/indexing-status.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/indexing-status.mdx index 791e9bca6..69b538e94 100644 --- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/indexing-status.mdx +++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/indexing-status.mdx @@ -10,10 +10,6 @@ import EnsNodeSchemaIntro from "@components/molecules/EnsNodeSchemaIntro.astro"; import EnsDbReaderIntro from "@components/molecules/EnsDbReaderIntro.astro"; import { exampleIndexingStatus } from "@data/unigraph-examples/indexing-status"; -:::caution[`unigraph` plugin required] -Performing SQL queries on the ENS Unigraph requires that you have the `unigraph` plugin activated in your ENSNode instance. [Learn more](/docs/services/ensindexer/usage/configuration) -::: - Read the indexing status snapshot for an ENSDb Writer instance from the shared `ensnode.metadata` table. See [Connect](/docs/integrate/unigraph/examples) for setup. - The Unigraph mirrors onchain state; ENS's resolution-time behavior is applied _on top_ of it by - [ENSApi](/docs/services/ensapi). A direct SQL read of resolver records is therefore **not** - ENSIP-10 / CCIP-Read compliant and **cannot** be used as a source of truth for name resolution. - For correct resolution, use the [ENS Omnigraph API](/docs/integrate/omnigraph) (which adds ENS - Protocol Acceleration on top of the Unigraph). Use Unigraph SQL for analytics, discovery, and - custom indexing. - - ## Get started + + - + 0) { type: ensIndexerSchema.domain.type, canonicalName: ensIndexerSchema.domain.canonicalName, canonicalNode: ensIndexerSchema.domain.canonicalNode, - id: ensIndexerSchema.domain.id, + ownerId: ensIndexerSchema.domain.ownerId, + domainId: ensIndexerSchema.domain.id, }) .from(ensIndexerSchema.domain) .where( @@ -104,33 +156,83 @@ if (parentDomains.length > 0) { result: [ { type: "ENSv1Domain", - canonicalName: "[52602a50858115661619fb28cf543ee766c182e0be6743c72d5bd674b3d12686].eth", - canonicalNode: "0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", - id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0xe91ce3506cd47457c2b3f04c2736875ca1d17ed74bf1a328a7e64cca5ae8c94b", + canonicalName: "app.ens.eth", + canonicalNode: "0x50a74dcf107973068dfc00db69ecf98b49d52f5361cb4db5feb740fc9f4f74d1", + ownerId: "0xb6e040c9ecaae172a89bd561c5f73e1c48d28cd9", + domainId: + "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x50a74dcf107973068dfc00db69ecf98b49d52f5361cb4db5feb740fc9f4f74d1", }, { type: "ENSv1Domain", - canonicalName: "[d90db363b8bc1371f7d738d264ff7294bfc5636f907c467adf68321a3c6d8188].eth", - canonicalNode: "0x08c0f01c419a8971af6b3eefe2a8bba1556cccf1163df60b1cdbcab632c8ab48", - id: "11155111-0xb6fb46e1458915dd828633d91e1df8e4c3f2d4dd-0x08c0f01c419a8971af6b3eefe2a8bba1556cccf1163df60b1cdbcab632c8ab48", + canonicalName: "attestations.ens.eth", + canonicalNode: "0x9e5c7a2f2ab8b565c6d2c4851a73decb53d1f6a23c97a2b5b66f21d8ace1bbd5", + ownerId: "0xb6e040c9ecaae172a89bd561c5f73e1c48d28cd9", + domainId: + "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x9e5c7a2f2ab8b565c6d2c4851a73decb53d1f6a23c97a2b5b66f21d8ace1bbd5", }, { - type: "ENSv2Domain", - canonicalName: "katrenpadu.eth", - canonicalNode: "0xf8ae81127bcd7ff99828b3dbd982a943d6dd961ee3f1a6ca707aa0eea913328e", - id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-112554048520345018269255786667391470421317806528110367240542760381540064034816", + type: "ENSv1Domain", + canonicalName: "coldwallet.ens.eth", + canonicalNode: "0xc867d2bd24b8a88c7d5d416dfab28fec6858b5a86f3a1c94faeab450c34023f6", + ownerId: "0x690f0581ececcf8389c223170778cd9d029606f2", + domainId: + "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xc867d2bd24b8a88c7d5d416dfab28fec6858b5a86f3a1c94faeab450c34023f6", }, { - type: "ENSv2Domain", - canonicalName: "roppp.eth", - canonicalNode: "0x39095c3dfb872d6441c95547f88591e7fb97014eef30cabe3df12a9b2a64dbe8", - id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-88275407146030613359050872632052369891139576190404928761656352489271755538432", + type: "ENSv1Domain", + canonicalName: "controller.ens.eth", + canonicalNode: "0xceecb75ad42a60ea38b777bf842c14af3303219e2722a192ddeac19faa7fbb1c", + ownerId: "0xb6e040c9ecaae172a89bd561c5f73e1c48d28cd9", + domainId: + "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xceecb75ad42a60ea38b777bf842c14af3303219e2722a192ddeac19faa7fbb1c", }, { - type: "ENSv2Domain", - canonicalName: "sfmpfv44d0mig.eth", - canonicalNode: "0x9b365136312d7ee6e232e3c98e459bc8667ec818c47fbbc55bb5e23d0a21e8cc", - id: "11155111-0x64c81210d0e580cfc7746f3fb910bf0e8f6378e1-30078755955643454526763071980293195785165410039216352470119925106082295316480", + type: "ENSv1Domain", + canonicalName: "design.ens.eth", + canonicalNode: "0xe55e79685b24c7b16542f3c613a8899986ace5e2e08b3c9444ce70d81d49bcd2", + ownerId: "0x690f0581ececcf8389c223170778cd9d029606f2", + domainId: + "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0xe55e79685b24c7b16542f3c613a8899986ace5e2e08b3c9444ce70d81d49bcd2", + }, + { + type: "ENSv1Domain", + canonicalName: "dnsname.ens.eth", + canonicalNode: "0x250712f87e86832e8bed775a563920aed01b926d9d21950e363a042af40ad2b5", + ownerId: "0xb6e040c9ecaae172a89bd561c5f73e1c48d28cd9", + domainId: + "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x250712f87e86832e8bed775a563920aed01b926d9d21950e363a042af40ad2b5", + }, + { + type: "ENSv1Domain", + canonicalName: "dnsregistrar.ens.eth", + canonicalNode: "0x3124e45545d17d9fda8e24a7a09f111a0802ea26ce6b1f14c75c832442deb65d", + ownerId: "0xb6e040c9ecaae172a89bd561c5f73e1c48d28cd9", + domainId: + "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x3124e45545d17d9fda8e24a7a09f111a0802ea26ce6b1f14c75c832442deb65d", + }, + { + type: "ENSv1Domain", + canonicalName: "dnssec.ens.eth", + canonicalNode: "0x287e74fe5b4463a7e8b8d4c4cccae51a8ab397df053bc829c6a4e26963c7ce2b", + ownerId: "0xb6e040c9ecaae172a89bd561c5f73e1c48d28cd9", + domainId: + "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x287e74fe5b4463a7e8b8d4c4cccae51a8ab397df053bc829c6a4e26963c7ce2b", + }, + { + type: "ENSv1Domain", + canonicalName: "docs.ens.eth", + canonicalNode: "0x08625bbdd59ae52e6a0e3f8f2bd6213e60ad35276510c83d117c7a2a68bc65c0", + ownerId: "0xee9eeaab0bb7d9b969d701f6f8212609edea252e", + domainId: + "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x08625bbdd59ae52e6a0e3f8f2bd6213e60ad35276510c83d117c7a2a68bc65c0", + }, + { + type: "ENSv1Domain", + canonicalName: "ecosystem.ens.eth", + canonicalNode: "0x44ea949951a1e21fe141e9979ef9af0cef3df0ac50004c19309df97fef6c9023", + ownerId: "0x690f0581ececcf8389c223170778cd9d029606f2", + domainId: + "1-0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e-0x44ea949951a1e21fe141e9979ef9af0cef3df0ac50004c19309df97fef6c9023", }, ], resultNote, From 312e4c2f1936a0de2a54da71f6640aa7e331b656 Mon Sep 17 00:00:00 2001 From: Tomasz Kopacki Date: Tue, 9 Jun 2026 17:50:26 +0200 Subject: [PATCH 10/12] Fix codestyle issue --- docs/ensnode.io/src/components/molecules/EnsUnigraphIntro.astro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ensnode.io/src/components/molecules/EnsUnigraphIntro.astro b/docs/ensnode.io/src/components/molecules/EnsUnigraphIntro.astro index fd0e58a15..609f140bc 100644 --- a/docs/ensnode.io/src/components/molecules/EnsUnigraphIntro.astro +++ b/docs/ensnode.io/src/components/molecules/EnsUnigraphIntro.astro @@ -1,5 +1,5 @@ --- -import { Aside } from "@astrojs/starlight/components" +import { Aside } from "@astrojs/starlight/components"; ---