Skip to content

ENSv2 Quickstart

ENSv2 is the next generation of the Ethereum Name Service — a protocol upgrade that fundamentally changes the onchain data model of ENS.

ENSNode fully supports ENSv2 via the Omnigraph API, a unified API over both ENSv1 and ENSv2. Note how when ENSv2 launches, ENSv1 continues to exist in parallel. ENSNode takes the guesswork out of building on ENS, whether you need to resolve up-to-date records, search all Domains, or see which Domains a user owns (and much, much more).

ENS Omnigraph diagram

ENS Omnigraph supports both ENSv1 and ENSv2 concurrently. This means you can integrate today (before ENSv2 launches) and continue with full ENSv2 support when it goes live with zero downtime!

ENSNode supports a full range of different integration options across the stack, whether you’re using React, any JavaScript runtime, raw GraphQL, or looking to go deep and build a new and fully custom service on ENS data.

Here’s a summary of some popular integration strategies:

With enskit, leverage ENSNode and the Omnigraph to power your React components using useOmnigraphQuery. enskit comes with built-in type-safety, Omnigraph-specific cache directives, easy infinite pagination, and much much more.

// this is fully typechecked and supports editor autocomplete!
const DomainFragment = graphql(`
fragment DomainFragment on Domain {
__typename
id
canonical { name }
owner { id address }
}
`);
// this is fully typechecked and supports editor autocomplete!
const DomainByNameQuery = graphql(`
query DomainByNameQuery($name: InterpretedName!) {
domain(by: { name: $name }) {
...DomainFragment
subdomains {
edges { node { ...DomainFragment } }
}
}
}
`,
[DomainFragment],
);
function RenderDomainFragment({ data }: { data: FragmentOf<typeof DomainFragment> }) {
// type-safe access to fragment data!
const domain = readFragment(DomainFragment, data);
return (
<>
<span>Name: {domain.canonical ? beautifyInterpretedName(domain.canonical.name) : 'Unnamed Domain'}</span>
<span>Protocol Version: {domain.__typename === 'ENSv1Domain' ? 'ENSv1' : 'ENSv2'}</span>
<span>Owner: {domain.owner ? domain.owner.address : 'Unowned'}</span>
</>
);
}
export function RenderDomainAndSubdomains({ name }: { name: InterpretedName }) {
// `result` is fully typed!
const [result] = useOmnigraphQuery({ query: DomainByNameQuery, variables: { name } });
const { data, fetching, error } = result;
// some loading/error handling
if (!data && fetching) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
if (!data?.domain) return <p>No domain was found with name '{name}'.</p>;
// now we have type-safe access to Domain!
const domain = readFragment(DomainFragment, data.domain);
const { subdomains } = data.domain;
return (
<div>
<RenderDomainFragment data={data.domain} />
<h2>Subdomains:</h2>
<ul>
{subdomains?.edges.map((edge) => {
const { id } = readFragment(DomainFragment, edge.node);
return (
<li key={id}>
<RenderDomainFragment data={edge.node} />
</li>
);
})}
</ul>
</div>
);
}

With enssdk, leverage ENSNode and the Omnigraph from any JavaScript runtime to power your frontend or backend apps. enssdk comes with built-in type-safety and editor autocomplete for Omnigraph queries.

// create and extend an EnsNodeClient with Omnigraph API support
const client = createEnsNodeClient({ url: process.env.ENSNODE_URL! }).extend(omnigraph);
// this is fully typechecked and supports editor autocomplete!
const HelloWorldQuery = graphql(`
query HelloWorld {
domain(by: { name: "eth" }) {
id
canonical { name }
owner { address }
}
}
`);
// `result` is fully typed!
const result = await client.omnigraph.query({ query: HelloWorldQuery });

The ENS Omnigraph API is a GraphQL API following the Relay specification, so you get built-in support for efficient infinite pagination and idiomatic access to all of the ENS protocol within a unified ENSv1 + ENSv2 datamodel.

query MyDomains($address: Address!) {
account(by: { address: $address }) {
domains {
edges {
node {
label { interpreted }
canonical { name }
}
}
}
}
}