diff --git a/apps/ensindexer/ponder.config.ts b/apps/ensindexer/ponder.config.ts index 6212e9916..8d0d62f45 100644 --- a/apps/ensindexer/ponder.config.ts +++ b/apps/ensindexer/ponder.config.ts @@ -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"; @@ -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"]>; diff --git a/apps/ensindexer/src/lib/globals.ts b/apps/ensindexer/src/lib/globals.ts index 14f38c0ff..0c0f7aff5 100644 --- a/apps/ensindexer/src/lib/globals.ts +++ b/apps/ensindexer/src/lib/globals.ts @@ -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 @@ -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, }; diff --git a/apps/ensindexer/src/lib/types.ts b/apps/ensindexer/src/lib/types.ts index ab63e50f7..3e16a3db7 100644 --- a/apps/ensindexer/src/lib/types.ts +++ b/apps/ensindexer/src/lib/types.ts @@ -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"; diff --git a/apps/ensindexer/src/plugins/ens-v2/handlers/EthRegistry.ts b/apps/ensindexer/src/plugins/ens-v2/handlers/EthRegistry.ts new file mode 100644 index 000000000..28909e880 --- /dev/null +++ b/apps/ensindexer/src/plugins/ens-v2/handlers/EthRegistry.ts @@ -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", + ); + }); +} diff --git a/apps/ensindexer/src/plugins/ens-v2/handlers/OwnedResolver.ts b/apps/ensindexer/src/plugins/ens-v2/handlers/OwnedResolver.ts new file mode 100644 index 000000000..ae2db4f69 --- /dev/null +++ b/apps/ensindexer/src/plugins/ens-v2/handlers/OwnedResolver.ts @@ -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"); + } + }); +} diff --git a/apps/ensindexer/src/plugins/ens-v2/handlers/RegistryDatastore.ts b/apps/ensindexer/src/plugins/ens-v2/handlers/RegistryDatastore.ts new file mode 100644 index 000000000..8254be625 --- /dev/null +++ b/apps/ensindexer/src/plugins/ens-v2/handlers/RegistryDatastore.ts @@ -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, + }); + }); +} diff --git a/apps/ensindexer/src/plugins/ens-v2/handlers/RootRegistry.ts b/apps/ensindexer/src/plugins/ens-v2/handlers/RootRegistry.ts new file mode 100644 index 000000000..a5f1d973a --- /dev/null +++ b/apps/ensindexer/src/plugins/ens-v2/handlers/RootRegistry.ts @@ -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", + ); + }); +} diff --git a/apps/ensindexer/src/plugins/ens-v2/ponder.plugin.ts b/apps/ensindexer/src/plugins/ens-v2/ponder.plugin.ts new file mode 100644 index 000000000..bc0eca30f --- /dev/null +++ b/apps/ensindexer/src/plugins/ens-v2/ponder.plugin.ts @@ -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"), + ], +}); diff --git a/apps/ensindexer/src/plugins/ens-v2/v2-lib.ts b/apps/ensindexer/src/plugins/ens-v2/v2-lib.ts new file mode 100644 index 000000000..0e7d77100 --- /dev/null +++ b/apps/ensindexer/src/plugins/ens-v2/v2-lib.ts @@ -0,0 +1,123 @@ +/** + * This file temporarily located here for prototyping—should be moved to ensnode-utils. + */ + +import { Context, Event } from "ponder:registry"; +import schema from "ponder:schema"; +import { eq } from "ponder"; +import { keccak256, toBytes } from "viem"; + +const LABEL_HASH_MASK = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000n; + +// Utility functions +export function createEventId(event: Event): string { + return [event.block.number, event.log.logIndex].join("-"); +} + +export function generateTokenId(label: string): string { + const hash = keccak256(toBytes(label)); + + // Convert the hash to BigInt and perform the bitwise operation + const hashBigInt = BigInt(hash); + const mask = BigInt(0x7); + const tokenId = hashBigInt & ~mask; // Equivalent to & ~0x7 + console.log("generateTokenId", label, hash, tokenId); + return tokenId.toString(); +} + +export function createDomainId(registryId: string | undefined, tokenId: string): string { + return `${registryId}-${tokenId}`; +} + +export async function updateDomainLabel( + context: Context, + domainId: string, + label: string, + tokenId: string, + timestamp: bigint, + event: any, + source: string, +) { + const domainRecord = await context.db.find(schema.v2_domain, { id: domainId }); + if (!domainRecord) { + console.log("Domain not found:", domainId); + return; + } + + console.log("Updating domain label:", domainRecord); + + // Update registry database if exists + const labelHash = BigInt(tokenId) & LABEL_HASH_MASK; + const registryRecord = await context.db.sql.query.v2_registry.findFirst({ + where: eq(schema.v2_registry.labelHash, labelHash.toString()), + }); + + if (registryRecord) { + console.log("Registry record found:", registryRecord); + await context.db + .update(schema.v2_registry, { id: registryRecord.id }) + .set({ ...registryRecord, label: label }); + } + let name = label; + if (source != "RootRegistry") { + let currentRegistryId = registryRecord!.id; + let currentName = name; + + while (true) { + const parentRegistryRecord = await context.db.sql.query.v2_registry.findFirst({ + where: eq(schema.v2_registry.subregistryId, currentRegistryId), + }); + + if (!parentRegistryRecord) { + break; // We've reached the top level + } + + console.log("Parent registry record found:", parentRegistryRecord); + let parentDomainRecord = await context.db.sql.query.v2_domain.findFirst({ + where: eq(schema.v2_domain.registry, parentRegistryRecord.id), + }); + + if (!parentDomainRecord) break; + + console.log("Parent domain record found:", parentDomainRecord); + + if (parentDomainRecord.isTld) { + currentName = currentName + "." + parentDomainRecord.label; + console.log("Reached TLD. Final name:", currentName); + break; + } + + currentName = currentName + "." + parentDomainRecord.label; + currentRegistryId = parentRegistryRecord.id; + console.log("Current name:", currentName); + } + + name = currentName; + } + // Update the domain record + const nameArray = domainRecord.name ? [...domainRecord.name, name] : [name]; + const newDomainRecord = { + ...domainRecord, + label: label, + name: nameArray, + labelHash: tokenId, + isTld: source === "RootRegistry" ? true : false, + updatedAt: timestamp, + }; + + await context.db.update(schema.v2_domain, { id: domainId }).set(newDomainRecord); + + // Store the event data + const eventId = createEventId(event); + await context.db.insert(schema.v2_newSubnameEvent).values({ + id: eventId, + registryId: domainRecord.registry, + label: label, + labelHash: tokenId, + source: source, + createdAt: timestamp, + updatedAt: timestamp, + }); + + console.log("Domain updated:", domainId); +} diff --git a/packages/ens-deployments/package.json b/packages/ens-deployments/package.json index cc5a40e87..54c660717 100644 --- a/packages/ens-deployments/package.json +++ b/packages/ens-deployments/package.json @@ -33,6 +33,7 @@ "devDependencies": { "@biomejs/biome": "catalog:", "@ensnode/shared-configs": "workspace:", + "ponder": "catalog:", "tsup": "catalog:", "typescript": "catalog:", "viem": "catalog:" diff --git a/packages/ens-deployments/src/abis/ens-v2/ETHRegistry.ts b/packages/ens-deployments/src/abis/ens-v2/ETHRegistry.ts new file mode 100644 index 000000000..49cf8d8bb --- /dev/null +++ b/packages/ens-deployments/src/abis/ens-v2/ETHRegistry.ts @@ -0,0 +1,1067 @@ +export const ETHRegistry = [ + { + inputs: [ + { + internalType: "contract IRegistryDatastore", + name: "_datastore", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + inputs: [], + name: "AccessControlBadConfirmation", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + { + internalType: "bytes32", + name: "neededRole", + type: "bytes32", + }, + ], + name: "AccessControlUnauthorizedAccount", + type: "error", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "caller", + type: "address", + }, + ], + name: "AccessDenied", + type: "error", + }, + { + inputs: [ + { + internalType: "uint64", + name: "oldExpiration", + type: "uint64", + }, + { + internalType: "uint64", + name: "newExpiration", + type: "uint64", + }, + ], + name: "CannotReduceExpiration", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address", + }, + { + internalType: "uint256", + name: "balance", + type: "uint256", + }, + { + internalType: "uint256", + name: "needed", + type: "uint256", + }, + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "ERC1155InsufficientBalance", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "approver", + type: "address", + }, + ], + name: "ERC1155InvalidApprover", + type: "error", + }, + { + inputs: [ + { + internalType: "uint256", + name: "idsLength", + type: "uint256", + }, + { + internalType: "uint256", + name: "valuesLength", + type: "uint256", + }, + ], + name: "ERC1155InvalidArrayLength", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "operator", + type: "address", + }, + ], + name: "ERC1155InvalidOperator", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "receiver", + type: "address", + }, + ], + name: "ERC1155InvalidReceiver", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "ERC1155InvalidSender", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "operator", + type: "address", + }, + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "ERC1155MissingApprovalForAll", + type: "error", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + { + internalType: "uint96", + name: "flags", + type: "uint96", + }, + { + internalType: "uint96", + name: "expected", + type: "uint96", + }, + ], + name: "InvalidResolverFlags", + type: "error", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + { + internalType: "uint96", + name: "flags", + type: "uint96", + }, + { + internalType: "uint96", + name: "expected", + type: "uint96", + }, + ], + name: "InvalidSubregistryFlags", + type: "error", + }, + { + inputs: [ + { + internalType: "string", + name: "label", + type: "string", + }, + ], + name: "NameAlreadyRegistered", + type: "error", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "NameExpired", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "approved", + type: "address", + }, + { + indexed: true, + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "account", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "operator", + type: "address", + }, + { + indexed: false, + internalType: "bool", + name: "approved", + type: "bool", + }, + ], + name: "ApprovalForAll", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "string", + name: "label", + type: "string", + }, + ], + name: "NewSubname", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "bytes32", + name: "role", + type: "bytes32", + }, + { + indexed: true, + internalType: "bytes32", + name: "previousAdminRole", + type: "bytes32", + }, + { + indexed: true, + internalType: "bytes32", + name: "newAdminRole", + type: "bytes32", + }, + ], + name: "RoleAdminChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "bytes32", + name: "role", + type: "bytes32", + }, + { + indexed: true, + internalType: "address", + name: "account", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "RoleGranted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "bytes32", + name: "role", + type: "bytes32", + }, + { + indexed: true, + internalType: "address", + name: "account", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "RoleRevoked", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "operator", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "from", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "to", + type: "address", + }, + { + indexed: false, + internalType: "uint256[]", + name: "ids", + type: "uint256[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + ], + name: "TransferBatch", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "operator", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "from", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "to", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "id", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "TransferSingle", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "string", + name: "value", + type: "string", + }, + { + indexed: true, + internalType: "uint256", + name: "id", + type: "uint256", + }, + ], + name: "URI", + type: "event", + }, + { + inputs: [], + name: "DEFAULT_ADMIN_ROLE", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "FLAGS_MASK", + outputs: [ + { + internalType: "uint96", + name: "", + type: "uint96", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "FLAG_FLAGS_LOCKED", + outputs: [ + { + internalType: "uint96", + name: "", + type: "uint96", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "FLAG_RESOLVER_LOCKED", + outputs: [ + { + internalType: "uint96", + name: "", + type: "uint96", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "FLAG_SUBREGISTRY_LOCKED", + outputs: [ + { + internalType: "uint96", + name: "", + type: "uint96", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "REGISTRAR_ROLE", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + { + internalType: "uint256", + name: "id", + type: "uint256", + }, + ], + name: "balanceOf", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address[]", + name: "accounts", + type: "address[]", + }, + { + internalType: "uint256[]", + name: "ids", + type: "uint256[]", + }, + ], + name: "balanceOfBatch", + outputs: [ + { + internalType: "uint256[]", + name: "", + type: "uint256[]", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "datastore", + outputs: [ + { + internalType: "contract IRegistryDatastore", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "flags", + outputs: [ + { + internalType: "uint96", + name: "", + type: "uint96", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "string", + name: "label", + type: "string", + }, + ], + name: "getResolver", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "role", + type: "bytes32", + }, + ], + name: "getRoleAdmin", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "string", + name: "label", + type: "string", + }, + ], + name: "getSubregistry", + outputs: [ + { + internalType: "contract IRegistry", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "role", + type: "bytes32", + }, + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "grantRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "role", + type: "bytes32", + }, + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "hasRole", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + { + internalType: "address", + name: "operator", + type: "address", + }, + ], + name: "isApprovedForAll", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + { + internalType: "uint96", + name: "flags", + type: "uint96", + }, + ], + name: "lock", + outputs: [ + { + internalType: "uint256", + name: "newTokenId", + type: "uint256", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "nameData", + outputs: [ + { + internalType: "uint64", + name: "expiry", + type: "uint64", + }, + { + internalType: "uint32", + name: "flags", + type: "uint32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "ownerOf", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "string", + name: "label", + type: "string", + }, + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "contract IRegistry", + name: "registry", + type: "address", + }, + { + internalType: "uint96", + name: "flags", + type: "uint96", + }, + { + internalType: "uint64", + name: "expires", + type: "uint64", + }, + ], + name: "register", + outputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + { + internalType: "uint64", + name: "expires", + type: "uint64", + }, + ], + name: "renew", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "role", + type: "bytes32", + }, + { + internalType: "address", + name: "callerConfirmation", + type: "address", + }, + ], + name: "renounceRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "role", + type: "bytes32", + }, + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "revokeRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256[]", + name: "ids", + type: "uint256[]", + }, + { + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + internalType: "bytes", + name: "data", + type: "bytes", + }, + ], + name: "safeBatchTransferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "id", + type: "uint256", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + { + internalType: "bytes", + name: "data", + type: "bytes", + }, + ], + name: "safeTransferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "operator", + type: "address", + }, + { + internalType: "bool", + name: "approved", + type: "bool", + }, + ], + name: "setApprovalForAll", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + { + internalType: "address", + name: "resolver", + type: "address", + }, + ], + name: "setResolver", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + { + internalType: "contract IRegistry", + name: "registry", + type: "address", + }, + ], + name: "setSubregistry", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes4", + name: "interfaceId", + type: "bytes4", + }, + ], + name: "supportsInterface", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + name: "uri", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "pure", + type: "function", + }, +] as const; diff --git a/packages/ens-deployments/src/abis/ens-v2/OwnedResolver.ts b/packages/ens-deployments/src/abis/ens-v2/OwnedResolver.ts new file mode 100644 index 000000000..2e161c1e6 --- /dev/null +++ b/packages/ens-deployments/src/abis/ens-v2/OwnedResolver.ts @@ -0,0 +1,1033 @@ +export const OwnedResolver = [ + { + inputs: [ + { + internalType: "address", + name: "target", + type: "address", + }, + ], + name: "AddressEmptyCode", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "implementation", + type: "address", + }, + ], + name: "ERC1967InvalidImplementation", + type: "error", + }, + { + inputs: [], + name: "ERC1967NonPayable", + type: "error", + }, + { + inputs: [], + name: "FailedCall", + type: "error", + }, + { + inputs: [], + name: "InvalidInitialization", + type: "error", + }, + { + inputs: [], + name: "NotInitializing", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "OwnableInvalidOwner", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "OwnableUnauthorizedAccount", + type: "error", + }, + { + inputs: [], + name: "UUPSUnauthorizedCallContext", + type: "error", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "slot", + type: "bytes32", + }, + ], + name: "UUPSUnsupportedProxiableUUID", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + indexed: true, + internalType: "uint256", + name: "contentType", + type: "uint256", + }, + ], + name: "ABIChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + indexed: false, + internalType: "address", + name: "a", + type: "address", + }, + ], + name: "AddrChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + indexed: false, + internalType: "uint256", + name: "coinType", + type: "uint256", + }, + { + indexed: false, + internalType: "bytes", + name: "newAddress", + type: "bytes", + }, + ], + name: "AddressChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + indexed: false, + internalType: "bytes", + name: "hash", + type: "bytes", + }, + ], + name: "ContenthashChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + indexed: false, + internalType: "bytes", + name: "name", + type: "bytes", + }, + { + indexed: false, + internalType: "uint16", + name: "resource", + type: "uint16", + }, + { + indexed: false, + internalType: "bytes", + name: "record", + type: "bytes", + }, + ], + name: "DNSRecordChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + indexed: false, + internalType: "bytes", + name: "name", + type: "bytes", + }, + { + indexed: false, + internalType: "uint16", + name: "resource", + type: "uint16", + }, + ], + name: "DNSRecordDeleted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + indexed: false, + internalType: "bytes", + name: "lastzonehash", + type: "bytes", + }, + { + indexed: false, + internalType: "bytes", + name: "zonehash", + type: "bytes", + }, + ], + name: "DNSZonehashChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint64", + name: "version", + type: "uint64", + }, + ], + name: "Initialized", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + indexed: true, + internalType: "bytes4", + name: "interfaceID", + type: "bytes4", + }, + { + indexed: false, + internalType: "address", + name: "implementer", + type: "address", + }, + ], + name: "InterfaceChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + indexed: false, + internalType: "string", + name: "name", + type: "string", + }, + ], + name: "NameChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "previousOwner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "OwnershipTransferred", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + indexed: false, + internalType: "bytes32", + name: "x", + type: "bytes32", + }, + { + indexed: false, + internalType: "bytes32", + name: "y", + type: "bytes32", + }, + ], + name: "PubkeyChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + indexed: true, + internalType: "string", + name: "indexedKey", + type: "string", + }, + { + indexed: false, + internalType: "string", + name: "key", + type: "string", + }, + { + indexed: false, + internalType: "string", + name: "value", + type: "string", + }, + ], + name: "TextChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "implementation", + type: "address", + }, + ], + name: "Upgraded", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + indexed: false, + internalType: "uint64", + name: "newVersion", + type: "uint64", + }, + ], + name: "VersionChanged", + type: "event", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + internalType: "uint256", + name: "contentTypes", + type: "uint256", + }, + ], + name: "ABI", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + { + internalType: "bytes", + name: "", + type: "bytes", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "UPGRADE_INTERFACE_VERSION", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + ], + name: "addr", + outputs: [ + { + internalType: "address payable", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + internalType: "uint256", + name: "coinType", + type: "uint256", + }, + ], + name: "addr", + outputs: [ + { + internalType: "bytes", + name: "", + type: "bytes", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + ], + name: "clearRecords", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + ], + name: "contenthash", + outputs: [ + { + internalType: "bytes", + name: "", + type: "bytes", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + internalType: "bytes32", + name: "name", + type: "bytes32", + }, + { + internalType: "uint16", + name: "resource", + type: "uint16", + }, + ], + name: "dnsRecord", + outputs: [ + { + internalType: "bytes", + name: "", + type: "bytes", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + internalType: "bytes32", + name: "name", + type: "bytes32", + }, + ], + name: "hasDNSRecords", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_owner", + type: "address", + }, + ], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + internalType: "bytes4", + name: "interfaceID", + type: "bytes4", + }, + ], + name: "interfaceImplementer", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + ], + name: "name", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "proxiableUUID", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + ], + name: "pubkey", + outputs: [ + { + internalType: "bytes32", + name: "x", + type: "bytes32", + }, + { + internalType: "bytes32", + name: "y", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + name: "recordVersions", + outputs: [ + { + internalType: "uint64", + name: "", + type: "uint64", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "renounceOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes", + name: "", + type: "bytes", + }, + { + internalType: "bytes", + name: "data", + type: "bytes", + }, + ], + name: "resolve", + outputs: [ + { + internalType: "bytes", + name: "", + type: "bytes", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + internalType: "uint256", + name: "contentType", + type: "uint256", + }, + { + internalType: "bytes", + name: "data", + type: "bytes", + }, + ], + name: "setABI", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + internalType: "uint256", + name: "coinType", + type: "uint256", + }, + { + internalType: "bytes", + name: "a", + type: "bytes", + }, + ], + name: "setAddr", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + internalType: "address", + name: "a", + type: "address", + }, + ], + name: "setAddr", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + internalType: "bytes", + name: "hash", + type: "bytes", + }, + ], + name: "setContenthash", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + internalType: "bytes", + name: "data", + type: "bytes", + }, + ], + name: "setDNSRecords", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + internalType: "bytes4", + name: "interfaceID", + type: "bytes4", + }, + { + internalType: "address", + name: "implementer", + type: "address", + }, + ], + name: "setInterface", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + internalType: "string", + name: "newName", + type: "string", + }, + ], + name: "setName", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + internalType: "bytes32", + name: "x", + type: "bytes32", + }, + { + internalType: "bytes32", + name: "y", + type: "bytes32", + }, + ], + name: "setPubkey", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + internalType: "string", + name: "key", + type: "string", + }, + { + internalType: "string", + name: "value", + type: "string", + }, + ], + name: "setText", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + internalType: "bytes", + name: "hash", + type: "bytes", + }, + ], + name: "setZonehash", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes4", + name: "interfaceID", + type: "bytes4", + }, + ], + name: "supportsInterface", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + { + internalType: "string", + name: "key", + type: "string", + }, + ], + name: "text", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newImplementation", + type: "address", + }, + { + internalType: "bytes", + name: "data", + type: "bytes", + }, + ], + name: "upgradeToAndCall", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "node", + type: "bytes32", + }, + ], + name: "zonehash", + outputs: [ + { + internalType: "bytes", + name: "", + type: "bytes", + }, + ], + stateMutability: "view", + type: "function", + }, +] as const; diff --git a/packages/ens-deployments/src/abis/ens-v2/RegistryDatastore.ts b/packages/ens-deployments/src/abis/ens-v2/RegistryDatastore.ts new file mode 100644 index 000000000..0108a2897 --- /dev/null +++ b/packages/ens-deployments/src/abis/ens-v2/RegistryDatastore.ts @@ -0,0 +1,216 @@ +export const RegistryDatastore = [ + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "registry", + type: "address", + }, + { + indexed: true, + internalType: "uint256", + name: "labelHash", + type: "uint256", + }, + { + indexed: false, + internalType: "address", + name: "resolver", + type: "address", + }, + { + indexed: false, + internalType: "uint96", + name: "flags", + type: "uint96", + }, + ], + name: "ResolverUpdate", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "registry", + type: "address", + }, + { + indexed: true, + internalType: "uint256", + name: "labelHash", + type: "uint256", + }, + { + indexed: false, + internalType: "address", + name: "subregistry", + type: "address", + }, + { + indexed: false, + internalType: "uint96", + name: "flags", + type: "uint96", + }, + ], + name: "SubregistryUpdate", + type: "event", + }, + { + inputs: [ + { + internalType: "address", + name: "registry", + type: "address", + }, + { + internalType: "uint256", + name: "labelHash", + type: "uint256", + }, + ], + name: "getResolver", + outputs: [ + { + internalType: "address", + name: "resolver", + type: "address", + }, + { + internalType: "uint96", + name: "flags", + type: "uint96", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "labelHash", + type: "uint256", + }, + ], + name: "getResolver", + outputs: [ + { + internalType: "address", + name: "resolver", + type: "address", + }, + { + internalType: "uint96", + name: "flags", + type: "uint96", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "labelHash", + type: "uint256", + }, + ], + name: "getSubregistry", + outputs: [ + { + internalType: "address", + name: "subregistry", + type: "address", + }, + { + internalType: "uint96", + name: "flags", + type: "uint96", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "registry", + type: "address", + }, + { + internalType: "uint256", + name: "labelHash", + type: "uint256", + }, + ], + name: "getSubregistry", + outputs: [ + { + internalType: "address", + name: "subregistry", + type: "address", + }, + { + internalType: "uint96", + name: "flags", + type: "uint96", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "labelHash", + type: "uint256", + }, + { + internalType: "address", + name: "resolver", + type: "address", + }, + { + internalType: "uint96", + name: "flags", + type: "uint96", + }, + ], + name: "setResolver", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "labelHash", + type: "uint256", + }, + { + internalType: "address", + name: "subregistry", + type: "address", + }, + { + internalType: "uint96", + name: "flags", + type: "uint96", + }, + ], + name: "setSubregistry", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +] as const; diff --git a/packages/ens-deployments/src/abis/ens-v2/RootRegistry.ts b/packages/ens-deployments/src/abis/ens-v2/RootRegistry.ts new file mode 100644 index 000000000..401231a4c --- /dev/null +++ b/packages/ens-deployments/src/abis/ens-v2/RootRegistry.ts @@ -0,0 +1,1018 @@ +export const RootRegistry = [ + { + inputs: [ + { + internalType: "contract IRegistryDatastore", + name: "_datastore", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + inputs: [], + name: "AccessControlBadConfirmation", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + { + internalType: "bytes32", + name: "neededRole", + type: "bytes32", + }, + ], + name: "AccessControlUnauthorizedAccount", + type: "error", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "address", + name: "caller", + type: "address", + }, + ], + name: "AccessDenied", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address", + }, + { + internalType: "uint256", + name: "balance", + type: "uint256", + }, + { + internalType: "uint256", + name: "needed", + type: "uint256", + }, + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "ERC1155InsufficientBalance", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "approver", + type: "address", + }, + ], + name: "ERC1155InvalidApprover", + type: "error", + }, + { + inputs: [ + { + internalType: "uint256", + name: "idsLength", + type: "uint256", + }, + { + internalType: "uint256", + name: "valuesLength", + type: "uint256", + }, + ], + name: "ERC1155InvalidArrayLength", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "operator", + type: "address", + }, + ], + name: "ERC1155InvalidOperator", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "receiver", + type: "address", + }, + ], + name: "ERC1155InvalidReceiver", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "ERC1155InvalidSender", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "operator", + type: "address", + }, + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + name: "ERC1155MissingApprovalForAll", + type: "error", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + { + internalType: "uint96", + name: "flags", + type: "uint96", + }, + { + internalType: "uint96", + name: "expected", + type: "uint96", + }, + ], + name: "InvalidResolverFlags", + type: "error", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + { + internalType: "uint96", + name: "flags", + type: "uint96", + }, + { + internalType: "uint96", + name: "expected", + type: "uint96", + }, + ], + name: "InvalidSubregistryFlags", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "approved", + type: "address", + }, + { + indexed: true, + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "account", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "operator", + type: "address", + }, + { + indexed: false, + internalType: "bool", + name: "approved", + type: "bool", + }, + ], + name: "ApprovalForAll", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "string", + name: "label", + type: "string", + }, + ], + name: "NewSubname", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "bytes32", + name: "role", + type: "bytes32", + }, + { + indexed: true, + internalType: "bytes32", + name: "previousAdminRole", + type: "bytes32", + }, + { + indexed: true, + internalType: "bytes32", + name: "newAdminRole", + type: "bytes32", + }, + ], + name: "RoleAdminChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "bytes32", + name: "role", + type: "bytes32", + }, + { + indexed: true, + internalType: "address", + name: "account", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "RoleGranted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "bytes32", + name: "role", + type: "bytes32", + }, + { + indexed: true, + internalType: "address", + name: "account", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "RoleRevoked", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "operator", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "from", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "to", + type: "address", + }, + { + indexed: false, + internalType: "uint256[]", + name: "ids", + type: "uint256[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + ], + name: "TransferBatch", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "operator", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "from", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "to", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "id", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "TransferSingle", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "string", + name: "value", + type: "string", + }, + { + indexed: true, + internalType: "uint256", + name: "id", + type: "uint256", + }, + ], + name: "URI", + type: "event", + }, + { + inputs: [], + name: "DEFAULT_ADMIN_ROLE", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "FLAGS_MASK", + outputs: [ + { + internalType: "uint96", + name: "", + type: "uint96", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "FLAG_FLAGS_LOCKED", + outputs: [ + { + internalType: "uint96", + name: "", + type: "uint96", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "FLAG_RESOLVER_LOCKED", + outputs: [ + { + internalType: "uint96", + name: "", + type: "uint96", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "FLAG_SUBREGISTRY_LOCKED", + outputs: [ + { + internalType: "uint96", + name: "", + type: "uint96", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "TLD_ISSUER_ROLE", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + { + internalType: "uint256", + name: "id", + type: "uint256", + }, + ], + name: "balanceOf", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address[]", + name: "accounts", + type: "address[]", + }, + { + internalType: "uint256[]", + name: "ids", + type: "uint256[]", + }, + ], + name: "balanceOfBatch", + outputs: [ + { + internalType: "uint256[]", + name: "", + type: "uint256[]", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "burn", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "datastore", + outputs: [ + { + internalType: "contract IRegistryDatastore", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "flags", + outputs: [ + { + internalType: "uint96", + name: "", + type: "uint96", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "string", + name: "label", + type: "string", + }, + ], + name: "getResolver", + outputs: [ + { + internalType: "address", + name: "resolver", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "role", + type: "bytes32", + }, + ], + name: "getRoleAdmin", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "string", + name: "label", + type: "string", + }, + ], + name: "getSubregistry", + outputs: [ + { + internalType: "contract IRegistry", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "role", + type: "bytes32", + }, + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "grantRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "role", + type: "bytes32", + }, + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "hasRole", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "account", + type: "address", + }, + { + internalType: "address", + name: "operator", + type: "address", + }, + ], + name: "isApprovedForAll", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + { + internalType: "uint96", + name: "flags", + type: "uint96", + }, + ], + name: "lock", + outputs: [ + { + internalType: "uint96", + name: "", + type: "uint96", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "string", + name: "label", + type: "string", + }, + { + internalType: "address", + name: "owner", + type: "address", + }, + { + internalType: "contract IRegistry", + name: "registry", + type: "address", + }, + { + internalType: "uint96", + name: "flags", + type: "uint96", + }, + { + internalType: "string", + name: "_uri", + type: "string", + }, + ], + name: "mint", + outputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "id", + type: "uint256", + }, + ], + name: "ownerOf", + outputs: [ + { + internalType: "address", + name: "owner", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "role", + type: "bytes32", + }, + { + internalType: "address", + name: "callerConfirmation", + type: "address", + }, + ], + name: "renounceRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "role", + type: "bytes32", + }, + { + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "revokeRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256[]", + name: "ids", + type: "uint256[]", + }, + { + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + internalType: "bytes", + name: "data", + type: "bytes", + }, + ], + name: "safeBatchTransferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "from", + type: "address", + }, + { + internalType: "address", + name: "to", + type: "address", + }, + { + internalType: "uint256", + name: "id", + type: "uint256", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + { + internalType: "bytes", + name: "data", + type: "bytes", + }, + ], + name: "safeTransferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "operator", + type: "address", + }, + { + internalType: "bool", + name: "approved", + type: "bool", + }, + ], + name: "setApprovalForAll", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + { + internalType: "address", + name: "resolver", + type: "address", + }, + ], + name: "setResolver", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + { + internalType: "contract IRegistry", + name: "registry", + type: "address", + }, + ], + name: "setSubregistry", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + { + internalType: "string", + name: "_uri", + type: "string", + }, + ], + name: "setUri", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes4", + name: "interfaceId", + type: "bytes4", + }, + ], + name: "supportsInterface", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "uri", + outputs: [ + { + internalType: "string", + name: "", + type: "string", + }, + ], + stateMutability: "view", + type: "function", + }, +] as const; diff --git a/packages/ens-deployments/src/sepolia.ts b/packages/ens-deployments/src/sepolia.ts index bdca7803b..0f0a8abab 100644 --- a/packages/ens-deployments/src/sepolia.ts +++ b/packages/ens-deployments/src/sepolia.ts @@ -1,4 +1,5 @@ import { mergeAbis } from "@ponder/utils"; +import { parseAbiItem } from "viem"; import { sepolia } from "viem/chains"; import { ETHResolverFilter } from "./filters"; @@ -13,6 +14,12 @@ import { NameWrapper as eth_NameWrapper } from "./abis/eth/NameWrapper"; import { Registry as eth_Registry } from "./abis/eth/Registry"; import { Resolver as eth_Resolver } from "./abis/eth/Resolver"; +// ENS v2 ABIs +import { ETHRegistry as ensV2_ETHRegistry } from "./abis/ens-v2/ETHRegistry"; +import { OwnedResolver as ensV2_OwnedResolver } from "./abis/ens-v2/OwnedResolver"; +import { RegistryDatastore as ensV2_RegistryDatastore } from "./abis/ens-v2/RegistryDatastore"; +import { RootRegistry as ensV2_RootRegistry } from "./abis/ens-v2/RootRegistry"; + /** * The "ENS deployment" configuration for 'sepolia'. */ @@ -63,6 +70,40 @@ export default { }, }, }, + "ens-v2": { + chain: sepolia, + + // Addresses and Start Blocks from ens-ponder + // https://github.com/ensdomains/ens-ponder + contracts: { + EthRegistry: { + abi: ensV2_ETHRegistry, + address: "0xFd8562F0B884b5f8d137ff50D25fc26b34868172", + startBlock: 7699319, + }, + RegistryDatastore: { + abi: ensV2_RegistryDatastore, + address: "0x73308B430b61958e3d8C4a6db08153372d5eb125", + startBlock: 7699319, + }, + RootRegistry: { + abi: ensV2_RootRegistry, + address: "0xc44D7201065190B290Aaaf6efaDFD49d530547A3", + startBlock: 7699319, + }, + OwnedResolver: { + abi: ensV2_OwnedResolver, + factory: { + address: "0x33d438bb85B76C9211c4F259109D94Fe83F5A5eC", + event: parseAbiItem( + "event ProxyDeployed(address indexed sender, address indexed proxyAddress, uint256 salt, address implementation)", + ), + parameter: "proxyAddress", + }, + startBlock: 7699319, + }, + }, + }, /** * On the Sepolia "ENS deployment" there is no known subregistry for direct subnames of 'base.eth'. * diff --git a/packages/ens-deployments/src/types.ts b/packages/ens-deployments/src/types.ts index 1ce013498..c8eb3295a 100644 --- a/packages/ens-deployments/src/types.ts +++ b/packages/ens-deployments/src/types.ts @@ -1,3 +1,4 @@ +import type { factory } from "ponder"; import type { Abi, Address, Chain } from "viem"; /** @@ -16,7 +17,7 @@ export type ENSDeploymentChain = "mainnet" | "sepolia" | "holesky" | "ens-test-e /** * Encodes a set of known subregistries. */ -export type SubregistryName = "eth" | "base" | "linea"; +export type SubregistryName = "eth" | "base" | "linea" | "ens-v2"; /** * EventFilter specifies a given event's name and arguments to filter that event by. @@ -42,12 +43,21 @@ export type SubregistryContractConfig = readonly abi: Abi; readonly address: Address; readonly filter?: never; + readonly factory?: never; readonly startBlock: number; } | { readonly abi: Abi; readonly address?: never; readonly filter: EventFilter[]; + readonly factory?: never; + readonly startBlock: number; + } + | { + readonly abi: Abi; + readonly address?: never; + readonly filter?: never; + readonly factory: Parameters[0]; readonly startBlock: number; }; @@ -83,4 +93,11 @@ export type ENSDeploymentConfig = { * Optional for each "ENS deployment". */ linea?: SubregistryDeploymentConfig; + + /** + * ENS v2 Contracts + * TODO: the naming in this package is no longer accurate — perhaps this should be 'AddressBook' + * or something like that. + */ + "ens-v2"?: SubregistryDeploymentConfig; }; diff --git a/packages/ponder-schema/src/ponder.schema.ts b/packages/ponder-schema/src/ponder.schema.ts index 7859ff325..f672c6b7d 100644 --- a/packages/ponder-schema/src/ponder.schema.ts +++ b/packages/ponder-schema/src/ponder.schema.ts @@ -678,3 +678,106 @@ export const versionChangedRelations = relations(versionChanged, ({ one }) => ({ references: [resolver.id], }), })); + +/** + * ENS v2 Isolated Schema + * + * NOTE: These entities kept namespaced for rapid prototyping—see v2 plans for additional context. + * https://www.ensnode.io/ensnode/reference/ensnode-v2-notes/ + * + * Original Schema from https://github.com/ensdomains/ens-ponder + */ + +export const v2_domain = onchainTable("v2_domain", (t) => ({ + id: t.text().primaryKey(), + label: t.text(), + name: t.text().array(), // Will store serialized array as JSON string + labelHash: t.text(), + owner: t.text(), + registry: t.text(), + isTld: t.boolean(), + createdAt: t.bigint("createdAt").notNull(), + updatedAt: t.bigint("updatedAt").notNull(), +})); + +export const v2_domainRelations = relations(v2_domain, ({ one }) => ({ + registry: one(v2_registry, { + fields: [v2_domain.registry], + references: [v2_registry.id], + }), +})); + +export const v2_registry = onchainTable("v2_registry", (t) => ({ + id: t.text().primaryKey(), + labelHash: t.text(), + label: t.text(), + subregistryId: t.text(), + resolver: t.text(), + flags: t.bigint(), + createdAt: t.bigint("createdAt").notNull(), + updatedAt: t.bigint("updatedAt").notNull(), +})); + +export const v2_subregistryUpdateEvent = onchainTable("v2_subregistryUpdateEvent", (t) => ({ + id: t.text().primaryKey(), + registryId: t.text(), + labelHash: t.text(), + subregistryId: t.text(), + flags: t.bigint(), + createdAt: t.bigint("createdAt").notNull(), + updatedAt: t.bigint("updatedAt").notNull(), +})); + +export const v2_resolverUpdateEvent = onchainTable("v2_resolverUpdateEvent", (t) => ({ + id: t.text().primaryKey(), + registryId: t.text(), + labelHash: t.text(), + resolverId: t.text(), + flags: t.bigint(), + createdAt: t.bigint("createdAt").notNull(), + updatedAt: t.bigint("updatedAt").notNull(), +})); + +export const v2_newSubnameEvent = onchainTable("v2_newSubnameEvent", (t) => ({ + id: t.text().primaryKey(), + registryId: t.text(), + label: t.text(), + labelHash: t.text(), + source: t.text(), // "EthRegistry" or "RootRegistry" + createdAt: t.bigint("createdAt").notNull(), + updatedAt: t.bigint("updatedAt").notNull(), +})); + +export const v2_registryRelations = relations(v2_registry, ({ one }) => ({ + subregistry: one(v2_registry, { + fields: [v2_registry.subregistryId], + references: [v2_registry.id], + }), +})); + +export const v2_resolver = onchainTable("v2_resolver", (t) => ({ + id: t.text().primaryKey(), + address: t.text(), + node: t.text(), + createdAt: t.bigint("createdAt").notNull(), + updatedAt: t.bigint("updatedAt").notNull(), +})); + +export const v2_registryResolverRelations = relations(v2_registry, ({ one }) => ({ + resolver: one(v2_resolver, { + fields: [v2_registry.resolver], + references: [v2_resolver.id], + }), +})); + +export const v2_transferSingleEvent = onchainTable("v2_transferSingleEvent", (t) => ({ + id: t.text().primaryKey(), + registryId: t.text(), + tokenId: t.text(), + from: t.text(), + to: t.text(), + value: t.bigint(), + source: t.text(), // "EthRegistry" or "RootRegistry" + createdAt: t.bigint("createdAt").notNull(), + updatedAt: t.bigint("updatedAt").notNull(), +})); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 51f7f6ae4..aa812c2ca 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -438,6 +438,9 @@ importers: '@ensnode/shared-configs': specifier: 'workspace:' version: link:../shared-configs + ponder: + specifier: 'catalog:' + version: 0.9.27(@opentelemetry/api@1.7.0)(@types/node@22.13.5)(hono@4.6.17)(lightningcss@1.29.1)(typescript@5.7.3)(viem@2.22.13(typescript@5.7.3)(zod@3.24.2))(zod@3.24.2) tsup: specifier: 'catalog:' version: 8.3.6(jiti@2.4.2)(postcss@8.5.1)(tsx@4.19.2)(typescript@5.7.3)(yaml@2.7.0)