diff --git a/.changeset/warm-ghosts-enjoy.md b/.changeset/warm-ghosts-enjoy.md new file mode 100644 index 0000000000..b6989e3ce6 --- /dev/null +++ b/.changeset/warm-ghosts-enjoy.md @@ -0,0 +1,5 @@ +--- +"ensapi": minor +--- + +Change `Query.permissions` to accept `by: { id, contract }` and `Query.account` to accept `by: { id, address }`, matching the `by` input pattern of `Query.registry` and `Query.resolver`. diff --git a/apps/ensadmin/package.json b/apps/ensadmin/package.json index 47c198fe9a..19035a985e 100644 --- a/apps/ensadmin/package.json +++ b/apps/ensadmin/package.json @@ -56,8 +56,8 @@ "lucide-react": "catalog:", "next": "^16.1.7", "next-themes": "^0.4.6", - "react": "19.2.1", - "react-dom": "19.2.1", + "react": "catalog:", + "react-dom": "catalog:", "rooks": "^8.4.0", "serve": "^14.2.5", "sonner": "^2.0.3", @@ -68,8 +68,8 @@ "devDependencies": { "@testing-library/react": "catalog:", "@types/node": "catalog:", - "@types/react": "19.2.7", - "@types/react-dom": "19.2.3", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", "@tailwindcss/postcss": "^4.1.18", "postcss": "^8.5.6", "tailwindcss": "catalog:", diff --git a/apps/ensapi/package.json b/apps/ensapi/package.json index 280041bc1a..306ddd8df5 100644 --- a/apps/ensapi/package.json +++ b/apps/ensapi/package.json @@ -15,7 +15,6 @@ "start": "tsx src/index.ts", "dev": "tsx watch --env-file ./.env.local src/index.ts", "test": "vitest", - "test:integration": "vitest run --config vitest.integration.config.ts", "lint": "biome check --write .", "lint:ci": "biome ci", "typecheck": "tsgo --noEmit", @@ -68,6 +67,7 @@ "@ensnode/shared-configs": "workspace:*", "@types/node": "catalog:", "@types/prismjs": "^1.26.6", + "@urql/introspection": "^1.2.1", "chalk": "^5.6.2", "graphql-request": "^7.4.0", "pino-pretty": "^13.1.2", diff --git a/apps/ensapi/src/lib/ensanalytics/referrer-leaderboard/database-v1.ts b/apps/ensapi/src/lib/ensanalytics/referrer-leaderboard/database-v1.ts index 8ec23d9126..139f77ddd3 100644 --- a/apps/ensapi/src/lib/ensanalytics/referrer-leaderboard/database-v1.ts +++ b/apps/ensapi/src/lib/ensanalytics/referrer-leaderboard/database-v1.ts @@ -5,9 +5,10 @@ import { type ReferrerMetrics, } from "@namehash/ens-referrals/v1"; import { and, asc, count, desc, eq, gte, isNotNull, lte, ne, sql, sum } from "drizzle-orm"; +import { stringifyAccountId } from "enssdk"; import { type Address, zeroAddress } from "viem"; -import { deserializeDuration, formatAccountId, priceEth } from "@ensnode/ensnode-sdk"; +import { deserializeDuration, priceEth } from "@ensnode/ensnode-sdk"; import { ensDb, ensIndexerSchema } from "@/lib/ensdb/singleton"; import logger from "@/lib/logger"; @@ -62,7 +63,10 @@ export const getReferrerMetrics = async ( // Filter by decodedReferrer not zero address ne(ensIndexerSchema.registrarActions.decodedReferrer, zeroAddress), // Filter by subregistryId matching the provided subregistryId - eq(ensIndexerSchema.registrarActions.subregistryId, formatAccountId(rules.subregistryId)), + eq( + ensIndexerSchema.registrarActions.subregistryId, + stringifyAccountId(rules.subregistryId), + ), ), ) .groupBy(ensIndexerSchema.registrarActions.decodedReferrer) @@ -126,7 +130,10 @@ export const getReferralEvents = async (rules: ReferralProgramRules): Promise; Scalars: { + // make sure to keep these scalars up to date with packages/enssdk/src/omnigraph/graphql.ts ! BigInt: { Input: bigint; Output: bigint }; Address: { Input: Address; Output: Address }; Hex: { Input: Hex; Output: Hex }; ChainId: { Input: ChainId; Output: ChainId }; CoinType: { Input: CoinType; Output: CoinType }; Node: { Input: Node; Output: Node }; - Name: { Input: InterpretedName; Output: InterpretedName }; + InterpretedName: { Input: InterpretedName; Output: InterpretedName }; + InterpretedLabel: { Input: InterpretedLabel; Output: InterpretedLabel }; DomainId: { Input: DomainId; Output: DomainId }; RegistryId: { Input: RegistryId; Output: RegistryId }; ResolverId: { Input: ResolverId; Output: ResolverId }; @@ -78,6 +81,9 @@ export const builder = new SchemaBuilder<{ Connection: { totalCount: MaybePromise; }; + + DefaultEdgesNullability: false; + DefaultNodeNullability: false; }>({ plugins: [TracingPlugin, DataloaderPlugin, RelayPlugin], tracing: { @@ -104,5 +110,9 @@ export const builder = new SchemaBuilder<{ // disable the Query.node & Query.nodes methods nodeQueryOptions: false, nodesQueryOptions: false, + + // globally configures Edge and Node types to be non-nullable + edgesFieldOptions: { nullable: false }, + nodeFieldOptions: { nullable: false }, }, }); diff --git a/apps/ensapi/src/omnigraph-api/lib/find-domains/layers/with-ordering-metadata.ts b/apps/ensapi/src/omnigraph-api/lib/find-domains/layers/with-ordering-metadata.ts index 1669ff554f..616209a7c3 100644 --- a/apps/ensapi/src/omnigraph-api/lib/find-domains/layers/with-ordering-metadata.ts +++ b/apps/ensapi/src/omnigraph-api/lib/find-domains/layers/with-ordering-metadata.ts @@ -56,7 +56,10 @@ export function withOrderingMetadata(base: BaseDomainSet) { ensIndexerSchema.registration, and( eq(ensIndexerSchema.registration.domainId, base.domainId), - eq(ensIndexerSchema.registration.index, ensIndexerSchema.latestRegistrationIndex.index), + eq( + ensIndexerSchema.registration.registrationIndex, + ensIndexerSchema.latestRegistrationIndex.registrationIndex, + ), ), ); diff --git a/apps/ensapi/src/omnigraph-api/lib/get-latest-registration.ts b/apps/ensapi/src/omnigraph-api/lib/get-latest-registration.ts index f5c79d91bb..3aa5da47fc 100644 --- a/apps/ensapi/src/omnigraph-api/lib/get-latest-registration.ts +++ b/apps/ensapi/src/omnigraph-api/lib/get-latest-registration.ts @@ -8,6 +8,6 @@ import { ensDb } from "@/lib/ensdb/singleton"; export async function getLatestRegistration(domainId: DomainId) { return await ensDb.query.registration.findFirst({ where: (t, { eq }) => eq(t.domainId, domainId), - orderBy: (t, { desc }) => desc(t.index), + orderBy: (t, { desc }) => desc(t.registrationIndex), }); } diff --git a/apps/ensapi/src/omnigraph-api/lib/write-graphql-schema.ts b/apps/ensapi/src/omnigraph-api/lib/write-graphql-schema.ts index 0e59b846dc..4ab24b471f 100644 --- a/apps/ensapi/src/omnigraph-api/lib/write-graphql-schema.ts +++ b/apps/ensapi/src/omnigraph-api/lib/write-graphql-schema.ts @@ -2,7 +2,8 @@ import { writeFile } from "node:fs/promises"; import { resolve } from "node:path"; import { fileURLToPath } from "node:url"; -import { lexicographicSortSchema, printSchema } from "graphql"; +import { minifyIntrospectionQuery } from "@urql/introspection"; +import { introspectionFromSchema, lexicographicSortSchema, printSchema } from "graphql"; import { makeLogger } from "@/lib/logger"; @@ -10,13 +11,21 @@ const logger = makeLogger("write-graphql-schema"); const MONOREPO_ROOT = resolve(import.meta.dirname, "../../../../../"); const ENSSDK_ROOT = resolve(MONOREPO_ROOT, "packages/enssdk/"); -const OUTPUT_PATH = resolve(ENSSDK_ROOT, "src/omnigraph/generated/schema.graphql"); +const GENERATED_DIR = resolve(ENSSDK_ROOT, "src/omnigraph/generated"); async function _writeGraphQLSchema() { - const { schema } = await import("@/omnigraph-api/schema"); - const schemaAsString = printSchema(lexicographicSortSchema(schema)); - - await writeFile(OUTPUT_PATH, schemaAsString); + const { schema: unsortedSchema } = await import("@/omnigraph-api/schema"); + const schema = lexicographicSortSchema(unsortedSchema); + const sdl = printSchema(schema); + const introspection = minifyIntrospectionQuery(introspectionFromSchema(schema)); + + await Promise.all([ + writeFile(resolve(GENERATED_DIR, "schema.graphql"), sdl), + writeFile( + resolve(GENERATED_DIR, "introspection.ts"), + `export const introspection = ${JSON.stringify(introspection)} as const;\n`, + ), + ]); } /** @@ -25,9 +34,9 @@ async function _writeGraphQLSchema() { export async function writeGraphQLSchema() { try { await _writeGraphQLSchema(); - logger.info(`Wrote SDL to ${OUTPUT_PATH}`); + logger.info(`Wrote SDL to ${GENERATED_DIR}`); } catch (error) { - logger.warn(error, `Unable to write SDL to ${OUTPUT_PATH}`); + logger.warn(error, `Unable to write SDL to ${GENERATED_DIR}`); } } @@ -35,7 +44,7 @@ export async function writeGraphQLSchema() { if (resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { try { await _writeGraphQLSchema(); - console.log(`Wrote SDL to ${OUTPUT_PATH}`); + console.log(`Wrote SDL to ${GENERATED_DIR}`); process.exit(0); } catch (error) { console.error(error); diff --git a/apps/ensapi/src/omnigraph-api/schema/account-id.ts b/apps/ensapi/src/omnigraph-api/schema/account-id.ts index a0d5132244..61661f88e9 100644 --- a/apps/ensapi/src/omnigraph-api/schema/account-id.ts +++ b/apps/ensapi/src/omnigraph-api/schema/account-id.ts @@ -6,8 +6,8 @@ export const AccountIdRef = builder.objectRef("AccountId"); AccountIdRef.implement({ description: "A CAIP-10 Account ID including chainId and address.", fields: (t) => ({ - chainId: t.expose("chainId", { type: "ChainId" }), - address: t.expose("address", { type: "Address" }), + chainId: t.expose("chainId", { type: "ChainId", nullable: false }), + address: t.expose("address", { type: "Address", nullable: false }), }), }); diff --git a/apps/ensapi/src/omnigraph-api/schema/account.integration.test.ts b/apps/ensapi/src/omnigraph-api/schema/account.integration.test.ts index dc824adcc9..a05b8ab96b 100644 --- a/apps/ensapi/src/omnigraph-api/schema/account.integration.test.ts +++ b/apps/ensapi/src/omnigraph-api/schema/account.integration.test.ts @@ -34,7 +34,7 @@ describe("Account.domains", () => { const AccountDomains = gql` query AccountDomains($address: Address!) { - account(address: $address) { + account(by: { address: $address }) { domains(order: { by: NAME, dir: ASC }) { edges { node { name } } } } } @@ -90,7 +90,7 @@ describe("Account.events", () => { const AccountEvents = gql` query AccountEvents($address: Address!) { - account(address: $address) { events { edges { node { ...EventFragment } } } } + account(by: { address: $address }) { events { edges { node { ...EventFragment } } } } } ${EventFragment} `; @@ -124,7 +124,7 @@ describe("Account.events filtering (AccountEventsWhereInput)", () => { const AccountEventsFiltered = gql` query AccountEventsFiltered($address: Address!, $where: AccountEventsWhereInput, $first: Int) { - account(address: $address) { events(where: $where, first: $first) { edges { node { ...EventFragment } } } } + account(by: { address: $address }) { events(where: $where, first: $first) { edges { node { ...EventFragment } } } } } ${EventFragment} `; diff --git a/apps/ensapi/src/omnigraph-api/schema/account.ts b/apps/ensapi/src/omnigraph-api/schema/account.ts index 60841d4928..c6f0017c1a 100644 --- a/apps/ensapi/src/omnigraph-api/schema/account.ts +++ b/apps/ensapi/src/omnigraph-api/schema/account.ts @@ -214,3 +214,16 @@ AccountRef.implement({ }), }), }); + +////////// +// Inputs +////////// + +export const AccountByInput = builder.inputType("AccountByInput", { + description: "Address an Account by ID or Address.", + isOneOf: true, + fields: (t) => ({ + id: t.field({ type: "Address" }), + address: t.field({ type: "Address" }), + }), +}); diff --git a/apps/ensapi/src/omnigraph-api/schema/constants.ts b/apps/ensapi/src/omnigraph-api/schema/constants.ts index c9aa4c59e7..606609b593 100644 --- a/apps/ensapi/src/omnigraph-api/schema/constants.ts +++ b/apps/ensapi/src/omnigraph-api/schema/constants.ts @@ -12,15 +12,3 @@ export const ID_PAGINATED_CONNECTION_ARGS = { defaultSize: PAGINATION_DEFAULT_PAGE_SIZE, maxSize: PAGINATION_DEFAULT_MAX_SIZE, } as const; - -/** - * Connection field arguments for entities paginated by a numeric `index` column. - * - * @dev we can use the index itself as a cursor because there are no collisions within a given scope - * (i.e. the `index` is only used once per Domain's Registration or per Registration's Renewal). - */ -export const INDEX_PAGINATED_CONNECTION_ARGS = { - toCursor: (model: T) => cursors.encode(String(model.index)), - defaultSize: PAGINATION_DEFAULT_PAGE_SIZE, - maxSize: PAGINATION_DEFAULT_MAX_SIZE, -} as const; diff --git a/apps/ensapi/src/omnigraph-api/schema/domain.integration.test.ts b/apps/ensapi/src/omnigraph-api/schema/domain.integration.test.ts index 3e4d66e211..9dce92052e 100644 --- a/apps/ensapi/src/omnigraph-api/schema/domain.integration.test.ts +++ b/apps/ensapi/src/omnigraph-api/schema/domain.integration.test.ts @@ -35,7 +35,7 @@ describe("Domain.subdomains", () => { }; const DomainSubdomains = gql` - query DomainSubdomains($name: Name!) { + query DomainSubdomains($name: InterpretedName!) { domain(by: { name: $name }) { subdomains { edges { node { name label { interpreted } } } } } @@ -68,7 +68,7 @@ describe("Domain.events", () => { }; const DomainEvents = gql` - query DomainEvents($name: Name!) { + query DomainEvents($name: InterpretedName!) { domain(by: { name: $name }) { events { edges { node { ...EventFragment } } } } } ${EventFragment} @@ -107,7 +107,7 @@ describe("Domain.events filtering (EventsWhereInput)", () => { }; const DomainEventsFiltered = gql` - query DomainEventsFiltered($name: Name!, $where: EventsWhereInput, $first: Int) { + query DomainEventsFiltered($name: InterpretedName!, $where: EventsWhereInput, $first: Int) { domain(by: { name: $name }) { events(where: $where, first: $first) { edges { node { ...EventFragment } } } } } ${EventFragment} diff --git a/apps/ensapi/src/omnigraph-api/schema/domain.ts b/apps/ensapi/src/omnigraph-api/schema/domain.ts index 716f5ff218..6ed8c662e2 100644 --- a/apps/ensapi/src/omnigraph-api/schema/domain.ts +++ b/apps/ensapi/src/omnigraph-api/schema/domain.ts @@ -17,6 +17,7 @@ import { paginateBy, paginateByInt, } from "@/omnigraph-api/lib/connection-helpers"; +import { cursors } from "@/omnigraph-api/lib/cursors"; import { resolveFindDomains } from "@/omnigraph-api/lib/find-domains/find-domains-resolver"; import { domainsBase, @@ -33,7 +34,8 @@ import { rejectAnyErrors } from "@/omnigraph-api/lib/reject-any-errors"; import { AccountRef } from "@/omnigraph-api/schema/account"; import { ID_PAGINATED_CONNECTION_ARGS, - INDEX_PAGINATED_CONNECTION_ARGS, + PAGINATION_DEFAULT_MAX_SIZE, + PAGINATION_DEFAULT_PAGE_SIZE, } from "@/omnigraph-api/schema/constants"; import { EventRef, EventsWhereInput } from "@/omnigraph-api/schema/event"; import { LabelRef } from "@/omnigraph-api/schema/label"; @@ -134,7 +136,7 @@ DomainInterfaceRef.implement({ description: "The Canonical Name for this Domain. If the Domain is not Canonical, then `name` will be null.", tracing: true, - type: "Name", + type: "InterpretedName", nullable: true, resolve: async (domain, args, context) => { const canonicalPath = isENSv1Domain(domain) @@ -228,15 +230,25 @@ DomainInterfaceRef.implement({ totalCount: () => ensDb.$count(ensIndexerSchema.registration, scope), connection: () => resolveCursorConnection( - { ...INDEX_PAGINATED_CONNECTION_ARGS, args }, + { + toCursor: (model) => cursors.encode(String(model.registrationIndex)), + defaultSize: PAGINATION_DEFAULT_PAGE_SIZE, + maxSize: PAGINATION_DEFAULT_MAX_SIZE, + args, + }, ({ before, after, limit, inverted }: ResolveCursorConnectionArgs) => ensDb .select() .from(ensIndexerSchema.registration) .where( - and(scope, paginateByInt(ensIndexerSchema.registration.index, before, after)), + and( + scope, + paginateByInt(ensIndexerSchema.registration.registrationIndex, before, after), + ), + ) + .orderBy( + orderPaginationBy(ensIndexerSchema.registration.registrationIndex, inverted), ) - .orderBy(orderPaginationBy(ensIndexerSchema.registration.index, inverted)) .limit(limit), ), }); @@ -417,7 +429,7 @@ export const DomainIdInput = builder.inputType("DomainIdInput", { description: "Reference a specific Domain.", isOneOf: true, fields: (t) => ({ - name: t.field({ type: "Name" }), + name: t.field({ type: "InterpretedName" }), id: t.field({ type: "DomainId" }), }), }); diff --git a/apps/ensapi/src/omnigraph-api/schema/label.ts b/apps/ensapi/src/omnigraph-api/schema/label.ts index 6e8ea181ee..2ea3fec004 100644 --- a/apps/ensapi/src/omnigraph-api/schema/label.ts +++ b/apps/ensapi/src/omnigraph-api/schema/label.ts @@ -22,7 +22,7 @@ LabelRef.implement({ interpreted: t.field({ description: "The Label represented as an Interpreted Label. This is either a normalized Literal Label or an Encoded LabelHash. \n(@see https://ensnode.io/docs/reference/terminology#interpreted-label)", - type: "String", + type: "InterpretedLabel", nullable: false, resolve: (parent) => parent.interpreted, }), diff --git a/apps/ensapi/src/omnigraph-api/schema/name-or-node.ts b/apps/ensapi/src/omnigraph-api/schema/name-or-node.ts index b2038bef2b..73f2938b87 100644 --- a/apps/ensapi/src/omnigraph-api/schema/name-or-node.ts +++ b/apps/ensapi/src/omnigraph-api/schema/name-or-node.ts @@ -7,7 +7,7 @@ export const NameOrNodeInput = builder.inputType("NameOrNodeInput", { description: "Constructs a reference to a specific Node via one of `name` or `node`.", isOneOf: true, fields: (t) => ({ - name: t.field({ type: "Name" }), + name: t.field({ type: "InterpretedName" }), node: t.field({ type: "Node" }), }), }); diff --git a/apps/ensapi/src/omnigraph-api/schema/permissions.integration.test.ts b/apps/ensapi/src/omnigraph-api/schema/permissions.integration.test.ts index 249e3876e7..a11b665d3a 100644 --- a/apps/ensapi/src/omnigraph-api/schema/permissions.integration.test.ts +++ b/apps/ensapi/src/omnigraph-api/schema/permissions.integration.test.ts @@ -61,7 +61,7 @@ describe("Permissions", () => { const PermissionsQuery = gql` query Permissions($contract: AccountIdInput!) { - permissions(for: $contract) { + permissions(by: { contract: $contract }) { id contract { chainId address } root { @@ -148,7 +148,7 @@ describe("Domain.permissions", () => { }; const DomainPermissions = gql` - query DomainPermissions($name: Name!) { + query DomainPermissions($name: InterpretedName!) { domain(by: { name: $name }) { ... on ENSv2Domain { permissions { edges { node { id resource user { address } roles } } } @@ -180,7 +180,7 @@ describe("Domain.permissions", () => { it("filters permissions by user address", async () => { const DomainPermissionsFiltered = gql` - query DomainPermissionsFiltered($name: Name!, $user: Address!) { + query DomainPermissionsFiltered($name: InterpretedName!, $user: Address!) { domain(by: { name: $name }) { ... on ENSv2Domain { permissions(where: { user: $user }) { edges { node { id resource user { address } roles } } } @@ -207,7 +207,7 @@ describe("Domain.permissions", () => { describe("Account.permissions and Account.registryPermissions", () => { const PermissionsRootUsers = gql` query PermissionsRootUsers($contract: AccountIdInput!) { - permissions(for: $contract) { + permissions(by: { contract: $contract }) { root { users { edges { node { user { address } } } } } } } @@ -215,7 +215,7 @@ describe("Account.permissions and Account.registryPermissions", () => { const AccountPermissions = gql` query AccountPermissions($address: Address!) { - account(address: $address) { + account(by: { address: $address }) { permissions { edges { node { id resource user { address } roles } } } } } @@ -223,7 +223,7 @@ describe("Account.permissions and Account.registryPermissions", () => { const AccountRegistryPermissions = gql` query AccountRegistryPermissions($address: Address!) { - account(address: $address) { + account(by: { address: $address }) { registryPermissions { edges { node { id registry { id } resource user { address } roles } } } } } @@ -288,7 +288,7 @@ describe("Account.permissions and Account.registryPermissions", () => { describe("Resolver.permissions", () => { const ResolverPermissions = gql` - query ResolverPermissions($name: Name!) { + query ResolverPermissions($name: InterpretedName!) { domain(by: { name: $name }) { resolver { permissions { id contract { chainId address } } } } @@ -321,7 +321,7 @@ describe("Permissions.events", () => { const PermissionsEvents = gql` query PermissionsEvents($contract: AccountIdInput!, $first: Int) { - permissions(for: $contract) { events(first: $first) { edges { node { ...EventFragment } } } } + permissions(by: { contract: $contract }) { events(first: $first) { edges { node { ...EventFragment } } } } } ${EventFragment} `; @@ -368,7 +368,7 @@ describe("Permissions.events filtering (EventsWhereInput)", () => { const PermissionsEventsFiltered = gql` query PermissionsEventsFiltered($contract: AccountIdInput!, $where: EventsWhereInput, $first: Int) { - permissions(for: $contract) { events(where: $where, first: $first) { edges { node { ...EventFragment } } } } + permissions(by: { contract: $contract }) { events(where: $where, first: $first) { edges { node { ...EventFragment } } } } } ${EventFragment} `; diff --git a/apps/ensapi/src/omnigraph-api/schema/permissions.ts b/apps/ensapi/src/omnigraph-api/schema/permissions.ts index 08558661ca..f7e9c52bf7 100644 --- a/apps/ensapi/src/omnigraph-api/schema/permissions.ts +++ b/apps/ensapi/src/omnigraph-api/schema/permissions.ts @@ -1,14 +1,14 @@ import { type ResolveCursorConnectionArgs, resolveCursorConnection } from "@pothos/plugin-relay"; import { and, eq } from "drizzle-orm"; - import { makePermissionsId, makePermissionsResourceId, type PermissionsId, type PermissionsResourceId, type PermissionsUserId, - ROOT_RESOURCE, -} from "@ensnode/ensnode-sdk"; +} from "enssdk"; + +import { ROOT_RESOURCE } from "@ensnode/ensnode-sdk"; import { ensDb, ensIndexerSchema } from "@/lib/ensdb/singleton"; import { builder } from "@/omnigraph-api/builder"; @@ -17,7 +17,7 @@ import { resolveFindEvents } from "@/omnigraph-api/lib/find-events/find-events-r import { getModelId } from "@/omnigraph-api/lib/get-model-id"; import { lazyConnection } from "@/omnigraph-api/lib/lazy-connection"; import { AccountRef } from "@/omnigraph-api/schema/account"; -import { AccountIdRef } from "@/omnigraph-api/schema/account-id"; +import { AccountIdInput, AccountIdRef } from "@/omnigraph-api/schema/account-id"; import { ID_PAGINATED_CONNECTION_ARGS } from "@/omnigraph-api/schema/constants"; import { EventRef, EventsWhereInput } from "@/omnigraph-api/schema/event"; @@ -278,3 +278,16 @@ PermissionsUserRef.implement({ }), }), }); + +////////// +// Inputs +////////// + +export const PermissionsIdInput = builder.inputType("PermissionsIdInput", { + description: "Address Permissions by ID or AccountId.", + isOneOf: true, + fields: (t) => ({ + id: t.field({ type: "PermissionsId" }), + contract: t.field({ type: AccountIdInput }), + }), +}); diff --git a/apps/ensapi/src/omnigraph-api/schema/query.integration.test.ts b/apps/ensapi/src/omnigraph-api/schema/query.integration.test.ts index 2a46c97da4..3b761f5d53 100644 --- a/apps/ensapi/src/omnigraph-api/schema/query.integration.test.ts +++ b/apps/ensapi/src/omnigraph-api/schema/query.integration.test.ts @@ -6,10 +6,10 @@ import { type DomainId, getDatasourceContract, getENSv2RootRegistryId, - getStorageId, type InterpretedLabel, makeENSv1DomainId, makeENSv2DomainId, + makeStorageId, type Name, } from "@ensnode/ensnode-sdk"; @@ -37,7 +37,7 @@ const V2_ROOT_REGISTRY = getDatasourceContract( const V1_ETH_DOMAIN_ID = makeENSv1DomainId(namehash("eth")); -const V2_ETH_STORAGE_ID = getStorageId(labelhash("eth")); +const V2_ETH_STORAGE_ID = makeStorageId(labelhash("eth")); const V2_ETH_DOMAIN_ID = makeENSv2DomainId(V2_ROOT_REGISTRY, V2_ETH_STORAGE_ID); describe("Query.root", () => { @@ -114,7 +114,7 @@ describe("Query.domains", () => { describe("Query.domain", () => { const DomainByName = gql` - query DomainByName($name: Name!) { + query DomainByName($name: InterpretedName!) { domain(by: { name: $name }) { name } diff --git a/apps/ensapi/src/omnigraph-api/schema/query.ts b/apps/ensapi/src/omnigraph-api/schema/query.ts index 8170455455..58148775ec 100644 --- a/apps/ensapi/src/omnigraph-api/schema/query.ts +++ b/apps/ensapi/src/omnigraph-api/schema/query.ts @@ -1,13 +1,9 @@ import config from "@/config"; import { type ResolveCursorConnectionArgs, resolveCursorConnection } from "@pothos/plugin-relay"; +import { makePermissionsId, makeRegistryId, makeResolverId } from "enssdk"; -import { - makePermissionsId, - makeRegistryId, - makeResolverId, - maybeGetENSv2RootRegistryId, -} from "@ensnode/ensnode-sdk"; +import { maybeGetENSv2RootRegistryId } from "@ensnode/ensnode-sdk"; import { ensDb, ensIndexerSchema } from "@/lib/ensdb/singleton"; import { builder } from "@/omnigraph-api/builder"; @@ -21,8 +17,7 @@ import { } from "@/omnigraph-api/lib/find-domains/layers"; import { getDomainIdByInterpretedName } from "@/omnigraph-api/lib/get-domain-by-interpreted-name"; import { lazyConnection } from "@/omnigraph-api/lib/lazy-connection"; -import { AccountRef } from "@/omnigraph-api/schema/account"; -import { AccountIdInput } from "@/omnigraph-api/schema/account-id"; +import { AccountByInput, AccountRef } from "@/omnigraph-api/schema/account"; import { ID_PAGINATED_CONNECTION_ARGS } from "@/omnigraph-api/schema/constants"; import { DomainIdInput, @@ -32,7 +27,7 @@ import { ENSv1DomainRef, ENSv2DomainRef, } from "@/omnigraph-api/schema/domain"; -import { PermissionsRef } from "@/omnigraph-api/schema/permissions"; +import { PermissionsIdInput, PermissionsRef } from "@/omnigraph-api/schema/permissions"; import { RegistrationInterfaceRef } from "@/omnigraph-api/schema/registration"; import { RegistryIdInput, RegistryRef } from "@/omnigraph-api/schema/registry"; import { ResolverIdInput, ResolverRef } from "@/omnigraph-api/schema/resolver"; @@ -164,20 +159,20 @@ builder.queryType({ type: DomainInterfaceRef, args: { by: t.arg({ type: DomainIdInput, required: true }) }, nullable: true, - resolve: async (parent, args, ctx, info) => { + resolve: (parent, args, ctx, info) => { if (args.by.id !== undefined) return args.by.id; return getDomainIdByInterpretedName(args.by.name); }, }), - ////////////////////////// - // Get Account by address - ////////////////////////// + ///////////////////////////////////// + // Get Account by Id or Address + ///////////////////////////////////// account: t.field({ - description: "Identify an Account by Address.", + description: "Identify an Account by ID or Address.", type: AccountRef, - args: { address: t.arg({ type: "Address", required: true }) }, - resolve: async (parent, args, context, info) => args.address, + args: { by: t.arg({ type: AccountByInput, required: true }) }, + resolve: (parent, args, context, info) => args.by.id ?? args.by.address, }), /////////////////////////////////// @@ -187,7 +182,7 @@ builder.queryType({ description: "Identify a Registry by ID or AccountId.", type: RegistryRef, args: { by: t.arg({ type: RegistryIdInput, required: true }) }, - resolve: async (parent, args, context, info) => { + resolve: (parent, args, context, info) => { if (args.by.id !== undefined) return args.by.id; return makeRegistryId(args.by.contract); }, @@ -200,20 +195,23 @@ builder.queryType({ description: "Identify a Resolver by ID or AccountId.", type: ResolverRef, args: { by: t.arg({ type: ResolverIdInput, required: true }) }, - resolve: async (parent, args, context, info) => { + resolve: (parent, args, context, info) => { if (args.by.id !== undefined) return args.by.id; return makeResolverId(args.by.contract); }, }), - /////////////////////////////// - // Get Permissions by Contract - /////////////////////////////// + /////////////////////////////////////// + // Get Permissions by Id or AccountId + /////////////////////////////////////// permissions: t.field({ - description: "Find Permissions in a contract by AccountId.", + description: "Identify Permissions by ID or AccountId.", type: PermissionsRef, - args: { for: t.arg({ type: AccountIdInput, required: true }) }, - resolve: (parent, args, context, info) => makePermissionsId(args.for), + args: { by: t.arg({ type: PermissionsIdInput, required: true }) }, + resolve: (parent, args, context, info) => { + if (args.by.id !== undefined) return args.by.id; + return makePermissionsId(args.by.contract); + }, }), ///////////////////// diff --git a/apps/ensapi/src/omnigraph-api/schema/registration.ts b/apps/ensapi/src/omnigraph-api/schema/registration.ts index 8c90bb28e3..97dca5a0c8 100644 --- a/apps/ensapi/src/omnigraph-api/schema/registration.ts +++ b/apps/ensapi/src/omnigraph-api/schema/registration.ts @@ -13,11 +13,15 @@ import { import { ensDb, ensIndexerSchema } from "@/lib/ensdb/singleton"; import { builder } from "@/omnigraph-api/builder"; import { orderPaginationBy, paginateByInt } from "@/omnigraph-api/lib/connection-helpers"; +import { cursors } from "@/omnigraph-api/lib/cursors"; import { getModelId } from "@/omnigraph-api/lib/get-model-id"; import { lazyConnection } from "@/omnigraph-api/lib/lazy-connection"; import { AccountRef } from "@/omnigraph-api/schema/account"; import { AccountIdRef } from "@/omnigraph-api/schema/account-id"; -import { INDEX_PAGINATED_CONNECTION_ARGS } from "@/omnigraph-api/schema/constants"; +import { + PAGINATION_DEFAULT_MAX_SIZE, + PAGINATION_DEFAULT_PAGE_SIZE, +} from "@/omnigraph-api/schema/constants"; import { DomainInterfaceRef } from "@/omnigraph-api/schema/domain"; import { EventRef } from "@/omnigraph-api/schema/event"; import { RenewalRef } from "@/omnigraph-api/schema/renewal"; @@ -37,7 +41,7 @@ export type RegistrationInterface = Pick< Registration, | "id" | "type" - | "index" + | "registrationIndex" | "domainId" | "expiry" | "registrarChainId" @@ -163,20 +167,27 @@ RegistrationInterfaceRef.implement({ resolve: (parent, args) => { const scope = and( eq(ensIndexerSchema.renewal.domainId, parent.domainId), - eq(ensIndexerSchema.renewal.registrationIndex, parent.index), + eq(ensIndexerSchema.renewal.registrationIndex, parent.registrationIndex), ); return lazyConnection({ totalCount: () => ensDb.$count(ensIndexerSchema.renewal, scope), connection: () => resolveCursorConnection( - { ...INDEX_PAGINATED_CONNECTION_ARGS, args }, + { + toCursor: (model) => cursors.encode(String(model.renewalIndex)), + defaultSize: PAGINATION_DEFAULT_PAGE_SIZE, + maxSize: PAGINATION_DEFAULT_MAX_SIZE, + args, + }, ({ before, after, limit, inverted }: ResolveCursorConnectionArgs) => ensDb .select() .from(ensIndexerSchema.renewal) - .where(and(scope, paginateByInt(ensIndexerSchema.renewal.index, before, after))) - .orderBy(orderPaginationBy(ensIndexerSchema.renewal.index, inverted)) + .where( + and(scope, paginateByInt(ensIndexerSchema.renewal.renewalIndex, before, after)), + ) + .orderBy(orderPaginationBy(ensIndexerSchema.renewal.renewalIndex, inverted)) .limit(limit), ), }); diff --git a/apps/ensapi/src/omnigraph-api/schema/registry-permissions-user.ts b/apps/ensapi/src/omnigraph-api/schema/registry-permissions-user.ts index bbc91106d4..5344b15b69 100644 --- a/apps/ensapi/src/omnigraph-api/schema/registry-permissions-user.ts +++ b/apps/ensapi/src/omnigraph-api/schema/registry-permissions-user.ts @@ -1,4 +1,4 @@ -import { makeRegistryId } from "@ensnode/ensnode-sdk"; +import { makeRegistryId } from "enssdk"; import type { ensIndexerSchema } from "@/lib/ensdb/singleton"; import { builder } from "@/omnigraph-api/builder"; diff --git a/apps/ensapi/src/omnigraph-api/schema/registry.ts b/apps/ensapi/src/omnigraph-api/schema/registry.ts index 333f3205e1..c1f932720d 100644 --- a/apps/ensapi/src/omnigraph-api/schema/registry.ts +++ b/apps/ensapi/src/omnigraph-api/schema/registry.ts @@ -1,7 +1,6 @@ import { type ResolveCursorConnectionArgs, resolveCursorConnection } from "@pothos/plugin-relay"; import { and, eq } from "drizzle-orm"; - -import { makePermissionsId, type RegistryId } from "@ensnode/ensnode-sdk"; +import { makePermissionsId, type RegistryId } from "enssdk"; import { ensDb, ensIndexerSchema } from "@/lib/ensdb/singleton"; import { builder } from "@/omnigraph-api/builder"; diff --git a/apps/ensapi/src/omnigraph-api/schema/resolver-permissions-user.ts b/apps/ensapi/src/omnigraph-api/schema/resolver-permissions-user.ts index b7c96fcb37..71a6bd81d2 100644 --- a/apps/ensapi/src/omnigraph-api/schema/resolver-permissions-user.ts +++ b/apps/ensapi/src/omnigraph-api/schema/resolver-permissions-user.ts @@ -1,4 +1,4 @@ -import { makeResolverId } from "@ensnode/ensnode-sdk"; +import { makeResolverId } from "enssdk"; import type { ensIndexerSchema } from "@/lib/ensdb/singleton"; import { builder } from "@/omnigraph-api/builder"; diff --git a/apps/ensapi/src/omnigraph-api/schema/resolver.integration.test.ts b/apps/ensapi/src/omnigraph-api/schema/resolver.integration.test.ts index ecea044380..967a0c347a 100644 --- a/apps/ensapi/src/omnigraph-api/schema/resolver.integration.test.ts +++ b/apps/ensapi/src/omnigraph-api/schema/resolver.integration.test.ts @@ -28,7 +28,7 @@ describe("Resolver.events", () => { }; const ResolverEvents = gql` - query ResolverEvents($name: Name!) { + query ResolverEvents($name: InterpretedName!) { domain(by: { name: $name }) { resolver { events { diff --git a/apps/ensapi/src/omnigraph-api/schema/resolver.ts b/apps/ensapi/src/omnigraph-api/schema/resolver.ts index 2e9d47783a..75e68bfee3 100644 --- a/apps/ensapi/src/omnigraph-api/schema/resolver.ts +++ b/apps/ensapi/src/omnigraph-api/schema/resolver.ts @@ -2,9 +2,9 @@ import config from "@/config"; import { type ResolveCursorConnectionArgs, resolveCursorConnection } from "@pothos/plugin-relay"; import { and, eq } from "drizzle-orm"; +import { makePermissionsId, makeResolverRecordsId, type ResolverId } from "enssdk"; import { namehash } from "viem"; -import { makePermissionsId, makeResolverRecordsId, type ResolverId } from "@ensnode/ensnode-sdk"; import { isBridgedResolver } from "@ensnode/ensnode-sdk/internal"; import { ensDb, ensIndexerSchema } from "@/lib/ensdb/singleton"; diff --git a/apps/ensapi/src/omnigraph-api/schema/scalars.ts b/apps/ensapi/src/omnigraph-api/schema/scalars.ts index 80133ec534..957ece2e10 100644 --- a/apps/ensapi/src/omnigraph-api/schema/scalars.ts +++ b/apps/ensapi/src/omnigraph-api/schema/scalars.ts @@ -5,7 +5,9 @@ import { type ChainId, type CoinType, type DomainId, + type InterpretedLabel, type InterpretedName, + isInterpetedLabel, isInterpretedName, type Name, type Node, @@ -88,8 +90,8 @@ builder.scalarType("Node", { .parse(value), }); -builder.scalarType("Name", { - description: "Name represents a @ensnode/ensnode-sdk#InterpretedName.", +builder.scalarType("InterpretedName", { + description: "InterpretedName represents a @ensnode/ensnode-sdk#InterpretedName.", serialize: (value: Name) => value, parseValue: (value) => z.coerce @@ -98,7 +100,8 @@ builder.scalarType("Name", { if (!isInterpretedName(ctx.value)) { ctx.issues.push({ code: "custom", - message: "Name must consist exclusively of Encoded LabelHashes or normalized labels.", + message: + "InterpretedName must consist exclusively of Encoded LabelHashes or normalized labels.", input: ctx.value, }); } @@ -107,6 +110,25 @@ builder.scalarType("Name", { .parse(value), }); +builder.scalarType("InterpretedLabel", { + description: "InterpretedLabel represents a @ensnode/ensnode-sdk#InterpretedLabel.", + serialize: (value: Name) => value, + parseValue: (value) => + z.coerce + .string() + .check((ctx) => { + if (!isInterpetedLabel(ctx.value)) { + ctx.issues.push({ + code: "custom", + message: "InterpretedLabel must be an Encoded LabelHash or normalized.", + input: ctx.value, + }); + } + }) + .transform((val) => val as InterpretedLabel) + .parse(value), +}); + builder.scalarType("DomainId", { description: "DomainId represents a @ensnode/ensnode-sdk#DomainId.", serialize: (value: DomainId) => value, diff --git a/apps/ensapi/src/omnigraph-api/yoga.ts b/apps/ensapi/src/omnigraph-api/yoga.ts index b68a484614..528e80546d 100644 --- a/apps/ensapi/src/omnigraph-api/yoga.ts +++ b/apps/ensapi/src/omnigraph-api/yoga.ts @@ -14,9 +14,11 @@ export const yoga = createYoga({ graphqlEndpoint: "*", schema, context, + // CORS is handled by the Hono middleware in app.ts + cors: false, graphiql: { defaultQuery: `query DomainsByOwner { - account(address: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266") { + account(by: { address: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" }) { domains { edges { node { diff --git a/apps/ensapi/src/test/integration/find-domains/domain-pagination-queries.ts b/apps/ensapi/src/test/integration/find-domains/domain-pagination-queries.ts index 8355a41dac..b9e7f90bd2 100644 --- a/apps/ensapi/src/test/integration/find-domains/domain-pagination-queries.ts +++ b/apps/ensapi/src/test/integration/find-domains/domain-pagination-queries.ts @@ -87,7 +87,7 @@ export const AccountDomainsPaginated = gql` $last: Int $before: String ) { - account(address: $address) { + account(by: { address: $address }) { domains(order: $order, first: $first, after: $after, last: $last, before: $before) { edges { cursor node { ...PaginatedDomainFragment } } pageInfo { ...PageInfoFragment } diff --git a/apps/ensapi/src/test/integration/find-events/event-pagination-queries.ts b/apps/ensapi/src/test/integration/find-events/event-pagination-queries.ts index c7d7dfaa6f..89b54f6edd 100644 --- a/apps/ensapi/src/test/integration/find-events/event-pagination-queries.ts +++ b/apps/ensapi/src/test/integration/find-events/event-pagination-queries.ts @@ -45,7 +45,7 @@ export type EventResult = { export const DomainEventsPaginated = gql` query DomainEventsPaginated( - $name: Name! + $name: InterpretedName! $first: Int $after: String $last: Int @@ -71,7 +71,7 @@ export const AccountEventsPaginated = gql` $last: Int $before: String ) { - account(address: $address) { + account(by: { address: $address }) { events(first: $first, after: $after, last: $last, before: $before) { edges { cursor node { ...EventFragment } } pageInfo { ...PageInfoFragment } @@ -85,7 +85,7 @@ export const AccountEventsPaginated = gql` export const ResolverEventsPaginated = gql` query ResolverEventsPaginated( - $name: Name! + $name: InterpretedName! $first: Int $after: String $last: Int @@ -113,7 +113,7 @@ export const PermissionsEventsPaginated = gql` $last: Int $before: String ) { - permissions(for: $contract) { + permissions(by: { contract: $contract }) { events(first: $first, after: $after, last: $last, before: $before) { edges { cursor node { ...EventFragment } } pageInfo { ...PageInfoFragment } diff --git a/apps/ensapi/src/test/integration/global-setup.ts b/apps/ensapi/src/test/integration/global-setup.ts deleted file mode 100644 index e0d36d3ec1..0000000000 --- a/apps/ensapi/src/test/integration/global-setup.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { client, ENSNODE_OMNIGRAPH_API_URL, gql } from "./omnigraph-api-client"; - -export async function setup() { - try { - await client.request(gql` - { - __schema { - queryType { - name - } - } - } - `); - } catch (error) { - throw new Error( - `Integration test health check failed: could not reach ${ENSNODE_OMNIGRAPH_API_URL}. ` + - `Ensure ensapi is running before running integration tests.\n` + - `Original error: ${error}`, - ); - } -} diff --git a/apps/ensapi/src/test/integration/omnigraph-api-client.ts b/apps/ensapi/src/test/integration/omnigraph-api-client.ts index dd48dfdc6a..3df7a75a08 100644 --- a/apps/ensapi/src/test/integration/omnigraph-api-client.ts +++ b/apps/ensapi/src/test/integration/omnigraph-api-client.ts @@ -2,9 +2,7 @@ import { GraphQLClient } from "graphql-request"; export { gql } from "graphql-request"; -export const ENSNODE_OMNIGRAPH_API_URL = new URL( - "/api/omnigraph", - process.env.ENSNODE_URL || "http://localhost:4334", -).href; +// biome-ignore lint/style/noNonNullAssertion: always available in integration tests +export const ENSNODE_OMNIGRAPH_API_URL = new URL("/api/omnigraph", process.env.ENSNODE_URL!).href; export const client = new GraphQLClient(ENSNODE_OMNIGRAPH_API_URL); diff --git a/apps/ensapi/vitest.integration.config.ts b/apps/ensapi/vitest.integration.config.ts index 594b7a687e..a038a13e4d 100644 --- a/apps/ensapi/vitest.integration.config.ts +++ b/apps/ensapi/vitest.integration.config.ts @@ -10,6 +10,5 @@ export default defineProject({ }, test: { include: ["src/**/*.integration.test.ts"], - globalSetup: "./src/test/integration/global-setup.ts", }, }); diff --git a/apps/ensindexer/package.json b/apps/ensindexer/package.json index d6da4c51b7..7de460af7e 100644 --- a/apps/ensindexer/package.json +++ b/apps/ensindexer/package.json @@ -34,8 +34,9 @@ "deepmerge-ts": "^7.1.5", "dns-packet": "^5.6.1", "drizzle-orm": "catalog:", - "p-retry": "catalog:", + "enssdk": "workspace:*", "hono": "catalog:", + "p-retry": "catalog:", "ponder": "catalog:", "viem": "catalog:", "zod": "catalog:" diff --git a/apps/ensindexer/src/lib/ensv2/event-db-helpers.ts b/apps/ensindexer/src/lib/ensv2/event-db-helpers.ts index 03c37b39bc..66cea2f372 100644 --- a/apps/ensindexer/src/lib/ensv2/event-db-helpers.ts +++ b/apps/ensindexer/src/lib/ensv2/event-db-helpers.ts @@ -1,12 +1,6 @@ +import { type AccountId, type DomainId, makePermissionsId, makeResolverId } from "enssdk"; import type { Hash } from "viem"; -import { - type AccountId, - type DomainId, - makePermissionsId, - makeResolverId, -} from "@ensnode/ensnode-sdk"; - import { ensIndexerSchema, type IndexingEngineContext } from "@/lib/indexing-engines/ponder"; import type { LogEventBase } from "@/lib/ponder-helpers"; diff --git a/apps/ensindexer/src/lib/ensv2/registration-db-helpers.ts b/apps/ensindexer/src/lib/ensv2/registration-db-helpers.ts index 2be2f74da4..779c7f0602 100644 --- a/apps/ensindexer/src/lib/ensv2/registration-db-helpers.ts +++ b/apps/ensindexer/src/lib/ensv2/registration-db-helpers.ts @@ -1,4 +1,4 @@ -import { type DomainId, makeRegistrationId, makeRenewalId } from "@ensnode/ensnode-sdk"; +import { type DomainId, makeRegistrationId, makeRenewalId } from "enssdk"; import { ensIndexerSchema, type IndexingEngineContext } from "@/lib/indexing-engines/ponder"; @@ -26,7 +26,7 @@ export async function getLatestRegistration(context: IndexingEngineContext, doma if (!pointer) return null; return context.ensDb.find(ensIndexerSchema.registration, { - id: makeRegistrationId(domainId, pointer.index), + id: makeRegistrationId(domainId, pointer.registrationIndex), }); } @@ -35,26 +35,26 @@ export async function getLatestRegistration(context: IndexingEngineContext, doma */ export async function insertLatestRegistration( context: IndexingEngineContext, - values: Omit, + values: Omit, ) { const { domainId } = values; // derive new Registration's index from previous, if exists const previous = await getLatestRegistration(context, domainId); - const index = previous ? previous.index + 1 : 0; + const registrationIndex = previous ? previous.registrationIndex + 1 : 0; // insert new Registration await context.ensDb.insert(ensIndexerSchema.registration).values({ - id: makeRegistrationId(domainId, index), - index, + id: makeRegistrationId(domainId, registrationIndex), + registrationIndex, ...values, }); // ensure this Registration is the latest await context.ensDb .insert(ensIndexerSchema.latestRegistrationIndex) - .values({ domainId, index }) - .onConflictDoUpdate({ index }); + .values({ domainId, registrationIndex }) + .onConflictDoUpdate({ registrationIndex }); } /** @@ -72,7 +72,7 @@ export async function getLatestRenewal( if (!pointer) return null; return context.ensDb.find(ensIndexerSchema.renewal, { - id: makeRenewalId(domainId, registrationIndex, pointer.index), + id: makeRenewalId(domainId, registrationIndex, pointer.renewalIndex), }); } @@ -81,27 +81,30 @@ export async function getLatestRenewal( */ export async function insertLatestRenewal( context: IndexingEngineContext, - registration: Pick, - values: Omit, + registration: Pick, + values: Omit< + typeof ensIndexerSchema.renewal.$inferInsert, + "id" | "registrationIndex" | "renewalIndex" + >, ) { - const { index: registrationIndex } = registration; + const { registrationIndex } = registration; const { domainId } = values; // derive new Renewal's index from previous, if exists const previous = await getLatestRenewal(context, domainId, registrationIndex); - const index = previous ? previous.index + 1 : 0; + const renewalIndex = previous ? previous.renewalIndex + 1 : 0; // insert new Renewal await context.ensDb.insert(ensIndexerSchema.renewal).values({ - id: makeRenewalId(domainId, registrationIndex, index), + id: makeRenewalId(domainId, registrationIndex, renewalIndex), registrationIndex, - index, + renewalIndex, ...values, }); // ensure this Renewal is the latest await context.ensDb .insert(ensIndexerSchema.latestRenewalIndex) - .values({ domainId, registrationIndex, index }) - .onConflictDoUpdate({ index }); + .values({ domainId, registrationIndex, renewalIndex }) + .onConflictDoUpdate({ renewalIndex }); } diff --git a/apps/ensindexer/src/lib/protocol-acceleration/resolver-db-helpers.ts b/apps/ensindexer/src/lib/protocol-acceleration/resolver-db-helpers.ts index dbfc07bfc3..f432d6929a 100644 --- a/apps/ensindexer/src/lib/protocol-acceleration/resolver-db-helpers.ts +++ b/apps/ensindexer/src/lib/protocol-acceleration/resolver-db-helpers.ts @@ -1,12 +1,12 @@ -import type { Address } from "viem"; - import { type AccountId, type CoinType, makeResolverId, makeResolverRecordsId, type Node, -} from "@ensnode/ensnode-sdk"; +} from "enssdk"; +import type { Address } from "viem"; + import { interpretAddressRecordValue, interpretNameRecordValue, diff --git a/apps/ensindexer/src/lib/tokenscope/nft-issuers.ts b/apps/ensindexer/src/lib/tokenscope/nft-issuers.ts index 0be58ea9bb..5c3ca8827b 100644 --- a/apps/ensindexer/src/lib/tokenscope/nft-issuers.ts +++ b/apps/ensindexer/src/lib/tokenscope/nft-issuers.ts @@ -1,3 +1,5 @@ +import { interpretTokenIdAsLabelHash, interpretTokenIdAsNode } from "enssdk"; + import { type DatasourceName, DatasourceNames, type ENSNamespaceId } from "@ensnode/datasources"; import { type AccountId, @@ -8,8 +10,6 @@ import { type DomainAssetId, ETH_NODE, getDatasourceContract, - interpretTokenIdAsLabelHash, - interpretTokenIdAsNode, LINEANAMES_NODE, makeSubdomainNode, maybeGetDatasourceContract, diff --git a/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/BaseRegistrar.ts b/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/BaseRegistrar.ts index 68c1f6af4b..101339dbdc 100644 --- a/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/BaseRegistrar.ts +++ b/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/BaseRegistrar.ts @@ -1,11 +1,10 @@ import { GRACE_PERIOD_SECONDS } from "@ensdomains/ensjs/utils"; +import { interpretTokenIdAsLabelHash, makeENSv1DomainId } from "enssdk"; import { type Address, isAddressEqual, zeroAddress } from "viem"; import { interpretAddress, - interpretTokenIdAsLabelHash, isRegistrationFullyExpired, - makeENSv1DomainId, makeSubdomainNode, PluginName, } from "@ensnode/ensnode-sdk"; diff --git a/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/ENSv1Registry.ts b/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/ENSv1Registry.ts index 50c204b959..09601f847d 100644 --- a/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/ENSv1Registry.ts +++ b/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/ENSv1Registry.ts @@ -1,15 +1,13 @@ import config from "@/config"; +import { type LabelHash, makeENSv1DomainId, type Node } from "enssdk"; import { type Address, isAddressEqual, zeroAddress } from "viem"; import { ADDR_REVERSE_NODE, getENSRootChainId, interpretAddress, - type LabelHash, - makeENSv1DomainId, makeSubdomainNode, - type Node, PluginName, ROOT_NODE, } from "@ensnode/ensnode-sdk"; diff --git a/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/NameWrapper.ts b/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/NameWrapper.ts index a2b60888a9..05007c4dac 100644 --- a/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/NameWrapper.ts +++ b/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/NameWrapper.ts @@ -1,3 +1,4 @@ +import { interpretTokenIdAsNode, makeENSv1DomainId, type Node } from "enssdk"; import { type Address, isAddressEqual, zeroAddress } from "viem"; import { @@ -5,16 +6,13 @@ import { type DNSEncodedName, decodeDNSEncodedLiteralName, interpretAddress, - interpretTokenIdAsNode, isPccFuseSet, isRegistrationExpired, isRegistrationFullyExpired, isRegistrationInGracePeriod, type LiteralLabel, labelhashLiteralLabel, - makeENSv1DomainId, makeSubdomainNode, - type Node, PluginName, } from "@ensnode/ensnode-sdk"; diff --git a/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/RegistrarController.ts b/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/RegistrarController.ts index cf48cc7ac6..c258fb6076 100644 --- a/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/RegistrarController.ts +++ b/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/RegistrarController.ts @@ -1,12 +1,12 @@ /** biome-ignore-all lint/correctness/noUnusedVariables: ignore for now */ +import { type LabelHash, makeENSv1DomainId } from "enssdk"; + import { type EncodedReferrer, type Label, - type LabelHash, type LiteralLabel, labelhashLiteralLabel, - makeENSv1DomainId, makeSubdomainNode, PluginName, } from "@ensnode/ensnode-sdk"; @@ -130,7 +130,7 @@ export default function () { ); } - const renewal = await getLatestRenewal(context, domainId, registration.index); + const renewal = await getLatestRenewal(context, domainId, registration.registrationIndex); if (!renewal) { throw new Error( `Invariant(RegistrarController:NameRenewed): NameRenewed but no Renewal for Registration\n${toJson( diff --git a/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts b/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts index 9e4adff730..b298e8d852 100644 --- a/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts +++ b/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts @@ -1,14 +1,16 @@ +import { + type AccountId, + type LabelHash, + makeENSv2DomainId, + makeRegistryId, + makeStorageId, +} from "enssdk"; import { type Address, hexToBigInt, labelhash } from "viem"; import { - type AccountId, - getStorageId, interpretAddress, isRegistrationFullyExpired, - type LabelHash, type LiteralLabel, - makeENSv2DomainId, - makeRegistryId, PluginName, } from "@ensnode/ensnode-sdk"; @@ -57,7 +59,7 @@ export default function () { const registry = getThisAccountId(context, event); const registryId = makeRegistryId(registry); - const storageId = getStorageId(tokenId); + const storageId = makeStorageId(tokenId); const domainId = makeENSv2DomainId(registry, storageId); // Sanity Check: LabelHash must match Label @@ -65,10 +67,10 @@ export default function () { throw new Error(`Sanity Check: labelHash !== labelhash(label)\n${toJson(event.args)}`); } - // Sanity Check: StorageId must match LabelHash - if (storageId !== getStorageId(hexToBigInt(labelHash))) { + // Sanity Check: StorageId derived from tokenId must match StorageId derived from LabelHash + if (storageId !== makeStorageId(hexToBigInt(labelHash))) { throw new Error( - `Sanity Check: storageId !== getStorageId(hexToBigInt(labelHash))\n${toJson(event.args)}`, + `Sanity Check: storageId !== makeStorageId(hexToBigInt(labelHash))\n${toJson(event.args)}`, ); } @@ -160,7 +162,7 @@ export default function () { const { tokenId, sender: unregistrant } = event.args; const registry = getThisAccountId(context, event); - const storageId = getStorageId(tokenId); + const storageId = makeStorageId(tokenId); const domainId = makeENSv2DomainId(registry, storageId); const registration = await getLatestRegistration(context, domainId); @@ -210,7 +212,7 @@ export default function () { const { tokenId, newExpiry: expiry, sender } = event.args; const registry = getThisAccountId(context, event); - const storageId = getStorageId(tokenId); + const storageId = makeStorageId(tokenId); const domainId = makeENSv2DomainId(registry, storageId); const registration = await getLatestRegistration(context, domainId); @@ -253,7 +255,7 @@ export default function () { const subregistry = interpretAddress(_subregistry); const registryAccountId = getThisAccountId(context, event); - const storageId = getStorageId(tokenId); + const storageId = makeStorageId(tokenId); const domainId = makeENSv2DomainId(registryAccountId, storageId); // update domain's subregistry @@ -308,11 +310,11 @@ export default function () { const { oldTokenId, newTokenId } = event.args; // Invariant: StorageIds must match - if (getStorageId(oldTokenId) !== getStorageId(newTokenId)) { + if (makeStorageId(oldTokenId) !== makeStorageId(newTokenId)) { throw new Error(`Invariant(ENSv2Registry:TokenRegenerated): Storage Id Malformed.`); } - const storageId = getStorageId(oldTokenId); + const storageId = makeStorageId(oldTokenId); const registryAccountId = getThisAccountId(context, event); const domainId = makeENSv2DomainId(registryAccountId, storageId); @@ -334,7 +336,7 @@ export default function () { }) { const { id: tokenId, to: owner } = event.args; - const storageId = getStorageId(tokenId); + const storageId = makeStorageId(tokenId); const registry = getThisAccountId(context, event); const domainId = makeENSv2DomainId(registry, storageId); diff --git a/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ETHRegistrar.ts b/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ETHRegistrar.ts index e411eda02d..a4fae11633 100644 --- a/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ETHRegistrar.ts +++ b/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ETHRegistrar.ts @@ -1,12 +1,10 @@ +import { type AccountId, makeENSv2DomainId, makeStorageId } from "enssdk"; import type { Address } from "viem"; import { - type AccountId, type EncodedReferrer, - getStorageId, interpretAddress, isRegistrationFullyExpired, - makeENSv2DomainId, PluginName, type TokenId, } from "@ensnode/ensnode-sdk"; @@ -70,7 +68,7 @@ export default function () { // _before_ this event. This event upserts the latest Registration with payment info. const { registrar, registry } = await getRegistrarAndRegistry(context, event); - const storageId = getStorageId(tokenId); + const storageId = makeStorageId(tokenId); const domainId = makeENSv2DomainId(registry, storageId); const registration = await getLatestRegistration(context, domainId); @@ -145,7 +143,7 @@ export default function () { // update Registration.expiry, it just needs to update the latest Renewal const { registry } = await getRegistrarAndRegistry(context, event); - const storageId = getStorageId(tokenId); + const storageId = makeStorageId(tokenId); const domainId = makeENSv2DomainId(registry, storageId); const registration = await getLatestRegistration(context, domainId); diff --git a/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/EnhancedAccessControl.ts b/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/EnhancedAccessControl.ts index d8b7ef208d..da1459e873 100644 --- a/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/EnhancedAccessControl.ts +++ b/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/EnhancedAccessControl.ts @@ -1,11 +1,13 @@ -import { type Address, isAddressEqual, zeroAddress } from "viem"; - import { + type EACResource, + type EACRoleBitmap, makePermissionsId, makePermissionsResourceId, makePermissionsUserId, - PluginName, -} from "@ensnode/ensnode-sdk"; +} from "enssdk"; +import { type Address, isAddressEqual, zeroAddress } from "viem"; + +import { PluginName } from "@ensnode/ensnode-sdk"; import { ensureAccount } from "@/lib/ensv2/account-db-helpers"; import { ensurePermissionsEvent } from "@/lib/ensv2/event-db-helpers"; @@ -29,7 +31,7 @@ type PermissionsCompositeKey = Pick< const ensurePermissionsResource = async ( context: IndexingEngineContext, contract: PermissionsCompositeKey, - resource: bigint, + resource: EACResource, ) => { const permissionsId = makePermissionsId(contract); const permissionsResourceId = makePermissionsResourceId(contract, resource); @@ -47,7 +49,7 @@ const ensurePermissionsResource = async ( .onConflictDoNothing(); }; -const isZeroRoles = (roles: bigint) => roles === 0n; +const isZeroRoles = (roles: EACRoleBitmap) => roles === 0n; export default function () { addOnchainEventListener( @@ -58,10 +60,10 @@ export default function () { }: { context: IndexingEngineContext; event: EventWithArgs<{ - resource: bigint; + resource: EACResource; account: Address; - oldRoleBitmap: bigint; - newRoleBitmap: bigint; + oldRoleBitmap: EACRoleBitmap; + newRoleBitmap: EACRoleBitmap; }>; }) => { // biome-ignore lint/correctness/noUnusedVariables: TODO: use oldRoleBitmap at all? diff --git a/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ENSv1Registry.ts b/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ENSv1Registry.ts index 326e041805..efe6898288 100644 --- a/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ENSv1Registry.ts +++ b/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ENSv1Registry.ts @@ -1,15 +1,10 @@ import config from "@/config"; +import { type LabelHash, makeENSv1DomainId, type Node } from "enssdk"; import type { Address } from "viem"; import { getENSRootChainId } from "@ensnode/datasources"; -import { - type LabelHash, - makeENSv1DomainId, - makeSubdomainNode, - type Node, - PluginName, -} from "@ensnode/ensnode-sdk"; +import { makeSubdomainNode, PluginName } from "@ensnode/ensnode-sdk"; import { getThisAccountId } from "@/lib/get-this-account-id"; import { addOnchainEventListener, type IndexingEngineContext } from "@/lib/indexing-engines/ponder"; diff --git a/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ENSv2Registry.ts b/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ENSv2Registry.ts index 4b791b721f..f159b4ae20 100644 --- a/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ENSv2Registry.ts +++ b/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ENSv2Registry.ts @@ -1,6 +1,7 @@ +import { makeENSv2DomainId, makeStorageId } from "enssdk"; import type { Address } from "viem"; -import { getStorageId, makeENSv2DomainId, PluginName } from "@ensnode/ensnode-sdk"; +import { PluginName } from "@ensnode/ensnode-sdk"; import { getThisAccountId } from "@/lib/get-this-account-id"; import { addOnchainEventListener, type IndexingEngineContext } from "@/lib/indexing-engines/ponder"; @@ -26,7 +27,7 @@ export default function () { const { tokenId, resolver } = event.args; const registry = getThisAccountId(context, event); - const storageId = getStorageId(tokenId); + const storageId = makeStorageId(tokenId); const domainId = makeENSv2DomainId(registry, storageId); await ensureDomainResolverRelation(context, registry, domainId, resolver); diff --git a/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ThreeDNSToken.ts b/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ThreeDNSToken.ts index acf45a948b..2e717d94d3 100644 --- a/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ThreeDNSToken.ts +++ b/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ThreeDNSToken.ts @@ -1,16 +1,10 @@ import config from "@/config"; +import { type LabelHash, makeENSv1DomainId, type Node } from "enssdk"; import type { Address } from "viem"; import { DatasourceNames, maybeGetDatasource } from "@ensnode/datasources"; -import { - type ChainId, - type LabelHash, - makeENSv1DomainId, - makeSubdomainNode, - type Node, - PluginName, -} from "@ensnode/ensnode-sdk"; +import { type ChainId, makeSubdomainNode, PluginName } from "@ensnode/ensnode-sdk"; import { getThisAccountId } from "@/lib/get-this-account-id"; import { addOnchainEventListener, type IndexingEngineContext } from "@/lib/indexing-engines/ponder"; diff --git a/apps/ensindexer/src/plugins/registrars/basenames/handlers/Basenames_Registrar.ts b/apps/ensindexer/src/plugins/registrars/basenames/handlers/Basenames_Registrar.ts index 59dc62120a..3633b2cfde 100644 --- a/apps/ensindexer/src/plugins/registrars/basenames/handlers/Basenames_Registrar.ts +++ b/apps/ensindexer/src/plugins/registrars/basenames/handlers/Basenames_Registrar.ts @@ -1,7 +1,8 @@ +import { interpretTokenIdAsLabelHash } from "enssdk"; + import { type BlockRef, bigIntToNumber, - interpretTokenIdAsLabelHash, makeSubdomainNode, PluginName, type Subregistry, diff --git a/apps/ensindexer/src/plugins/registrars/ethnames/handlers/Ethnames_Registrar.ts b/apps/ensindexer/src/plugins/registrars/ethnames/handlers/Ethnames_Registrar.ts index d98dfd6b86..49f19c188b 100644 --- a/apps/ensindexer/src/plugins/registrars/ethnames/handlers/Ethnames_Registrar.ts +++ b/apps/ensindexer/src/plugins/registrars/ethnames/handlers/Ethnames_Registrar.ts @@ -1,7 +1,8 @@ +import { interpretTokenIdAsLabelHash } from "enssdk"; + import { type BlockRef, bigIntToNumber, - interpretTokenIdAsLabelHash, makeSubdomainNode, PluginName, type Subregistry, diff --git a/apps/ensindexer/src/plugins/registrars/lineanames/handlers/Lineanames_Registrar.ts b/apps/ensindexer/src/plugins/registrars/lineanames/handlers/Lineanames_Registrar.ts index dcedc64b1c..a8d2d229bb 100644 --- a/apps/ensindexer/src/plugins/registrars/lineanames/handlers/Lineanames_Registrar.ts +++ b/apps/ensindexer/src/plugins/registrars/lineanames/handlers/Lineanames_Registrar.ts @@ -1,7 +1,8 @@ +import { interpretTokenIdAsLabelHash } from "enssdk"; + import { type BlockRef, bigIntToNumber, - interpretTokenIdAsLabelHash, makeSubdomainNode, PluginName, type Subregistry, diff --git a/apps/ensindexer/src/plugins/registrars/shared/lib/registrar-action.ts b/apps/ensindexer/src/plugins/registrars/shared/lib/registrar-action.ts index fd89a9448f..ea6b3ce706 100644 --- a/apps/ensindexer/src/plugins/registrars/shared/lib/registrar-action.ts +++ b/apps/ensindexer/src/plugins/registrars/shared/lib/registrar-action.ts @@ -1,6 +1,7 @@ +import { type Node, stringifyAccountId } from "enssdk"; import type { Hash } from "viem"; -import { formatAccountId, type Node, type RegistrarAction } from "@ensnode/ensnode-sdk"; +import type { RegistrarAction } from "@ensnode/ensnode-sdk"; import { ensIndexerSchema, type IndexingEngineContext } from "@/lib/indexing-engines/ponder"; @@ -74,7 +75,7 @@ export async function insertRegistrarAction( await context.ensDb.insert(ensIndexerSchema.registrarActions).values({ id, type, - subregistryId: formatAccountId(subregistryId), + subregistryId: stringifyAccountId(subregistryId), node, incrementalDuration: BigInt(incrementalDuration), registrant, diff --git a/apps/ensindexer/src/plugins/registrars/shared/lib/registrar-events.ts b/apps/ensindexer/src/plugins/registrars/shared/lib/registrar-events.ts index a6a739efdd..790649541c 100644 --- a/apps/ensindexer/src/plugins/registrars/shared/lib/registrar-events.ts +++ b/apps/ensindexer/src/plugins/registrars/shared/lib/registrar-events.ts @@ -2,15 +2,13 @@ * This file contains handlers used in event handlers for a Registrar contract. */ +import { type AccountId, type Node, stringifyAccountId } from "enssdk"; import type { Address, Hash } from "viem"; import { - type AccountId, type BlockRef, bigIntToNumber, durationBetween, - formatAccountId, - type Node, RegistrarActionTypes, type UnixTimestamp, } from "@ensnode/ensnode-sdk"; @@ -72,7 +70,7 @@ export async function handleRegistrarEventRegistration( // Invariant: subregistry record must exist if (!subregistry) { - throw new Error(`Subregistry record must exists for '${formatAccountId(subregistryId)}.'`); + throw new Error(`Subregistry record must exist for '${stringifyAccountId(subregistryId)}.'`); } // 3. Calculate incremental duration @@ -134,7 +132,7 @@ export async function handleRegistrarEventRenewal( // Invariant: subregistry record must exist if (!subregistry) { - throw new Error(`Subregistry record must exists for '${formatAccountId(subregistryId)}.'`); + throw new Error(`Subregistry record must exist for '${stringifyAccountId(subregistryId)}.'`); } // 2. Get the current registration lifecycle before this registrar action diff --git a/apps/ensindexer/src/plugins/registrars/shared/lib/registration-lifecycle.ts b/apps/ensindexer/src/plugins/registrars/shared/lib/registration-lifecycle.ts index ecad5342aa..d6a7430fba 100644 --- a/apps/ensindexer/src/plugins/registrars/shared/lib/registration-lifecycle.ts +++ b/apps/ensindexer/src/plugins/registrars/shared/lib/registration-lifecycle.ts @@ -1,9 +1,6 @@ -import { - type AccountId, - formatAccountId, - type Node, - type UnixTimestamp, -} from "@ensnode/ensnode-sdk"; +import { type AccountId, type Node, stringifyAccountId } from "enssdk"; + +import type { UnixTimestamp } from "@ensnode/ensnode-sdk"; import { ensIndexerSchema, type IndexingEngineContext } from "@/lib/indexing-engines/ponder"; @@ -36,7 +33,7 @@ export async function insertRegistrationLifecycle( }, ): Promise { await context.ensDb.insert(ensIndexerSchema.registrationLifecycles).values({ - subregistryId: formatAccountId(subregistryId), + subregistryId: stringifyAccountId(subregistryId), node, expiresAt: BigInt(expiresAt), }); diff --git a/apps/ensindexer/src/plugins/registrars/shared/lib/subregistry.ts b/apps/ensindexer/src/plugins/registrars/shared/lib/subregistry.ts index ce0364105a..3fec1ba99e 100644 --- a/apps/ensindexer/src/plugins/registrars/shared/lib/subregistry.ts +++ b/apps/ensindexer/src/plugins/registrars/shared/lib/subregistry.ts @@ -2,7 +2,7 @@ * This file contains handlers used in event handlers for a subregistry contract. */ -import { type AccountId, formatAccountId, type Node } from "@ensnode/ensnode-sdk"; +import { type AccountId, type Node, stringifyAccountId } from "enssdk"; import { ensIndexerSchema, type IndexingEngineContext } from "@/lib/indexing-engines/ponder"; @@ -24,7 +24,7 @@ export async function upsertSubregistry( await context.ensDb .insert(ensIndexerSchema.subregistries) .values({ - subregistryId: formatAccountId(subregistryId), + subregistryId: stringifyAccountId(subregistryId), node, }) .onConflictDoNothing(); @@ -38,6 +38,6 @@ export async function getSubregistry( { subregistryId }: { subregistryId: AccountId }, ): Promise { return context.ensDb.find(ensIndexerSchema.subregistries, { - subregistryId: formatAccountId(subregistryId), + subregistryId: stringifyAccountId(subregistryId), }); } diff --git a/apps/ensindexer/src/plugins/subgraph/plugins/basenames/handlers/Registrar.ts b/apps/ensindexer/src/plugins/subgraph/plugins/basenames/handlers/Registrar.ts index 340dfd5b59..9f720ed29a 100644 --- a/apps/ensindexer/src/plugins/subgraph/plugins/basenames/handlers/Registrar.ts +++ b/apps/ensindexer/src/plugins/subgraph/plugins/basenames/handlers/Registrar.ts @@ -1,4 +1,6 @@ -import { interpretTokenIdAsLabelHash, PluginName } from "@ensnode/ensnode-sdk"; +import { interpretTokenIdAsLabelHash } from "enssdk"; + +import { PluginName } from "@ensnode/ensnode-sdk"; import { addOnchainEventListener } from "@/lib/indexing-engines/ponder"; import { namespaceContract } from "@/lib/plugin-helpers"; diff --git a/apps/ensindexer/src/plugins/subgraph/plugins/lineanames/handlers/Registrar.ts b/apps/ensindexer/src/plugins/subgraph/plugins/lineanames/handlers/Registrar.ts index d4f11cdecb..5ba0a25047 100644 --- a/apps/ensindexer/src/plugins/subgraph/plugins/lineanames/handlers/Registrar.ts +++ b/apps/ensindexer/src/plugins/subgraph/plugins/lineanames/handlers/Registrar.ts @@ -1,4 +1,6 @@ -import { interpretTokenIdAsLabelHash, PluginName } from "@ensnode/ensnode-sdk"; +import { interpretTokenIdAsLabelHash } from "enssdk"; + +import { PluginName } from "@ensnode/ensnode-sdk"; import { addOnchainEventListener } from "@/lib/indexing-engines/ponder"; import { namespaceContract } from "@/lib/plugin-helpers"; diff --git a/apps/ensindexer/src/plugins/subgraph/plugins/subgraph/handlers/Registrar.ts b/apps/ensindexer/src/plugins/subgraph/plugins/subgraph/handlers/Registrar.ts index 09dd49bcab..fe432f6cbc 100644 --- a/apps/ensindexer/src/plugins/subgraph/plugins/subgraph/handlers/Registrar.ts +++ b/apps/ensindexer/src/plugins/subgraph/plugins/subgraph/handlers/Registrar.ts @@ -1,4 +1,6 @@ -import { interpretTokenIdAsLabelHash, PluginName } from "@ensnode/ensnode-sdk"; +import { interpretTokenIdAsLabelHash } from "enssdk"; + +import { PluginName } from "@ensnode/ensnode-sdk"; import { addOnchainEventListener } from "@/lib/indexing-engines/ponder"; import { namespaceContract } from "@/lib/plugin-helpers"; diff --git a/apps/ensindexer/src/plugins/subgraph/shared-handlers/NameWrapper.ts b/apps/ensindexer/src/plugins/subgraph/shared-handlers/NameWrapper.ts index 3d13b635cb..aef9124b3d 100644 --- a/apps/ensindexer/src/plugins/subgraph/shared-handlers/NameWrapper.ts +++ b/apps/ensindexer/src/plugins/subgraph/shared-handlers/NameWrapper.ts @@ -15,6 +15,7 @@ import config from "@/config"; * Related GitHub issue: https://github.com/ensdomains/ens-subgraph/issues/88 */ import { checkPccBurned as isPccFuseUnset } from "@ensdomains/ensjs/utils"; +import { interpretTokenIdAsNode } from "enssdk"; import type { Address } from "viem"; import { @@ -23,7 +24,6 @@ import { decodeDNSEncodedLiteralName, type InterpretedLabel, type InterpretedName, - interpretTokenIdAsNode, literalLabelsToInterpretedName, literalLabelToInterpretedLabel, type Node, diff --git a/apps/ensindexer/src/plugins/tokenscope/handlers/Seaport.ts b/apps/ensindexer/src/plugins/tokenscope/handlers/Seaport.ts index 4e8eb8026d..9b855a8493 100644 --- a/apps/ensindexer/src/plugins/tokenscope/handlers/Seaport.ts +++ b/apps/ensindexer/src/plugins/tokenscope/handlers/Seaport.ts @@ -1,6 +1,8 @@ import config from "@/config"; -import { formatAssetId, PluginName } from "@ensnode/ensnode-sdk"; +import { stringifyAssetId } from "enssdk"; + +import { PluginName } from "@ensnode/ensnode-sdk"; import { addOnchainEventListener, ensIndexerSchema } from "@/lib/indexing-engines/ponder"; import { namespaceContract } from "@/lib/plugin-helpers"; @@ -39,7 +41,7 @@ export default function () { await upsertAccount(context, sale.seller); await upsertAccount(context, sale.buyer); - const assetIdString = formatAssetId(sale.nft); + const assetIdString = stringifyAssetId(sale.nft); // insert NameSale entity await context.ensDb.insert(ensIndexerSchema.nameSales).values({ diff --git a/apps/ensindexer/src/plugins/tokenscope/lib/handle-nft-transfer.ts b/apps/ensindexer/src/plugins/tokenscope/lib/handle-nft-transfer.ts index 5f36c47369..89a13dd05e 100644 --- a/apps/ensindexer/src/plugins/tokenscope/lib/handle-nft-transfer.ts +++ b/apps/ensindexer/src/plugins/tokenscope/lib/handle-nft-transfer.ts @@ -1,8 +1,8 @@ +import { stringifyAssetId } from "enssdk"; import { type Address, zeroAddress } from "viem"; import { type DomainAssetId, - formatAssetId, formatNFTTransferEventMetadata, getNFTTransferType, NFTMintStatuses, @@ -41,7 +41,7 @@ export const handleNFTTransfer = async ( nft: DomainAssetId, metadata: NFTTransferEventMetadata, ): Promise => { - const assetIdString = formatAssetId(nft); + const assetIdString = stringifyAssetId(nft); // get the previously indexed record for the assetId (if it exists) const previous = await context.ensDb.find(ensIndexerSchema.nameTokens, { id: assetIdString }); diff --git a/docs/ensnode.io/package.json b/docs/ensnode.io/package.json index e5c887a76d..2fc06b8ec3 100644 --- a/docs/ensnode.io/package.json +++ b/docs/ensnode.io/package.json @@ -1,6 +1,7 @@ { "name": "@docs/ensnode", "private": true, + "license": "MIT", "type": "module", "version": "1.9.0", "packageManager": "pnpm@10.28.0", diff --git a/docs/ensrainbow.io/package.json b/docs/ensrainbow.io/package.json index 3420452aa8..f04bc1acdb 100644 --- a/docs/ensrainbow.io/package.json +++ b/docs/ensrainbow.io/package.json @@ -2,6 +2,7 @@ "name": "@docs/ensrainbow", "type": "module", "version": "1.9.0", + "license": "MIT", "packageManager": "pnpm@10.28.0", "private": true, "scripts": { @@ -22,13 +23,13 @@ "astro-font": "catalog:", "astro-seo": "catalog:", "classcat": "5.0.5", - "react": "^19.0.0", - "react-dom": "^19.0.0", + "react": "catalog:", + "react-dom": "catalog:", "react-wrap-balancer": "^1.1.1", "tailwindcss": "4.2.2" }, "devDependencies": { - "@types/react": "^19.0.0", - "@types/react-dom": "^19.0.0" + "@types/react": "catalog:", + "@types/react-dom": "catalog:" } } diff --git a/examples/enskit-react-example/LICENSE b/examples/enskit-react-example/LICENSE new file mode 100644 index 0000000000..24d66814d7 --- /dev/null +++ b/examples/enskit-react-example/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 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. diff --git a/examples/enskit-react-example/README.md b/examples/enskit-react-example/README.md new file mode 100644 index 0000000000..0eab9a9fc5 --- /dev/null +++ b/examples/enskit-react-example/README.md @@ -0,0 +1,27 @@ +# enskit React Example + +A minimal React app demonstrating how to use `enskit` and `enssdk` to query the ENS Omnigraph API. + +The app connects to a local ENSNode instance and includes demos for browsing domains, registry cache usage, and paginated queries. + +## Usage (with NameHash Hosted Instance) + +```sh +# from the ENSNode monorepo root +pnpm install + +# set the ENSNODE_URL to a NameHash Hosted Instance and run this example in dev mode +ENSNODE_URL=https://api.alpha.ensnode.io pnpm -F enskit-react-example dev +``` + +## Usage (with Local ENSNode) + +First, follow the [ENSNode Contributing Documentation](https://ensnode.io/docs/contributing) to get ENSNode running on your local machine. At the end of this, ENSApi should be available on port `:4334`. + +```sh +# from the ENSNode monorepo root +pnpm install + +# run this example in dev mode, defaults to connecting to an ENSApi at http://localhost:4334 +pnpm -F enskit-react-example dev +``` diff --git a/examples/enskit-react-example/index.html b/examples/enskit-react-example/index.html new file mode 100644 index 0000000000..0c83249c47 --- /dev/null +++ b/examples/enskit-react-example/index.html @@ -0,0 +1,12 @@ + + + + + + enskit React Example + + +
+ + + diff --git a/examples/enskit-react-example/package.json b/examples/enskit-react-example/package.json new file mode 100644 index 0000000000..15b312a44c --- /dev/null +++ b/examples/enskit-react-example/package.json @@ -0,0 +1,27 @@ +{ + "name": "@ensnode/enskit-react-example", + "private": true, + "version": "0.0.0", + "license": "MIT", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "typecheck": "tsgo --noEmit" + }, + "dependencies": { + "enskit": "workspace:*", + "enssdk": "workspace:*", + "react": "catalog:", + "react-dom": "catalog:", + "react-router": "^7.6.1" + }, + "devDependencies": { + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@vitejs/plugin-react": "^4.5.2", + "typescript": "catalog:", + "vite": "catalog:" + } +} diff --git a/examples/enskit-react-example/src/App.tsx b/examples/enskit-react-example/src/App.tsx new file mode 100644 index 0000000000..fd49652039 --- /dev/null +++ b/examples/enskit-react-example/src/App.tsx @@ -0,0 +1,51 @@ +import { OmnigraphProvider } from "enskit/react/omnigraph"; +import { createEnsNodeClient } from "enssdk/core"; +import { omnigraph } from "enssdk/omnigraph"; +import { StrictMode } from "react"; +import { BrowserRouter, Link, Route, Routes } from "react-router"; + +import { DomainView } from "./DomainView"; +import { PaginationView } from "./PaginationView"; +import { RegistryView } from "./RegistryView"; + +/** + * Gets the ENSNODE_URL from the environment, defaulting to a local ENSNode at http://localhost:4334. + * + * To override, provide ENSNODE_URL in your environment like: + * ENSNODE_URL=https://api.alpha.ensnode.io pnpm dev + */ +const ENSNODE_URL = import.meta.env.ENSNODE_URL ?? "http://localhost:4334"; + +/** + * Constructs an EnsNodeClient and extends it with the Omnigraph module, for use with `enskit`. + */ +const client = createEnsNodeClient({ url: ENSNODE_URL }).extend(omnigraph); + +export function App() { + return ( + + +

+ enskit Example App +

+ + + + Domain Browser |{" "} + Registry Cache Demo |{" "} + Pagination Demo + + } + /> + } /> + } /> + } /> + + +
+
+ ); +} diff --git a/examples/enskit-react-example/src/DomainView.tsx b/examples/enskit-react-example/src/DomainView.tsx new file mode 100644 index 0000000000..e56e72fb20 --- /dev/null +++ b/examples/enskit-react-example/src/DomainView.tsx @@ -0,0 +1,79 @@ +import { type FragmentOf, graphql, readFragment, useOmnigraphQuery } from "enskit/react/omnigraph"; +import type { InterpretedName } from "enssdk"; +import { Link, useParams } from "react-router"; + +const DomainFragment = graphql(` + fragment DomainFragment on Domain { + id + name + owner { id address } + } +`); + +const DomainByNameQuery = graphql( + ` + query DomainByName($name: InterpretedName!) { + domain(by: { name: $name }) { + ...DomainFragment + subdomains(first: 20) { + edges { + node { + ...DomainFragment + } + } + } + } + } +`, + [DomainFragment], +); + +function SubdomainLink({ data }: { data: FragmentOf }) { + const domain = readFragment(DomainFragment, data); + + return ( +
  • + {domain.name} + — {domain.owner?.address ?? "no owner"} +
  • + ); +} + +export function DomainView() { + const { "*": name = "eth" } = useParams(); + + const [result] = useOmnigraphQuery({ + query: DomainByNameQuery, + variables: { name: name as InterpretedName }, + }); + + const { data, fetching, error } = result; + + if (fetching) return

    Loading...

    ; + if (error) return

    Error: {error.message}

    ; + if (!data?.domain) return

    Not found

    ; + + const domain = readFragment(DomainFragment, data.domain); + const parentName = name.includes(".") ? name.slice(name.indexOf(".") + 1) : null; + + return ( +
    +

    {domain.name}

    +

    Owner: {domain.owner?.address ?? "none"}

    + + {parentName && ( +

    + ← {parentName} +

    + )} + +

    Subdomains

    +
      + {data.domain.subdomains?.edges.map((edge) => { + const { id } = readFragment(DomainFragment, edge.node); + return ; + })} +
    +
    + ); +} diff --git a/examples/enskit-react-example/src/PaginationView.tsx b/examples/enskit-react-example/src/PaginationView.tsx new file mode 100644 index 0000000000..d87b90ecca --- /dev/null +++ b/examples/enskit-react-example/src/PaginationView.tsx @@ -0,0 +1,68 @@ +import { graphql, useOmnigraphQuery } from "enskit/react/omnigraph"; +import { useState } from "react"; +import { Link } from "react-router"; + +const EthSubdomainsQuery = graphql(` + query EthSubdomains($first: Int!, $after: String) { + domain(by: { name: "eth" }) { + id + subdomains(first: $first, after: $after) { + edges { + node { id name } + } + pageInfo { + hasNextPage + endCursor + } + } + } + } +`); + +const PAGE_SIZE = 3; + +export function PaginationView() { + const [after, setAfter] = useState(null); + + const [result] = useOmnigraphQuery({ + query: EthSubdomainsQuery, + variables: { first: PAGE_SIZE, after }, + }); + + const { data, fetching, error } = result; + + if (!data && fetching) return

    Loading...

    ; + if (error) return

    Error: {error.message}

    ; + if (!data?.domain) return

    Not found

    ; + + const { subdomains } = data.domain; + + return ( +
    +

    Subdomains of eth (page size: {PAGE_SIZE})

    + +

    + This showcases trivial cursor-based pagination (inc. infinite-scroll) for resources in the + Omnigraph API. +

    + +
      + {subdomains?.edges.map((edge) => ( +
    • + {edge.node.name ?? edge.node.id} +
    • + ))} +
    + + {subdomains?.pageInfo.hasNextPage && ( + + )} +
    + ); +} diff --git a/examples/enskit-react-example/src/RegistryView.tsx b/examples/enskit-react-example/src/RegistryView.tsx new file mode 100644 index 0000000000..b762e64495 --- /dev/null +++ b/examples/enskit-react-example/src/RegistryView.tsx @@ -0,0 +1,110 @@ +import { graphql, type UseOmnigraphQueryResult, useOmnigraphQuery } from "enskit/react/omnigraph"; +import { useMemo } from "react"; + +const RootRegistryQuery = graphql(` + query RootRegistry { + root { + id + contract { chainId address } + } + } +`); + +const RegistryByIdQuery = graphql(` + query RegistryById($id: RegistryId!) { + registry(by: { id: $id }) { id } + } +`); + +const RegistryByContractQuery = graphql(` + query RegistryByContract($contract: AccountIdInput!) { + registry(by: { contract: $contract }) { id } + } +`); + +function CacheStatus({ result }: { result: UseOmnigraphQueryResult[0] }) { + const cacheOutcome = result.operation?.context.meta?.cacheOutcome; + if (cacheOutcome === "hit") return [hit]; + if (cacheOutcome === "partial") return [partial]; + return [uncached]; +} + +export function RegistryView() { + const [rootResult, reloadRoot] = useOmnigraphQuery({ + query: RootRegistryQuery, + // NOTE: urql `context` args _must_ be memoized to avoid infinite re-renders + context: useMemo(() => ({ requestPolicy: "network-only" }), []), + }); + + const root = rootResult.data?.root; + + const [byIdResult, reloadById] = useOmnigraphQuery({ + query: RegistryByIdQuery, + variables: root ? { id: root.id } : undefined, + pause: !root, + }); + + const [byContractResult, reloadByContract] = useOmnigraphQuery({ + query: RegistryByContractQuery, + variables: root ? { contract: root.contract } : undefined, + pause: !root, + }); + + if (rootResult.fetching) return

    Loading root registry...

    ; + if (rootResult.error) return

    Error: {rootResult.error.message}

    ; + if (!root) return

    No ENSv2 root registry found for this namespace.

    ; + + return ( +
    +

    Registry Cache Demo

    + +

    + Demonstrates the loading of the same Registry (the ENSv2 Root Registry) in three different + ways. After the first is populated in the cache, the others load instantly from the cache, + without a subsequent network request. +

    + +
    +

    + 1. Query.root (network-only) — +

    +
    +          id: {root.id}
    +          {"\n"}contract: {root.contract.chainId}:{root.contract.address}
    +        
    + +
    + +
    +

    + 2. registry(by: {"{ id }"}) — +

    +

    + Same entity looked up by id: "{root.id}" +

    +
    id: {byIdResult.data?.registry?.id ?? "-"}
    + +
    + +
    +

    + 3. registry(by: {"{ contract }"}) — +

    +

    + Same entity looked up by{" "} + + contract: {root.contract.chainId}:{root.contract.address} + +

    +
    id: {byContractResult.data?.registry?.id ?? "-"}
    + +
    +
    + ); +} diff --git a/examples/enskit-react-example/src/main.tsx b/examples/enskit-react-example/src/main.tsx new file mode 100644 index 0000000000..d571c28dda --- /dev/null +++ b/examples/enskit-react-example/src/main.tsx @@ -0,0 +1,7 @@ +import { createRoot } from "react-dom/client"; + +import { App } from "./App"; + +// mount the in the #root div +// biome-ignore lint/style/noNonNullAssertion: the #root element definitely exists (see index.html) +createRoot(document.getElementById("root")!).render(); diff --git a/examples/enskit-react-example/src/vite-env.d.ts b/examples/enskit-react-example/src/vite-env.d.ts new file mode 100644 index 0000000000..11f02fe2a0 --- /dev/null +++ b/examples/enskit-react-example/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/enskit-react-example/tsconfig.json b/examples/enskit-react-example/tsconfig.json new file mode 100644 index 0000000000..c7397b1aa4 --- /dev/null +++ b/examples/enskit-react-example/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "plugins": [ + // here we enable the gql.tada typescript plugin for + { + "name": "gql.tada/ts-plugin", + + // because this example is in the ENSNode monorepo, it imports from src + "schema": "node_modules/enssdk/src/omnigraph/generated/schema.graphql", + // but in a normal app you'd import it from the package like so: + // "schema": "node_modules/enssdk/omnigraph/schema.graphql", + + "tadaOutputLocation": "./src/generated/graphql-env.d.ts" + } + ] + }, + "include": ["src"] +} diff --git a/examples/enskit-react-example/vite.config.ts b/examples/enskit-react-example/vite.config.ts new file mode 100644 index 0000000000..58676f788a --- /dev/null +++ b/examples/enskit-react-example/vite.config.ts @@ -0,0 +1,6 @@ +import react from "@vitejs/plugin-react"; +import { defineConfig } from "vite"; + +export default defineConfig({ + plugins: [react()], +}); diff --git a/packages/ensdb-sdk/src/ensindexer-abstract/ensv2.schema.ts b/packages/ensdb-sdk/src/ensindexer-abstract/ensv2.schema.ts index bb67d283f4..4ea79f2f66 100644 --- a/packages/ensdb-sdk/src/ensindexer-abstract/ensv2.schema.ts +++ b/packages/ensdb-sdk/src/ensindexer-abstract/ensv2.schema.ts @@ -333,11 +333,11 @@ export const registrationType = onchainEnum("RegistrationType", [ export const registration = onchainTable( "registrations", (t) => ({ - // keyed by (domainId, index) + // keyed by (domainId, registrationIndex) id: t.text().primaryKey().$type(), domainId: t.text().notNull().$type(), - index: t.integer().notNull(), + registrationIndex: t.integer().notNull(), // has a type type: registrationType().notNull(), @@ -380,13 +380,13 @@ export const registration = onchainTable( eventId: t.text().notNull(), }), (t) => ({ - byId: uniqueIndex().on(t.domainId, t.index), + byId: uniqueIndex().on(t.domainId, t.registrationIndex), }), ); export const latestRegistrationIndex = onchainTable("latest_registration_indexes", (t) => ({ domainId: t.text().primaryKey().$type(), - index: t.integer().notNull(), + registrationIndex: t.integer().notNull(), })); export const registration_relations = relations(registration, ({ one, many }) => ({ @@ -436,7 +436,7 @@ export const renewal = onchainTable( domainId: t.text().notNull().$type(), registrationIndex: t.integer().notNull(), - index: t.integer().notNull(), + renewalIndex: t.integer().notNull(), // all renewals have a duration duration: t.bigint().notNull(), @@ -456,7 +456,7 @@ export const renewal = onchainTable( eventId: t.text().notNull(), }), (t) => ({ - byId: uniqueIndex().on(t.domainId, t.registrationIndex, t.index), + byId: uniqueIndex().on(t.domainId, t.registrationIndex, t.renewalIndex), }), ); @@ -464,7 +464,7 @@ export const renewal_relations = relations(renewal, ({ one }) => ({ // belongs to registration registration: one(registration, { fields: [renewal.domainId, renewal.registrationIndex], - references: [registration.domainId, registration.index], + references: [registration.domainId, registration.registrationIndex], }), // has an event @@ -479,7 +479,7 @@ export const latestRenewalIndex = onchainTable( (t) => ({ domainId: t.text().notNull().$type(), registrationIndex: t.integer().notNull(), - index: t.integer().notNull(), + renewalIndex: t.integer().notNull(), }), (t) => ({ pk: primaryKey({ columns: [t.domainId, t.registrationIndex] }) }), ); diff --git a/packages/enskit/biome.jsonc b/packages/enskit/biome.jsonc new file mode 100644 index 0000000000..3bac83229a --- /dev/null +++ b/packages/enskit/biome.jsonc @@ -0,0 +1,17 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.3.2/schema.json", + "extends": "//", + "overrides": [ + // ignore unused resolver args + { + "includes": ["src/react/omnigraph/lib/cache-exchange.ts"], + "linter": { + "rules": { + "correctness": { + "noUnusedFunctionParameters": "off" + } + } + } + } + ] +} diff --git a/packages/enskit/package.json b/packages/enskit/package.json index 5e46714b5d..eadc9e7898 100644 --- a/packages/enskit/package.json +++ b/packages/enskit/package.json @@ -1,12 +1,65 @@ { "name": "enskit", "version": "1.9.0", - "description": "Reserved for the ENSNode project by NameHash Labs. See https://ensnode.io", + "type": "module", + "description": "The ENS toolkit for React applications", + "license": "MIT", "repository": { "type": "git", - "url": "https://github.com/namehash/ensnode.git", + "url": "git+https://github.com/namehash/ensnode.git", "directory": "packages/enskit" }, - "license": "MIT", - "homepage": "https://ensnode.io" + "homepage": "https://ensnode.io", + "keywords": [ + "ENS", + "ENSNode", + "React", + "Omnigraph" + ], + "files": [ + "dist" + ], + "exports": { + "./react/omnigraph": "./src/react/omnigraph/index.ts" + }, + "publishConfig": { + "access": "public", + "exports": { + "./react/omnigraph": { + "types": "./dist/react/omnigraph/index.d.ts", + "default": "./dist/react/omnigraph/index.js" + } + } + }, + "sideEffects": false, + "scripts": { + "prepublish": "tsup", + "lint": "biome check --write .", + "lint:ci": "biome ci", + "test": "vitest", + "typecheck": "tsgo --noEmit" + }, + "dependencies": { + "enssdk": "workspace:*", + "@urql/core": "^6.0.0", + "@urql/exchange-graphcache": "^9.0.0", + "urql": "^5.0.1" + }, + "peerDependencies": { + "gql.tada": "^1.8.10", + "graphql": "^16", + "react": "^18.0.0 || ^19.0.0", + "viem": "^2" + }, + "devDependencies": { + "@ensnode/shared-configs": "workspace:*", + "@types/react": "catalog:", + "gql.tada": "^1.8.10", + "graphql": "^16.11.0", + "react": "catalog:", + "tsup": "catalog:", + "typescript": "catalog:", + "viem": "catalog:", + "vitest": "catalog:" + } } diff --git a/packages/enskit/src/react/omnigraph/client.ts b/packages/enskit/src/react/omnigraph/client.ts new file mode 100644 index 0000000000..0438d7bdaf --- /dev/null +++ b/packages/enskit/src/react/omnigraph/client.ts @@ -0,0 +1,14 @@ +import { Client, fetchExchange } from "@urql/core"; +import type { EnsNodeClientConfig } from "enssdk/core"; + +import { omnigraphCacheExchange } from "./lib/cache-exchange"; + +export function createOmnigraphUrqlClient(config: EnsNodeClientConfig): Client { + const url = new URL("/api/omnigraph", config.url).href; + + return new Client({ + url, + fetch: config.fetch, + exchanges: [omnigraphCacheExchange, fetchExchange], + }); +} diff --git a/packages/enskit/src/react/omnigraph/hooks.ts b/packages/enskit/src/react/omnigraph/hooks.ts new file mode 100644 index 0000000000..3c92c6d55e --- /dev/null +++ b/packages/enskit/src/react/omnigraph/hooks.ts @@ -0,0 +1,29 @@ +"use client"; + +import type { AnyVariables, OperationContext } from "@urql/core"; +import type { TadaDocumentNode } from "gql.tada"; +import type { DocumentNode } from "graphql"; +import { type UseQueryResponse, useQuery } from "urql"; + +export type UseOmnigraphQueryArgs = { + query: DocumentNode | TadaDocumentNode | string; + variables?: Variables; + pause?: boolean; + context?: Partial; +}; + +export type UseOmnigraphQueryResult< + Data = unknown, + Variables extends AnyVariables = AnyVariables, +> = UseQueryResponse; + +export function useOmnigraphQuery( + args: UseOmnigraphQueryArgs, +): UseOmnigraphQueryResult { + return useQuery({ + query: args.query as DocumentNode, + variables: args.variables as Variables, + pause: args.pause, + context: args.context, + }); +} diff --git a/packages/enskit/src/react/omnigraph/index.ts b/packages/enskit/src/react/omnigraph/index.ts new file mode 100644 index 0000000000..24f3c8750f --- /dev/null +++ b/packages/enskit/src/react/omnigraph/index.ts @@ -0,0 +1,6 @@ +// export the gql.tada subset of enssdk/omnigraph so consumers only need the one dependency +export type { FragmentOf, ResultOf, VariablesOf } from "enssdk/omnigraph"; +export { graphql, readFragment } from "enssdk/omnigraph"; + +export * from "./hooks"; +export * from "./provider"; diff --git a/packages/enskit/src/react/omnigraph/lib/cache-exchange.ts b/packages/enskit/src/react/omnigraph/lib/cache-exchange.ts new file mode 100644 index 0000000000..77a1f1ebb6 --- /dev/null +++ b/packages/enskit/src/react/omnigraph/lib/cache-exchange.ts @@ -0,0 +1,105 @@ +import { + type Cache, + cacheExchange, + type ResolveInfo, + type Variables, +} from "@urql/exchange-graphcache"; +import type { AccountId, PermissionsId, RegistryId, ResolverId } from "enssdk"; +import { makePermissionsId, makeRegistryId, makeResolverId, stringifyAccountId } from "enssdk"; +import { introspection } from "enssdk/omnigraph"; +import type { Address } from "viem"; + +import { localConnectionResolvers } from "./local-connection-resolvers"; + +/** + * Entities without keys are 'Embedded Data', and we tell graphcache about them to avoid warnings + * about the inability to normalize them. + * + * @see https://nearform.com/open-source/urql/docs/graphcache/normalized-caching/#custom-keys-and-non-keyable-entities + */ +const EMBEDDED_DATA = () => null; + +/** + * This local resolver delegates to graphcache's built-in cache resolution with the full argument set, + * effectively telling urql 'not found locally' and to fetch from the network. + */ +const passthrough = (args: Variables, cache: Cache, info: ResolveInfo) => + cache.resolve(info.parentTypeName, info.fieldName, args); + +// produce relayPagination() local resolvers for each t.connection in the schema +const connectionResolvers = localConnectionResolvers(introspection); + +// TODO: add bigint parsing to the relevant scalar fields ala localConnectionResolvers +// @see https://nearform.com/open-source/urql/docs/graphcache/local-resolvers/#transforming-records + +export const omnigraphCacheExchange = cacheExchange({ + schema: introspection, + keys: { + // by default, all Entities are assumed to match the Relay spec, and graphcache treats + // them as keyable by `id`. if it encounters an Entity with no `id` field and no other + // special handling here in the cacheExchange.keys definitions, it will issue a warning. + + // AccountIds are keyable by stringifying them + AccountId: (data) => stringifyAccountId(data as unknown as AccountId), + + // These entities are Embedded Data and don't have a relevant key + Label: EMBEDDED_DATA, + WrappedBaseRegistrarRegistration: EMBEDDED_DATA, + }, + resolvers: { + // TODO: maybe there's a better way to import/cast the type of args in these local resolvers? + + // derive relayPagination() resolvers for all connection fields in the schema + ...connectionResolvers, + + Query: { + ...connectionResolvers.Query, + + domain(parent, args, cache, info) { + const by = args.by as { id?: string; name?: string }; + + if (by.id) { + const v1Key = cache.keyOfEntity({ __typename: "ENSv1Domain", id: by.id }); + if (v1Key && cache.resolve(v1Key, "id")) return v1Key; + + const v2Key = cache.keyOfEntity({ __typename: "ENSv2Domain", id: by.id }); + if (v2Key && cache.resolve(v2Key, "id")) return v2Key; + } + + return passthrough(args, cache, info); + }, + account(parent, args, cache, info) { + const by = args.by as { id?: Address; address?: Address }; + + if (by.id) return { __typename: "Account", id: by.id }; + if (by.address) return { __typename: "Account", id: by.address }; + + throw new Error("never"); + }, + registry(parent, args, cache, info) { + const by = args.by as { id?: RegistryId; contract?: AccountId }; + + if (by.id) return { __typename: "Registry", id: by.id }; + if (by.contract) return { __typename: "Registry", id: makeRegistryId(by.contract) }; + + throw new Error("never"); + }, + resolver(parent, args, cache, info) { + const by = args.by as { id?: ResolverId; contract?: AccountId }; + + if (by.id) return { __typename: "Resolver", id: by.id }; + if (by.contract) return { __typename: "Resolver", id: makeResolverId(by.contract) }; + + throw new Error("never"); + }, + permissions(parent, args, cache, info) { + const by = args.by as { id?: PermissionsId; contract?: AccountId }; + + if (by.id) return { __typename: "Permissions", id: by.id }; + if (by.contract) return { __typename: "Permissions", id: makePermissionsId(by.contract) }; + + throw new Error("never"); + }, + }, + }, +}); diff --git a/packages/enskit/src/react/omnigraph/lib/local-connection-resolvers.ts b/packages/enskit/src/react/omnigraph/lib/local-connection-resolvers.ts new file mode 100644 index 0000000000..2b777bae25 --- /dev/null +++ b/packages/enskit/src/react/omnigraph/lib/local-connection-resolvers.ts @@ -0,0 +1,52 @@ +import type { Resolver } from "@urql/exchange-graphcache"; +import { relayPagination } from "@urql/exchange-graphcache/extras"; + +interface IntrospectionTypeRef { + readonly kind: string; + readonly name?: string; + readonly ofType?: IntrospectionTypeRef | null; +} + +interface IntrospectionField { + readonly name: string; + readonly type: IntrospectionTypeRef; +} + +interface IntrospectionType { + readonly kind: string; + readonly name: string; + readonly fields?: readonly IntrospectionField[] | null; +} + +interface IntrospectionSchema { + readonly __schema: { + readonly types: readonly IntrospectionType[]; + }; +} + +function unwrapType(type: IntrospectionTypeRef): IntrospectionTypeRef { + return type.ofType ? unwrapType(type.ofType) : type; +} + +/** + * Derives `relayPagination()` local resolvers for all connection fields in the schema. + */ +export function localConnectionResolvers( + schema: IntrospectionSchema, +): Record> { + const resolvers: Record> = {}; + + for (const type of schema.__schema.types) { + if (type.kind !== "OBJECT" || type.name.startsWith("__")) continue; + + for (const field of type.fields ?? []) { + const leaf = unwrapType(field.type); + if (leaf.name?.endsWith("Connection")) { + resolvers[type.name] ??= {}; + resolvers[type.name][field.name] = relayPagination(); + } + } + } + + return resolvers; +} diff --git a/packages/enskit/src/react/omnigraph/provider.tsx b/packages/enskit/src/react/omnigraph/provider.tsx new file mode 100644 index 0000000000..49cd7c9b7d --- /dev/null +++ b/packages/enskit/src/react/omnigraph/provider.tsx @@ -0,0 +1,18 @@ +"use client"; + +import type { EnsNodeClient } from "enssdk/core"; +import { createElement, type ReactNode, useMemo } from "react"; +import { Provider } from "urql"; + +import { createOmnigraphUrqlClient } from "./client"; + +export interface OmnigraphProviderProps { + client: EnsNodeClient; + children?: ReactNode; +} + +export function OmnigraphProvider({ client, children }: OmnigraphProviderProps) { + const urqlClient = useMemo(() => createOmnigraphUrqlClient(client.config), [client]); + + return createElement(Provider, { value: urqlClient }, children); +} diff --git a/packages/enskit/tsconfig.json b/packages/enskit/tsconfig.json new file mode 100644 index 0000000000..dcabaae785 --- /dev/null +++ b/packages/enskit/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "@ensnode/shared-configs/tsconfig.lib.json", + "compilerOptions": { + "jsx": "react-jsx", + "rootDir": "." + }, + "include": ["src/**/*"], + "exclude": ["dist"] +} diff --git a/packages/enskit/tsup.config.ts b/packages/enskit/tsup.config.ts new file mode 100644 index 0000000000..68a31c889a --- /dev/null +++ b/packages/enskit/tsup.config.ts @@ -0,0 +1,26 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: { + "react/omnigraph/index": "src/react/omnigraph/index.ts", + }, + platform: "browser", + format: ["esm"], + target: "es2022", + bundle: true, + splitting: false, + sourcemap: true, + dts: true, + clean: true, + external: [ + "react", + "react-dom", + "enssdk", + "graphql", + "gql.tada", + "@urql/core", + "@urql/exchange-graphcache", + "urql", + ], + outDir: "./dist", +}); diff --git a/packages/enskit/vitest.config.ts b/packages/enskit/vitest.config.ts new file mode 100644 index 0000000000..d4d4df5301 --- /dev/null +++ b/packages/enskit/vitest.config.ts @@ -0,0 +1,8 @@ +import { configDefaults, defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + environment: "jsdom", + exclude: [...configDefaults.exclude, "**/*.integration.test.ts"], + }, +}); diff --git a/packages/enskit/vitest.integration.config.ts b/packages/enskit/vitest.integration.config.ts new file mode 100644 index 0000000000..6436893b69 --- /dev/null +++ b/packages/enskit/vitest.integration.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + environment: "jsdom", + include: ["**/*.integration.test.ts"], + }, +}); diff --git a/packages/ensnode-react/package.json b/packages/ensnode-react/package.json index 2386da2397..62fa680529 100644 --- a/packages/ensnode-react/package.json +++ b/packages/ensnode-react/package.json @@ -49,8 +49,8 @@ "@tanstack/react-query": "^5.62.14", "@testing-library/react": "catalog:", "@types/node": "catalog:", - "@types/react": "19.2.7", - "react": "19.2.1", + "@types/react": "catalog:", + "react": "catalog:", "tsup": "^8.3.6", "typescript": "catalog:", "vitest": "catalog:" diff --git a/packages/ensnode-sdk/src/ens/subname-helpers.test.ts b/packages/ensnode-sdk/src/ens/subname-helpers.test.ts index 15d088cc86..ca6a6df4f8 100644 --- a/packages/ensnode-sdk/src/ens/subname-helpers.test.ts +++ b/packages/ensnode-sdk/src/ens/subname-helpers.test.ts @@ -1,18 +1,7 @@ -import { IntegerOutOfRangeError, labelhash, namehash, zeroHash } from "viem"; +import { labelhash, namehash } from "viem"; import { describe, expect, it } from "vitest"; -import { makeSubdomainNode, uint256ToHex32 } from "./subname-helpers"; - -describe("uint256ToHex32", () => { - it("should convert bigint to hex string", () => { - expect(() => uint256ToHex32(-1n)).toThrow(IntegerOutOfRangeError); - expect(uint256ToHex32(0n)).toBe(zeroHash); - expect(uint256ToHex32(2n ** 256n - 1n)).toBe( - "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - ); - expect(() => uint256ToHex32(2n ** 256n)).toThrow(IntegerOutOfRangeError); - }); -}); +import { makeSubdomainNode } from "./subname-helpers"; describe("makeSubdomainNode", () => { it("should return the correct namehash for a subnode", () => { diff --git a/packages/ensnode-sdk/src/ens/subname-helpers.ts b/packages/ensnode-sdk/src/ens/subname-helpers.ts index 19cadf2e9e..9c8281f778 100644 --- a/packages/ensnode-sdk/src/ens/subname-helpers.ts +++ b/packages/ensnode-sdk/src/ens/subname-helpers.ts @@ -1,5 +1,5 @@ import type { LabelHash, Node } from "enssdk"; -import { concat, type Hex, keccak256, toHex } from "viem"; +import { concat, keccak256 } from "viem"; /** * Implements one step of the namehash algorithm, combining `labelHash` with `node` to produce @@ -8,10 +8,3 @@ import { concat, type Hex, keccak256, toHex } from "viem"; */ export const makeSubdomainNode = (labelHash: LabelHash, node: Node): Node => keccak256(concat([node, labelHash])); -/** - * Encodes a uint256 bigint as hex string sized to 32 bytes. - * Uses include, in the context of ENS, decoding the uint256-encoded tokenId of NFT-issuing contracts - * into Node or LabelHash, which is a common behavior in the ENS ecosystem. - * (see NameWrapper, ETHRegistrarController) - */ -export const uint256ToHex32 = (num: bigint): Hex => toHex(num, { size: 32 }); diff --git a/packages/ensnode-sdk/src/ensv2/ids-lib.ts b/packages/ensnode-sdk/src/ensv2/ids-lib.ts deleted file mode 100644 index dc1a26986c..0000000000 --- a/packages/ensnode-sdk/src/ensv2/ids-lib.ts +++ /dev/null @@ -1,95 +0,0 @@ -import type { - AccountId, - DomainId, - ENSv1DomainId, - ENSv2DomainId, - LabelHash, - Node, - PermissionsId, - PermissionsResourceId, - PermissionsUserId, - RegistrationId, - RegistryId, - RenewalId, - ResolverId, - ResolverRecordsId, - StorageId, -} from "enssdk"; -import { AssetNamespaces } from "enssdk"; -import { type Address, hexToBigInt } from "viem"; - -import { formatAccountId, formatAssetId } from "@ensnode/ensnode-sdk"; - -/** - * Formats and brands an AccountId as a RegistryId. - */ -export const makeRegistryId = (accountId: AccountId) => formatAccountId(accountId) as RegistryId; - -/** - * Makes an ENSv1 Domain Id given the ENSv1 Domain's `node` - */ -export const makeENSv1DomainId = (node: Node) => node as ENSv1DomainId; - -/** - * Makes an ENSv2 Domain Id given the parent `registry` and the domain's `storageId`. - */ -export const makeENSv2DomainId = (registry: AccountId, storageId: StorageId) => - formatAssetId({ - assetNamespace: AssetNamespaces.ERC1155, - contract: registry, - tokenId: storageId, - }) as ENSv2DomainId; - -/** - * Masks the lower 32 bits of `num`. - */ -const maskLower32Bits = (num: bigint) => num ^ (num & 0xffffffffn); - -/** - * Computes a Label's {@link StorageId} given its tokenId or LabelHash as `input`. - */ -export const getStorageId = (input: bigint | LabelHash): StorageId => { - if (typeof input === "bigint") return maskLower32Bits(input); - return getStorageId(hexToBigInt(input)); -}; - -/** - * Formats and brands an AccountId as a PermissionsId. - */ -export const makePermissionsId = (contract: AccountId) => - formatAccountId(contract) as PermissionsId; - -/** - * Constructs a PermissionsResourceId for a given `contract`'s `resource`. - */ -export const makePermissionsResourceId = (contract: AccountId, resource: bigint) => - `${makePermissionsId(contract)}/${resource}` as PermissionsResourceId; - -/** - * Constructs a PermissionsUserId for a given `contract`'s `resource`'s `user`. - */ -export const makePermissionsUserId = (contract: AccountId, resource: bigint, user: Address) => - `${makePermissionsId(contract)}/${resource}/${user}` as PermissionsUserId; - -/** - * Formats and brands an AccountId as a ResolverId. - */ -export const makeResolverId = (contract: AccountId) => formatAccountId(contract) as ResolverId; - -/** - * Constructs a ResolverRecordsId for a given `node` under `resolver`. - */ -export const makeResolverRecordsId = (resolver: AccountId, node: Node) => - `${makeResolverId(resolver)}/${node}` as ResolverRecordsId; - -/** - * Constructs a RegistrationId for a `domainId`'s `index`'thd Registration. - */ -export const makeRegistrationId = (domainId: DomainId, index: number) => - `${domainId}/${index}` as RegistrationId; - -/** - * Constructs a RenewalId for a `domainId`'s `registrationIndex`thd Registration's `index`'thd Renewal. - */ -export const makeRenewalId = (domainId: DomainId, registrationIndex: number, index: number) => - `${makeRegistrationId(domainId, registrationIndex)}/${index}` as RenewalId; diff --git a/packages/ensnode-sdk/src/ensv2/index.ts b/packages/ensnode-sdk/src/ensv2/index.ts deleted file mode 100644 index 237cf6adae..0000000000 --- a/packages/ensnode-sdk/src/ensv2/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./ids-lib"; diff --git a/packages/ensnode-sdk/src/index.ts b/packages/ensnode-sdk/src/index.ts index 666ba0cec6..e3ef28bbea 100644 --- a/packages/ensnode-sdk/src/index.ts +++ b/packages/ensnode-sdk/src/index.ts @@ -7,7 +7,6 @@ export * from "./ens"; export * from "./ensapi"; export * from "./ensindexer"; export * from "./ensrainbow"; -export * from "./ensv2"; export * from "./identity"; export * from "./indexing-status"; export * from "./omnigraph-api/prerequisites"; diff --git a/packages/ensnode-sdk/src/omnigraph-api/example-queries.ts b/packages/ensnode-sdk/src/omnigraph-api/example-queries.ts index 28801ab213..27edd4a485 100644 --- a/packages/ensnode-sdk/src/omnigraph-api/example-queries.ts +++ b/packages/ensnode-sdk/src/omnigraph-api/example-queries.ts @@ -96,7 +96,7 @@ query FindDomains( /////////////////// { query: ` -query DomainByName($name: Name!) { +query DomainByName($name: InterpretedName!) { domain(by: {name: $name}) { __typename id @@ -123,7 +123,7 @@ query DomainByName($name: Name!) { ////////////////////// { query: ` -query DomainSubdomains($name: Name!) { +query DomainSubdomains($name: InterpretedName!) { domain(by: {name: $name}) { name subdomains(first: 10) { @@ -143,7 +143,7 @@ query DomainSubdomains($name: Name!) { ///////////////// { query: ` -query DomainEvents($name: Name!) { +query DomainEvents($name: InterpretedName!) { domain(by: {name: $name}) { events { totalCount @@ -171,7 +171,7 @@ query DomainEvents($name: Name!) { query AccountDomains( $address: Address! ) { - account(address: $address) { + account(by: { address: $address }) { domains { edges { node { @@ -196,7 +196,7 @@ query AccountDomains( query AccountEvents( $address: Address! ) { - account(address: $address) { + account(by: { address: $address }) { events { totalCount edges { node { topics data timestamp } } } } }`, @@ -240,7 +240,7 @@ query RegistryDomains( query PermissionsByContract( $contract: AccountIdInput! ) { - permissions(for: $contract) { + permissions(by: { contract: $contract }) { resources { edges { node { @@ -273,7 +273,7 @@ query PermissionsByContract( { query: ` query PermissionsByUser($address: Address!) { - account(address: $address) { + account(by: { address: $address }) { permissions { edges { node { @@ -297,7 +297,7 @@ query PermissionsByUser($address: Address!) { { query: ` query AccountResolverPermissions($address: Address!) { - account(address: $address) { + account(by: { address: $address }) { resolverPermissions { edges { node { @@ -323,7 +323,7 @@ query AccountResolverPermissions($address: Address!) { ////////////////////////////// { query: ` -query DomainResolver($name: Name!) { +query DomainResolver($name: InterpretedName!) { domain(by: { name: $name }) { resolver { records { edges { node { node keys coinTypes } } } diff --git a/packages/ensnode-sdk/src/shared/account-id.test.ts b/packages/ensnode-sdk/src/shared/account-id.test.ts index c639eb4ff6..29913f87f6 100644 --- a/packages/ensnode-sdk/src/shared/account-id.test.ts +++ b/packages/ensnode-sdk/src/shared/account-id.test.ts @@ -1,9 +1,9 @@ import type { AccountId } from "enssdk"; +import { stringifyAccountId } from "enssdk"; import type { Address } from "viem"; import { describe, expect, it } from "vitest"; import { parseAccountId } from "./deserialize"; -import { formatAccountId } from "./serialize"; const vitalikEthAddressLowercase: Address = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; const vitalikEthAddressChecksummed: Address = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"; @@ -11,14 +11,14 @@ const vitalikEthAddressChecksummed: Address = "0xd8dA6BF26964aF9D7eEd9e03E53415D describe("ENSNode SDK Shared: AccountId", () => { it("can serialize AccountId object into a CAIP-10 formatted inline string", () => { expect( - formatAccountId({ + stringifyAccountId({ chainId: 1, address: vitalikEthAddressLowercase, }), ).toStrictEqual(`eip155:1:${vitalikEthAddressLowercase}`); expect( - formatAccountId({ + stringifyAccountId({ chainId: 1, address: vitalikEthAddressChecksummed, }), diff --git a/packages/ensnode-sdk/src/shared/interpretation/index.ts b/packages/ensnode-sdk/src/shared/interpretation/index.ts index 1dbbd7d060..1741768c13 100644 --- a/packages/ensnode-sdk/src/shared/interpretation/index.ts +++ b/packages/ensnode-sdk/src/shared/interpretation/index.ts @@ -1,4 +1,3 @@ export * from "./interpret-address"; export * from "./interpret-record-values"; -export * from "./interpret-tokenid"; export * from "./interpreted-names-and-labels"; diff --git a/packages/ensnode-sdk/src/shared/interpretation/interpret-tokenid.ts b/packages/ensnode-sdk/src/shared/interpretation/interpret-tokenid.ts deleted file mode 100644 index 8076fa1d2b..0000000000 --- a/packages/ensnode-sdk/src/shared/interpretation/interpret-tokenid.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type { LabelHash, Node } from "enssdk"; - -import { uint256ToHex32 } from "../../ens"; - -/** - * Decodes a uint256-encoded-LabelHash (eg. from a tokenId) into a {@link LabelHash}. - * - * Remember that contracts that operate in the context of a Managed Name frequently store and operate - * over _LabelHashes_ that represent a direct subname of a Managed Name. These contracts also frequently - * implement ERC721 or ERC1155 to represent ownership of these Names. As such, to construct the - * ERC721/ERC1155 tokenId, they may encode the direct subnames's LabelHash as a uint256. - * - * This is true for the ENSv1 BaseRegistrar, RegistrarControllers, as well as any - * contracts forked from it (which includes Basenames' and Lineanames' implementations). - * - * So, in order to turn the tokenId into a LabelHash, we perform the opposite operation, decoding - * from a uint256 into a Hex (of size 32) and cast it as our semantic {@link LabelHash} type. - * - * @see https://github.com/ensdomains/ens-contracts/blob/db613bc/contracts/ethregistrar/ETHRegistrarController.sol#L215 - * @see https://github.com/base/basenames/blob/1b5c1ad/src/L2/RegistrarController.sol#L488 - * @see https://github.com/Consensys/linea-ens/blob/3a4f02f/packages/linea-ens-contracts/contracts/ethregistrar/ETHRegistrarController.sol#L447 - */ -export const interpretTokenIdAsLabelHash = (tokenId: bigint): LabelHash => uint256ToHex32(tokenId); - -/** - * Decodes a uint256-encoded-Node (eg. from a tokenId) into a {@link Node}. - * - * Contracts in the ENSv1 ecosystem frequently implement ERC721 or ERC1155 to represent - * ownership of a Domain. As such, to construct the ERC721/ERC1155 tokenId, they may encode the - * domain's {@link Node} as a uint256. - * - * This is true for the ENSv1 NameWrapper, as well as any contracts forked from it (which includes - * Lineanames' implementation). - * - * So, in order to turn the tokenId into a Node, we perform the opposite operation, decoding - * from a uint256 into a Hex (of size 32) and cast it as our semantic {@link Node} type. - * - * @see https://github.com/ensdomains/ens-contracts/blob/db613bc/contracts/wrapper/ERC1155Fuse.sol#L262 - */ -export const interpretTokenIdAsNode = (tokenId: bigint): Node => uint256ToHex32(tokenId); diff --git a/packages/ensnode-sdk/src/shared/serialize.ts b/packages/ensnode-sdk/src/shared/serialize.ts index 1c2efc5d94..e29c08b9b8 100644 --- a/packages/ensnode-sdk/src/shared/serialize.ts +++ b/packages/ensnode-sdk/src/shared/serialize.ts @@ -1,16 +1,5 @@ -import { AccountId as CaipAccountId, AssetId as CaipAssetId } from "caip"; -import type { - AccountId, - AccountIdString, - AssetId, - AssetIdString, - ChainId, - ChainIdString, - DatetimeISO8601, - UrlString, -} from "enssdk"; +import type { ChainId, ChainIdString, DatetimeISO8601, UrlString } from "enssdk"; -import { uint256ToHex32 } from "../ens"; import type { Price, PriceDai, @@ -74,36 +63,3 @@ export function serializePriceUsdc(price: PriceUsdc): SerializedPriceUsdc { export function serializePriceDai(price: PriceDai): SerializedPriceDai { return serializePrice(price) as SerializedPriceDai; } - -/** - * Format {@link AccountId} object as a string. - * - * Formatted as a fully lowercase CAIP-10 AccountId. - * - * @see https://chainagnostic.org/CAIPs/caip-10 - */ -export function formatAccountId(accountId: AccountId): AccountIdString { - return CaipAccountId.format({ - chainId: { namespace: "eip155", reference: accountId.chainId.toString() }, - address: accountId.address, - }).toLowerCase(); -} - -/** - * Format {@link AssetId} object as a string. - * - * Formatted as a fully lowercase CAIP-19 AssetId. - * - * @see https://chainagnostic.org/CAIPs/caip-19 - */ -export function formatAssetId({ - assetNamespace, - contract: { chainId, address }, - tokenId, -}: AssetId): AssetIdString { - return CaipAssetId.format({ - chainId: { namespace: "eip155", reference: chainId.toString() }, - assetName: { namespace: assetNamespace, reference: address }, - tokenId: uint256ToHex32(tokenId), - }).toLowerCase(); -} diff --git a/packages/ensnode-sdk/src/tokenscope/assets.ts b/packages/ensnode-sdk/src/tokenscope/assets.ts index 79fd495c2a..de8d7201fc 100644 --- a/packages/ensnode-sdk/src/tokenscope/assets.ts +++ b/packages/ensnode-sdk/src/tokenscope/assets.ts @@ -1,17 +1,16 @@ -import type { - AccountId, - AssetId, - AssetIdString, - AssetNamespace, - ChainId, - Node, - TokenId, +import { + type AccountId, + type AssetId, + type AssetIdString, + type AssetNamespace, + type ChainId, + type Node, + stringifyAssetId, + type TokenId, } from "enssdk"; import { type Address, type Hex, isAddressEqual, zeroAddress } from "viem"; import { prettifyError } from "zod/v4"; -import { uint256ToHex32 } from "../ens"; -import { formatAssetId } from "../shared/serialize"; import { makeAssetIdSchema, makeAssetIdStringSchema } from "./zod-schemas"; /** @@ -33,7 +32,7 @@ export function serializeAssetId(assetId: AssetId): SerializedAssetId { return { assetNamespace: assetId.assetNamespace, contract: assetId.contract, - tokenId: uint256ToHex32(assetId.tokenId), + tokenId: assetId.tokenId.toString(), }; } @@ -142,7 +141,7 @@ export interface NFTTransferEventMetadata { } export const formatNFTTransferEventMetadata = (metadata: NFTTransferEventMetadata): string => { - const assetIdString = formatAssetId(metadata.nft); + const assetIdString = stringifyAssetId(metadata.nft); return [ `Event: ${metadata.eventHandlerName}`, diff --git a/packages/enssdk/package.json b/packages/enssdk/package.json index acbfcef1de..50177b32ae 100644 --- a/packages/enssdk/package.json +++ b/packages/enssdk/package.json @@ -16,12 +16,14 @@ "Omnigraph" ], "files": [ - "dist" + "dist", + "src/omnigraph/generated/schema.graphql" ], "exports": { ".": "./src/index.ts", "./core": "./src/core/index.ts", - "./omnigraph": "./src/omnigraph/index.ts" + "./omnigraph": "./src/omnigraph/index.ts", + "./omnigraph/schema.graphql": "./src/omnigraph/generated/schema.graphql" }, "sideEffects": false, "publishConfig": { @@ -38,7 +40,8 @@ "./omnigraph": { "types": "./dist/omnigraph/index.d.ts", "default": "./dist/omnigraph/index.js" - } + }, + "./omnigraph/schema.graphql": "./src/omnigraph/generated/schema.graphql" } }, "scripts": { @@ -51,14 +54,18 @@ }, "dependencies": { "@ensdomains/address-encoder": "^1.1.2", - "gql.tada": "^1.8.10", - "graphql": "^16.11.0" + "caip": "catalog:" }, "peerDependencies": { + "gql.tada": "^1.8.10", + "graphql": "^16", "viem": "^2" }, "devDependencies": { "@ensnode/shared-configs": "workspace:*", + "@types/node": "catalog:", + "gql.tada": "^1.8.10", + "graphql": "^16.11.0", "tsup": "catalog:", "typescript": "catalog:", "viem": "catalog:", diff --git a/packages/enssdk/src/_lib/README.md b/packages/enssdk/src/_lib/README.md new file mode 100644 index 0000000000..973b4ffc55 --- /dev/null +++ b/packages/enssdk/src/_lib/README.md @@ -0,0 +1 @@ +enssdk-internal libs or helpers not meant for export to consumers diff --git a/packages/enssdk/src/_lib/uint256ToHex32.test.ts b/packages/enssdk/src/_lib/uint256ToHex32.test.ts new file mode 100644 index 0000000000..71839541d1 --- /dev/null +++ b/packages/enssdk/src/_lib/uint256ToHex32.test.ts @@ -0,0 +1,15 @@ +import { IntegerOutOfRangeError, zeroHash } from "viem"; +import { describe, expect, it } from "vitest"; + +import { uint256ToHex32 } from "./uint256ToHex32"; + +describe("uint256ToHex32", () => { + it("should convert bigint to hex string", () => { + expect(() => uint256ToHex32(-1n)).toThrow(IntegerOutOfRangeError); + expect(uint256ToHex32(0n)).toBe(zeroHash); + expect(uint256ToHex32(2n ** 256n - 1n)).toBe( + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + ); + expect(() => uint256ToHex32(2n ** 256n)).toThrow(IntegerOutOfRangeError); + }); +}); diff --git a/packages/enssdk/src/_lib/uint256ToHex32.ts b/packages/enssdk/src/_lib/uint256ToHex32.ts new file mode 100644 index 0000000000..04d0de1692 --- /dev/null +++ b/packages/enssdk/src/_lib/uint256ToHex32.ts @@ -0,0 +1,6 @@ +import { type Hex, toHex } from "viem"; + +/** + * Converts a uint256 bigint to a zero-padded 32-byte (64-character) lowercase hex string. + */ +export const uint256ToHex32 = (num: bigint): Hex => toHex(num, { size: 32 }); diff --git a/packages/enssdk/src/_lib/zeroLower32Bits.ts b/packages/enssdk/src/_lib/zeroLower32Bits.ts new file mode 100644 index 0000000000..05f3d25f09 --- /dev/null +++ b/packages/enssdk/src/_lib/zeroLower32Bits.ts @@ -0,0 +1,4 @@ +/** + * Zeros the lower 32 bits of `num`. + */ +export const zeroLower32Bits = (num: bigint) => num ^ (num & 0xffffffffn); diff --git a/packages/enssdk/src/index.ts b/packages/enssdk/src/index.ts index fb4d8ecafb..8cd5167d1c 100644 --- a/packages/enssdk/src/index.ts +++ b/packages/enssdk/src/index.ts @@ -1 +1 @@ -export * from "./lib/types"; +export * from "./lib"; diff --git a/packages/enssdk/src/lib/caip.ts b/packages/enssdk/src/lib/caip.ts new file mode 100644 index 0000000000..209ee9fba3 --- /dev/null +++ b/packages/enssdk/src/lib/caip.ts @@ -0,0 +1,32 @@ +import { AccountId as CaipAccountId, AssetId as CaipAssetId } from "caip"; + +import type { AccountId, AccountIdString, AssetId, AssetIdString } from "./types"; + +/** + * Stringify an {@link AccountId} as a fully lowercase CAIP-10 AccountId string. + * + * @see https://chainagnostic.org/CAIPs/caip-10 + */ +export function stringifyAccountId({ chainId, address }: AccountId): AccountIdString { + return CaipAccountId.format({ + chainId: { namespace: "eip155", reference: chainId.toString() }, + address, + }).toLowerCase(); +} + +/** + * Stringify an {@link AssetId} as a fully lowercase CAIP-19 AssetId string. + * + * @see https://chainagnostic.org/CAIPs/caip-19 + */ +export function stringifyAssetId({ + assetNamespace, + contract: { chainId, address }, + tokenId, +}: AssetId): AssetIdString { + return CaipAssetId.format({ + chainId: { namespace: "eip155", reference: chainId.toString() }, + assetName: { namespace: assetNamespace, reference: address }, + tokenId: tokenId.toString(), + }).toLowerCase(); +} diff --git a/packages/enssdk/src/lib/ids.ts b/packages/enssdk/src/lib/ids.ts new file mode 100644 index 0000000000..5450fcf49a --- /dev/null +++ b/packages/enssdk/src/lib/ids.ts @@ -0,0 +1,63 @@ +import { type Address, hexToBigInt } from "viem"; + +import { zeroLower32Bits } from "../_lib/zeroLower32Bits"; +import { stringifyAccountId, stringifyAssetId } from "./caip"; +import type { + AccountId, + DomainId, + EACResource, + ENSv1DomainId, + ENSv2DomainId, + LabelHash, + Node, + PermissionsId, + PermissionsResourceId, + PermissionsUserId, + RegistrationId, + RegistryId, + RenewalId, + ResolverId, + ResolverRecordsId, + StorageId, + TokenId, +} from "./types"; +import { AssetNamespaces } from "./types"; + +export const makeRegistryId = (accountId: AccountId) => stringifyAccountId(accountId) as RegistryId; + +export const makeResolverId = (contract: AccountId) => stringifyAccountId(contract) as ResolverId; + +export const makeENSv1DomainId = (node: Node) => node as ENSv1DomainId; + +export const makeENSv2DomainId = (registry: AccountId, storageId: StorageId) => + stringifyAssetId({ + assetNamespace: AssetNamespaces.ERC1155, + contract: registry, + tokenId: storageId, + }) as ENSv2DomainId; + +/** + * Computes a Label's {@link StorageId} given its TokenId or LabelHash. + */ +export const makeStorageId = (labelRef: TokenId | LabelHash): StorageId => { + if (typeof labelRef === "bigint") return zeroLower32Bits(labelRef) as StorageId; + return zeroLower32Bits(hexToBigInt(labelRef)) as StorageId; +}; + +export const makePermissionsId = (contract: AccountId) => + stringifyAccountId(contract) as PermissionsId; + +export const makePermissionsResourceId = (contract: AccountId, resource: EACResource) => + `${makePermissionsId(contract)}/${resource}` as PermissionsResourceId; + +export const makePermissionsUserId = (contract: AccountId, resource: EACResource, user: Address) => + `${makePermissionsResourceId(contract, resource)}/${user}` as PermissionsUserId; + +export const makeResolverRecordsId = (resolver: AccountId, node: Node) => + `${makeResolverId(resolver)}/${node}` as ResolverRecordsId; + +export const makeRegistrationId = (domainId: DomainId, registrationIndex: number) => + `${domainId}/${registrationIndex}` as RegistrationId; + +export const makeRenewalId = (domainId: DomainId, registrationIndex: number, index: number) => + `${makeRegistrationId(domainId, registrationIndex)}/${index}` as RenewalId; diff --git a/packages/enssdk/src/lib/index.ts b/packages/enssdk/src/lib/index.ts new file mode 100644 index 0000000000..bc7f9b56c2 --- /dev/null +++ b/packages/enssdk/src/lib/index.ts @@ -0,0 +1,4 @@ +export * from "./caip"; +export * from "./ids"; +export * from "./interpretation"; +export * from "./types"; diff --git a/packages/enssdk/src/lib/interpretation/index.ts b/packages/enssdk/src/lib/interpretation/index.ts new file mode 100644 index 0000000000..dafa9a3393 --- /dev/null +++ b/packages/enssdk/src/lib/interpretation/index.ts @@ -0,0 +1 @@ +export * from "./token-id"; diff --git a/packages/enssdk/src/lib/interpretation/token-id.ts b/packages/enssdk/src/lib/interpretation/token-id.ts new file mode 100644 index 0000000000..0ec37c066e --- /dev/null +++ b/packages/enssdk/src/lib/interpretation/token-id.ts @@ -0,0 +1,16 @@ +import { uint256ToHex32 } from "../../_lib/uint256ToHex32"; +import type { LabelHash, Node, TokenId } from "../types"; + +/** + * Decodes a uint256-encoded-LabelHash (eg. from a tokenId) into a {@link LabelHash}. + * + * @see https://github.com/ensdomains/ens-contracts/blob/db613bc/contracts/ethregistrar/ETHRegistrarController.sol#L215 + */ +export const interpretTokenIdAsLabelHash = (tokenId: TokenId): LabelHash => uint256ToHex32(tokenId); + +/** + * Decodes a uint256-encoded-Node (eg. from a tokenId) into a {@link Node}. + * + * @see https://github.com/ensdomains/ens-contracts/blob/db613bc/contracts/wrapper/ERC1155Fuse.sol#L262 + */ +export const interpretTokenIdAsNode = (tokenId: TokenId): Node => uint256ToHex32(tokenId); diff --git a/packages/enssdk/src/lib/types/eac.ts b/packages/enssdk/src/lib/types/eac.ts new file mode 100644 index 0000000000..c3b3a5b6ed --- /dev/null +++ b/packages/enssdk/src/lib/types/eac.ts @@ -0,0 +1,13 @@ +/** + * Describes an EnhancedAccessControl (EAC) Resource. + * + * @see https://github.com/ensdomains/contracts-v2/blob/e8696c6787e2e7a2fc17c67a3b06955a6b890adc/contracts/src/access-control/EnhancedAccessControl.sol#L17 + */ +export type EACResource = bigint; + +/** + * Describes an EnhancedAccessControl (EAC) Role Bitmap. + * + * @see https://github.com/ensdomains/contracts-v2/blob/e8696c6787e2e7a2fc17c67a3b06955a6b890adc/contracts/src/access-control/EnhancedAccessControl.sol#L33 + */ +export type EACRoleBitmap = bigint; diff --git a/packages/enssdk/src/lib/types/ensv2.ts b/packages/enssdk/src/lib/types/ensv2.ts index 3fee2e4452..d5d484a82c 100644 --- a/packages/enssdk/src/lib/types/ensv2.ts +++ b/packages/enssdk/src/lib/types/ensv2.ts @@ -12,7 +12,7 @@ export type RegistryId = string & { __brand: "RegistryContractId" }; * In ENSv2, the rightmost 32 bits of a TokenId is used for version management, and it is the leftmost * 224 bits that are a stable identifier for a Label within a Registry. */ -export type StorageId = bigint; +export type StorageId = bigint & { __brand: "StorageId" }; /** * The node that uniquely identifies an ENSv1 name. diff --git a/packages/enssdk/src/lib/types/index.ts b/packages/enssdk/src/lib/types/index.ts index 742549e4a7..e4b959b91a 100644 --- a/packages/enssdk/src/lib/types/index.ts +++ b/packages/enssdk/src/lib/types/index.ts @@ -1,4 +1,5 @@ export * from "./coin-type"; +export * from "./eac"; export * from "./ens"; export * from "./ensv2"; export * from "./evm"; diff --git a/packages/enssdk/src/omnigraph/generated/graphql-env.d.ts b/packages/enssdk/src/omnigraph/generated/graphql-env.d.ts index 0e932636f1..48f7523682 100644 --- a/packages/enssdk/src/omnigraph/generated/graphql-env.d.ts +++ b/packages/enssdk/src/omnigraph/generated/graphql-env.d.ts @@ -3,43 +3,44 @@ export type introspection_types = { 'Account': { kind: 'OBJECT'; name: 'Account'; fields: { 'address': { name: 'address'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Address'; ofType: null; }; } }; 'domains': { name: 'domains'; type: { kind: 'OBJECT'; name: 'AccountDomainsConnection'; ofType: null; } }; 'events': { name: 'events'; type: { kind: 'OBJECT'; name: 'AccountEventsConnection'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Address'; ofType: null; }; } }; 'permissions': { name: 'permissions'; type: { kind: 'OBJECT'; name: 'AccountPermissionsConnection'; ofType: null; } }; 'registryPermissions': { name: 'registryPermissions'; type: { kind: 'OBJECT'; name: 'AccountRegistryPermissionsConnection'; ofType: null; } }; 'resolverPermissions': { name: 'resolverPermissions'; type: { kind: 'OBJECT'; name: 'AccountResolverPermissionsConnection'; ofType: null; } }; }; }; - 'AccountDomainsConnection': { kind: 'OBJECT'; name: 'AccountDomainsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountDomainsConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'AccountDomainsConnectionEdge': { kind: 'OBJECT'; name: 'AccountDomainsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; } }; }; }; + 'AccountByInput': { kind: 'INPUT_OBJECT'; name: 'AccountByInput'; isOneOf: true; inputFields: [{ name: 'address'; type: { kind: 'SCALAR'; name: 'Address'; ofType: null; }; defaultValue: null }, { name: 'id'; type: { kind: 'SCALAR'; name: 'Address'; ofType: null; }; defaultValue: null }]; }; + 'AccountDomainsConnection': { kind: 'OBJECT'; name: 'AccountDomainsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountDomainsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'AccountDomainsConnectionEdge': { kind: 'OBJECT'; name: 'AccountDomainsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; } }; }; }; 'AccountDomainsWhereInput': { kind: 'INPUT_OBJECT'; name: 'AccountDomainsWhereInput'; isOneOf: false; inputFields: [{ name: 'canonical'; type: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; defaultValue: "false" }, { name: 'name'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; }; defaultValue: null }]; }; - 'AccountEventsConnection': { kind: 'OBJECT'; name: 'AccountEventsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountEventsConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'AccountEventsConnectionEdge': { kind: 'OBJECT'; name: 'AccountEventsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'OBJECT'; name: 'Event'; ofType: null; } }; }; }; + 'AccountEventsConnection': { kind: 'OBJECT'; name: 'AccountEventsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountEventsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'AccountEventsConnectionEdge': { kind: 'OBJECT'; name: 'AccountEventsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Event'; ofType: null; }; } }; }; }; 'AccountEventsWhereInput': { kind: 'INPUT_OBJECT'; name: 'AccountEventsWhereInput'; isOneOf: false; inputFields: [{ name: 'selector_in'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Hex'; ofType: null; }; }; }; defaultValue: null }, { name: 'timestamp_gte'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; defaultValue: null }, { name: 'timestamp_lte'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; defaultValue: null }]; }; - 'AccountId': { kind: 'OBJECT'; name: 'AccountId'; fields: { 'address': { name: 'address'; type: { kind: 'SCALAR'; name: 'Address'; ofType: null; } }; 'chainId': { name: 'chainId'; type: { kind: 'SCALAR'; name: 'ChainId'; ofType: null; } }; }; }; + 'AccountId': { kind: 'OBJECT'; name: 'AccountId'; fields: { 'address': { name: 'address'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Address'; ofType: null; }; } }; 'chainId': { name: 'chainId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ChainId'; ofType: null; }; } }; }; }; 'AccountIdInput': { kind: 'INPUT_OBJECT'; name: 'AccountIdInput'; isOneOf: false; inputFields: [{ name: 'address'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Address'; ofType: null; }; }; defaultValue: null }, { name: 'chainId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ChainId'; ofType: null; }; }; defaultValue: null }]; }; - 'AccountPermissionsConnection': { kind: 'OBJECT'; name: 'AccountPermissionsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountPermissionsConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'AccountPermissionsConnectionEdge': { kind: 'OBJECT'; name: 'AccountPermissionsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'OBJECT'; name: 'PermissionsUser'; ofType: null; } }; }; }; - 'AccountRegistryPermissionsConnection': { kind: 'OBJECT'; name: 'AccountRegistryPermissionsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountRegistryPermissionsConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'AccountRegistryPermissionsConnectionEdge': { kind: 'OBJECT'; name: 'AccountRegistryPermissionsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'OBJECT'; name: 'RegistryPermissionsUser'; ofType: null; } }; }; }; - 'AccountResolverPermissionsConnection': { kind: 'OBJECT'; name: 'AccountResolverPermissionsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountResolverPermissionsConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'AccountResolverPermissionsConnectionEdge': { kind: 'OBJECT'; name: 'AccountResolverPermissionsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'OBJECT'; name: 'ResolverPermissionsUser'; ofType: null; } }; }; }; + 'AccountPermissionsConnection': { kind: 'OBJECT'; name: 'AccountPermissionsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountPermissionsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'AccountPermissionsConnectionEdge': { kind: 'OBJECT'; name: 'AccountPermissionsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PermissionsUser'; ofType: null; }; } }; }; }; + 'AccountRegistryPermissionsConnection': { kind: 'OBJECT'; name: 'AccountRegistryPermissionsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountRegistryPermissionsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'AccountRegistryPermissionsConnectionEdge': { kind: 'OBJECT'; name: 'AccountRegistryPermissionsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'RegistryPermissionsUser'; ofType: null; }; } }; }; }; + 'AccountResolverPermissionsConnection': { kind: 'OBJECT'; name: 'AccountResolverPermissionsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountResolverPermissionsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'AccountResolverPermissionsConnectionEdge': { kind: 'OBJECT'; name: 'AccountResolverPermissionsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'ResolverPermissionsUser'; ofType: null; }; } }; }; }; 'Address': unknown; 'BaseRegistrarRegistration': { kind: 'OBJECT'; name: 'BaseRegistrarRegistration'; fields: { 'baseCost': { name: 'baseCost'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'domain': { name: 'domain'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; } }; 'event': { name: 'event'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Event'; ofType: null; }; } }; 'expired': { name: 'expired'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'expiry': { name: 'expiry'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'RegistrationId'; ofType: null; }; } }; 'isInGracePeriod': { name: 'isInGracePeriod'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'premium': { name: 'premium'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'referrer': { name: 'referrer'; type: { kind: 'SCALAR'; name: 'Hex'; ofType: null; } }; 'registrant': { name: 'registrant'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'registrar': { name: 'registrar'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; }; } }; 'renewals': { name: 'renewals'; type: { kind: 'OBJECT'; name: 'RegistrationRenewalsConnection'; ofType: null; } }; 'start': { name: 'start'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'unregistrant': { name: 'unregistrant'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'wrapped': { name: 'wrapped'; type: { kind: 'OBJECT'; name: 'WrappedBaseRegistrarRegistration'; ofType: null; } }; }; }; 'BigInt': unknown; 'Boolean': unknown; 'ChainId': unknown; 'CoinType': unknown; - 'Domain': { kind: 'INTERFACE'; name: 'Domain'; fields: { 'events': { name: 'events'; type: { kind: 'OBJECT'; name: 'DomainEventsConnection'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'DomainId'; ofType: null; }; } }; 'label': { name: 'label'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Label'; ofType: null; }; } }; 'name': { name: 'name'; type: { kind: 'SCALAR'; name: 'Name'; ofType: null; } }; 'owner': { name: 'owner'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'path': { name: 'path'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; }; } }; 'registration': { name: 'registration'; type: { kind: 'INTERFACE'; name: 'Registration'; ofType: null; } }; 'registrations': { name: 'registrations'; type: { kind: 'OBJECT'; name: 'DomainRegistrationsConnection'; ofType: null; } }; 'resolver': { name: 'resolver'; type: { kind: 'OBJECT'; name: 'Resolver'; ofType: null; } }; 'subdomains': { name: 'subdomains'; type: { kind: 'OBJECT'; name: 'DomainSubdomainsConnection'; ofType: null; } }; }; possibleTypes: 'ENSv1Domain' | 'ENSv2Domain'; }; - 'DomainEventsConnection': { kind: 'OBJECT'; name: 'DomainEventsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'DomainEventsConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'DomainEventsConnectionEdge': { kind: 'OBJECT'; name: 'DomainEventsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'OBJECT'; name: 'Event'; ofType: null; } }; }; }; + 'Domain': { kind: 'INTERFACE'; name: 'Domain'; fields: { 'events': { name: 'events'; type: { kind: 'OBJECT'; name: 'DomainEventsConnection'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'DomainId'; ofType: null; }; } }; 'label': { name: 'label'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Label'; ofType: null; }; } }; 'name': { name: 'name'; type: { kind: 'SCALAR'; name: 'InterpretedName'; ofType: null; } }; 'owner': { name: 'owner'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'path': { name: 'path'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; }; } }; 'registration': { name: 'registration'; type: { kind: 'INTERFACE'; name: 'Registration'; ofType: null; } }; 'registrations': { name: 'registrations'; type: { kind: 'OBJECT'; name: 'DomainRegistrationsConnection'; ofType: null; } }; 'resolver': { name: 'resolver'; type: { kind: 'OBJECT'; name: 'Resolver'; ofType: null; } }; 'subdomains': { name: 'subdomains'; type: { kind: 'OBJECT'; name: 'DomainSubdomainsConnection'; ofType: null; } }; }; possibleTypes: 'ENSv1Domain' | 'ENSv2Domain'; }; + 'DomainEventsConnection': { kind: 'OBJECT'; name: 'DomainEventsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'DomainEventsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'DomainEventsConnectionEdge': { kind: 'OBJECT'; name: 'DomainEventsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Event'; ofType: null; }; } }; }; }; 'DomainId': unknown; - 'DomainIdInput': { kind: 'INPUT_OBJECT'; name: 'DomainIdInput'; isOneOf: true; inputFields: [{ name: 'id'; type: { kind: 'SCALAR'; name: 'DomainId'; ofType: null; }; defaultValue: null }, { name: 'name'; type: { kind: 'SCALAR'; name: 'Name'; ofType: null; }; defaultValue: null }]; }; + 'DomainIdInput': { kind: 'INPUT_OBJECT'; name: 'DomainIdInput'; isOneOf: true; inputFields: [{ name: 'id'; type: { kind: 'SCALAR'; name: 'DomainId'; ofType: null; }; defaultValue: null }, { name: 'name'; type: { kind: 'SCALAR'; name: 'InterpretedName'; ofType: null; }; defaultValue: null }]; }; 'DomainPermissionsWhereInput': { kind: 'INPUT_OBJECT'; name: 'DomainPermissionsWhereInput'; isOneOf: false; inputFields: [{ name: 'user'; type: { kind: 'SCALAR'; name: 'Address'; ofType: null; }; defaultValue: null }]; }; - 'DomainRegistrationsConnection': { kind: 'OBJECT'; name: 'DomainRegistrationsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'DomainRegistrationsConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'DomainRegistrationsConnectionEdge': { kind: 'OBJECT'; name: 'DomainRegistrationsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'INTERFACE'; name: 'Registration'; ofType: null; } }; }; }; - 'DomainSubdomainsConnection': { kind: 'OBJECT'; name: 'DomainSubdomainsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'DomainSubdomainsConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'DomainSubdomainsConnectionEdge': { kind: 'OBJECT'; name: 'DomainSubdomainsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; } }; }; }; + 'DomainRegistrationsConnection': { kind: 'OBJECT'; name: 'DomainRegistrationsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'DomainRegistrationsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'DomainRegistrationsConnectionEdge': { kind: 'OBJECT'; name: 'DomainRegistrationsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Registration'; ofType: null; }; } }; }; }; + 'DomainSubdomainsConnection': { kind: 'OBJECT'; name: 'DomainSubdomainsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'DomainSubdomainsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'DomainSubdomainsConnectionEdge': { kind: 'OBJECT'; name: 'DomainSubdomainsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; } }; }; }; 'DomainsOrderBy': { name: 'DomainsOrderBy'; enumValues: 'NAME' | 'REGISTRATION_EXPIRY' | 'REGISTRATION_TIMESTAMP'; }; 'DomainsOrderInput': { kind: 'INPUT_OBJECT'; name: 'DomainsOrderInput'; isOneOf: false; inputFields: [{ name: 'by'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'ENUM'; name: 'DomainsOrderBy'; ofType: null; }; }; defaultValue: null }, { name: 'dir'; type: { kind: 'ENUM'; name: 'OrderDirection'; ofType: null; }; defaultValue: "ASC" }]; }; 'DomainsWhereInput': { kind: 'INPUT_OBJECT'; name: 'DomainsWhereInput'; isOneOf: false; inputFields: [{ name: 'canonical'; type: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; defaultValue: "false" }, { name: 'name'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; }; defaultValue: null }]; }; - 'ENSv1Domain': { kind: 'OBJECT'; name: 'ENSv1Domain'; fields: { 'events': { name: 'events'; type: { kind: 'OBJECT'; name: 'DomainEventsConnection'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'DomainId'; ofType: null; }; } }; 'label': { name: 'label'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Label'; ofType: null; }; } }; 'name': { name: 'name'; type: { kind: 'SCALAR'; name: 'Name'; ofType: null; } }; 'owner': { name: 'owner'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'parent': { name: 'parent'; type: { kind: 'OBJECT'; name: 'ENSv1Domain'; ofType: null; } }; 'path': { name: 'path'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; }; } }; 'registration': { name: 'registration'; type: { kind: 'INTERFACE'; name: 'Registration'; ofType: null; } }; 'registrations': { name: 'registrations'; type: { kind: 'OBJECT'; name: 'DomainRegistrationsConnection'; ofType: null; } }; 'resolver': { name: 'resolver'; type: { kind: 'OBJECT'; name: 'Resolver'; ofType: null; } }; 'rootRegistryOwner': { name: 'rootRegistryOwner'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'subdomains': { name: 'subdomains'; type: { kind: 'OBJECT'; name: 'DomainSubdomainsConnection'; ofType: null; } }; }; }; - 'ENSv2Domain': { kind: 'OBJECT'; name: 'ENSv2Domain'; fields: { 'events': { name: 'events'; type: { kind: 'OBJECT'; name: 'DomainEventsConnection'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'DomainId'; ofType: null; }; } }; 'label': { name: 'label'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Label'; ofType: null; }; } }; 'name': { name: 'name'; type: { kind: 'SCALAR'; name: 'Name'; ofType: null; } }; 'owner': { name: 'owner'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'path': { name: 'path'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; }; } }; 'permissions': { name: 'permissions'; type: { kind: 'OBJECT'; name: 'ENSv2DomainPermissionsConnection'; ofType: null; } }; 'registration': { name: 'registration'; type: { kind: 'INTERFACE'; name: 'Registration'; ofType: null; } }; 'registrations': { name: 'registrations'; type: { kind: 'OBJECT'; name: 'DomainRegistrationsConnection'; ofType: null; } }; 'registry': { name: 'registry'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Registry'; ofType: null; }; } }; 'resolver': { name: 'resolver'; type: { kind: 'OBJECT'; name: 'Resolver'; ofType: null; } }; 'subdomains': { name: 'subdomains'; type: { kind: 'OBJECT'; name: 'DomainSubdomainsConnection'; ofType: null; } }; 'subregistry': { name: 'subregistry'; type: { kind: 'OBJECT'; name: 'Registry'; ofType: null; } }; 'tokenId': { name: 'tokenId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; }; }; - 'ENSv2DomainPermissionsConnection': { kind: 'OBJECT'; name: 'ENSv2DomainPermissionsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'ENSv2DomainPermissionsConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'ENSv2DomainPermissionsConnectionEdge': { kind: 'OBJECT'; name: 'ENSv2DomainPermissionsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'OBJECT'; name: 'PermissionsUser'; ofType: null; } }; }; }; + 'ENSv1Domain': { kind: 'OBJECT'; name: 'ENSv1Domain'; fields: { 'events': { name: 'events'; type: { kind: 'OBJECT'; name: 'DomainEventsConnection'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'DomainId'; ofType: null; }; } }; 'label': { name: 'label'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Label'; ofType: null; }; } }; 'name': { name: 'name'; type: { kind: 'SCALAR'; name: 'InterpretedName'; ofType: null; } }; 'owner': { name: 'owner'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'parent': { name: 'parent'; type: { kind: 'OBJECT'; name: 'ENSv1Domain'; ofType: null; } }; 'path': { name: 'path'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; }; } }; 'registration': { name: 'registration'; type: { kind: 'INTERFACE'; name: 'Registration'; ofType: null; } }; 'registrations': { name: 'registrations'; type: { kind: 'OBJECT'; name: 'DomainRegistrationsConnection'; ofType: null; } }; 'resolver': { name: 'resolver'; type: { kind: 'OBJECT'; name: 'Resolver'; ofType: null; } }; 'rootRegistryOwner': { name: 'rootRegistryOwner'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'subdomains': { name: 'subdomains'; type: { kind: 'OBJECT'; name: 'DomainSubdomainsConnection'; ofType: null; } }; }; }; + 'ENSv2Domain': { kind: 'OBJECT'; name: 'ENSv2Domain'; fields: { 'events': { name: 'events'; type: { kind: 'OBJECT'; name: 'DomainEventsConnection'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'DomainId'; ofType: null; }; } }; 'label': { name: 'label'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Label'; ofType: null; }; } }; 'name': { name: 'name'; type: { kind: 'SCALAR'; name: 'InterpretedName'; ofType: null; } }; 'owner': { name: 'owner'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'path': { name: 'path'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; }; } }; 'permissions': { name: 'permissions'; type: { kind: 'OBJECT'; name: 'ENSv2DomainPermissionsConnection'; ofType: null; } }; 'registration': { name: 'registration'; type: { kind: 'INTERFACE'; name: 'Registration'; ofType: null; } }; 'registrations': { name: 'registrations'; type: { kind: 'OBJECT'; name: 'DomainRegistrationsConnection'; ofType: null; } }; 'registry': { name: 'registry'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Registry'; ofType: null; }; } }; 'resolver': { name: 'resolver'; type: { kind: 'OBJECT'; name: 'Resolver'; ofType: null; } }; 'subdomains': { name: 'subdomains'; type: { kind: 'OBJECT'; name: 'DomainSubdomainsConnection'; ofType: null; } }; 'subregistry': { name: 'subregistry'; type: { kind: 'OBJECT'; name: 'Registry'; ofType: null; } }; 'tokenId': { name: 'tokenId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; }; }; + 'ENSv2DomainPermissionsConnection': { kind: 'OBJECT'; name: 'ENSv2DomainPermissionsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'ENSv2DomainPermissionsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'ENSv2DomainPermissionsConnectionEdge': { kind: 'OBJECT'; name: 'ENSv2DomainPermissionsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PermissionsUser'; ofType: null; }; } }; }; }; 'ENSv2RegistryRegistration': { kind: 'OBJECT'; name: 'ENSv2RegistryRegistration'; fields: { 'domain': { name: 'domain'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; } }; 'event': { name: 'event'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Event'; ofType: null; }; } }; 'expired': { name: 'expired'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'expiry': { name: 'expiry'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'RegistrationId'; ofType: null; }; } }; 'referrer': { name: 'referrer'; type: { kind: 'SCALAR'; name: 'Hex'; ofType: null; } }; 'registrant': { name: 'registrant'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'registrar': { name: 'registrar'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; }; } }; 'renewals': { name: 'renewals'; type: { kind: 'OBJECT'; name: 'RegistrationRenewalsConnection'; ofType: null; } }; 'start': { name: 'start'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'unregistrant': { name: 'unregistrant'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; }; }; 'ENSv2RegistryReservation': { kind: 'OBJECT'; name: 'ENSv2RegistryReservation'; fields: { 'domain': { name: 'domain'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; } }; 'event': { name: 'event'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Event'; ofType: null; }; } }; 'expired': { name: 'expired'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'expiry': { name: 'expiry'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'RegistrationId'; ofType: null; }; } }; 'referrer': { name: 'referrer'; type: { kind: 'SCALAR'; name: 'Hex'; ofType: null; } }; 'registrant': { name: 'registrant'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'registrar': { name: 'registrar'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; }; } }; 'renewals': { name: 'renewals'; type: { kind: 'OBJECT'; name: 'RegistrationRenewalsConnection'; ofType: null; } }; 'start': { name: 'start'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'unregistrant': { name: 'unregistrant'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; }; }; 'Event': { kind: 'OBJECT'; name: 'Event'; fields: { 'address': { name: 'address'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Address'; ofType: null; }; } }; 'blockHash': { name: 'blockHash'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Hex'; ofType: null; }; } }; 'blockNumber': { name: 'blockNumber'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'chainId': { name: 'chainId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ChainId'; ofType: null; }; } }; 'data': { name: 'data'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Hex'; ofType: null; }; } }; 'from': { name: 'from'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Address'; ofType: null; }; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ID'; ofType: null; }; } }; 'logIndex': { name: 'logIndex'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; 'timestamp': { name: 'timestamp'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'to': { name: 'to'; type: { kind: 'SCALAR'; name: 'Address'; ofType: null; } }; 'topics': { name: 'topics'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Hex'; ofType: null; }; }; }; } }; 'transactionHash': { name: 'transactionHash'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Hex'; ofType: null; }; } }; 'transactionIndex': { name: 'transactionIndex'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; @@ -47,60 +48,62 @@ export type introspection_types = { 'Hex': unknown; 'ID': unknown; 'Int': unknown; - 'Label': { kind: 'OBJECT'; name: 'Label'; fields: { 'hash': { name: 'hash'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Hex'; ofType: null; }; } }; 'interpreted': { name: 'interpreted'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; }; }; - 'Name': unknown; - 'NameOrNodeInput': { kind: 'INPUT_OBJECT'; name: 'NameOrNodeInput'; isOneOf: true; inputFields: [{ name: 'name'; type: { kind: 'SCALAR'; name: 'Name'; ofType: null; }; defaultValue: null }, { name: 'node'; type: { kind: 'SCALAR'; name: 'Node'; ofType: null; }; defaultValue: null }]; }; + 'InterpretedLabel': unknown; + 'InterpretedName': unknown; + 'Label': { kind: 'OBJECT'; name: 'Label'; fields: { 'hash': { name: 'hash'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Hex'; ofType: null; }; } }; 'interpreted': { name: 'interpreted'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'InterpretedLabel'; ofType: null; }; } }; }; }; + 'NameOrNodeInput': { kind: 'INPUT_OBJECT'; name: 'NameOrNodeInput'; isOneOf: true; inputFields: [{ name: 'name'; type: { kind: 'SCALAR'; name: 'InterpretedName'; ofType: null; }; defaultValue: null }, { name: 'node'; type: { kind: 'SCALAR'; name: 'Node'; ofType: null; }; defaultValue: null }]; }; 'NameWrapperRegistration': { kind: 'OBJECT'; name: 'NameWrapperRegistration'; fields: { 'domain': { name: 'domain'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; } }; 'event': { name: 'event'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Event'; ofType: null; }; } }; 'expired': { name: 'expired'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'expiry': { name: 'expiry'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'fuses': { name: 'fuses'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'RegistrationId'; ofType: null; }; } }; 'referrer': { name: 'referrer'; type: { kind: 'SCALAR'; name: 'Hex'; ofType: null; } }; 'registrant': { name: 'registrant'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'registrar': { name: 'registrar'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; }; } }; 'renewals': { name: 'renewals'; type: { kind: 'OBJECT'; name: 'RegistrationRenewalsConnection'; ofType: null; } }; 'start': { name: 'start'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'unregistrant': { name: 'unregistrant'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; }; }; 'Node': unknown; 'OrderDirection': { name: 'OrderDirection'; enumValues: 'ASC' | 'DESC'; }; 'PageInfo': { kind: 'OBJECT'; name: 'PageInfo'; fields: { 'endCursor': { name: 'endCursor'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'hasNextPage': { name: 'hasNextPage'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'hasPreviousPage': { name: 'hasPreviousPage'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'startCursor': { name: 'startCursor'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; }; }; 'Permissions': { kind: 'OBJECT'; name: 'Permissions'; fields: { 'contract': { name: 'contract'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; }; } }; 'events': { name: 'events'; type: { kind: 'OBJECT'; name: 'PermissionsEventsConnection'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'PermissionsId'; ofType: null; }; } }; 'resources': { name: 'resources'; type: { kind: 'OBJECT'; name: 'PermissionsResourcesConnection'; ofType: null; } }; 'root': { name: 'root'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PermissionsResource'; ofType: null; }; } }; }; }; - 'PermissionsEventsConnection': { kind: 'OBJECT'; name: 'PermissionsEventsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'PermissionsEventsConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'PermissionsEventsConnectionEdge': { kind: 'OBJECT'; name: 'PermissionsEventsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'OBJECT'; name: 'Event'; ofType: null; } }; }; }; + 'PermissionsEventsConnection': { kind: 'OBJECT'; name: 'PermissionsEventsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PermissionsEventsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'PermissionsEventsConnectionEdge': { kind: 'OBJECT'; name: 'PermissionsEventsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Event'; ofType: null; }; } }; }; }; 'PermissionsId': unknown; + 'PermissionsIdInput': { kind: 'INPUT_OBJECT'; name: 'PermissionsIdInput'; isOneOf: true; inputFields: [{ name: 'contract'; type: { kind: 'INPUT_OBJECT'; name: 'AccountIdInput'; ofType: null; }; defaultValue: null }, { name: 'id'; type: { kind: 'SCALAR'; name: 'PermissionsId'; ofType: null; }; defaultValue: null }]; }; 'PermissionsResource': { kind: 'OBJECT'; name: 'PermissionsResource'; fields: { 'contract': { name: 'contract'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; }; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'PermissionsResourceId'; ofType: null; }; } }; 'permissions': { name: 'permissions'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Permissions'; ofType: null; }; } }; 'resource': { name: 'resource'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'users': { name: 'users'; type: { kind: 'OBJECT'; name: 'PermissionsResourceUsersConnection'; ofType: null; } }; }; }; 'PermissionsResourceId': unknown; - 'PermissionsResourceUsersConnection': { kind: 'OBJECT'; name: 'PermissionsResourceUsersConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'PermissionsResourceUsersConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'PermissionsResourceUsersConnectionEdge': { kind: 'OBJECT'; name: 'PermissionsResourceUsersConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'OBJECT'; name: 'PermissionsUser'; ofType: null; } }; }; }; - 'PermissionsResourcesConnection': { kind: 'OBJECT'; name: 'PermissionsResourcesConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'PermissionsResourcesConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'PermissionsResourcesConnectionEdge': { kind: 'OBJECT'; name: 'PermissionsResourcesConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'OBJECT'; name: 'PermissionsResource'; ofType: null; } }; }; }; + 'PermissionsResourceUsersConnection': { kind: 'OBJECT'; name: 'PermissionsResourceUsersConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PermissionsResourceUsersConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'PermissionsResourceUsersConnectionEdge': { kind: 'OBJECT'; name: 'PermissionsResourceUsersConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PermissionsUser'; ofType: null; }; } }; }; }; + 'PermissionsResourcesConnection': { kind: 'OBJECT'; name: 'PermissionsResourcesConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PermissionsResourcesConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'PermissionsResourcesConnectionEdge': { kind: 'OBJECT'; name: 'PermissionsResourcesConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PermissionsResource'; ofType: null; }; } }; }; }; 'PermissionsUser': { kind: 'OBJECT'; name: 'PermissionsUser'; fields: { 'contract': { name: 'contract'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; }; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'PermissionsUserId'; ofType: null; }; } }; 'resource': { name: 'resource'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'roles': { name: 'roles'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'user': { name: 'user'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Account'; ofType: null; }; } }; }; }; 'PermissionsUserId': unknown; 'Query': { kind: 'OBJECT'; name: 'Query'; fields: { 'account': { name: 'account'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'domain': { name: 'domain'; type: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; } }; 'domains': { name: 'domains'; type: { kind: 'OBJECT'; name: 'QueryDomainsConnection'; ofType: null; } }; 'permissions': { name: 'permissions'; type: { kind: 'OBJECT'; name: 'Permissions'; ofType: null; } }; 'registrations': { name: 'registrations'; type: { kind: 'OBJECT'; name: 'QueryRegistrationsConnection'; ofType: null; } }; 'registry': { name: 'registry'; type: { kind: 'OBJECT'; name: 'Registry'; ofType: null; } }; 'resolver': { name: 'resolver'; type: { kind: 'OBJECT'; name: 'Resolver'; ofType: null; } }; 'resolvers': { name: 'resolvers'; type: { kind: 'OBJECT'; name: 'QueryResolversConnection'; ofType: null; } }; 'root': { name: 'root'; type: { kind: 'OBJECT'; name: 'Registry'; ofType: null; } }; 'v1Domains': { name: 'v1Domains'; type: { kind: 'OBJECT'; name: 'QueryV1DomainsConnection'; ofType: null; } }; 'v2Domains': { name: 'v2Domains'; type: { kind: 'OBJECT'; name: 'QueryV2DomainsConnection'; ofType: null; } }; }; }; - 'QueryDomainsConnection': { kind: 'OBJECT'; name: 'QueryDomainsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'QueryDomainsConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'QueryDomainsConnectionEdge': { kind: 'OBJECT'; name: 'QueryDomainsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; } }; }; }; - 'QueryRegistrationsConnection': { kind: 'OBJECT'; name: 'QueryRegistrationsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'QueryRegistrationsConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'QueryRegistrationsConnectionEdge': { kind: 'OBJECT'; name: 'QueryRegistrationsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'INTERFACE'; name: 'Registration'; ofType: null; } }; }; }; - 'QueryResolversConnection': { kind: 'OBJECT'; name: 'QueryResolversConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'QueryResolversConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'QueryResolversConnectionEdge': { kind: 'OBJECT'; name: 'QueryResolversConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'OBJECT'; name: 'Resolver'; ofType: null; } }; }; }; - 'QueryV1DomainsConnection': { kind: 'OBJECT'; name: 'QueryV1DomainsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'QueryV1DomainsConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'QueryV1DomainsConnectionEdge': { kind: 'OBJECT'; name: 'QueryV1DomainsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'OBJECT'; name: 'ENSv1Domain'; ofType: null; } }; }; }; - 'QueryV2DomainsConnection': { kind: 'OBJECT'; name: 'QueryV2DomainsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'QueryV2DomainsConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'QueryV2DomainsConnectionEdge': { kind: 'OBJECT'; name: 'QueryV2DomainsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'OBJECT'; name: 'ENSv2Domain'; ofType: null; } }; }; }; + 'QueryDomainsConnection': { kind: 'OBJECT'; name: 'QueryDomainsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'QueryDomainsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'QueryDomainsConnectionEdge': { kind: 'OBJECT'; name: 'QueryDomainsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; } }; }; }; + 'QueryRegistrationsConnection': { kind: 'OBJECT'; name: 'QueryRegistrationsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'QueryRegistrationsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'QueryRegistrationsConnectionEdge': { kind: 'OBJECT'; name: 'QueryRegistrationsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Registration'; ofType: null; }; } }; }; }; + 'QueryResolversConnection': { kind: 'OBJECT'; name: 'QueryResolversConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'QueryResolversConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'QueryResolversConnectionEdge': { kind: 'OBJECT'; name: 'QueryResolversConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Resolver'; ofType: null; }; } }; }; }; + 'QueryV1DomainsConnection': { kind: 'OBJECT'; name: 'QueryV1DomainsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'QueryV1DomainsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'QueryV1DomainsConnectionEdge': { kind: 'OBJECT'; name: 'QueryV1DomainsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'ENSv1Domain'; ofType: null; }; } }; }; }; + 'QueryV2DomainsConnection': { kind: 'OBJECT'; name: 'QueryV2DomainsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'QueryV2DomainsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'QueryV2DomainsConnectionEdge': { kind: 'OBJECT'; name: 'QueryV2DomainsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'ENSv2Domain'; ofType: null; }; } }; }; }; 'Registration': { kind: 'INTERFACE'; name: 'Registration'; fields: { 'domain': { name: 'domain'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; } }; 'event': { name: 'event'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Event'; ofType: null; }; } }; 'expired': { name: 'expired'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'expiry': { name: 'expiry'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'RegistrationId'; ofType: null; }; } }; 'referrer': { name: 'referrer'; type: { kind: 'SCALAR'; name: 'Hex'; ofType: null; } }; 'registrant': { name: 'registrant'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'registrar': { name: 'registrar'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; }; } }; 'renewals': { name: 'renewals'; type: { kind: 'OBJECT'; name: 'RegistrationRenewalsConnection'; ofType: null; } }; 'start': { name: 'start'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'unregistrant': { name: 'unregistrant'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; }; possibleTypes: 'BaseRegistrarRegistration' | 'ENSv2RegistryRegistration' | 'ENSv2RegistryReservation' | 'NameWrapperRegistration' | 'ThreeDNSRegistration'; }; 'RegistrationId': unknown; - 'RegistrationRenewalsConnection': { kind: 'OBJECT'; name: 'RegistrationRenewalsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'RegistrationRenewalsConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'RegistrationRenewalsConnectionEdge': { kind: 'OBJECT'; name: 'RegistrationRenewalsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'OBJECT'; name: 'Renewal'; ofType: null; } }; }; }; + 'RegistrationRenewalsConnection': { kind: 'OBJECT'; name: 'RegistrationRenewalsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'RegistrationRenewalsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'RegistrationRenewalsConnectionEdge': { kind: 'OBJECT'; name: 'RegistrationRenewalsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Renewal'; ofType: null; }; } }; }; }; 'Registry': { kind: 'OBJECT'; name: 'Registry'; fields: { 'contract': { name: 'contract'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; }; } }; 'domains': { name: 'domains'; type: { kind: 'OBJECT'; name: 'RegistryDomainsConnection'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'RegistryId'; ofType: null; }; } }; 'parents': { name: 'parents'; type: { kind: 'OBJECT'; name: 'RegistryParentsConnection'; ofType: null; } }; 'permissions': { name: 'permissions'; type: { kind: 'OBJECT'; name: 'Permissions'; ofType: null; } }; }; }; - 'RegistryDomainsConnection': { kind: 'OBJECT'; name: 'RegistryDomainsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'RegistryDomainsConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'RegistryDomainsConnectionEdge': { kind: 'OBJECT'; name: 'RegistryDomainsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; } }; }; }; + 'RegistryDomainsConnection': { kind: 'OBJECT'; name: 'RegistryDomainsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'RegistryDomainsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'RegistryDomainsConnectionEdge': { kind: 'OBJECT'; name: 'RegistryDomainsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; } }; }; }; 'RegistryDomainsWhereInput': { kind: 'INPUT_OBJECT'; name: 'RegistryDomainsWhereInput'; isOneOf: false; inputFields: [{ name: 'name'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; }; defaultValue: null }]; }; 'RegistryId': unknown; 'RegistryIdInput': { kind: 'INPUT_OBJECT'; name: 'RegistryIdInput'; isOneOf: true; inputFields: [{ name: 'contract'; type: { kind: 'INPUT_OBJECT'; name: 'AccountIdInput'; ofType: null; }; defaultValue: null }, { name: 'id'; type: { kind: 'SCALAR'; name: 'RegistryId'; ofType: null; }; defaultValue: null }]; }; - 'RegistryParentsConnection': { kind: 'OBJECT'; name: 'RegistryParentsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'RegistryParentsConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'RegistryParentsConnectionEdge': { kind: 'OBJECT'; name: 'RegistryParentsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'OBJECT'; name: 'ENSv2Domain'; ofType: null; } }; }; }; + 'RegistryParentsConnection': { kind: 'OBJECT'; name: 'RegistryParentsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'RegistryParentsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'RegistryParentsConnectionEdge': { kind: 'OBJECT'; name: 'RegistryParentsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'ENSv2Domain'; ofType: null; }; } }; }; }; 'RegistryPermissionsUser': { kind: 'OBJECT'; name: 'RegistryPermissionsUser'; fields: { 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'PermissionsUserId'; ofType: null; }; } }; 'registry': { name: 'registry'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Registry'; ofType: null; }; } }; 'resource': { name: 'resource'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'roles': { name: 'roles'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'user': { name: 'user'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Account'; ofType: null; }; } }; }; }; 'Renewal': { kind: 'OBJECT'; name: 'Renewal'; fields: { 'base': { name: 'base'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'duration': { name: 'duration'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'event': { name: 'event'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Event'; ofType: null; }; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'RenewalId'; ofType: null; }; } }; 'premium': { name: 'premium'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'referrer': { name: 'referrer'; type: { kind: 'SCALAR'; name: 'Hex'; ofType: null; } }; }; }; 'RenewalId': unknown; 'Resolver': { kind: 'OBJECT'; name: 'Resolver'; fields: { 'bridged': { name: 'bridged'; type: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; } }; 'contract': { name: 'contract'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; }; } }; 'events': { name: 'events'; type: { kind: 'OBJECT'; name: 'ResolverEventsConnection'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ResolverId'; ofType: null; }; } }; 'permissions': { name: 'permissions'; type: { kind: 'OBJECT'; name: 'Permissions'; ofType: null; } }; 'records': { name: 'records'; type: { kind: 'OBJECT'; name: 'ResolverRecordsConnection'; ofType: null; } }; 'records_': { name: 'records_'; type: { kind: 'OBJECT'; name: 'ResolverRecords'; ofType: null; } }; }; }; - 'ResolverEventsConnection': { kind: 'OBJECT'; name: 'ResolverEventsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'ResolverEventsConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'ResolverEventsConnectionEdge': { kind: 'OBJECT'; name: 'ResolverEventsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'OBJECT'; name: 'Event'; ofType: null; } }; }; }; + 'ResolverEventsConnection': { kind: 'OBJECT'; name: 'ResolverEventsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'ResolverEventsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'ResolverEventsConnectionEdge': { kind: 'OBJECT'; name: 'ResolverEventsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Event'; ofType: null; }; } }; }; }; 'ResolverId': unknown; 'ResolverIdInput': { kind: 'INPUT_OBJECT'; name: 'ResolverIdInput'; isOneOf: true; inputFields: [{ name: 'contract'; type: { kind: 'INPUT_OBJECT'; name: 'AccountIdInput'; ofType: null; }; defaultValue: null }, { name: 'id'; type: { kind: 'SCALAR'; name: 'ResolverId'; ofType: null; }; defaultValue: null }]; }; 'ResolverPermissionsUser': { kind: 'OBJECT'; name: 'ResolverPermissionsUser'; fields: { 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'PermissionsUserId'; ofType: null; }; } }; 'resolver': { name: 'resolver'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Resolver'; ofType: null; }; } }; 'resource': { name: 'resource'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'roles': { name: 'roles'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'user': { name: 'user'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Account'; ofType: null; }; } }; }; }; 'ResolverRecords': { kind: 'OBJECT'; name: 'ResolverRecords'; fields: { 'coinTypes': { name: 'coinTypes'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'CoinType'; ofType: null; }; }; }; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ResolverRecordsId'; ofType: null; }; } }; 'keys': { name: 'keys'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; }; }; } }; 'name': { name: 'name'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Node'; ofType: null; }; } }; }; }; - 'ResolverRecordsConnection': { kind: 'OBJECT'; name: 'ResolverRecordsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'ResolverRecordsConnectionEdge'; ofType: null; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'ResolverRecordsConnectionEdge': { kind: 'OBJECT'; name: 'ResolverRecordsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'OBJECT'; name: 'ResolverRecords'; ofType: null; } }; }; }; + 'ResolverRecordsConnection': { kind: 'OBJECT'; name: 'ResolverRecordsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'ResolverRecordsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; + 'ResolverRecordsConnectionEdge': { kind: 'OBJECT'; name: 'ResolverRecordsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'ResolverRecords'; ofType: null; }; } }; }; }; 'ResolverRecordsId': unknown; 'String': unknown; 'SubdomainsWhereInput': { kind: 'INPUT_OBJECT'; name: 'SubdomainsWhereInput'; isOneOf: false; inputFields: [{ name: 'name'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; }; defaultValue: null }]; }; diff --git a/packages/enssdk/src/omnigraph/generated/introspection.ts b/packages/enssdk/src/omnigraph/generated/introspection.ts new file mode 100644 index 0000000000..2c0c938fc9 --- /dev/null +++ b/packages/enssdk/src/omnigraph/generated/introspection.ts @@ -0,0 +1 @@ +export const introspection = {"__schema":{"queryType":{"name":"Query","kind":"OBJECT"},"mutationType":null,"subscriptionType":null,"types":[{"kind":"OBJECT","name":"Account","fields":[{"name":"address","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"domains","type":{"kind":"OBJECT","name":"AccountDomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"events","type":{"kind":"OBJECT","name":"AccountEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"permissions","type":{"kind":"OBJECT","name":"AccountPermissionsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"in","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"registryPermissions","type":{"kind":"OBJECT","name":"AccountRegistryPermissionsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"resolverPermissions","type":{"kind":"OBJECT","name":"AccountResolverPermissionsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountDomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountDomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountDomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountEventsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountEventsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountEventsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountId","fields":[{"name":"address","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"chainId","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountPermissionsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountPermissionsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountPermissionsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsUser","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountRegistryPermissionsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountRegistryPermissionsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountRegistryPermissionsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"RegistryPermissionsUser","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountResolverPermissionsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountResolverPermissionsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountResolverPermissionsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ResolverPermissionsUser","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"BaseRegistrarRegistration","fields":[{"name":"baseCost","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"isInGracePeriod","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"premium","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"wrapped","type":{"kind":"OBJECT","name":"WrappedBaseRegistrarRegistration","ofType":null},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Registration"}]},{"kind":"INTERFACE","name":"Domain","fields":[{"name":"events","type":{"kind":"OBJECT","name":"DomainEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"label","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Label","ofType":null}},"args":[]},{"name":"name","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"owner","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"path","type":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}}},"args":[]},{"name":"registration","type":{"kind":"INTERFACE","name":"Registration","ofType":null},"args":[]},{"name":"registrations","type":{"kind":"OBJECT","name":"DomainRegistrationsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"resolver","type":{"kind":"OBJECT","name":"Resolver","ofType":null},"args":[]},{"name":"subdomains","type":{"kind":"OBJECT","name":"DomainSubdomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]}],"interfaces":[],"possibleTypes":[{"kind":"OBJECT","name":"ENSv1Domain"},{"kind":"OBJECT","name":"ENSv2Domain"}]},{"kind":"OBJECT","name":"DomainEventsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"DomainEventsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"DomainEventsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"DomainRegistrationsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"DomainRegistrationsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"DomainRegistrationsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Registration","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"DomainSubdomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"DomainSubdomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"DomainSubdomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ENSv1Domain","fields":[{"name":"events","type":{"kind":"OBJECT","name":"DomainEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"label","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Label","ofType":null}},"args":[]},{"name":"name","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"owner","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"parent","type":{"kind":"OBJECT","name":"ENSv1Domain","ofType":null},"args":[]},{"name":"path","type":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}}},"args":[]},{"name":"registration","type":{"kind":"INTERFACE","name":"Registration","ofType":null},"args":[]},{"name":"registrations","type":{"kind":"OBJECT","name":"DomainRegistrationsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"resolver","type":{"kind":"OBJECT","name":"Resolver","ofType":null},"args":[]},{"name":"rootRegistryOwner","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"subdomains","type":{"kind":"OBJECT","name":"DomainSubdomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]}],"interfaces":[{"kind":"INTERFACE","name":"Domain"}]},{"kind":"OBJECT","name":"ENSv2Domain","fields":[{"name":"events","type":{"kind":"OBJECT","name":"DomainEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"label","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Label","ofType":null}},"args":[]},{"name":"name","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"owner","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"path","type":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}}},"args":[]},{"name":"permissions","type":{"kind":"OBJECT","name":"ENSv2DomainPermissionsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"registration","type":{"kind":"INTERFACE","name":"Registration","ofType":null},"args":[]},{"name":"registrations","type":{"kind":"OBJECT","name":"DomainRegistrationsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"registry","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Registry","ofType":null}},"args":[]},{"name":"resolver","type":{"kind":"OBJECT","name":"Resolver","ofType":null},"args":[]},{"name":"subdomains","type":{"kind":"OBJECT","name":"DomainSubdomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"subregistry","type":{"kind":"OBJECT","name":"Registry","ofType":null},"args":[]},{"name":"tokenId","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Domain"}]},{"kind":"OBJECT","name":"ENSv2DomainPermissionsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ENSv2DomainPermissionsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ENSv2DomainPermissionsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsUser","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ENSv2RegistryRegistration","fields":[{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Registration"}]},{"kind":"OBJECT","name":"ENSv2RegistryReservation","fields":[{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Registration"}]},{"kind":"OBJECT","name":"Event","fields":[{"name":"address","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"blockHash","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"blockNumber","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"chainId","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"data","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"from","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"logIndex","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"timestamp","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"to","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"topics","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}},"args":[]},{"name":"transactionHash","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"transactionIndex","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"Label","fields":[{"name":"hash","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"interpreted","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"NameWrapperRegistration","fields":[{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"fuses","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Registration"}]},{"kind":"OBJECT","name":"PageInfo","fields":[{"name":"endCursor","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"hasNextPage","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"hasPreviousPage","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"startCursor","type":{"kind":"SCALAR","name":"Any"},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"Permissions","fields":[{"name":"contract","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"events","type":{"kind":"OBJECT","name":"PermissionsEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"resources","type":{"kind":"OBJECT","name":"PermissionsResourcesConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"root","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsResource","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsEventsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsEventsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsEventsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsResource","fields":[{"name":"contract","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"permissions","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Permissions","ofType":null}},"args":[]},{"name":"resource","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"users","type":{"kind":"OBJECT","name":"PermissionsResourceUsersConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsResourceUsersConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsResourceUsersConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsResourceUsersConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsUser","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsResourcesConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsResourcesConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsResourcesConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsResource","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsUser","fields":[{"name":"contract","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"resource","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"roles","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"user","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Account","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"Query","fields":[{"name":"account","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[{"name":"by","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"domain","type":{"kind":"INTERFACE","name":"Domain","ofType":null},"args":[{"name":"by","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"domains","type":{"kind":"OBJECT","name":"QueryDomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"permissions","type":{"kind":"OBJECT","name":"Permissions","ofType":null},"args":[{"name":"by","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"registrations","type":{"kind":"OBJECT","name":"QueryRegistrationsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"registry","type":{"kind":"OBJECT","name":"Registry","ofType":null},"args":[{"name":"by","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"resolver","type":{"kind":"OBJECT","name":"Resolver","ofType":null},"args":[{"name":"by","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"resolvers","type":{"kind":"OBJECT","name":"QueryResolversConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"root","type":{"kind":"OBJECT","name":"Registry","ofType":null},"args":[]},{"name":"v1Domains","type":{"kind":"OBJECT","name":"QueryV1DomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"v2Domains","type":{"kind":"OBJECT","name":"QueryV2DomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryDomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"QueryDomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryDomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryRegistrationsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"QueryRegistrationsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryRegistrationsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Registration","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryResolversConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"QueryResolversConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryResolversConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Resolver","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryV1DomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"QueryV1DomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryV1DomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ENSv1Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryV2DomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"QueryV2DomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryV2DomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ENSv2Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"INTERFACE","name":"Registration","fields":[{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]}],"interfaces":[],"possibleTypes":[{"kind":"OBJECT","name":"BaseRegistrarRegistration"},{"kind":"OBJECT","name":"ENSv2RegistryRegistration"},{"kind":"OBJECT","name":"ENSv2RegistryReservation"},{"kind":"OBJECT","name":"NameWrapperRegistration"},{"kind":"OBJECT","name":"ThreeDNSRegistration"}]},{"kind":"OBJECT","name":"RegistrationRenewalsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"RegistrationRenewalsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistrationRenewalsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Renewal","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"Registry","fields":[{"name":"contract","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"domains","type":{"kind":"OBJECT","name":"RegistryDomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"parents","type":{"kind":"OBJECT","name":"RegistryParentsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"permissions","type":{"kind":"OBJECT","name":"Permissions","ofType":null},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistryDomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"RegistryDomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistryDomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistryParentsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"RegistryParentsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistryParentsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ENSv2Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistryPermissionsUser","fields":[{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"registry","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Registry","ofType":null}},"args":[]},{"name":"resource","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"roles","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"user","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Account","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"Renewal","fields":[{"name":"base","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"duration","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"premium","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Any"},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"Resolver","fields":[{"name":"bridged","type":{"kind":"OBJECT","name":"AccountId","ofType":null},"args":[]},{"name":"contract","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"events","type":{"kind":"OBJECT","name":"ResolverEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"permissions","type":{"kind":"OBJECT","name":"Permissions","ofType":null},"args":[]},{"name":"records","type":{"kind":"OBJECT","name":"ResolverRecordsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"records_","type":{"kind":"OBJECT","name":"ResolverRecords","ofType":null},"args":[{"name":"for","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverEventsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ResolverEventsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverEventsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverPermissionsUser","fields":[{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"resolver","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Resolver","ofType":null}},"args":[]},{"name":"resource","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"roles","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"user","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Account","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverRecords","fields":[{"name":"coinTypes","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"keys","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}},"args":[]},{"name":"name","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverRecordsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ResolverRecordsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverRecordsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ResolverRecords","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ThreeDNSRegistration","fields":[{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Registration"}]},{"kind":"OBJECT","name":"WrappedBaseRegistrarRegistration","fields":[{"name":"fuses","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"tokenId","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"Any"}],"directives":[]}} as const; diff --git a/packages/enssdk/src/omnigraph/generated/schema.graphql b/packages/enssdk/src/omnigraph/generated/schema.graphql index 7a59f7bd9c..25aee8d996 100644 --- a/packages/enssdk/src/omnigraph/generated/schema.graphql +++ b/packages/enssdk/src/omnigraph/generated/schema.graphql @@ -26,15 +26,21 @@ type Account { resolverPermissions(after: String, before: String, first: Int, last: Int): AccountResolverPermissionsConnection } +"""Address an Account by ID or Address.""" +input AccountByInput @oneOf { + address: Address + id: Address +} + type AccountDomainsConnection { - edges: [AccountDomainsConnectionEdge] + edges: [AccountDomainsConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type AccountDomainsConnectionEdge { cursor: String! - node: Domain + node: Domain! } """Filter for Account.domains query.""" @@ -51,14 +57,14 @@ input AccountDomainsWhereInput { } type AccountEventsConnection { - edges: [AccountEventsConnectionEdge] + edges: [AccountEventsConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type AccountEventsConnectionEdge { cursor: String! - node: Event + node: Event! } """ @@ -79,8 +85,8 @@ input AccountEventsWhereInput { """A CAIP-10 Account ID including chainId and address.""" type AccountId { - address: Address - chainId: ChainId + address: Address! + chainId: ChainId! } """A CAIP-10 Account ID including chainId and address.""" @@ -90,36 +96,36 @@ input AccountIdInput { } type AccountPermissionsConnection { - edges: [AccountPermissionsConnectionEdge] + edges: [AccountPermissionsConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type AccountPermissionsConnectionEdge { cursor: String! - node: PermissionsUser + node: PermissionsUser! } type AccountRegistryPermissionsConnection { - edges: [AccountRegistryPermissionsConnectionEdge] + edges: [AccountRegistryPermissionsConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type AccountRegistryPermissionsConnectionEdge { cursor: String! - node: RegistryPermissionsUser + node: RegistryPermissionsUser! } type AccountResolverPermissionsConnection { - edges: [AccountResolverPermissionsConnectionEdge] + edges: [AccountResolverPermissionsConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type AccountResolverPermissionsConnectionEdge { cursor: String! - node: ResolverPermissionsUser + node: ResolverPermissionsUser! } """Address represents a lowercase (unchecksummed) viem#Address.""" @@ -208,7 +214,7 @@ interface Domain { """ The Canonical Name for this Domain. If the Domain is not Canonical, then `name` will be null. """ - name: Name + name: InterpretedName """The owner of this Domain.""" owner: Account @@ -236,14 +242,14 @@ interface Domain { } type DomainEventsConnection { - edges: [DomainEventsConnectionEdge] + edges: [DomainEventsConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type DomainEventsConnectionEdge { cursor: String! - node: Event + node: Event! } """DomainId represents a @ensnode/ensnode-sdk#DomainId.""" @@ -252,7 +258,7 @@ scalar DomainId """Reference a specific Domain.""" input DomainIdInput @oneOf { id: DomainId - name: Name + name: InterpretedName } """Filter Permissions over this Domain by a specific User address.""" @@ -261,25 +267,25 @@ input DomainPermissionsWhereInput { } type DomainRegistrationsConnection { - edges: [DomainRegistrationsConnectionEdge] + edges: [DomainRegistrationsConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type DomainRegistrationsConnectionEdge { cursor: String! - node: Registration + node: Registration! } type DomainSubdomainsConnection { - edges: [DomainSubdomainsConnectionEdge] + edges: [DomainSubdomainsConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type DomainSubdomainsConnectionEdge { cursor: String! - node: Domain + node: Domain! } """Fields by which domains can be ordered""" @@ -324,7 +330,7 @@ type ENSv1Domain implements Domain { """ The Canonical Name for this Domain. If the Domain is not Canonical, then `name` will be null. """ - name: Name + name: InterpretedName """The owner of this Domain.""" owner: Account @@ -373,7 +379,7 @@ type ENSv2Domain implements Domain { """ The Canonical Name for this Domain. If the Domain is not Canonical, then `name` will be null. """ - name: Name + name: InterpretedName """The owner of this Domain.""" owner: Account @@ -415,14 +421,14 @@ type ENSv2Domain implements Domain { } type ENSv2DomainPermissionsConnection { - edges: [ENSv2DomainPermissionsConnectionEdge] + edges: [ENSv2DomainPermissionsConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type ENSv2DomainPermissionsConnectionEdge { cursor: String! - node: PermissionsUser + node: PermissionsUser! } """ @@ -579,6 +585,12 @@ input EventsWhereInput { """Hex represents viem#Hex.""" scalar Hex +"""InterpretedLabel represents a @ensnode/ensnode-sdk#InterpretedLabel.""" +scalar InterpretedLabel + +"""InterpretedName represents a @ensnode/ensnode-sdk#InterpretedName.""" +scalar InterpretedName + """ Represents a Label within ENS, providing its hash and interpreted representation. """ @@ -593,15 +605,12 @@ type Label { The Label represented as an Interpreted Label. This is either a normalized Literal Label or an Encoded LabelHash. (@see https://ensnode.io/docs/reference/terminology#interpreted-label) """ - interpreted: String! + interpreted: InterpretedLabel! } -"""Name represents a @ensnode/ensnode-sdk#InterpretedName.""" -scalar Name - """Constructs a reference to a specific Node via one of `name` or `node`.""" input NameOrNodeInput @oneOf { - name: Name + name: InterpretedName node: Node } @@ -685,19 +694,25 @@ type Permissions { } type PermissionsEventsConnection { - edges: [PermissionsEventsConnectionEdge] + edges: [PermissionsEventsConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type PermissionsEventsConnectionEdge { cursor: String! - node: Event + node: Event! } """PermissionsId represents a @ensnode/ensnode-sdk#PermissionsId.""" scalar PermissionsId +"""Address Permissions by ID or AccountId.""" +input PermissionsIdInput @oneOf { + contract: AccountIdInput + id: PermissionsId +} + """PermissionsResource""" type PermissionsResource { """The contract within which these Permissions are granted.""" @@ -722,25 +737,25 @@ PermissionsResourceId represents a @ensnode/ensnode-sdk#PermissionsResourceId. scalar PermissionsResourceId type PermissionsResourceUsersConnection { - edges: [PermissionsResourceUsersConnectionEdge] + edges: [PermissionsResourceUsersConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type PermissionsResourceUsersConnectionEdge { cursor: String! - node: PermissionsUser + node: PermissionsUser! } type PermissionsResourcesConnection { - edges: [PermissionsResourcesConnectionEdge] + edges: [PermissionsResourcesConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type PermissionsResourcesConnectionEdge { cursor: String! - node: PermissionsResource + node: PermissionsResource! } """PermissionsUser""" @@ -765,8 +780,8 @@ type PermissionsUser { scalar PermissionsUserId type Query { - """Identify an Account by Address.""" - account(address: Address!): Account + """Identify an Account by ID or Address.""" + account(by: AccountByInput!): Account """Identify a Domain by Name or DomainId""" domain(by: DomainIdInput!): Domain @@ -774,8 +789,8 @@ type Query { """Find Domains by Name.""" domains(after: String, before: String, first: Int, last: Int, order: DomainsOrderInput, where: DomainsWhereInput!): QueryDomainsConnection - """Find Permissions in a contract by AccountId.""" - permissions(for: AccountIdInput!): Permissions + """Identify Permissions by ID or AccountId.""" + permissions(by: PermissionsIdInput!): Permissions """TODO""" registrations(after: String, before: String, first: Int, last: Int): QueryRegistrationsConnection @@ -800,58 +815,58 @@ type Query { } type QueryDomainsConnection { - edges: [QueryDomainsConnectionEdge] + edges: [QueryDomainsConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type QueryDomainsConnectionEdge { cursor: String! - node: Domain + node: Domain! } type QueryRegistrationsConnection { - edges: [QueryRegistrationsConnectionEdge] + edges: [QueryRegistrationsConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type QueryRegistrationsConnectionEdge { cursor: String! - node: Registration + node: Registration! } type QueryResolversConnection { - edges: [QueryResolversConnectionEdge] + edges: [QueryResolversConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type QueryResolversConnectionEdge { cursor: String! - node: Resolver + node: Resolver! } type QueryV1DomainsConnection { - edges: [QueryV1DomainsConnectionEdge] + edges: [QueryV1DomainsConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type QueryV1DomainsConnectionEdge { cursor: String! - node: ENSv1Domain + node: ENSv1Domain! } type QueryV2DomainsConnection { - edges: [QueryV2DomainsConnectionEdge] + edges: [QueryV2DomainsConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type QueryV2DomainsConnectionEdge { cursor: String! - node: ENSv2Domain + node: ENSv2Domain! } """ @@ -900,14 +915,14 @@ interface Registration { scalar RegistrationId type RegistrationRenewalsConnection { - edges: [RegistrationRenewalsConnectionEdge] + edges: [RegistrationRenewalsConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type RegistrationRenewalsConnectionEdge { cursor: String! - node: Renewal + node: Renewal! } """A Registry represents an ENSv2 Registry contract.""" @@ -929,14 +944,14 @@ type Registry { } type RegistryDomainsConnection { - edges: [RegistryDomainsConnectionEdge] + edges: [RegistryDomainsConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type RegistryDomainsConnectionEdge { cursor: String! - node: Domain + node: Domain! } """Filter for Registry.domains query.""" @@ -957,14 +972,14 @@ input RegistryIdInput @oneOf { } type RegistryParentsConnection { - edges: [RegistryParentsConnectionEdge] + edges: [RegistryParentsConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type RegistryParentsConnectionEdge { cursor: String! - node: ENSv2Domain + node: ENSv2Domain! } type RegistryPermissionsUser { @@ -1033,14 +1048,14 @@ type Resolver { } type ResolverEventsConnection { - edges: [ResolverEventsConnectionEdge] + edges: [ResolverEventsConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type ResolverEventsConnectionEdge { cursor: String! - node: Event + node: Event! } """ResolverId represents a @ensnode/ensnode-sdk#ResolverId.""" @@ -1088,14 +1103,14 @@ type ResolverRecords { } type ResolverRecordsConnection { - edges: [ResolverRecordsConnectionEdge] + edges: [ResolverRecordsConnectionEdge!]! pageInfo: PageInfo! totalCount: Int! } type ResolverRecordsConnectionEdge { cursor: String! - node: ResolverRecords + node: ResolverRecords! } """ResolverRecordsId represents a @ensnode/ensnode-sdk#ResolverRecordsId.""" diff --git a/packages/enssdk/src/omnigraph/graphql.ts b/packages/enssdk/src/omnigraph/graphql.ts index 21634d555e..a67c4102ff 100644 --- a/packages/enssdk/src/omnigraph/graphql.ts +++ b/packages/enssdk/src/omnigraph/graphql.ts @@ -5,6 +5,7 @@ import type { ChainId, CoinType, DomainId, + InterpretedLabel, InterpretedName, Node, PermissionsId, @@ -31,7 +32,8 @@ export const graphql = initGraphQLTada<{ Hex: Hex; ChainId: ChainId; CoinType: CoinType; - Name: InterpretedName; + InterpretedName: InterpretedName; + InterpretedLabel: InterpretedLabel; Node: Node; DomainId: DomainId; RegistryId: RegistryId; diff --git a/packages/enssdk/src/omnigraph/index.ts b/packages/enssdk/src/omnigraph/index.ts index a5a833d95c..b718f00f8b 100644 --- a/packages/enssdk/src/omnigraph/index.ts +++ b/packages/enssdk/src/omnigraph/index.ts @@ -1,58 +1,3 @@ -import type { TadaDocumentNode } from "gql.tada"; -import type { DocumentNode } from "graphql"; -import { print } from "graphql"; - -import type { EnsNodeClient } from "../core/index"; - -export type { FragmentOf, ResultOf, VariablesOf } from "./graphql"; -export { graphql, readFragment } from "./graphql"; - -type GraphQLDocument = string | DocumentNode | TadaDocumentNode; - -type QueryOptions | undefined> = { - query: GraphQLDocument; - signal?: AbortSignal; -} & (V extends Record ? { variables: V } : { variables?: undefined }); - -type QueryResult = { - data?: R | null; - errors?: Array<{ - message: string; - path?: (string | number)[]; - extensions?: Record; - }>; -}; - -export interface OmnigraphModule { - omnigraph: { - query | undefined = undefined>( - options: QueryOptions, - ): Promise>; - }; -} - -export function omnigraph(client: EnsNodeClient): OmnigraphModule { - const { config } = client; - const _fetch = config.fetch ?? globalThis.fetch; - const endpoint = new URL("/api/omnigraph", config.url).href; - - return { - omnigraph: { - async query | undefined>( - opts: QueryOptions, - ): Promise> { - const response = await _fetch(endpoint, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - query: typeof opts.query === "string" ? opts.query : print(opts.query), - variables: opts.variables, - }), - signal: opts.signal, - }); - - return response.json() as Promise>; - }, - }, - }; -} +export * from "./graphql"; +export * from "./introspection"; +export * from "./module"; diff --git a/packages/enssdk/src/omnigraph/introspection.ts b/packages/enssdk/src/omnigraph/introspection.ts new file mode 100644 index 0000000000..f25a9a828c --- /dev/null +++ b/packages/enssdk/src/omnigraph/introspection.ts @@ -0,0 +1 @@ +export { introspection } from "./generated/introspection"; diff --git a/packages/enssdk/src/omnigraph/module.integration.test.ts b/packages/enssdk/src/omnigraph/module.integration.test.ts new file mode 100644 index 0000000000..fd441e8232 --- /dev/null +++ b/packages/enssdk/src/omnigraph/module.integration.test.ts @@ -0,0 +1,40 @@ +import type { Address } from "viem"; +import { describe, expect, expectTypeOf, it } from "vitest"; + +import { createEnsNodeClient } from "../core"; +import type { DomainId, InterpretedName } from "../lib/types"; +import { graphql } from "./graphql"; +import { omnigraph } from "./module"; + +const client = createEnsNodeClient({ url: process.env.ENSNODE_URL! }).extend(omnigraph); + +// hover over this query to see typechecking in action! +const HelloWorldQuery = graphql(` + query HelloWorld { + domain(by: { name: "eth" }) { + id + name + owner { address } + } + } +`); + +describe("omnigraph module (integration)", () => { + it("executes HelloWorld query", async () => { + const result = await client.omnigraph.query({ query: HelloWorldQuery }); + + expect(result.errors).toBeUndefined(); + + // look, our semantic types! + expectTypeOf(result.data!.domain!.id).toEqualTypeOf(); + expectTypeOf(result.data!.domain!.name).toEqualTypeOf(); + expectTypeOf(result.data!.domain!.owner!.address).toEqualTypeOf
    (); + + // the 'eth' domain should exist + expect(result.data!.domain).toMatchObject({ + id: expect.any(String), + name: "eth", + owner: { address: expect.any(String) }, + }); + }); +}); diff --git a/packages/enssdk/src/omnigraph/omnigraph.test.ts b/packages/enssdk/src/omnigraph/module.test.ts similarity index 81% rename from packages/enssdk/src/omnigraph/omnigraph.test.ts rename to packages/enssdk/src/omnigraph/module.test.ts index 62c2bbdbfe..ac647a18b1 100644 --- a/packages/enssdk/src/omnigraph/omnigraph.test.ts +++ b/packages/enssdk/src/omnigraph/module.test.ts @@ -2,7 +2,7 @@ import { parse } from "graphql"; import { describe, expect, it, vi } from "vitest"; import { createEnsNodeClient } from "../core/index"; -import { omnigraph } from "./index"; +import { omnigraph } from "./module"; function createMockClient(mockFetch: ReturnType) { return createEnsNodeClient({ @@ -22,6 +22,7 @@ describe("omnigraph module", () => { it("sends a POST request with string query", async () => { const mockResponse = { data: { domain: { name: "nick.eth" } } }; const mockFetch = vi.fn().mockResolvedValue({ + ok: true, json: () => Promise.resolve(mockResponse), }); @@ -46,6 +47,7 @@ describe("omnigraph module", () => { it("sends variables when provided", async () => { const mockFetch = vi.fn().mockResolvedValue({ + ok: true, json: () => Promise.resolve({ data: null }), }); @@ -62,6 +64,7 @@ describe("omnigraph module", () => { it("passes signal for abort support", async () => { const mockFetch = vi.fn().mockResolvedValue({ + ok: true, json: () => Promise.resolve({ data: null }), }); const controller = new AbortController(); @@ -76,8 +79,25 @@ describe("omnigraph module", () => { expect(mockFetch.mock.calls[0][1].signal).toBe(controller.signal); }); + it("throws on non-2xx response with body included", async () => { + const errorBody = JSON.stringify({ errors: [{ message: "Unauthorized" }] }); + const mockFetch = vi.fn().mockResolvedValue({ + ok: false, + status: 401, + statusText: "Unauthorized", + text: () => Promise.resolve(errorBody), + }); + + const client = createMockClient(mockFetch); + + await expect( + client.omnigraph.query({ query: 'query { domain(by: { name: "eth" }) { name } }' }), + ).rejects.toThrow(`Omnigraph query failed: 401 Unauthorized\n${errorBody}`); + }); + it("prints DocumentNode queries to string", async () => { const mockFetch = vi.fn().mockResolvedValue({ + ok: true, json: () => Promise.resolve({ data: null }), }); diff --git a/packages/enssdk/src/omnigraph/module.ts b/packages/enssdk/src/omnigraph/module.ts new file mode 100644 index 0000000000..2da8ab8503 --- /dev/null +++ b/packages/enssdk/src/omnigraph/module.ts @@ -0,0 +1,66 @@ +import type { TadaDocumentNode } from "gql.tada"; +import type { DocumentNode } from "graphql"; +import { print } from "graphql"; + +import type { EnsNodeClient } from "../core/index"; + +type GraphQLDocument = string | DocumentNode | TadaDocumentNode; + +type QueryOptions | undefined> = { + query: GraphQLDocument; + signal?: AbortSignal; +} & (V extends Record + ? keyof V extends never + ? { variables?: V } + : { variables: V } + : { variables?: undefined }); + +type QueryResult = { + data?: R | null; + errors?: Array<{ + message: string; + path?: (string | number)[]; + extensions?: Record; + }>; +}; + +export interface OmnigraphModule { + omnigraph: { + query | undefined = undefined>( + options: QueryOptions, + ): Promise>; + }; +} + +export function omnigraph(client: EnsNodeClient): OmnigraphModule { + const { config } = client; + const _fetch = config.fetch ?? globalThis.fetch; + const endpoint = new URL("/api/omnigraph", config.url).href; + + return { + omnigraph: { + async query | undefined>( + opts: QueryOptions, + ): Promise> { + const response = await _fetch(endpoint, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + query: typeof opts.query === "string" ? opts.query : print(opts.query), + variables: opts.variables, + }), + signal: opts.signal, + }); + + if (!response.ok) { + const body = await response.text().catch(() => ""); + throw new Error( + `Omnigraph query failed: ${response.status} ${response.statusText}${body ? `\n${body}` : ""}`, + ); + } + + return response.json() as Promise>; + }, + }, + }; +} diff --git a/packages/enssdk/vitest.config.ts b/packages/enssdk/vitest.config.ts index 8e3d64e885..ce487d95b8 100644 --- a/packages/enssdk/vitest.config.ts +++ b/packages/enssdk/vitest.config.ts @@ -1,13 +1,6 @@ -import { resolve } from "node:path"; +import { configDefaults, defineConfig } from "vitest/config"; -import { configDefaults, defineProject } from "vitest/config"; - -export default defineProject({ - resolve: { - alias: { - "@": resolve(__dirname, "./src"), - }, - }, +export default defineConfig({ test: { environment: "node", exclude: [...configDefaults.exclude, "**/*.integration.test.ts"], diff --git a/packages/enssdk/vitest.integration.config.ts b/packages/enssdk/vitest.integration.config.ts new file mode 100644 index 0000000000..20213b523d --- /dev/null +++ b/packages/enssdk/vitest.integration.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + environment: "node", + include: ["**/*.integration.test.ts"], + }, +}); diff --git a/packages/integration-test-env/package.json b/packages/integration-test-env/package.json index 97c10db21c..95c4fd92d7 100644 --- a/packages/integration-test-env/package.json +++ b/packages/integration-test-env/package.json @@ -2,6 +2,7 @@ "name": "@ensnode/integration-test-env", "version": "0.0.3", "private": true, + "license": "MIT", "type": "module", "description": "Integration test environment orchestration for ENSNode", "scripts": { diff --git a/packages/namehash-ui/package.json b/packages/namehash-ui/package.json index 8d2b736c20..65362169e0 100644 --- a/packages/namehash-ui/package.json +++ b/packages/namehash-ui/package.json @@ -66,11 +66,11 @@ "@tailwindcss/postcss": "^4.1.18", "@testing-library/react": "catalog:", "@types/node": "catalog:", - "@types/react": "19.2.7", - "@types/react-dom": "19.2.3", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", "postcss": "^8.5.6", "postcss-cli": "^11.0.1", - "react": "19.2.1", + "react": "catalog:", "tailwindcss": "catalog:", "tsup": "^8.3.6", "typescript": "catalog:", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e13f5f21fe..edb80d94eb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,6 +24,12 @@ catalogs: '@types/node': specifier: 24.10.9 version: 24.10.9 + '@types/react': + specifier: 19.2.7 + version: 19.2.7 + '@types/react-dom': + specifier: 19.2.3 + version: 19.2.3 astro: specifier: ^5.18.1 version: 5.18.1 @@ -60,6 +66,12 @@ catalogs: ponder: specifier: 0.16.3 version: 0.16.3 + react: + specifier: 19.2.1 + version: 19.2.1 + react-dom: + specifier: 19.2.1 + version: 19.2.1 tailwind-merge: specifier: ^3.4.0 version: 3.4.0 @@ -78,6 +90,9 @@ catalogs: viem: specifier: ^2.22.13 version: 2.38.5 + vite: + specifier: ^7.3.2 + version: 7.3.2 vitest: specifier: ^4.0.2 version: 4.0.5 @@ -257,10 +272,10 @@ importers: specifier: ^0.4.6 version: 0.4.6(react-dom@19.2.1(react@19.2.1))(react@19.2.1) react: - specifier: 19.2.1 + specifier: 'catalog:' version: 19.2.1 react-dom: - specifier: 19.2.1 + specifier: 'catalog:' version: 19.2.1(react@19.2.1) rooks: specifier: ^8.4.0 @@ -291,10 +306,10 @@ importers: specifier: 'catalog:' version: 24.10.9 '@types/react': - specifier: 19.2.7 + specifier: 'catalog:' version: 19.2.7 '@types/react-dom': - specifier: 19.2.3 + specifier: 'catalog:' version: 19.2.3(@types/react@19.2.7) postcss: specifier: ^8.5.6 @@ -444,6 +459,9 @@ importers: '@types/prismjs': specifier: ^1.26.6 version: 1.26.6 + '@urql/introspection': + specifier: ^1.2.1 + version: 1.2.1(graphql@16.11.0) chalk: specifier: ^5.6.2 version: 5.6.2 @@ -504,6 +522,9 @@ importers: drizzle-orm: specifier: 'catalog:' version: 0.41.0(@electric-sql/pglite@0.2.13)(@opentelemetry/api@1.9.0(patch_hash=4b2adeefaf7c22f9987d0a125d69cab900719bec7ed7636648bea6947107033a))(@types/pg@8.16.0)(kysely@0.28.14)(pg@8.16.3) + enssdk: + specifier: workspace:* + version: link:../../packages/enssdk hono: specifier: 'catalog:' version: 4.12.7 @@ -763,10 +784,10 @@ importers: specifier: 5.0.5 version: 5.0.5 react: - specifier: ^19.0.0 + specifier: 'catalog:' version: 19.2.1 react-dom: - specifier: ^19.0.0 + specifier: 'catalog:' version: 19.2.1(react@19.2.1) react-wrap-balancer: specifier: ^1.1.1 @@ -776,12 +797,46 @@ importers: version: 4.2.2 devDependencies: '@types/react': - specifier: ^19.0.0 + specifier: 'catalog:' version: 19.2.7 '@types/react-dom': - specifier: ^19.0.0 + specifier: 'catalog:' version: 19.2.3(@types/react@19.2.7) + examples/enskit-react-example: + dependencies: + enskit: + specifier: workspace:* + version: link:../../packages/enskit + enssdk: + specifier: workspace:* + version: link:../../packages/enssdk + react: + specifier: 'catalog:' + version: 19.2.1 + react-dom: + specifier: 'catalog:' + version: 19.2.1(react@19.2.1) + react-router: + specifier: ^7.6.1 + version: 7.14.0(react-dom@19.2.1(react@19.2.1))(react@19.2.1) + devDependencies: + '@types/react': + specifier: 'catalog:' + version: 19.2.7 + '@types/react-dom': + specifier: 'catalog:' + version: 19.2.3(@types/react@19.2.7) + '@vitejs/plugin-react': + specifier: ^4.5.2 + version: 4.7.0(vite@7.3.2(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.3)) + typescript: + specifier: 'catalog:' + version: 5.9.3 + vite: + specifier: 'catalog:' + version: 7.3.2(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.3) + packages/datasources: dependencies: '@ponder/utils': @@ -874,7 +929,48 @@ importers: specifier: 'catalog:' version: 4.0.5(@types/debug@4.1.12)(@types/node@24.10.9)(jiti@2.6.1)(jsdom@27.0.1(postcss@8.5.6))(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.3) - packages/enskit: {} + packages/enskit: + dependencies: + '@urql/core': + specifier: ^6.0.0 + version: 6.0.1(graphql@16.11.0) + '@urql/exchange-graphcache': + specifier: ^9.0.0 + version: 9.0.0(@urql/core@6.0.1(graphql@16.11.0))(graphql@16.11.0) + enssdk: + specifier: workspace:* + version: link:../enssdk + urql: + specifier: ^5.0.1 + version: 5.0.1(@urql/core@6.0.1(graphql@16.11.0))(react@19.2.1) + devDependencies: + '@ensnode/shared-configs': + specifier: workspace:* + version: link:../shared-configs + '@types/react': + specifier: 'catalog:' + version: 19.2.7 + gql.tada: + specifier: ^1.8.10 + version: 1.9.1(graphql@16.11.0)(typescript@5.9.3) + graphql: + specifier: ^16.11.0 + version: 16.11.0 + react: + specifier: 'catalog:' + version: 19.2.1 + tsup: + specifier: 'catalog:' + version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3) + typescript: + specifier: 'catalog:' + version: 5.9.3 + viem: + specifier: 'catalog:' + version: 2.38.5(typescript@5.9.3)(zod@4.3.6) + vitest: + specifier: 'catalog:' + version: 4.0.5(@types/debug@4.1.12)(@types/node@24.10.9)(jiti@2.6.1)(jsdom@27.0.1(postcss@8.5.6))(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.3) packages/ensnode-react: dependencies: @@ -895,10 +991,10 @@ importers: specifier: 'catalog:' version: 24.10.9 '@types/react': - specifier: 19.2.7 + specifier: 'catalog:' version: 19.2.7 react: - specifier: 19.2.1 + specifier: 'catalog:' version: 19.2.1 tsup: specifier: ^8.3.6 @@ -980,16 +1076,22 @@ importers: '@ensdomains/address-encoder': specifier: ^1.1.2 version: 1.1.4 + caip: + specifier: 'catalog:' + version: 1.1.1 + devDependencies: + '@ensnode/shared-configs': + specifier: workspace:* + version: link:../shared-configs + '@types/node': + specifier: 'catalog:' + version: 24.10.9 gql.tada: specifier: ^1.8.10 version: 1.9.1(graphql@16.11.0)(typescript@5.9.3) graphql: specifier: ^16.11.0 version: 16.11.0 - devDependencies: - '@ensnode/shared-configs': - specifier: workspace:* - version: link:../shared-configs tsup: specifier: 'catalog:' version: 8.5.0(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3) @@ -1093,10 +1195,10 @@ importers: specifier: 'catalog:' version: 24.10.9 '@types/react': - specifier: 19.2.7 + specifier: 'catalog:' version: 19.2.7 '@types/react-dom': - specifier: 19.2.3 + specifier: 'catalog:' version: 19.2.3(@types/react@19.2.7) postcss: specifier: ^8.5.6 @@ -1105,7 +1207,7 @@ importers: specifier: ^11.0.1 version: 11.0.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0) react: - specifier: 19.2.1 + specifier: 'catalog:' version: 19.2.1 tailwindcss: specifier: 'catalog:' @@ -4769,6 +4871,19 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + '@urql/core@6.0.1': + resolution: {integrity: sha512-FZDiQk6jxbj5hixf2rEPv0jI+IZz0EqqGW8mJBEug68/zHTtT+f34guZDmyjJZyiWbj0vL165LoMr/TkeDHaug==} + + '@urql/exchange-graphcache@9.0.0': + resolution: {integrity: sha512-5ACktvMFdnD5JC6DaSUrlj345c1JIUi7PwgvmnkwVOWsCRt/Vo9946UaG+sg69ku8seESMBK4xkeI41M39Dd5A==} + peerDependencies: + '@urql/core': ^6.0.0 + + '@urql/introspection@1.2.1': + resolution: {integrity: sha512-U9FTSISz69EEK3bHWDsqux9JqOeiLzr3eDFBQ5DmHuTLaBsd5mjPdtLRzzzmb9nW1Ygd6IR8YcuM7zeNqQ5lCQ==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + '@vitejs/plugin-react@4.7.0': resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==} engines: {node: ^14.18.0 || >=16.0.0} @@ -8052,6 +8167,16 @@ packages: '@types/react': optional: true + react-router@7.14.0: + resolution: {integrity: sha512-m/xR9N4LQLmAS0ZhkY2nkPA1N7gQ5TUVa5n8TgANuDTARbn1gt+zLPXEm7W0XDTbrQ2AJSJKhoa6yx1D8BcpxQ==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + peerDependenciesMeta: + react-dom: + optional: true + react-style-singleton@2.2.3: resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} engines: {node: '>=10'} @@ -8328,6 +8453,9 @@ packages: engines: {node: '>= 14'} hasBin: true + set-cookie-parser@2.7.2: + resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} + set-value@4.1.0: resolution: {integrity: sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw==} engines: {node: '>=11.0'} @@ -9006,6 +9134,12 @@ packages: urlpattern-polyfill@10.1.0: resolution: {integrity: sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==} + urql@5.0.1: + resolution: {integrity: sha512-r58gYlWvCTC19QvkTaARaCLV9/bp870byH/qbLaw3S7f8i/bC6x2Szub8RVXptiMxWmqq5dyVBjUL9G+xPEuqg==} + peerDependencies: + '@urql/core': ^6.0.0 + react: '>= 16.8.0' + use-callback-ref@1.3.3: resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} engines: {node: '>=10'} @@ -9368,6 +9502,9 @@ packages: resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} engines: {node: '>=18'} + wonka@6.3.6: + resolution: {integrity: sha512-MXH+6mDHAZ2GuMpgKS055FR6v0xVP3XwquxIMYXgiW+FejHQlMGlvVRZT4qMCxR+bEo/FCtIdKxwej9WV3YQag==} + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -13586,6 +13723,25 @@ snapshots: '@ungap/structured-clone@1.3.0': {} + '@urql/core@6.0.1(graphql@16.11.0)': + dependencies: + '@0no-co/graphql.web': 1.2.0(graphql@16.11.0) + wonka: 6.3.6 + transitivePeerDependencies: + - graphql + + '@urql/exchange-graphcache@9.0.0(@urql/core@6.0.1(graphql@16.11.0))(graphql@16.11.0)': + dependencies: + '@0no-co/graphql.web': 1.2.0(graphql@16.11.0) + '@urql/core': 6.0.1(graphql@16.11.0) + wonka: 6.3.6 + transitivePeerDependencies: + - graphql + + '@urql/introspection@1.2.1(graphql@16.11.0)': + dependencies: + graphql: 16.11.0 + '@vitejs/plugin-react@4.7.0(vite@6.4.2(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@babel/core': 7.28.5 @@ -13598,6 +13754,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@vitejs/plugin-react@4.7.0(vite@7.3.2(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.3))': + dependencies: + '@babel/core': 7.28.5 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.5) + '@rolldown/pluginutils': 1.0.0-beta.27 + '@types/babel__core': 7.20.5 + react-refresh: 0.17.0 + vite: 7.3.2(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.3) + transitivePeerDependencies: + - supports-color + '@vitest/expect@4.0.5': dependencies: '@standard-schema/spec': 1.0.0 @@ -17501,6 +17669,14 @@ snapshots: optionalDependencies: '@types/react': 19.2.7 + react-router@7.14.0(react-dom@19.2.1(react@19.2.1))(react@19.2.1): + dependencies: + cookie: 1.1.1 + react: 19.2.1 + set-cookie-parser: 2.7.2 + optionalDependencies: + react-dom: 19.2.1(react@19.2.1) + react-style-singleton@2.2.3(@types/react@19.2.7)(react@19.2.1): dependencies: get-nonce: 1.0.1 @@ -17910,6 +18086,8 @@ snapshots: transitivePeerDependencies: - supports-color + set-cookie-parser@2.7.2: {} + set-value@4.1.0: dependencies: is-plain-object: 2.0.4 @@ -18647,6 +18825,12 @@ snapshots: urlpattern-polyfill@10.1.0: {} + urql@5.0.1(@urql/core@6.0.1(graphql@16.11.0))(react@19.2.1): + dependencies: + '@urql/core': 6.0.1(graphql@16.11.0) + react: 19.2.1 + wonka: 6.3.6 + use-callback-ref@1.3.3(@types/react@19.2.7)(react@19.2.1): dependencies: react: 19.2.1 @@ -19042,6 +19226,8 @@ snapshots: dependencies: string-width: 7.2.0 + wonka@6.3.6: {} + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 2b4839e063..ed48717b39 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,6 +1,7 @@ packages: - apps/* - docs/* + - examples/* - packages/* catalog: @@ -11,6 +12,8 @@ catalog: "@ponder/utils": 0.2.16 "@testing-library/react": ^16.3.0 "@types/node": 24.10.9 + "@types/react": 19.2.7 + "@types/react-dom": 19.2.3 astro: ^5.18.1 astro-font: ^1.1.0 astro-seo: ^0.8.4 @@ -19,13 +22,15 @@ catalog: drizzle-orm: 0.41.0 hono: ^4.12.7 lucide-react: ^0.548.0 + p-retry: 7.1.1 pg-connection-string: ^2.9.1 pino: 10.1.0 ponder: 0.16.3 - p-retry: 7.1.1 + react: 19.2.1 + react-dom: 19.2.1 + tailwind-merge: ^3.4.0 tailwindcss: ^4.1.18 tailwindcss-animate: ^1.0.7 - tailwind-merge: ^3.4.0 tsup: ^8.3.6 typescript: ^5.7.3 viem: ^2.22.13 diff --git a/vitest.integration.config.ts b/vitest.integration.config.ts index eb4c9b295d..163ed6b701 100644 --- a/vitest.integration.config.ts +++ b/vitest.integration.config.ts @@ -2,10 +2,11 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ test: { - projects: ["apps/*/vitest.integration.config.ts", "packages/*/vitest.integration.config.ts"], + projects: ["./**/*/vitest.integration.config.ts"], env: { // allows the syntax highlight of graphql request/responses to propagate through vitest's logs FORCE_COLOR: "true", + ENSNODE_URL: process.env.ENSNODE_URL ?? "http://localhost:4334", }, }, });