ENS Resolution
The ENS protocol defines two forms of resolution:
- Forward resolution — given a name (
vitalik.eth), resolve its records: avatar, bio, links, multichain addresses, and more. - Reverse resolution — given an address, resolve its primary name on a chain (ENSIP-19).
One of the most common patterns when building on ENS is to combine both: given an address, first perform reverse resolution to get the primary name, then perform forward resolution on that name to fetch its avatar, social handles, and other display details. Because this pattern is so common, the Omnigraph provides support for it as complete resolution — reverse and forward in a single query with no extra round trip.
Moreover, the Omnigraph handles the underlying protocol complexity for you — resolver contracts, coin-type encoding, inconsistent text-record keys, and avatar formats that may be URLs, IPFS paths, or NFT references — and returns clean, structured results for all three patterns.
Forward resolution — interpreted profile
Section titled “Forward resolution — interpreted profile”When you have a name and need display-ready data, query domain.resolve.profile. This is where the Omnigraph does the heavy lifting: instead of decoding coin types, normalizing text-record keys, and chasing avatar formats yourself, you get a consumer-shaped view of the most common display fields — ready to drop into a UI or hand straight to an AI agent.
This query below loads a domain's high-level profile (avatar, socials, addresses, and more).
query DomainProfile($name: InterpretedName!) { domain(by: {name: $name}) { resolve { profile { description avatar { httpUrl } addresses { ethereum base solana bitcoin rootstock } socials { github { handle httpUrl } twitter { handle httpUrl } } website { httpUrl } header { httpUrl } } } }}{ "name": "gregskril.eth"}{ "data": { "domain": { "resolve": { "profile": { "description": "I like baking and building apps on web3 protocols.", "avatar": { "httpUrl": "https://gregskril.com/img/profile.jpg" }, "addresses": { "ethereum": "0x179a862703a4adfb29896552df9e307980d19285", "base": "0x179a862703a4adfb29896552df9e307980d19285", "solana": "2JQANQn1kccapb7GT8XScf9qBy59uMo9vh9WwVQhwStJ", "bitcoin": "3NnpwUMGdGKuYaPDQagNXAgVXz9HdnJDNS", "rootstock": "0x179a862703A4AdFb29896552dF9e307980D19285" }, "socials": { "github": { "handle": "gskril", "httpUrl": "https://github.com/gskril" }, "twitter": { "handle": "gregskril", "httpUrl": "https://x.com/gregskril" } }, "website": { "httpUrl": "https://gregskril.com/" }, "header": { "httpUrl": "https://files.gregskril.com/cdn/QmfGaXqmqasCrKktBgD4AvvJb3DLndiKXdz457uBGLTFGK" } } } } }}Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.
import { createEnsNodeClient } from "enssdk/core";import { asInterpretedName } from "enssdk";import { graphql, omnigraph } from "enssdk/omnigraph";
const client = createEnsNodeClient({ url: process.env.ENSNODE_URL || "https://api.alpha.ensnode.io"}).extend(omnigraph);
const DomainProfileQuery = graphql(` query DomainProfile($name: InterpretedName!) { domain(by: {name: $name}) { resolve { profile { description avatar { httpUrl } addresses { ethereum base solana bitcoin rootstock } socials { github { handle httpUrl } twitter { handle httpUrl } } website { httpUrl } header { httpUrl } } } } }`);
const result = await client.omnigraph.query({ query: DomainProfileQuery, variables: { name: asInterpretedName("gregskril.eth"), },});
if (result.errors) throw new Error(JSON.stringify(result.errors));console.log(JSON.stringify(result.data, null, 2));{ "data": { "domain": { "resolve": { "profile": { "description": "I like baking and building apps on web3 protocols.", "avatar": { "httpUrl": "https://gregskril.com/img/profile.jpg" }, "addresses": { "ethereum": "0x179a862703a4adfb29896552df9e307980d19285", "base": "0x179a862703a4adfb29896552df9e307980d19285", "solana": "2JQANQn1kccapb7GT8XScf9qBy59uMo9vh9WwVQhwStJ", "bitcoin": "3NnpwUMGdGKuYaPDQagNXAgVXz9HdnJDNS", "rootstock": "0x179a862703A4AdFb29896552dF9e307980D19285" }, "socials": { "github": { "handle": "gskril", "httpUrl": "https://github.com/gskril" }, "twitter": { "handle": "gregskril", "httpUrl": "https://x.com/gregskril" } }, "website": { "httpUrl": "https://gregskril.com/" }, "header": { "httpUrl": "https://files.gregskril.com/cdn/QmfGaXqmqasCrKktBgD4AvvJb3DLndiKXdz457uBGLTFGK" } } } } }}Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.
enssdk package manager setup
# 1. Create projectmkdir -p my-ens-script/src && cd my-ens-scriptnpm init -y && touch src/index.tsnpm pkg set type=module scripts.start="tsx src/index.ts"# 2. Install dependenciesnpm install enssdk@1.15.1 && npm install -D tsx typescript @types/node# 3. Paste the TypeScript snippet above into src/index.ts# 4. RunENSNODE_URL=https://api.alpha.ensnode.io npm startSee the enssdk docs for gql.tada plugin and tsconfig setup.
import { OmnigraphProvider, useOmnigraphQuery, graphql } from "enskit/react/omnigraph";import { createEnsNodeClient } from "enssdk/core";import { asInterpretedName } from "enssdk";import { omnigraph } from "enssdk/omnigraph";
const client = createEnsNodeClient({ url: import.meta.env.VITE_ENSNODE_URL || "https://api.alpha.ensnode.io"}).extend(omnigraph);
const DomainProfileQuery = graphql(` query DomainProfile($name: InterpretedName!) { domain(by: {name: $name}) { resolve { profile { description avatar { httpUrl } addresses { ethereum base solana bitcoin rootstock } socials { github { handle httpUrl } twitter { handle httpUrl } } website { httpUrl } header { httpUrl } } } } }`);
function DomainProfileResult() { const [result] = useOmnigraphQuery({ query: DomainProfileQuery, variables: { name: asInterpretedName("gregskril.eth"), }, }); const { data, fetching, error } = result; if (!data && fetching) return <p>Loading…</p>; if (error) return <p>Error: {error.message}</p>; if (!data) return <p>No data returned.</p>; const formatted = JSON.stringify( data, (_, value) => (typeof value === "bigint" ? value.toString() : value), 2, ); return <code>{formatted}</code>;}
export default function App() { return ( <OmnigraphProvider client={client}> <DomainProfileResult /> </OmnigraphProvider> );}{ "data": { "domain": { "resolve": { "profile": { "description": "I like baking and building apps on web3 protocols.", "avatar": { "httpUrl": "https://gregskril.com/img/profile.jpg" }, "addresses": { "ethereum": "0x179a862703a4adfb29896552df9e307980d19285", "base": "0x179a862703a4adfb29896552df9e307980d19285", "solana": "2JQANQn1kccapb7GT8XScf9qBy59uMo9vh9WwVQhwStJ", "bitcoin": "3NnpwUMGdGKuYaPDQagNXAgVXz9HdnJDNS", "rootstock": "0x179a862703A4AdFb29896552dF9e307980D19285" }, "socials": { "github": { "handle": "gskril", "httpUrl": "https://github.com/gskril" }, "twitter": { "handle": "gregskril", "httpUrl": "https://x.com/gregskril" } }, "website": { "httpUrl": "https://gregskril.com/" }, "header": { "httpUrl": "https://files.gregskril.com/cdn/QmfGaXqmqasCrKktBgD4AvvJb3DLndiKXdz457uBGLTFGK" } } } } }}Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.
enskit package manager setup
# 1. Create projectnpm create vite@latest my-ens-app -- --template react-ts --no-interactive --no-immediatecd my-ens-app# 2. Install dependenciesnpm installnpm install enskit@1.15.1 enssdk@1.15.1# 3. Copy the TSX snippet above into src/App.tsx# 4. RunVITE_ENSNODE_URL=https://api.alpha.ensnode.io npm run devSee the enskit docs for gql.tada plugin and provider setup.
# POST JSON to your ENSNode Omnigraph endpoint (same path enssdk uses).curl -sS -X POST "https://api.alpha.ensnode.io/api/omnigraph" \ -H "Content-Type: application/json" \ -d '{ "query": "query DomainProfile($name: InterpretedName!) { domain(by: {name: $name}) { resolve { profile { description avatar { httpUrl } addresses { ethereum base solana bitcoin rootstock } socials { github { handle httpUrl } twitter { handle httpUrl } } website { httpUrl } header { httpUrl } } } } }", "variables": {"name":"gregskril.eth"}}'{ "data": { "domain": { "resolve": { "profile": { "description": "I like baking and building apps on web3 protocols.", "avatar": { "httpUrl": "https://gregskril.com/img/profile.jpg" }, "addresses": { "ethereum": "0x179a862703a4adfb29896552df9e307980d19285", "base": "0x179a862703a4adfb29896552df9e307980d19285", "solana": "2JQANQn1kccapb7GT8XScf9qBy59uMo9vh9WwVQhwStJ", "bitcoin": "3NnpwUMGdGKuYaPDQagNXAgVXz9HdnJDNS", "rootstock": "0x179a862703A4AdFb29896552dF9e307980D19285" }, "socials": { "github": { "handle": "gskril", "httpUrl": "https://github.com/gskril" }, "twitter": { "handle": "gregskril", "httpUrl": "https://x.com/gregskril" } }, "website": { "httpUrl": "https://gregskril.com/" }, "header": { "httpUrl": "https://files.gregskril.com/cdn/QmfGaXqmqasCrKktBgD4AvvJb3DLndiKXdz457uBGLTFGK" } } } } }}Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.
What you get in resolve.profile:
- Addresses — keyed by chain (
ethereum,solana,base, …) in chain-native encodings. - Social accounts —
{ handle, httpUrl }pairs, ready to link. - Avatar and header images —
httpUrlvalues you can use directly in<img src="…" />, including derivation from NFT references per ENSIP-12. - Missing or invalid records —
null, so you can render without extra guards.
The same predictable shape works well for AI agents — structured fields and null for anything missing or invalid, without decoding resolver data in the prompt.
Forward resolution — raw records
Section titled “Forward resolution — raw records”resolve.records returns protocol-accurate resolver data: numeric coin types, arbitrary text keys, and unparsed bytes. This is the shape you would work with if you decoded resolver storage yourself — or if you need records that profile does not model.
This query below resolves raw records for a given name, such as addresses, texts, and contenthash.
query DomainRecords($name: InterpretedName!) { domain(by: {name: $name}) { canonical { name { interpreted } } resolve { records { addresses(coinTypes: [60, 2147483658, 501]) { coinType address } texts(keys: ["description", "avatar", "url", "com.github", "com.twitter"]) { key value } contenthash } } }}{ "name": "gregskril.eth"}{ "data": { "domain": { "canonical": { "name": { "interpreted": "gregskril.eth" } }, "resolve": { "records": { "addresses": [ { "coinType": 60, "address": "0x179a862703a4adfb29896552df9e307980d19285" }, { "coinType": 2147483658, "address": "0x179a862703a4adfb29896552df9e307980d19285" }, { "coinType": 501, "address": "0x1350bfe02357c8bc583d7514f44ba2c31821d8739160e7b79a0a94bc113a4f73" } ], "texts": [ { "key": "description", "value": "I like baking and building apps on web3 protocols." }, { "key": "avatar", "value": "https://gregskril.com/img/profile.jpg" }, { "key": "url", "value": "https://gregskril.com/" }, { "key": "com.github", "value": "gskril" }, { "key": "com.twitter", "value": "gregskril" } ], "contenthash": "0xe30101701220f0bd3d5d672c6197d341797bb34d4a5e31fbb40c437fead8756213522b976ed9" } } } }}Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.
import { createEnsNodeClient } from "enssdk/core";import { asInterpretedName } from "enssdk";import { graphql, omnigraph } from "enssdk/omnigraph";
const client = createEnsNodeClient({ url: process.env.ENSNODE_URL || "https://api.alpha.ensnode.io"}).extend(omnigraph);
const DomainRecordsQuery = graphql(` query DomainRecords($name: InterpretedName!) { domain(by: {name: $name}) { canonical { name { interpreted } } resolve { records { addresses(coinTypes: [60, 2147483658, 501]) { coinType address } texts(keys: ["description", "avatar", "url", "com.github", "com.twitter"]) { key value } contenthash } } } }`);
const result = await client.omnigraph.query({ query: DomainRecordsQuery, variables: { name: asInterpretedName("gregskril.eth"), },});
if (result.errors) throw new Error(JSON.stringify(result.errors));console.log(JSON.stringify(result.data, null, 2));{ "data": { "domain": { "canonical": { "name": { "interpreted": "gregskril.eth" } }, "resolve": { "records": { "addresses": [ { "coinType": 60, "address": "0x179a862703a4adfb29896552df9e307980d19285" }, { "coinType": 2147483658, "address": "0x179a862703a4adfb29896552df9e307980d19285" }, { "coinType": 501, "address": "0x1350bfe02357c8bc583d7514f44ba2c31821d8739160e7b79a0a94bc113a4f73" } ], "texts": [ { "key": "description", "value": "I like baking and building apps on web3 protocols." }, { "key": "avatar", "value": "https://gregskril.com/img/profile.jpg" }, { "key": "url", "value": "https://gregskril.com/" }, { "key": "com.github", "value": "gskril" }, { "key": "com.twitter", "value": "gregskril" } ], "contenthash": "0xe30101701220f0bd3d5d672c6197d341797bb34d4a5e31fbb40c437fead8756213522b976ed9" } } } }}Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.
enssdk package manager setup
# 1. Create projectmkdir -p my-ens-script/src && cd my-ens-scriptnpm init -y && touch src/index.tsnpm pkg set type=module scripts.start="tsx src/index.ts"# 2. Install dependenciesnpm install enssdk@1.15.1 && npm install -D tsx typescript @types/node# 3. Paste the TypeScript snippet above into src/index.ts# 4. RunENSNODE_URL=https://api.alpha.ensnode.io npm startSee the enssdk docs for gql.tada plugin and tsconfig setup.
import { OmnigraphProvider, useOmnigraphQuery, graphql } from "enskit/react/omnigraph";import { createEnsNodeClient } from "enssdk/core";import { asInterpretedName } from "enssdk";import { omnigraph } from "enssdk/omnigraph";
const client = createEnsNodeClient({ url: import.meta.env.VITE_ENSNODE_URL || "https://api.alpha.ensnode.io"}).extend(omnigraph);
const DomainRecordsQuery = graphql(` query DomainRecords($name: InterpretedName!) { domain(by: {name: $name}) { canonical { name { interpreted } } resolve { records { addresses(coinTypes: [60, 2147483658, 501]) { coinType address } texts(keys: ["description", "avatar", "url", "com.github", "com.twitter"]) { key value } contenthash } } } }`);
function DomainRecordsResult() { const [result] = useOmnigraphQuery({ query: DomainRecordsQuery, variables: { name: asInterpretedName("gregskril.eth"), }, }); const { data, fetching, error } = result; if (!data && fetching) return <p>Loading…</p>; if (error) return <p>Error: {error.message}</p>; if (!data) return <p>No data returned.</p>; const formatted = JSON.stringify( data, (_, value) => (typeof value === "bigint" ? value.toString() : value), 2, ); return <code>{formatted}</code>;}
export default function App() { return ( <OmnigraphProvider client={client}> <DomainRecordsResult /> </OmnigraphProvider> );}{ "data": { "domain": { "canonical": { "name": { "interpreted": "gregskril.eth" } }, "resolve": { "records": { "addresses": [ { "coinType": 60, "address": "0x179a862703a4adfb29896552df9e307980d19285" }, { "coinType": 2147483658, "address": "0x179a862703a4adfb29896552df9e307980d19285" }, { "coinType": 501, "address": "0x1350bfe02357c8bc583d7514f44ba2c31821d8739160e7b79a0a94bc113a4f73" } ], "texts": [ { "key": "description", "value": "I like baking and building apps on web3 protocols." }, { "key": "avatar", "value": "https://gregskril.com/img/profile.jpg" }, { "key": "url", "value": "https://gregskril.com/" }, { "key": "com.github", "value": "gskril" }, { "key": "com.twitter", "value": "gregskril" } ], "contenthash": "0xe30101701220f0bd3d5d672c6197d341797bb34d4a5e31fbb40c437fead8756213522b976ed9" } } } }}Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.
enskit package manager setup
# 1. Create projectnpm create vite@latest my-ens-app -- --template react-ts --no-interactive --no-immediatecd my-ens-app# 2. Install dependenciesnpm installnpm install enskit@1.15.1 enssdk@1.15.1# 3. Copy the TSX snippet above into src/App.tsx# 4. RunVITE_ENSNODE_URL=https://api.alpha.ensnode.io npm run devSee the enskit docs for gql.tada plugin and provider setup.
# POST JSON to your ENSNode Omnigraph endpoint (same path enssdk uses).curl -sS -X POST "https://api.alpha.ensnode.io/api/omnigraph" \ -H "Content-Type: application/json" \ -d '{ "query": "query DomainRecords($name: InterpretedName!) { domain(by: {name: $name}) { canonical { name { interpreted } } resolve { records { addresses(coinTypes: [60, 2147483658, 501]) { coinType address } texts(keys: [\"description\", \"avatar\", \"url\", \"com.github\", \"com.twitter\"]) { key value } contenthash } } } }", "variables": {"name":"gregskril.eth"}}'{ "data": { "domain": { "canonical": { "name": { "interpreted": "gregskril.eth" } }, "resolve": { "records": { "addresses": [ { "coinType": 60, "address": "0x179a862703a4adfb29896552df9e307980d19285" }, { "coinType": 2147483658, "address": "0x179a862703a4adfb29896552df9e307980d19285" }, { "coinType": 501, "address": "0x1350bfe02357c8bc583d7514f44ba2c31821d8739160e7b79a0a94bc113a4f73" } ], "texts": [ { "key": "description", "value": "I like baking and building apps on web3 protocols." }, { "key": "avatar", "value": "https://gregskril.com/img/profile.jpg" }, { "key": "url", "value": "https://gregskril.com/" }, { "key": "com.github", "value": "gskril" }, { "key": "com.twitter", "value": "gregskril" } ], "contenthash": "0xe30101701220f0bd3d5d672c6197d341797bb34d4a5e31fbb40c437fead8756213522b976ed9" } } } }}Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.
Reverse resolution — primaryName
Section titled “Reverse resolution — primaryName”Given an address, reverse resolution answers: what name does this address want to be known by? If the address has not set a primary name, the result is null — safe to render like any other missing field.
Primary names are stored linked to coin-types, but Omnigraph allows using friendly chain names like ETHEREUM or BASE. beautified is ready for UI rendering; interpreted is the stable form for lookups and links. See Beautified Name.
This query loads the primary names for an account on Ethereum and Base.
query AccountPrimaryNames($address: Address!) { account(by: { address: $address }) { address resolve { onePrimaryName: primaryName(by: { chainName: OPTIMISM }) { chainName name { interpreted beautified } }
twoPrimaryNames: primaryNames(where: { chainNames: [ETHEREUM, BASE] }) { chainName name { interpreted beautified } } } }}{ "address": "0x179a862703a4adfb29896552df9e307980d19285"}{ "data": { "account": { "address": "0x179a862703a4adfb29896552df9e307980d19285", "resolve": { "onePrimaryName": { "chainName": "OPTIMISM", "name": { "interpreted": "gregskril.eth", "beautified": "gregskril.eth" } }, "twoPrimaryNames": [ { "chainName": "ETHEREUM", "name": { "interpreted": "gregskril.eth", "beautified": "gregskril.eth" } }, { "chainName": "BASE", "name": { "interpreted": "greg.base.eth", "beautified": "greg.base.eth" } } ] } } }}Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.
import { createEnsNodeClient } from "enssdk/core";import { graphql, omnigraph } from "enssdk/omnigraph";
const client = createEnsNodeClient({ url: process.env.ENSNODE_URL || "https://api.alpha.ensnode.io"}).extend(omnigraph);
const AccountPrimaryNamesQuery = graphql(` query AccountPrimaryNames($address: Address!) { account(by: { address: $address }) { address resolve { onePrimaryName: primaryName(by: { chainName: OPTIMISM }) { chainName name { interpreted beautified } }
twoPrimaryNames: primaryNames(where: { chainNames: [ETHEREUM, BASE] }) { chainName name { interpreted beautified } } } } }`);
const result = await client.omnigraph.query({ query: AccountPrimaryNamesQuery, variables: { address: "0x179a862703a4adfb29896552df9e307980d19285", },});
if (result.errors) throw new Error(JSON.stringify(result.errors));console.log(JSON.stringify(result.data, null, 2));{ "data": { "account": { "address": "0x179a862703a4adfb29896552df9e307980d19285", "resolve": { "onePrimaryName": { "chainName": "OPTIMISM", "name": { "interpreted": "gregskril.eth", "beautified": "gregskril.eth" } }, "twoPrimaryNames": [ { "chainName": "ETHEREUM", "name": { "interpreted": "gregskril.eth", "beautified": "gregskril.eth" } }, { "chainName": "BASE", "name": { "interpreted": "greg.base.eth", "beautified": "greg.base.eth" } } ] } } }}Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.
enssdk package manager setup
# 1. Create projectmkdir -p my-ens-script/src && cd my-ens-scriptnpm init -y && touch src/index.tsnpm pkg set type=module scripts.start="tsx src/index.ts"# 2. Install dependenciesnpm install enssdk@1.15.1 && npm install -D tsx typescript @types/node# 3. Paste the TypeScript snippet above into src/index.ts# 4. RunENSNODE_URL=https://api.alpha.ensnode.io npm startSee the enssdk docs for gql.tada plugin and tsconfig setup.
import { OmnigraphProvider, useOmnigraphQuery, graphql } from "enskit/react/omnigraph";import { createEnsNodeClient } from "enssdk/core";import { omnigraph } from "enssdk/omnigraph";
const client = createEnsNodeClient({ url: import.meta.env.VITE_ENSNODE_URL || "https://api.alpha.ensnode.io"}).extend(omnigraph);
const AccountPrimaryNamesQuery = graphql(` query AccountPrimaryNames($address: Address!) { account(by: { address: $address }) { address resolve { onePrimaryName: primaryName(by: { chainName: OPTIMISM }) { chainName name { interpreted beautified } }
twoPrimaryNames: primaryNames(where: { chainNames: [ETHEREUM, BASE] }) { chainName name { interpreted beautified } } } } }`);
function AccountPrimaryNamesResult() { const [result] = useOmnigraphQuery({ query: AccountPrimaryNamesQuery, variables: { address: "0x179a862703a4adfb29896552df9e307980d19285", }, }); const { data, fetching, error } = result; if (!data && fetching) return <p>Loading…</p>; if (error) return <p>Error: {error.message}</p>; if (!data) return <p>No data returned.</p>; const formatted = JSON.stringify( data, (_, value) => (typeof value === "bigint" ? value.toString() : value), 2, ); return <code>{formatted}</code>;}
export default function App() { return ( <OmnigraphProvider client={client}> <AccountPrimaryNamesResult /> </OmnigraphProvider> );}{ "data": { "account": { "address": "0x179a862703a4adfb29896552df9e307980d19285", "resolve": { "onePrimaryName": { "chainName": "OPTIMISM", "name": { "interpreted": "gregskril.eth", "beautified": "gregskril.eth" } }, "twoPrimaryNames": [ { "chainName": "ETHEREUM", "name": { "interpreted": "gregskril.eth", "beautified": "gregskril.eth" } }, { "chainName": "BASE", "name": { "interpreted": "greg.base.eth", "beautified": "greg.base.eth" } } ] } } }}Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.
enskit package manager setup
# 1. Create projectnpm create vite@latest my-ens-app -- --template react-ts --no-interactive --no-immediatecd my-ens-app# 2. Install dependenciesnpm installnpm install enskit@1.15.1 enssdk@1.15.1# 3. Copy the TSX snippet above into src/App.tsx# 4. RunVITE_ENSNODE_URL=https://api.alpha.ensnode.io npm run devSee the enskit docs for gql.tada plugin and provider setup.
# POST JSON to your ENSNode Omnigraph endpoint (same path enssdk uses).curl -sS -X POST "https://api.alpha.ensnode.io/api/omnigraph" \ -H "Content-Type: application/json" \ -d '{ "query": "query AccountPrimaryNames($address: Address!) { account(by: { address: $address }) { address resolve { onePrimaryName: primaryName(by: { chainName: OPTIMISM }) { chainName name { interpreted beautified } } twoPrimaryNames: primaryNames(where: { chainNames: [ETHEREUM, BASE] }) { chainName name { interpreted beautified } } } } }", "variables": {"address":"0x179a862703a4adfb29896552df9e307980d19285"}}'{ "data": { "account": { "address": "0x179a862703a4adfb29896552df9e307980d19285", "resolve": { "onePrimaryName": { "chainName": "OPTIMISM", "name": { "interpreted": "gregskril.eth", "beautified": "gregskril.eth" } }, "twoPrimaryNames": [ { "chainName": "ETHEREUM", "name": { "interpreted": "gregskril.eth", "beautified": "gregskril.eth" } }, { "chainName": "BASE", "name": { "interpreted": "greg.base.eth", "beautified": "greg.base.eth" } } ] } } }}Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.
Complete resolution
Section titled “Complete resolution”Complete resolution is the pattern most wallets and explorers actually implement: given an address, resolve its primary name and then immediately forward-resolve the records on that name.
This query loads the primary name for an account on Ethereum and forward-resolves its profile in the same request.
query AccountPrimaryNameRecords($address: Address!) { account(by: { address: $address }) { address resolve { primaryName(by: { chainName: ETHEREUM }) { name { interpreted beautified } resolve { profile { description socials { twitter { httpUrl } } } } } } }}{ "address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"}{ "data": { "account": { "address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "resolve": { "primaryName": { "name": { "interpreted": "vitalik.eth", "beautified": "vitalik.eth" }, "resolve": { "profile": { "description": "mi pinxe lo crino tcati", "socials": { "twitter": { "httpUrl": "https://x.com/VitalikButerin" } } } } } } } }}Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.
import { createEnsNodeClient } from "enssdk/core";import { graphql, omnigraph } from "enssdk/omnigraph";
const client = createEnsNodeClient({ url: process.env.ENSNODE_URL || "https://api.alpha.ensnode.io"}).extend(omnigraph);
const AccountPrimaryNameRecordsQuery = graphql(` query AccountPrimaryNameRecords($address: Address!) { account(by: { address: $address }) { address resolve { primaryName(by: { chainName: ETHEREUM }) { name { interpreted beautified } resolve { profile { description socials { twitter { httpUrl } } } } } } } }`);
const result = await client.omnigraph.query({ query: AccountPrimaryNameRecordsQuery, variables: { address: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", },});
if (result.errors) throw new Error(JSON.stringify(result.errors));console.log(JSON.stringify(result.data, null, 2));{ "data": { "account": { "address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "resolve": { "primaryName": { "name": { "interpreted": "vitalik.eth", "beautified": "vitalik.eth" }, "resolve": { "profile": { "description": "mi pinxe lo crino tcati", "socials": { "twitter": { "httpUrl": "https://x.com/VitalikButerin" } } } } } } } }}Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.
enssdk package manager setup
# 1. Create projectmkdir -p my-ens-script/src && cd my-ens-scriptnpm init -y && touch src/index.tsnpm pkg set type=module scripts.start="tsx src/index.ts"# 2. Install dependenciesnpm install enssdk@1.15.1 && npm install -D tsx typescript @types/node# 3. Paste the TypeScript snippet above into src/index.ts# 4. RunENSNODE_URL=https://api.alpha.ensnode.io npm startSee the enssdk docs for gql.tada plugin and tsconfig setup.
import { OmnigraphProvider, useOmnigraphQuery, graphql } from "enskit/react/omnigraph";import { createEnsNodeClient } from "enssdk/core";import { omnigraph } from "enssdk/omnigraph";
const client = createEnsNodeClient({ url: import.meta.env.VITE_ENSNODE_URL || "https://api.alpha.ensnode.io"}).extend(omnigraph);
const AccountPrimaryNameRecordsQuery = graphql(` query AccountPrimaryNameRecords($address: Address!) { account(by: { address: $address }) { address resolve { primaryName(by: { chainName: ETHEREUM }) { name { interpreted beautified } resolve { profile { description socials { twitter { httpUrl } } } } } } } }`);
function AccountPrimaryNameRecordsResult() { const [result] = useOmnigraphQuery({ query: AccountPrimaryNameRecordsQuery, variables: { address: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", }, }); const { data, fetching, error } = result; if (!data && fetching) return <p>Loading…</p>; if (error) return <p>Error: {error.message}</p>; if (!data) return <p>No data returned.</p>; const formatted = JSON.stringify( data, (_, value) => (typeof value === "bigint" ? value.toString() : value), 2, ); return <code>{formatted}</code>;}
export default function App() { return ( <OmnigraphProvider client={client}> <AccountPrimaryNameRecordsResult /> </OmnigraphProvider> );}{ "data": { "account": { "address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "resolve": { "primaryName": { "name": { "interpreted": "vitalik.eth", "beautified": "vitalik.eth" }, "resolve": { "profile": { "description": "mi pinxe lo crino tcati", "socials": { "twitter": { "httpUrl": "https://x.com/VitalikButerin" } } } } } } } }}Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.
enskit package manager setup
# 1. Create projectnpm create vite@latest my-ens-app -- --template react-ts --no-interactive --no-immediatecd my-ens-app# 2. Install dependenciesnpm installnpm install enskit@1.15.1 enssdk@1.15.1# 3. Copy the TSX snippet above into src/App.tsx# 4. RunVITE_ENSNODE_URL=https://api.alpha.ensnode.io npm run devSee the enskit docs for gql.tada plugin and provider setup.
# POST JSON to your ENSNode Omnigraph endpoint (same path enssdk uses).curl -sS -X POST "https://api.alpha.ensnode.io/api/omnigraph" \ -H "Content-Type: application/json" \ -d '{ "query": "query AccountPrimaryNameRecords($address: Address!) { account(by: { address: $address }) { address resolve { primaryName(by: { chainName: ETHEREUM }) { name { interpreted beautified } resolve { profile { description socials { twitter { httpUrl } } } } } } } }", "variables": {"address":"0xd8da6bf26964af9d7eed9e03e53415d37aa96045"}}'{ "data": { "account": { "address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "resolve": { "primaryName": { "name": { "interpreted": "vitalik.eth", "beautified": "vitalik.eth" }, "resolve": { "profile": { "description": "mi pinxe lo crino tcati", "socials": { "twitter": { "httpUrl": "https://x.com/VitalikButerin" } } } } } } } }}Output matches a point in time snapshot GraphQL response from our alpha ENSNode instance. Live output depends on the configuration of your ENSNode instance and ENS state updates.
Breaking down the example above:
- Start from an address — pass any wallet address; the query looks up that account’s primary name.
- Pick a chain — primary names are per-chain (e.g. Ethereum mainnet). Use friendly chain names like
ETHEREUMorBASEinstead of raw coin types. - Display the name —
beautifiedis ready for UI rendering;interpretedis the stable form for lookups and links. - Load the records in the same request — avatar, bio, and social links are forward-resolved from the primary name. The response shape is the same
resolve.profilestructure from the forward resolution section above.