Skip to content

Commit 429bae0

Browse files
shrugsdjstrong
authored andcommitted
ENSv2: Index ENSv1 Root Registry Owner and Surface via API (#1733)
1 parent b93c4f8 commit 429bae0

File tree

5 files changed

+47
-18
lines changed

5 files changed

+47
-18
lines changed

.changeset/strong-baboons-help.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"ensapi": minor
3+
---
4+
5+
ENSNode GraphQL API: `ENSv1Domain.rootRegistryOwner` is now available, indicating the owner of the Domain's node within the ENSv1 Registry contract.

apps/ensapi/src/graphql-api/schema/domain.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,17 @@ ENSv1DomainRef.implement({
262262
nullable: true,
263263
resolve: (parent) => parent.parentId,
264264
}),
265+
266+
/////////////////////////////////
267+
// ENSv1Domain.rootRegistryOwner
268+
/////////////////////////////////
269+
rootRegistryOwner: t.field({
270+
description:
271+
"The rootRegistryOwner of this Domain, i.e. the owner() of this Domain within the ENSv1 Registry.",
272+
type: AccountRef,
273+
nullable: true,
274+
resolve: (parent) => parent.rootRegistryOwnerId,
275+
}),
265276
}),
266277
});
267278

apps/ensindexer/src/plugins/ensv2/handlers/ensv1/ENSv1Registry.ts

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,14 @@ export default function () {
7676
// upsert domain
7777
await context.db
7878
.insert(schema.v1Domain)
79-
.values({
80-
id: domainId,
81-
parentId,
82-
labelHash,
83-
})
79+
.values({ id: domainId, parentId, labelHash })
8480
.onConflictDoNothing();
8581

82+
// update rootRegistryOwner
83+
await context.db
84+
.update(schema.v1Domain, { id: domainId })
85+
.set({ rootRegistryOwnerId: interpretAddress(owner) });
86+
8687
// materialize domain owner
8788
// NOTE: despite Domain.ownerId being materialized from other sources of truth (i.e. Registrars
8889
// like BaseRegistrars & NameWrapper) it's ok to always set it here because the Registrar-emitted
@@ -99,25 +100,25 @@ export default function () {
99100
context: Context;
100101
event: EventWithArgs<{ node: Node; owner: Address }>;
101102
}) {
102-
const { node, owner: _owner } = event.args;
103-
const owner = interpretAddress(_owner);
103+
const { node, owner } = event.args;
104104

105105
// ENSv2 model does not include root node, no-op
106106
if (node === ROOT_NODE) return;
107107

108108
const domainId = makeENSv1DomainId(node);
109109

110-
if (owner === null) {
111-
await context.db.delete(schema.v1Domain, { id: domainId });
112-
} else {
113-
// materialize domain owner
114-
// NOTE: despite Domain.ownerId being materialized from other sources of truth (i.e. Registrars
115-
// like BaseRegistrars & NameWrapper) it's ok to always set it here because the Registrar-emitted
116-
// events occur _after_ the Registry events. So when a name is wrapped, for example, the Registry's
117-
// owner changes to that of the NameWrapper but then the NameWrapper emits NameWrapped, and this
118-
// indexing code re-materializes the Domain.ownerId to the NameWraper-emitted value.
119-
await materializeENSv1DomainEffectiveOwner(context, domainId, owner);
120-
}
110+
// set the domain's rootRegistryOwner to `owner`
111+
await context.db
112+
.update(schema.v1Domain, { id: domainId })
113+
.set({ rootRegistryOwnerId: interpretAddress(owner) });
114+
115+
// materialize domain owner
116+
// NOTE: despite Domain.ownerId being materialized from other sources of truth (i.e. Registrars
117+
// like BaseRegistrars & NameWrapper) it's ok to always set it here because the Registrar-emitted
118+
// events occur _after_ the Registry events. So when a name is wrapped, for example, the Registry's
119+
// owner changes to that of the NameWrapper but then the NameWrapper emits NameWrapped, and this
120+
// indexing code re-materializes the Domain.ownerId to the NameWraper-emitted value.
121+
await materializeENSv1DomainEffectiveOwner(context, domainId, owner);
121122
}
122123

123124
/**

packages/ensnode-schema/src/schemas/ensv2.schema.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ export const v1Domain = onchainTable(
174174
// represents a labelHash
175175
labelHash: t.hex().notNull().$type<LabelHash>(),
176176

177+
// may have a `rootRegistryOwner` (ENSv1Registry's owner()), zeroAddress interpreted as null
178+
rootRegistryOwnerId: t.hex().$type<Address>(),
179+
177180
// NOTE: Domain-Resolver Relations tracked via Protocol Acceleration plugin
178181
}),
179182
(t) => ({
@@ -190,6 +193,11 @@ export const relations_v1Domain = relations(v1Domain, ({ one, many }) => ({
190193
references: [v1Domain.id],
191194
}),
192195
children: many(v1Domain, { relationName: "parent" }),
196+
rootRegistryOwner: one(account, {
197+
relationName: "rootRegistryOwner",
198+
fields: [v1Domain.rootRegistryOwnerId],
199+
references: [account.id],
200+
}),
193201

194202
// shared
195203
owner: one(account, {

packages/ensnode-sdk/src/graphql-api/example-queries.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ query DomainByName($name: Name!) {
101101
label { interpreted }
102102
name
103103
104+
... on ENSv1Domain {
105+
rootRegistryOwner { address }
106+
}
107+
104108
... on ENSv2Domain {
105109
subregistry {
106110
contract { chainId address }

0 commit comments

Comments
 (0)