Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/ensindexer/ponder.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { deepMergeRecursive } from "./src/lib/ponder-helpers";
import type { PluginName } from "./src/lib/types";

import * as baseEthPlugin from "./src/plugins/base/ponder.plugin";
import * as ensV2Plugin from "./src/plugins/ens-v2/ponder.plugin";
import * as ethPlugin from "./src/plugins/eth/ponder.plugin";
import * as lineaEthPlugin from "./src/plugins/linea/ponder.plugin";

Expand All @@ -12,7 +13,7 @@ import * as lineaEthPlugin from "./src/plugins/linea/ponder.plugin";
// so ponder's typechecking of the indexing handlers and their event arguments is correct.
////////

const ALL_PLUGINS = [ethPlugin, baseEthPlugin, lineaEthPlugin] as const;
const ALL_PLUGINS = [ethPlugin, baseEthPlugin, lineaEthPlugin, ensV2Plugin] as const;

type AllPluginConfigs = MergedTypes<(typeof ALL_PLUGINS)[number]["config"]>;

Expand Down
7 changes: 5 additions & 2 deletions apps/ensindexer/src/lib/globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import { getEnsDeploymentChain } from "./ponder-helpers";
export const SELECTED_DEPLOYMENT_CONFIG = DeploymentConfigs[getEnsDeploymentChain()];

/**
* Note that here, we define the global DEPLOYMENT_CONFIG as the _merge_ of mainnet (which fully
* specifies all plugin configs), overrided with the SELECTED_DEPLOYMENT_CONFIG.
* Note that here, we define the global DEPLOYMENT_CONFIG as the _merge_ of all possible deployments
* (therefore fully specifying all plugin configs), overrided with the SELECTED_DEPLOYMENT_CONFIG.
*
* This ensures that at type-check-time and in `ALL_PLUGINS` every plugin's `config` has valid values
* (and therefore its type can continue to be inferred). This means that initially upon building the
Expand All @@ -26,6 +26,9 @@ export const SELECTED_DEPLOYMENT_CONFIG = DeploymentConfigs[getEnsDeploymentChai
*/
export const DEPLOYMENT_CONFIG = {
...DeploymentConfigs.mainnet,
...DeploymentConfigs.sepolia,
...DeploymentConfigs.holesky,
...DeploymentConfigs["ens-test-env"],
...SELECTED_DEPLOYMENT_CONFIG,
};

Expand Down
2 changes: 1 addition & 1 deletion apps/ensindexer/src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ export type OwnedName = string;
* @ensnode/ens-deployments SubregistryName, simplifying the relationship between an ENSDeploymentConfig
* and the plugins in this project.
*/
export type PluginName = "eth" | "base" | "linea";
export type PluginName = "eth" | "base" | "linea" | "ens-v2";
54 changes: 54 additions & 0 deletions apps/ensindexer/src/plugins/ens-v2/handlers/EthRegistry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { ponder } from "ponder:registry";
import schema from "ponder:schema";

import { PonderENSPluginHandlerArgs } from "../../../lib/plugin-helpers";
import { createDomainId, createEventId, generateTokenId, updateDomainLabel } from "../v2-lib";

export default function ({ namespace }: PonderENSPluginHandlerArgs<"ens-v2">) {
ponder.on(namespace("EthRegistry:TransferSingle"), async ({ event, context }) => {
console.log("EthRegistry:TransferSingle", event.transaction.to);
const timestamp = event.block.timestamp;
const labelHash = event.args.id.toString();
const domainId = createDomainId(event.transaction.to?.toString(), labelHash);

await context.db.insert(schema.v2_domain).values({
id: domainId,
labelHash: labelHash,
owner: event.args.to.toString(),
registry: event.transaction.to?.toString(),
createdAt: timestamp,
updatedAt: timestamp,
});

// Store the event data
const eventId = createEventId(event);
await context.db.insert(schema.v2_transferSingleEvent).values({
id: eventId,
registryId: event.transaction.to?.toString(),
tokenId: event.args.id.toString(),
from: event.args.from.toString(),
to: event.args.to.toString(),
value: event.args.value,
source: "EthRegistry",
createdAt: timestamp,
updatedAt: timestamp,
});
});

ponder.on(namespace("EthRegistry:NewSubname"), async ({ event, context }) => {
console.log("EthRegistry:NewSubname", event.transaction.to);
const tokenId = generateTokenId(event.args.label);
const registryId = event.transaction.to?.toString();
const domainId = createDomainId(registryId, tokenId);

await updateDomainLabel(
context,
domainId,
event.args.label,
tokenId,
event.block.timestamp,
event,
"EthRegistry",
);
});
}
26 changes: 26 additions & 0 deletions apps/ensindexer/src/plugins/ens-v2/handlers/OwnedResolver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { ponder } from "ponder:registry";
import schema from "ponder:schema";

import { PonderENSPluginHandlerArgs } from "../../../lib/plugin-helpers";

export default function ({ namespace }: PonderENSPluginHandlerArgs<"ens-v2">) {
ponder.on(namespace("OwnedResolver:AddressChanged"), async ({ event, context }) => {
const timestamp = event.block.timestamp;
const resolverId = event.transaction.to?.toString();
if (!resolverId) return;

console.log("OwnedResolver:AddressChanged", event.args, resolverId);
const record = await context.db.find(schema.v2_resolver, { id: resolverId });
if (record) {
console.log("OwnedResolver:AddressChanged", "Record found", record);
await context.db.update(schema.v2_resolver, { id: record.id }).set({
...record,
address: event.args.newAddress.toString(),
updatedAt: timestamp,
node: event.args.node.toString(),
});
} else {
console.log("OwnedResolver:AddressChanged", "No record found");
}
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { ponder } from "ponder:registry";
import schema from "ponder:schema";

import { PonderENSPluginHandlerArgs } from "../../../lib/plugin-helpers";
import { createEventId } from "../v2-lib";

export default function ({ namespace }: PonderENSPluginHandlerArgs<"ens-v2">) {
ponder.on(namespace("RegistryDatastore:SubregistryUpdate"), async ({ context, event }) => {
console.log("RegistryDatastore:SubregistryUpdate", event.args);
const timestamp = event.block.timestamp;
await context.db.insert(schema.v2_registry).values({
id: event.args.registry.toString(),
labelHash: event.args.labelHash.toString(),
subregistryId: event.args.subregistry,
flags: event.args.flags,
createdAt: timestamp,
updatedAt: timestamp,
});
console.log(event);
const eventId = createEventId(event);
await context.db.insert(schema.v2_subregistryUpdateEvent).values({
id: eventId,
registryId: event.args.registry.toString(),
labelHash: event.args.labelHash.toString(),
subregistryId: event.args.subregistry,
flags: event.args.flags,
createdAt: timestamp,
updatedAt: timestamp,
});
});

ponder.on(namespace("RegistryDatastore:ResolverUpdate"), async ({ context, event }) => {
console.log("RegistryDatastore:ResolverUpdate", event.args);
const timestamp = event.block.timestamp;
const record2 = await context.db.find(schema.v2_registry, {
id: event.args.registry.toString(),
});
if (record2) {
console.log("RegistryDatastore:ResolverUpdate", "Record found", record2);
await context.db
.update(schema.v2_registry, { id: record2.id })
.set({ ...record2, resolver: event.args.resolver.toString() });

const record3 = await context.db.find(schema.v2_resolver, {
id: event.args.resolver.toString(),
});
if (!record3) {
console.log("RegistryDatastore:ResolverUpdate", "Creating new resolver record");
await context.db.insert(schema.v2_resolver).values({
id: event.args.resolver.toString(),
createdAt: timestamp,
updatedAt: timestamp,
});
}
} else {
console.log("RegistryDatastore:ResolverUpdate", "No record found");
}

// Store the event data
const eventId = createEventId(event);
await context.db.insert(schema.v2_resolverUpdateEvent).values({
id: eventId,
registryId: event.args.registry.toString(),
labelHash: event.args.labelHash.toString(),
resolverId: event.args.resolver.toString(),
flags: event.args.flags,
createdAt: timestamp,
updatedAt: timestamp,
});
});
}
54 changes: 54 additions & 0 deletions apps/ensindexer/src/plugins/ens-v2/handlers/RootRegistry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { ponder } from "ponder:registry";
import schema from "ponder:schema";

import { PonderENSPluginHandlerArgs } from "../../../lib/plugin-helpers";
import { createDomainId, createEventId, generateTokenId, updateDomainLabel } from "../v2-lib";

export default function ({ namespace }: PonderENSPluginHandlerArgs<"ens-v2">) {
ponder.on(namespace("RootRegistry:TransferSingle"), async ({ event, context }) => {
const timestamp = event.block.timestamp;
const tokenId = event.args.id.toString();
const registryId = event.transaction.to?.toString();
const domainId = createDomainId(registryId, tokenId);
const values = {
id: domainId,
labelHash: tokenId,
owner: event.args.to.toString(),
registry: registryId,
createdAt: timestamp,
updatedAt: timestamp,
};
console.log("RootRegistry:TransferSingle", values);
await context.db.insert(schema.v2_domain).values(values);
// Store the event data
const eventId = createEventId(event);
await context.db.insert(schema.v2_transferSingleEvent).values({
id: eventId,
registryId: registryId,
tokenId: tokenId,
from: event.args.from.toString(),
to: event.args.to.toString(),
value: event.args.value,
source: "RootRegistry",
createdAt: timestamp,
updatedAt: timestamp,
});
});

ponder.on(namespace("RootRegistry:NewSubname"), async ({ event, context }) => {
console.log("RootRegistry:NewSubname", event.transaction.to);
const tokenId = generateTokenId(event.args.label);
const registryId = event.transaction.to?.toString();
const domainId = createDomainId(registryId, tokenId);

await updateDomainLabel(
context,
domainId,
event.args.label,
tokenId,
event.block.timestamp,
event,
"RootRegistry",
);
});
}
46 changes: 46 additions & 0 deletions apps/ensindexer/src/plugins/ens-v2/ponder.plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { createConfig } from "ponder";
import { DEPLOYMENT_CONFIG } from "../../lib/globals";
import {
activateHandlers,
createPluginNamespace,
networkConfigForContract,
networksConfigForChain,
} from "../../lib/plugin-helpers";

export const pluginName = "ens-v2" as const;

const { chain, contracts } = DEPLOYMENT_CONFIG[pluginName];
const namespace = createPluginNamespace(pluginName);

export const config = createConfig({
networks: networksConfigForChain(chain),
contracts: {
[namespace("EthRegistry")]: {
network: networkConfigForContract(chain, contracts.EthRegistry),
abi: contracts.EthRegistry.abi,
},
[namespace("RegistryDatastore")]: {
network: networkConfigForContract(chain, contracts.RegistryDatastore),
abi: contracts.RegistryDatastore.abi,
},
[namespace("RootRegistry")]: {
network: networkConfigForContract(chain, contracts.RootRegistry),
abi: contracts.RootRegistry.abi,
},
[namespace("OwnedResolver")]: {
network: networkConfigForContract(chain, contracts.OwnedResolver),
abi: contracts.OwnedResolver.abi,
},
},
});

export const activate = activateHandlers({
ownedName: pluginName,
namespace,
handlers: [
import("./handlers/EthRegistry"),
import("./handlers/RegistryDatastore"),
import("./handlers/RootRegistry"),
import("./handlers/OwnedResolver"),
],
});
Loading