Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

demo(partial-index): demonstrate working queries on partial index #32

Closed
wants to merge 11 commits into from
3 changes: 3 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Default owners for everything in the repo

* @shrugs @tk-o @djstrong @BanaSeba @lightwalker-eth
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2023 NameHash

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ens-multichain indexer
# ENSNode

> powered by ponder
> a multichain ENS indexer, powered by Ponder

estimated backfill time @ 50rps = 24-36 hours on M1 Macbook (~10x speedup)

Expand All @@ -14,7 +14,7 @@ estimated backfill time @ 50rps = 24-36 hours on M1 Macbook (~10x speedup)
- 1:1 equivalency of results for queries via ensjs
- 100% ensjs, ens-app-v3 test suites passing
- should 'just work', following [this documentation](https://github.com/ensdomains/ensjs/blob/main/docs/basics/custom-subgraph-uris.md)
- ensjs equivalency confirmed via [ens-indexer-transition-tools](https://github.com/namehash/ens-indexer-transition-tools)
- ensjs equivalency confirmed via [ens-subgraph-transition-tools](https://github.com/namehash/ens-subgraph-transition-tools)
- v2 — **optimized multichain indexer w/ unified namespace**
- true multichain indexing (mainnet, base, linea, etc)
- flattened, unified, multichain namespace
Expand Down
18 changes: 16 additions & 2 deletions src/handlers/Registrar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ export const makeRegistrarHandlers = (ownedName: `${string}eth`) => {

const node = makeSubnodeNamehash(ownedSubnameNode, label);
const domain = await context.db.find(schema.domain, { id: node });
if (!domain) throw new Error("domain expected");
if (!domain) {
return;
}

if (domain.labelName !== name) {
await context.db
Expand Down Expand Up @@ -106,6 +108,12 @@ export const makeRegistrarHandlers = (ownedName: `${string}eth`) => {
const label = tokenIdToLabel(id);
const node = makeSubnodeNamehash(ownedSubnameNode, label);

const registration = await context.db.find(schema.registration, { id: label });

if (!registration) {
return;
}

await context.db.update(schema.registration, { id: label }).set({ expiryDate: expires });

await context.db
Expand Down Expand Up @@ -136,7 +144,13 @@ export const makeRegistrarHandlers = (ownedName: `${string}eth`) => {

await context.db.update(schema.registration, { id: label }).set({ registrantId: to });

await context.db.update(schema.domain, { id: node }).set({ registrantId: to });
const domain = await context.db.find(schema.domain, { id: node });

if (!domain) {
return;
}

await context.db.update(schema.domain, { id: domain.id }).set({ registrantId: to });

// TODO: log Event
},
Expand Down
31 changes: 26 additions & 5 deletions src/handlers/Registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,17 @@ function isDomainEmpty(domain: typeof schema.domain.$inferSelect) {
// https://github.com/ensdomains/ens-subgraph/blob/master/src/ensRegistry.ts#L64
async function recursivelyRemoveEmptyDomainFromParentSubdomainCount(context: Context, node: Hex) {
const domain = await context.db.find(schema.domain, { id: node });
if (!domain) throw new Error(`Domain not found: ${node}`);
if (!domain) {
return;
}

if (isDomainEmpty(domain) && domain.parentId !== null) {
const parent = await context.db.find(schema.domain, { id: domain.parentId });

if (!parent) {
return;
}

// decrement parent's subdomain count
await context.db
.update(schema.domain, { id: domain.parentId })
Expand Down Expand Up @@ -132,10 +140,16 @@ export const handleNewOwner =
isMigrated,
});

// and increment parent subdomainCount
await context.db
.update(schema.domain, { id: node })
.set((row) => ({ subdomainCount: row.subdomainCount + 1 }));
const parent = await context.db.find(schema.domain, { id: node });

// to support testing a partial-index use case,
// first ensure the parent domain exists before incrementing its subdomainCount
if (parent) {
// and increment parent subdomainCount
await context.db
.update(schema.domain, { id: parent.id })
.set((row) => ({ subdomainCount: row.subdomainCount + 1 }));
}
}

// if the domain doesn't yet have a name, construct it here
Expand Down Expand Up @@ -206,6 +220,13 @@ export async function handleNewResolver({
})
.onConflictDoNothing();

const domain = await context.db.find(schema.domain, { id: node });

if (!domain) {
console.error(`Domain not found: ${node}`);
return;
}

// update the domain to point to it, and denormalize the eth addr
await context.db
.update(schema.domain, { id: node })
Expand Down
4 changes: 3 additions & 1 deletion src/handlers/Resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,9 @@ export async function handleVersionChanged({
const { node } = event.args;
const id = makeResolverId(node, event.log.address);
const domain = await context.db.find(schema.domain, { id: node });
if (!domain) throw new Error("domain expected");
if (!domain) {
return;
}

// materialize the Domain's resolvedAddress field
if (domain.resolverId === id) {
Expand Down
20 changes: 14 additions & 6 deletions src/plugins/base.eth/ponder.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@ export const ownedName = "base.eth" as const;

export const pluginNamespace = createPluginNamespace(ownedName);

// demo for `0xtko.base.eth`
// minted at block: 24_944_153

// constrain the ponder indexing between the following start/end blocks
// https://ponder.sh/0_6/docs/contracts-and-networks#block-range
const START_BLOCK: ContractConfig["startBlock"] = undefined;
const START_BLOCK: ContractConfig["startBlock"] = 24_943_153;
const END_BLOCK: ContractConfig["endBlock"] = undefined;

export const config = createConfig({
Expand All @@ -32,7 +35,8 @@ export const config = createConfig({
network: "base",
abi: Registry,
address: "0xb94704422c2a1e396835a571837aa5ae53285a95",
...blockConfig(START_BLOCK, 17571480, END_BLOCK),
startBlock: START_BLOCK,
endBlock: END_BLOCK,
},
[pluginNamespace("Resolver")]: {
network: "base",
Expand All @@ -42,25 +46,29 @@ export const config = createConfig({
event: getAbiItem({ abi: Registry, name: "NewResolver" }),
parameter: "resolver",
}),
...blockConfig(START_BLOCK, 17575714, END_BLOCK),
startBlock: START_BLOCK,
endBlock: END_BLOCK,
},
[pluginNamespace("BaseRegistrar")]: {
network: "base",
abi: BaseRegistrar,
address: "0x03c4738Ee98aE44591e1A4A4F3CaB6641d95DD9a",
...blockConfig(START_BLOCK, 17571486, END_BLOCK),
startBlock: START_BLOCK,
endBlock: END_BLOCK,
},
[pluginNamespace("EARegistrarController")]: {
network: "base",
abi: EarlyAccessRegistrarController,
address: "0xd3e6775ed9b7dc12b205c8e608dc3767b9e5efda",
...blockConfig(START_BLOCK, 17575699, END_BLOCK),
startBlock: START_BLOCK,
endBlock: END_BLOCK,
},
[pluginNamespace("RegistrarController")]: {
network: "base",
abi: RegistrarController,
address: "0x4cCb0BB02FCABA27e82a56646E81d8c5bC4119a5",
...blockConfig(START_BLOCK, 18619035, END_BLOCK),
startBlock: START_BLOCK,
endBlock: END_BLOCK,
},
},
});
Expand Down
29 changes: 20 additions & 9 deletions src/plugins/eth/ponder.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@ export const ownedName = "eth";

export const pluginNamespace = createPluginNamespace(ownedName);

// demo for `didsendit.eth`
// minted at block: 21_610_362

// constrain the ponder indexing between the following start/end blocks
// https://ponder.sh/0_6/docs/contracts-and-networks#block-range
const START_BLOCK: ContractConfig["startBlock"] = undefined;
const START_BLOCK: ContractConfig["startBlock"] = 21_610_262;
const END_BLOCK: ContractConfig["endBlock"] = undefined;

export const config = createConfig({
Expand All @@ -36,13 +39,15 @@ export const config = createConfig({
network: "mainnet",
abi: Registry,
address: "0x314159265dd8dbb310642f98f50c066173c1259b",
...blockConfig(START_BLOCK, 3327417, END_BLOCK),
startBlock: START_BLOCK,
endBlock: END_BLOCK,
},
[pluginNamespace("Registry")]: {
network: "mainnet",
abi: Registry,
address: "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e",
...blockConfig(START_BLOCK, 9380380, END_BLOCK),
startBlock: START_BLOCK,
endBlock: END_BLOCK,
},
[pluginNamespace("OldRegistryResolvers")]: {
network: "mainnet",
Expand All @@ -52,7 +57,8 @@ export const config = createConfig({
event: getAbiItem({ abi: Registry, name: "NewResolver" }),
parameter: "resolver",
}),
...blockConfig(START_BLOCK, 9380380, END_BLOCK),
startBlock: START_BLOCK,
endBlock: END_BLOCK,
},
[pluginNamespace("Resolver")]: {
network: "mainnet",
Expand All @@ -62,31 +68,36 @@ export const config = createConfig({
event: getAbiItem({ abi: Registry, name: "NewResolver" }),
parameter: "resolver",
}),
...blockConfig(START_BLOCK, 9380380, END_BLOCK),
startBlock: START_BLOCK,
endBlock: END_BLOCK,
},
[pluginNamespace("BaseRegistrar")]: {
network: "mainnet",
abi: BaseRegistrar,
address: "0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85",
...blockConfig(START_BLOCK, 9380410, END_BLOCK),
startBlock: START_BLOCK,
endBlock: END_BLOCK,
},
[pluginNamespace("EthRegistrarControllerOld")]: {
network: "mainnet",
abi: EthRegistrarControllerOld,
address: "0x283Af0B28c62C092C9727F1Ee09c02CA627EB7F5",
...blockConfig(START_BLOCK, 9380471, END_BLOCK),
startBlock: START_BLOCK,
endBlock: END_BLOCK,
},
[pluginNamespace("EthRegistrarController")]: {
network: "mainnet",
abi: EthRegistrarController,
address: "0x253553366Da8546fC250F225fe3d25d0C782303b",
...blockConfig(START_BLOCK, 16925618, END_BLOCK),
startBlock: START_BLOCK,
endBlock: END_BLOCK,
},
[pluginNamespace("NameWrapper")]: {
network: "mainnet",
abi: NameWrapper,
address: "0xD4416b13d2b3a9aBae7AcD5D6C2BbDBE25686401",
...blockConfig(START_BLOCK, 16925608, END_BLOCK),
startBlock: START_BLOCK,
endBlock: END_BLOCK,
},
},
});
Expand Down
20 changes: 14 additions & 6 deletions src/plugins/linea.eth/ponder.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@ export const ownedName = "linea.eth";

export const pluginNamespace = createPluginNamespace(ownedName);

// demo for `0xtko.linea.eth`
// minted at block: 14_491_235

// constrain the ponder indexing between the following start/end blocks
// https://ponder.sh/0_6/docs/contracts-and-networks#block-range
const START_BLOCK: ContractConfig["startBlock"] = undefined;
const START_BLOCK: ContractConfig["startBlock"] = 14_490_000;
const END_BLOCK: ContractConfig["endBlock"] = undefined;

export const config = createConfig({
Expand All @@ -32,7 +35,8 @@ export const config = createConfig({
network: "linea",
abi: Registry,
address: "0x50130b669B28C339991d8676FA73CF122a121267",
...blockConfig(START_BLOCK, 6682888, END_BLOCK),
startBlock: START_BLOCK,
endBlock: END_BLOCK,
},
[pluginNamespace("Resolver")]: {
network: "linea",
Expand All @@ -42,25 +46,29 @@ export const config = createConfig({
event: getAbiItem({ abi: Registry, name: "NewResolver" }),
parameter: "resolver",
}),
...blockConfig(START_BLOCK, 6682888, END_BLOCK),
startBlock: START_BLOCK,
endBlock: END_BLOCK,
},
[pluginNamespace("BaseRegistrar")]: {
network: "linea",
abi: BaseRegistrar,
address: "0x6e84390dCc5195414eC91A8c56A5c91021B95704",
...blockConfig(START_BLOCK, 6682892, END_BLOCK),
startBlock: START_BLOCK,
endBlock: END_BLOCK,
},
[pluginNamespace("EthRegistrarController")]: {
network: "linea",
abi: EthRegistrarController,
address: "0xDb75Db974B1F2bD3b5916d503036208064D18295",
...blockConfig(START_BLOCK, 6682978, END_BLOCK),
startBlock: START_BLOCK,
endBlock: END_BLOCK,
},
[pluginNamespace("NameWrapper")]: {
network: "linea",
abi: NameWrapper,
address: "0xA53cca02F98D590819141Aa85C891e2Af713C223",
...blockConfig(START_BLOCK, 6682956, END_BLOCK),
startBlock: START_BLOCK,
endBlock: END_BLOCK,
},
},
});
Expand Down