diff --git a/.changeset/config.json b/.changeset/config.json index 81f9844bfb..426bc1dfde 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -11,6 +11,10 @@ "ensrainbow", "ensapi", "fallback-ensapi", + "enssdk", + "enscli", + "enskit", + "ensskills", "@ensnode/datasources", "@ensnode/ensrainbow-sdk", "@ensnode/ensdb-sdk", diff --git a/.changeset/warm-snails-teach.md b/.changeset/warm-snails-teach.md new file mode 100644 index 0000000000..53a0c551be --- /dev/null +++ b/.changeset/warm-snails-teach.md @@ -0,0 +1,5 @@ +--- +"enssdk": minor +--- + +add core client factory with viem-style extend() and omnigraph module with gql.tada typed queries diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a9964e9c57..ab17fcf67b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -105,6 +105,10 @@ jobs: or .name == "@ensnode/namehash-ui" or .name == "@ensnode/ponder-sdk" or .name == "@ensnode/ponder-subgraph" + or .name == "enssdk" + or .name == "enskit" + or .name == "enscli" + or .name == "ensskills" )) - name: Filter Published Packages For Lambdas diff --git a/.github/workflows/test_ci.yml b/.github/workflows/test_ci.yml index 57c3eef201..f14f510614 100644 --- a/.github/workflows/test_ci.yml +++ b/.github/workflows/test_ci.yml @@ -89,6 +89,31 @@ jobs: - name: Validate OpenAPI spec with Mintlify run: pnpm dlx mint@^4.1.0 openapi-check docs/docs.ensnode.io/ensapi-openapi.json + graphql-schema-check: + name: "GraphQL Schema Check" + runs-on: blacksmith-4vcpu-ubuntu-2204 + steps: + - uses: actions/checkout@v6 + - uses: ./.github/actions/setup_node_environment + + - name: Generate Schemas & Typings + run: pnpm generate:gqlschema + + - name: Verify generated files are committed + run: | + if ! git diff --quiet packages/enssdk/src/omnigraph/generated/; then + echo "Error: Generated files are out of sync" + echo "" + echo "The following generated files differ from what is committed:" + git diff --name-status packages/enssdk/src/omnigraph/generated/ + echo "" + echo "To fix, run:" + echo " pnpm generate:gqlschema" + echo "Then commit the updated generated files." + exit 1 + fi + echo "GraphQL schema generated files are in sync" + integrity-check: name: "Integrity Check" runs-on: blacksmith-4vcpu-ubuntu-2204 diff --git a/.gitignore b/.gitignore index e7b333e666..eae700ab06 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ dist # Ponder generated +!packages/enssdk/src/omnigraph/generated/ .ponder #jetbrains elements diff --git a/.vscode/settings.json b/.vscode/settings.json index a7d408410d..f2bf775887 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,7 @@ { - "typescript.tsdk": "node_modules/typescript/lib", - "typescript.preferences.importModuleSpecifier": "non-relative", + "js/ts.tsdk.path": "node_modules/typescript/lib", + "js/ts.preferences.importModuleSpecifier": "non-relative", + "js/ts.tsdk.promptToUseWorkspaceVersion": true, "files.insertFinalNewline": true, "editor.formatOnSave": true, "editor.codeActionsOnSave": { diff --git a/apps/ensapi/package.json b/apps/ensapi/package.json index 3049946ac8..db942274f5 100644 --- a/apps/ensapi/package.json +++ b/apps/ensapi/package.json @@ -18,7 +18,8 @@ "test:integration": "vitest run --config vitest.integration.config.ts", "lint": "biome check --write .", "lint:ci": "biome ci", - "typecheck": "tsgo --noEmit" + "typecheck": "tsgo --noEmit", + "generate:gqlschema": "tsx src/graphql-api/lib/write-graphql-schema.ts" }, "dependencies": { "@ensdomains/ensjs": "^4.0.2", diff --git a/apps/ensapi/src/graphql-api/lib/write-graphql-schema.ts b/apps/ensapi/src/graphql-api/lib/write-graphql-schema.ts new file mode 100644 index 0000000000..a1ade33f10 --- /dev/null +++ b/apps/ensapi/src/graphql-api/lib/write-graphql-schema.ts @@ -0,0 +1,44 @@ +import { writeFile } from "node:fs/promises"; +import { resolve } from "node:path"; +import { fileURLToPath } from "node:url"; + +import { lexicographicSortSchema, printSchema } from "graphql"; + +import { makeLogger } from "@/lib/logger"; + +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"); + +async function _writeGraphQLSchema() { + const { schema } = await import("@/graphql-api/schema"); + const schemaAsString = printSchema(lexicographicSortSchema(schema)); + + await writeFile(OUTPUT_PATH, schemaAsString); +} + +/** + * Attempts to write the GraphQL Schema, swallowing any errors. + */ +export async function writeGraphQLSchema() { + try { + await _writeGraphQLSchema(); + logger.info(`Wrote SDL to ${OUTPUT_PATH}`); + } catch (error) { + logger.warn(error, `Unable to write SDL to ${OUTPUT_PATH}`); + } +} + +// when executed directly (`pnpm generate:gqlschema`), write generated schema and produce an exit code +if (resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { + try { + await _writeGraphQLSchema(); + console.log(`Wrote SDL to ${OUTPUT_PATH}`); + process.exit(0); + } catch (error) { + console.error(error); + process.exit(1); + } +} diff --git a/apps/ensapi/src/handlers/api/graphql/ensnode-graphql-api.ts b/apps/ensapi/src/handlers/api/graphql/ensnode-graphql-api.ts index 04efec0aa1..920e95e609 100644 --- a/apps/ensapi/src/handlers/api/graphql/ensnode-graphql-api.ts +++ b/apps/ensapi/src/handlers/api/graphql/ensnode-graphql-api.ts @@ -6,7 +6,7 @@ import { createApp } from "@/lib/hono-factory"; const app = createApp(); -// 503 if ensv2 plugin not available +// 503 if prerequisites not met app.use(async (c, next) => { const prerequisite = hasGraphqlApiConfigSupport(config.ensIndexerPublicConfig); if (!prerequisite.supported) { diff --git a/apps/ensapi/src/index.ts b/apps/ensapi/src/index.ts index 456716a369..1c741b90b0 100644 --- a/apps/ensapi/src/index.ts +++ b/apps/ensapi/src/index.ts @@ -7,6 +7,7 @@ import { getReferralLeaderboardEditionsCaches } from "@/cache/referral-leaderboa import { referralProgramEditionConfigSetCache } from "@/cache/referral-program-edition-set.cache"; import { referrerLeaderboardCache } from "@/cache/referrer-leaderboard.cache"; import { redactEnsApiConfig } from "@/config/redact"; +import { writeGraphQLSchema } from "@/graphql-api/lib/write-graphql-schema"; import { sdk } from "@/lib/instrumentation"; import logger from "@/lib/logger"; @@ -26,12 +27,15 @@ const server = serve( async (info) => { logger.info({ config: redactEnsApiConfig(config) }, `ENSApi listening on port ${info.port}`); + // Write the generated graphql schema in the background + void writeGraphQLSchema(); + // Trigger proactive initialization of the indexing status cache at startup. // SWRCache with proactivelyInitialize: true starts fetching immediately upon // construction, but construction is deferred via the lazy proxy until first // access — so we access it explicitly here rather than waiting for the first // user request. - indexingStatusCache.read(); + void indexingStatusCache.read(); }, ); diff --git a/docker-compose.yml b/docker-compose.yml index 3e1bf72b7d..dfc2e3a10c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,7 +7,7 @@ services: environment: # Override environment variables to point to docker instances DATABASE_URL: postgresql://postgres:password@postgres:5432/postgres - DATABASE_SCHEMA: ensindexer_0 + DATABASE_SCHEMA: docker_compose_ensindexer_schema ENSRAINBOW_URL: http://ensrainbow:3223 env_file: # NOTE: must define apps/ensindexer/.env.local (see apps/ensindexer/.env.local.example) @@ -35,7 +35,7 @@ services: environment: # Override environment variables to point to docker instances DATABASE_URL: postgresql://postgres:password@postgres:5432/postgres - ENSINDEXER_SCHEMA_NAME: ensindexer_0 + ENSINDEXER_SCHEMA_NAME: docker_compose_ensindexer_schema env_file: # NOTE: must define apps/ensapi/.env.local (see apps/ensapi/.env.local.example) # Copy .env.local.example to .env.local and configure all required values diff --git a/package.json b/package.json index a7b8af8779..4b6d2fce7b 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,8 @@ "docker:build:ensrainbow": "docker build -f apps/ensrainbow/Dockerfile -t ghcr.io/namehash/ensnode/ensrainbow:latest .", "docker:build:ensapi": "docker build -f apps/ensapi/Dockerfile -t ghcr.io/namehash/ensnode/ensapi:latest .", "otel-desktop-viewer": "docker run -p 8000:8000 -p 4317:4317 -p 4318:4318 davetron5000/otel-desktop-viewer:alpine-3", - "generate:openapi": "pnpm -r --if-present generate:openapi" + "generate:openapi": "pnpm -r --if-present generate:openapi", + "generate:gqlschema": "pnpm -F ensapi generate:gqlschema && pnpm -F enssdk generate:gqlschema" }, "devDependencies": { "@biomejs/biome": "^2.3.1", diff --git a/packages/enscli/LICENSE b/packages/enscli/LICENSE new file mode 100644 index 0000000000..24d66814d7 --- /dev/null +++ b/packages/enscli/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/packages/enscli/README.md b/packages/enscli/README.md new file mode 100644 index 0000000000..3ce7543ea3 --- /dev/null +++ b/packages/enscli/README.md @@ -0,0 +1,5 @@ +# enscli + +This package name is reserved for the [ENSNode](https://ensnode.io) project by [NameHash Labs](https://namehashlabs.org). + +For more information, visit [ensnode.io](https://ensnode.io). diff --git a/packages/enscli/package.json b/packages/enscli/package.json new file mode 100644 index 0000000000..d439590f65 --- /dev/null +++ b/packages/enscli/package.json @@ -0,0 +1,13 @@ +{ + "private": true, + "name": "enscli", + "version": "1.9.0", + "description": "Reserved for the ENSNode project by NameHash Labs. See https://ensnode.io", + "repository": { + "type": "git", + "url": "https://github.com/namehash/ensnode.git", + "directory": "packages/enscli" + }, + "license": "MIT", + "homepage": "https://ensnode.io" +} diff --git a/packages/enskit/LICENSE b/packages/enskit/LICENSE new file mode 100644 index 0000000000..24d66814d7 --- /dev/null +++ b/packages/enskit/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/packages/enskit/README.md b/packages/enskit/README.md new file mode 100644 index 0000000000..12214ac9d2 --- /dev/null +++ b/packages/enskit/README.md @@ -0,0 +1,5 @@ +# enskit + +This package name is reserved for the [ENSNode](https://ensnode.io) project by [NameHash Labs](https://namehashlabs.org). + +For more information, visit [ensnode.io](https://ensnode.io). diff --git a/packages/enskit/package.json b/packages/enskit/package.json new file mode 100644 index 0000000000..5e46714b5d --- /dev/null +++ b/packages/enskit/package.json @@ -0,0 +1,12 @@ +{ + "name": "enskit", + "version": "1.9.0", + "description": "Reserved for the ENSNode project by NameHash Labs. See https://ensnode.io", + "repository": { + "type": "git", + "url": "https://github.com/namehash/ensnode.git", + "directory": "packages/enskit" + }, + "license": "MIT", + "homepage": "https://ensnode.io" +} diff --git a/packages/enssdk/LICENSE b/packages/enssdk/LICENSE new file mode 100644 index 0000000000..24d66814d7 --- /dev/null +++ b/packages/enssdk/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/packages/enssdk/README.md b/packages/enssdk/README.md new file mode 100644 index 0000000000..d753ee4ca3 --- /dev/null +++ b/packages/enssdk/README.md @@ -0,0 +1,53 @@ +# enssdk + +The foundational ENS developer library. Isomorphic, tree-shakable, with composable modules via subpath exports. + +Learn more about [ENSNode](https://ensnode.io/) from [the ENSNode docs](https://ensnode.io/docs). + +## Installation + +```bash +npm install enssdk +``` + +## Usage + +### Core Client + +```typescript +import { createEnsNodeClient } from "enssdk/core"; + +const client = createEnsNodeClient({ url: "https://api.alpha.ensnode.io" }); +``` + +### Omnigraph (Typed GraphQL) + +```typescript +import { createEnsNodeClient } from "enssdk/core"; +import { omnigraph, graphql } from "enssdk/omnigraph"; + +const client = createEnsNodeClient({ url: "https://api.alpha.ensnode.io" }) + .extend(omnigraph); + +const MyQuery = graphql(` + query MyQuery($name: Name!) { + domain(by: { name: $name }) { + name + registration { expiry } + } + } +`); + +const result = await client.omnigraph.query({ + query: MyQuery, + variables: { name: "nick.eth" }, +}); +``` + +Modules are composable via `extend()` — only import what you use. + +## License + +Licensed under the MIT License, Copyright © 2025-present [NameHash Labs](https://namehashlabs.org). + +See [LICENSE](./LICENSE) for more information. diff --git a/packages/enssdk/biome.jsonc b/packages/enssdk/biome.jsonc new file mode 100644 index 0000000000..608ccaefbb --- /dev/null +++ b/packages/enssdk/biome.jsonc @@ -0,0 +1,7 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.3.2/schema.json", + "extends": "//", + "files": { + "includes": ["**", "!src/omnigraph/generated"] + } +} diff --git a/packages/enssdk/package.json b/packages/enssdk/package.json new file mode 100644 index 0000000000..276fa00e5c --- /dev/null +++ b/packages/enssdk/package.json @@ -0,0 +1,57 @@ +{ + "name": "enssdk", + "version": "1.9.0", + "type": "module", + "description": "The foundational ENS development library", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/namehash/ensnode.git", + "directory": "packages/enssdk" + }, + "homepage": "https://ensnode.io", + "keywords": [ + "ENS", + "ENSNode", + "Omnigraph" + ], + "files": [ + "dist" + ], + "exports": { + "./core": "./src/core/index.ts", + "./omnigraph": "./src/omnigraph/index.ts" + }, + "sideEffects": false, + "publishConfig": { + "access": "public", + "exports": { + "./core": { + "types": "./dist/core/index.d.ts", + "default": "./dist/core/index.js" + }, + "./omnigraph": { + "types": "./dist/omnigraph/index.d.ts", + "default": "./dist/omnigraph/index.js" + } + } + }, + "scripts": { + "prepublish": "tsup", + "lint": "biome check --write .", + "lint:ci": "biome ci", + "test": "vitest", + "typecheck": "tsgo --noEmit", + "generate:gqlschema": "gql.tada generate-output" + }, + "dependencies": { + "gql.tada": "^1.8.10", + "graphql": "^16.11.0" + }, + "devDependencies": { + "@ensnode/shared-configs": "workspace:*", + "tsup": "catalog:", + "typescript": "catalog:", + "vitest": "catalog:" + } +} diff --git a/packages/enssdk/src/core/core.test.ts b/packages/enssdk/src/core/core.test.ts new file mode 100644 index 0000000000..38b4f04ac5 --- /dev/null +++ b/packages/enssdk/src/core/core.test.ts @@ -0,0 +1,62 @@ +import { describe, expect, it, vi } from "vitest"; + +import { createEnsNodeClient } from "./index"; + +describe("createEnsNodeClient", () => { + it("creates a client with frozen config", () => { + const client = createEnsNodeClient({ url: "https://example.com" }); + + expect(client.config.url).toBe("https://example.com"); + expect(client.config.fetch).toBeUndefined(); + expect(Object.isFrozen(client.config)).toBe(true); + }); + + it("preserves custom fetch in config", () => { + const customFetch = vi.fn(); + const client = createEnsNodeClient({ + url: "https://example.com", + fetch: customFetch as unknown as typeof globalThis.fetch, + }); + + expect(client.config.fetch).toBe(customFetch); + }); +}); + +describe("extend", () => { + it("adds module properties to the client", () => { + const client = createEnsNodeClient({ url: "https://example.com" }).extend(() => ({ + myModule: { greet: () => "hello" }, + })); + + expect(client.myModule.greet()).toBe("hello"); + expect(client.config.url).toBe("https://example.com"); + }); + + it("passes the base client to the decorator function", () => { + const client = createEnsNodeClient({ url: "https://example.com" }).extend((base) => ({ + meta: { getUrl: () => base.config.url }, + })); + + expect(client.meta.getUrl()).toBe("https://example.com"); + }); + + it("supports chaining multiple extend calls", () => { + const client = createEnsNodeClient({ url: "https://example.com" }) + .extend(() => ({ a: { value: 1 } })) + .extend(() => ({ b: { value: 2 } })); + + expect(client.a.value).toBe(1); + expect(client.b.value).toBe(2); + expect(client.config.url).toBe("https://example.com"); + }); + + it("later extensions can see earlier extensions via the base client", () => { + const client = createEnsNodeClient({ url: "https://example.com" }) + .extend(() => ({ a: { value: 42 } })) + .extend((base) => ({ + b: { doubled: () => base.a.value * 2 }, + })); + + expect(client.b.doubled()).toBe(84); + }); +}); diff --git a/packages/enssdk/src/core/index.ts b/packages/enssdk/src/core/index.ts new file mode 100644 index 0000000000..ac55b6d66a --- /dev/null +++ b/packages/enssdk/src/core/index.ts @@ -0,0 +1,39 @@ +export interface EnsNodeClientConfig { + /** + * ENSNode instance URL (e.g. "https://api.alpha.ensnode.io") + */ + url: string; + + /** + * Optional fetch implementation (for Node/edge runtimes) + */ + fetch?: typeof globalThis.fetch; +} + +export type EnsNodeClient = TExtended & { + readonly config: Readonly; + extend( + fn: (client: EnsNodeClient) => T, + ): EnsNodeClient; +}; + +export function createEnsNodeClient(config: EnsNodeClientConfig): EnsNodeClient { + const frozenConfig = Object.freeze({ ...config }); + + function makeClient(base: Record): EnsNodeClient> { + const client = { + ...base, + config: frozenConfig, + extend(fn: (client: any) => object) { + const extension = fn(client); + return makeClient({ + ...base, + ...(extension as Record), + }); + }, + }; + return client as EnsNodeClient>; + } + + return makeClient({}) as EnsNodeClient; +} diff --git a/packages/enssdk/src/omnigraph/generated/graphql-env.d.ts b/packages/enssdk/src/omnigraph/generated/graphql-env.d.ts new file mode 100644 index 0000000000..68dc4c8e32 --- /dev/null +++ b/packages/enssdk/src/omnigraph/generated/graphql-env.d.ts @@ -0,0 +1,133 @@ +/* eslint-disable */ +/* prettier-ignore */ + +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; } }; }; }; + '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; } }; }; }; + '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; } }; }; }; + '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; } }; }; }; + '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; } }; }; }; + '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 }]; }; + '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; } }; }; }; + '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: { 'canonicalId': { name: 'canonicalId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; '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; } }; }; }; + '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; }; } }; }; }; + 'EventsWhereInput': { kind: 'INPUT_OBJECT'; name: 'EventsWhereInput'; isOneOf: false; inputFields: [{ name: 'from'; type: { kind: 'SCALAR'; name: 'Address'; ofType: null; }; defaultValue: null }, { 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 }]; }; + '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 }]; }; + '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; } }; }; }; + 'PermissionsId': unknown; + '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; } }; }; }; + '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; } }; }; }; + '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; } }; }; }; + '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; } }; }; }; + '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; } }; }; }; + '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; } }; }; }; + '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; } }; }; }; + 'ResolverRecordsId': unknown; + 'String': unknown; + 'SubdomainsWhereInput': { kind: 'INPUT_OBJECT'; name: 'SubdomainsWhereInput'; isOneOf: false; inputFields: [{ name: 'name'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; }; defaultValue: null }]; }; + 'ThreeDNSRegistration': { kind: 'OBJECT'; name: 'ThreeDNSRegistration'; 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; } }; }; }; + 'WrappedBaseRegistrarRegistration': { kind: 'OBJECT'; name: 'WrappedBaseRegistrarRegistration'; fields: { 'fuses': { name: 'fuses'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; 'tokenId': { name: 'tokenId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; }; }; +}; + +/** An IntrospectionQuery representation of your schema. + * + * @remarks + * This is an introspection of your schema saved as a file by GraphQLSP. + * It will automatically be used by `gql.tada` to infer the types of your GraphQL documents. + * If you need to reuse this data or update your `scalars`, update `tadaOutputLocation` to + * instead save to a .ts instead of a .d.ts file. + */ +export type introspection = { + name: never; + query: 'Query'; + mutation: never; + subscription: never; + types: introspection_types; +}; + +import * as gqlTada from 'gql.tada'; + +declare module 'gql.tada' { + interface setupSchema { + introspection: introspection + } +} \ No newline at end of file diff --git a/packages/enssdk/src/omnigraph/generated/schema.graphql b/packages/enssdk/src/omnigraph/generated/schema.graphql new file mode 100644 index 0000000000..c80de6e7c1 --- /dev/null +++ b/packages/enssdk/src/omnigraph/generated/schema.graphql @@ -0,0 +1,1162 @@ +"""Represents an individual Account, keyed by its Address.""" +type Account { + """An EVM Address that uniquely identifies this Account on-chain.""" + address: Address! + + """The Domains that are owned by the Account.""" + domains(after: String, before: String, first: Int, last: Int, order: DomainsOrderInput, where: AccountDomainsWhereInput): AccountDomainsConnection + + """ + All Events for which this Account is the sender (i.e. `Transaction.from`). + """ + events(after: String, before: String, first: Int, last: Int, where: AccountEventsWhereInput): AccountEventsConnection + + """A unique reference to this Account.""" + id: Address! + + """ + The Permissions granted to this Account, optionally filtered to Permissions in a specific contract. + """ + permissions(after: String, before: String, first: Int, in: AccountIdInput, last: Int): AccountPermissionsConnection + + """The Permissions on Registries granted to this Account.""" + registryPermissions(after: String, before: String, first: Int, last: Int): AccountRegistryPermissionsConnection + + """The Permissions on Resolvers granted to this Account.""" + resolverPermissions(after: String, before: String, first: Int, last: Int): AccountResolverPermissionsConnection +} + +type AccountDomainsConnection { + edges: [AccountDomainsConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type AccountDomainsConnectionEdge { + cursor: String! + node: Domain +} + +"""Filter for Account.domains query.""" +input AccountDomainsWhereInput { + """ + Optional, defaults to false. If true, filters the set of Domains by those that are Canonical (i.e. reachable by ENS Forward Resolution). + """ + canonical: Boolean = false + + """ + A partial Interpreted Name by which to search the set of Domains. ex: 'example', 'example.', 'example.et'. + """ + name: String +} + +type AccountEventsConnection { + edges: [AccountEventsConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type AccountEventsConnectionEdge { + cursor: String! + node: Event +} + +""" +Filter conditions for Account.events (where `from` is implied by the Account). +""" +input AccountEventsWhereInput { + """ + Filter to events whose selector (event signature) is one of the provided values. + """ + selector_in: [Hex!] + + """Filter to events at or after this UnixTimestamp.""" + timestamp_gte: BigInt + + """Filter to events at or before this UnixTimestamp.""" + timestamp_lte: BigInt +} + +"""A CAIP-10 Account ID including chainId and address.""" +type AccountId { + address: Address + chainId: ChainId +} + +"""A CAIP-10 Account ID including chainId and address.""" +input AccountIdInput { + address: Address! + chainId: ChainId! +} + +type AccountPermissionsConnection { + edges: [AccountPermissionsConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type AccountPermissionsConnectionEdge { + cursor: String! + node: PermissionsUser +} + +type AccountRegistryPermissionsConnection { + edges: [AccountRegistryPermissionsConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type AccountRegistryPermissionsConnectionEdge { + cursor: String! + node: RegistryPermissionsUser +} + +type AccountResolverPermissionsConnection { + edges: [AccountResolverPermissionsConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type AccountResolverPermissionsConnectionEdge { + cursor: String! + node: ResolverPermissionsUser +} + +"""Address represents a lowercase (unchecksummed) viem#Address.""" +scalar Address + +""" +A BaseRegistrarRegistration represents a Registration within an ENSv1 BaseRegistrar contract, including those deployed by Basenames and Lineanames. +""" +type BaseRegistrarRegistration implements Registration { + """The `baseCost` for registering this Domain, in wei.""" + baseCost: BigInt + + """The Domain for which this Registration exists.""" + domain: Domain! + + """The Event for which this Registration was created.""" + event: Event! + + """ + Indicates whether this Registration is expired. If the Registration is for an ENSv1Domain, a Registration is only considered `expired` after the Grace Period has elapsed. + """ + expired: Boolean! + + """A UnixTimestamp indicating the Registration's expiry, if exists.""" + expiry: BigInt + + """A unique reference to this Registration.""" + id: RegistrationId! + + """ + Whether this Registration is in the Grace Period (90 days) and can be renewed by the current owner. + """ + isInGracePeriod: Boolean! + + """The `premium` for registering this Domain, in wei.""" + premium: BigInt + + """The extra `referrer` data provided with a Registration, if exists.""" + referrer: Hex + + """The Registrant of a Registration, if exists.""" + registrant: Account + + """The Registrar contract under which this Registration is managed.""" + registrar: AccountId! + + """ + Renewals that have occurred within this Registration's lifespan to extend its expiration. + """ + renewals(after: String, before: String, first: Int, last: Int): RegistrationRenewalsConnection + + """A UnixTimestamp indicating when this Registration was created.""" + start: BigInt! + + """The Unregistrant of a Registration, if exists.""" + unregistrant: Account + + """ + Additional metadata if this BaseRegistrarRegistration is wrapped by the NameWrapper (i.e. in the case of wrapped .eth names). + """ + wrapped: WrappedBaseRegistrarRegistration +} + +"""BigInt represents non-fractional signed whole numeric values.""" +scalar BigInt + +"""ChainId represents a @ensnode/ensnode-sdk#ChainId.""" +scalar ChainId + +"""CoinType represents a @ensnode/ensnode-sdk#CoinType.""" +scalar CoinType + +""" +A Domain represents an individual Label within the ENS namegraph. It may or may not be Canonical. It may be an ENSv1Domain or an ENSv2Domain. +""" +interface Domain { + """All Events associated with this Domain.""" + events(after: String, before: String, first: Int, last: Int, where: EventsWhereInput): DomainEventsConnection + + """A unique reference to this Domain.""" + id: DomainId! + + """The Label this Domain represents in the ENS Namegraph""" + label: Label! + + """ + The Canonical Name for this Domain. If the Domain is not Canonical, then `name` will be null. + """ + name: Name + + """The owner of this Domain.""" + owner: Account + + """ + The Canonical Path from the ENS Root to this Domain. `path` is null if the Domain is not Canonical. + """ + path: [Domain!] + + """The latest Registration for this Domain, if exists.""" + registration: Registration + + """All Registrations for a Domain, including the latest Registration.""" + registrations(after: String, before: String, first: Int, last: Int): DomainRegistrationsConnection + + """ + The Resolver that this Domain has assigned, if any. NOTE that this is the Domain's _assigned_ Resolver, _not_ its _effective_ Resolver, which can only be determined by following ENS Forward Resolution and ENSIP-10. + """ + resolver: Resolver + + """ + All Domains that are direct descendents of this Domain in the namegraph. + """ + subdomains(after: String, before: String, first: Int, last: Int, order: DomainsOrderInput, where: SubdomainsWhereInput): DomainSubdomainsConnection +} + +type DomainEventsConnection { + edges: [DomainEventsConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type DomainEventsConnectionEdge { + cursor: String! + node: Event +} + +"""DomainId represents a @ensnode/ensnode-sdk#DomainId.""" +scalar DomainId + +"""Reference a specific Domain.""" +input DomainIdInput @oneOf { + id: DomainId + name: Name +} + +"""Filter Permissions over this Domain by a specific User address.""" +input DomainPermissionsWhereInput { + user: Address +} + +type DomainRegistrationsConnection { + edges: [DomainRegistrationsConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type DomainRegistrationsConnectionEdge { + cursor: String! + node: Registration +} + +type DomainSubdomainsConnection { + edges: [DomainSubdomainsConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type DomainSubdomainsConnectionEdge { + cursor: String! + node: Domain +} + +"""Fields by which domains can be ordered""" +enum DomainsOrderBy { + NAME + REGISTRATION_EXPIRY + REGISTRATION_TIMESTAMP +} + +""" +Ordering options for domains query. If no order is provided, the default is ASC. +""" +input DomainsOrderInput { + by: DomainsOrderBy! + dir: OrderDirection = ASC +} + +"""Filter for the top-level domains query.""" +input DomainsWhereInput { + """ + Optional, defaults to false. If true, filters the set of Domains by those that are Canonical (i.e. reachable by ENS Forward Resolution). If false, the set of Domains is not filtered, and may include ENSv2 Domains not reachable by ENS Forward Resolution. + """ + canonical: Boolean = false + + """ + A partial Interpreted Name by which to search the set of Domains. ex: 'example', 'example.', 'example.et'. + """ + name: String! +} + +"""An ENSv1Domain represents an ENSv1 Domain.""" +type ENSv1Domain implements Domain { + """All Events associated with this Domain.""" + events(after: String, before: String, first: Int, last: Int, where: EventsWhereInput): DomainEventsConnection + + """A unique reference to this Domain.""" + id: DomainId! + + """The Label this Domain represents in the ENS Namegraph""" + label: Label! + + """ + The Canonical Name for this Domain. If the Domain is not Canonical, then `name` will be null. + """ + name: Name + + """The owner of this Domain.""" + owner: Account + + """The parent Domain of this Domain in the ENSv1 nametree.""" + parent: ENSv1Domain + + """ + The Canonical Path from the ENS Root to this Domain. `path` is null if the Domain is not Canonical. + """ + path: [Domain!] + + """The latest Registration for this Domain, if exists.""" + registration: Registration + + """All Registrations for a Domain, including the latest Registration.""" + registrations(after: String, before: String, first: Int, last: Int): DomainRegistrationsConnection + + """ + The Resolver that this Domain has assigned, if any. NOTE that this is the Domain's _assigned_ Resolver, _not_ its _effective_ Resolver, which can only be determined by following ENS Forward Resolution and ENSIP-10. + """ + resolver: Resolver + + """ + The rootRegistryOwner of this Domain, i.e. the owner() of this Domain within the ENSv1 Registry. + """ + rootRegistryOwner: Account + + """ + All Domains that are direct descendents of this Domain in the namegraph. + """ + subdomains(after: String, before: String, first: Int, last: Int, order: DomainsOrderInput, where: SubdomainsWhereInput): DomainSubdomainsConnection +} + +"""An ENSv2Domain represents an ENSv2 Domain.""" +type ENSv2Domain implements Domain { + """The ENSv2Domain's Canonical Id.""" + canonicalId: BigInt! + + """All Events associated with this Domain.""" + events(after: String, before: String, first: Int, last: Int, where: EventsWhereInput): DomainEventsConnection + + """A unique reference to this Domain.""" + id: DomainId! + + """The Label this Domain represents in the ENS Namegraph""" + label: Label! + + """ + The Canonical Name for this Domain. If the Domain is not Canonical, then `name` will be null. + """ + name: Name + + """The owner of this Domain.""" + owner: Account + + """ + The Canonical Path from the ENS Root to this Domain. `path` is null if the Domain is not Canonical. + """ + path: [Domain!] + + """ + Permissions for this Domain within its Registry, representing the roles granted to users for this Domain's token. + """ + permissions(after: String, before: String, first: Int, last: Int, where: DomainPermissionsWhereInput): ENSv2DomainPermissionsConnection + + """The latest Registration for this Domain, if exists.""" + registration: Registration + + """All Registrations for a Domain, including the latest Registration.""" + registrations(after: String, before: String, first: Int, last: Int): DomainRegistrationsConnection + + """The Registry under which this ENSv2Domain exists.""" + registry: Registry! + + """ + The Resolver that this Domain has assigned, if any. NOTE that this is the Domain's _assigned_ Resolver, _not_ its _effective_ Resolver, which can only be determined by following ENS Forward Resolution and ENSIP-10. + """ + resolver: Resolver + + """ + All Domains that are direct descendents of this Domain in the namegraph. + """ + subdomains(after: String, before: String, first: Int, last: Int, order: DomainsOrderInput, where: SubdomainsWhereInput): DomainSubdomainsConnection + + """The Registry this ENSv2Domain declares as its Subregistry, if exists.""" + subregistry: Registry + + """The ENSv2Domain's current Token Id.""" + tokenId: BigInt! +} + +type ENSv2DomainPermissionsConnection { + edges: [ENSv2DomainPermissionsConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type ENSv2DomainPermissionsConnectionEdge { + cursor: String! + node: PermissionsUser +} + +""" +ENSv2RegistryRegistration represents a Registration within an ENSv2 Registry. +""" +type ENSv2RegistryRegistration implements Registration { + """The Domain for which this Registration exists.""" + domain: Domain! + + """The Event for which this Registration was created.""" + event: Event! + + """ + Indicates whether this Registration is expired. If the Registration is for an ENSv1Domain, a Registration is only considered `expired` after the Grace Period has elapsed. + """ + expired: Boolean! + + """A UnixTimestamp indicating the Registration's expiry, if exists.""" + expiry: BigInt + + """A unique reference to this Registration.""" + id: RegistrationId! + + """The extra `referrer` data provided with a Registration, if exists.""" + referrer: Hex + + """The Registrant of a Registration, if exists.""" + registrant: Account + + """The Registrar contract under which this Registration is managed.""" + registrar: AccountId! + + """ + Renewals that have occurred within this Registration's lifespan to extend its expiration. + """ + renewals(after: String, before: String, first: Int, last: Int): RegistrationRenewalsConnection + + """A UnixTimestamp indicating when this Registration was created.""" + start: BigInt! + + """The Unregistrant of a Registration, if exists.""" + unregistrant: Account +} + +""" +ENSv2RegistryReservation represents a Reservation within an ENSv2 Registry. +""" +type ENSv2RegistryReservation implements Registration { + """The Domain for which this Registration exists.""" + domain: Domain! + + """The Event for which this Registration was created.""" + event: Event! + + """ + Indicates whether this Registration is expired. If the Registration is for an ENSv1Domain, a Registration is only considered `expired` after the Grace Period has elapsed. + """ + expired: Boolean! + + """A UnixTimestamp indicating the Registration's expiry, if exists.""" + expiry: BigInt + + """A unique reference to this Registration.""" + id: RegistrationId! + + """The extra `referrer` data provided with a Registration, if exists.""" + referrer: Hex + + """The Registrant of a Registration, if exists.""" + registrant: Account + + """The Registrar contract under which this Registration is managed.""" + registrar: AccountId! + + """ + Renewals that have occurred within this Registration's lifespan to extend its expiration. + """ + renewals(after: String, before: String, first: Int, last: Int): RegistrationRenewalsConnection + + """A UnixTimestamp indicating when this Registration was created.""" + start: BigInt! + + """The Unregistrant of a Registration, if exists.""" + unregistrant: Account +} + +""" +An Event represents a discrete Log Event that was emitted on an EVM chain, including associated metadata. +""" +type Event { + """Identifies the contract by which this Event was emitted.""" + address: Address! + + """Identifies the Block within which this Event was emitted.""" + blockHash: Hex! + + """The block number within which this Event was emitted.""" + blockNumber: BigInt! + + """The ChainId upon which this Event was emitted.""" + chainId: ChainId! + + """The non-indexed data of this Event's log.""" + data: Hex! + + """ + Identifies the sender of the Transaction within which this Event was emitted. + """ + from: Address! + + """A unique reference to this Event.""" + id: ID! + + """The index of this Event's log within the Block.""" + logIndex: Int! + + """ + The UnixTimestamp indicating the moment in which this Event was emitted. + """ + timestamp: BigInt! + + """ + Identifies the recipient of the Transaction within which this Event was emitted. Null if the transaction deployed a contract. + """ + to: Address + + """The indexed topics of this Event's log.""" + topics: [Hex!]! + + """Identifies the Transaction within which this Event was emitted.""" + transactionHash: Hex! + + """The index of the Transaction within the Block.""" + transactionIndex: Int! +} + +"""Filter conditions for an events connection.""" +input EventsWhereInput { + """Filter to events sent by this address.""" + from: Address + + """ + Filter to events whose selector (event signature) is one of the provided values. + """ + selector_in: [Hex!] + + """Filter to events at or after this UnixTimestamp.""" + timestamp_gte: BigInt + + """Filter to events at or before this UnixTimestamp.""" + timestamp_lte: BigInt +} + +"""Hex represents viem#Hex.""" +scalar Hex + +""" +Represents a Label within ENS, providing its hash and interpreted representation. +""" +type Label { + """ + The Label's LabelHash + (@see https://ensnode.io/docs/reference/terminology#labels-labelhashes-labelhash-function) + """ + hash: Hex! + + """ + 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! +} + +"""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 + node: Node +} + +""" +A NameWrapperRegistration represents a Registration initiated by the ENSv1 NameWrapper. +""" +type NameWrapperRegistration implements Registration { + """The Domain for which this Registration exists.""" + domain: Domain! + + """The Event for which this Registration was created.""" + event: Event! + + """ + Indicates whether this Registration is expired. If the Registration is for an ENSv1Domain, a Registration is only considered `expired` after the Grace Period has elapsed. + """ + expired: Boolean! + + """A UnixTimestamp indicating the Registration's expiry, if exists.""" + expiry: BigInt + + """The Fuses for this Registration's Domain in the NameWrapper.""" + fuses: Int! + + """A unique reference to this Registration.""" + id: RegistrationId! + + """The extra `referrer` data provided with a Registration, if exists.""" + referrer: Hex + + """The Registrant of a Registration, if exists.""" + registrant: Account + + """The Registrar contract under which this Registration is managed.""" + registrar: AccountId! + + """ + Renewals that have occurred within this Registration's lifespan to extend its expiration. + """ + renewals(after: String, before: String, first: Int, last: Int): RegistrationRenewalsConnection + + """A UnixTimestamp indicating when this Registration was created.""" + start: BigInt! + + """The Unregistrant of a Registration, if exists.""" + unregistrant: Account +} + +"""Node represents a @ensnode/ensnode-sdk#Node.""" +scalar Node + +"""Sort direction""" +enum OrderDirection { + ASC + DESC +} + +type PageInfo { + endCursor: String + hasNextPage: Boolean! + hasPreviousPage: Boolean! + startCursor: String +} + +"""Permissions""" +type Permissions { + """The contract within which these Permissions are granted.""" + contract: AccountId! + + """All Events associated with these Permissions.""" + events(after: String, before: String, first: Int, last: Int, where: EventsWhereInput): PermissionsEventsConnection + + """A unique reference to this Permission.""" + id: PermissionsId! + + """All PermissionResources managed by this contract.""" + resources(after: String, before: String, first: Int, last: Int): PermissionsResourcesConnection + + """The Root Resource.""" + root: PermissionsResource! +} + +type PermissionsEventsConnection { + edges: [PermissionsEventsConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type PermissionsEventsConnectionEdge { + cursor: String! + node: Event +} + +"""PermissionsId represents a @ensnode/ensnode-sdk#PermissionsId.""" +scalar PermissionsId + +"""PermissionsResource""" +type PermissionsResource { + """The contract within which these Permissions are granted.""" + contract: AccountId! + + """A unique reference to this PermissionsResource.""" + id: PermissionsResourceId! + + """The Permissions within which this Resource is managed.""" + permissions: Permissions! + + """Identifies the Resource that this PermissionsResource represents.""" + resource: BigInt! + + """The PermissionUsers who have Roles within this Resource.""" + users(after: String, before: String, first: Int, last: Int): PermissionsResourceUsersConnection +} + +""" +PermissionsResourceId represents a @ensnode/ensnode-sdk#PermissionsResourceId. +""" +scalar PermissionsResourceId + +type PermissionsResourceUsersConnection { + edges: [PermissionsResourceUsersConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type PermissionsResourceUsersConnectionEdge { + cursor: String! + node: PermissionsUser +} + +type PermissionsResourcesConnection { + edges: [PermissionsResourcesConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type PermissionsResourcesConnectionEdge { + cursor: String! + node: PermissionsResource +} + +"""PermissionsUser""" +type PermissionsUser { + """The contract within which these Permissions are granted.""" + contract: AccountId! + + """A unique reference to this PermissionsUser.""" + id: PermissionsUserId! + + """The Resource that this user has Roles within.""" + resource: BigInt! + + """The Roles this User has been granted within this Resource.""" + roles: BigInt! + + """The User for whom these Roles are granted.""" + user: Account! +} + +"""PermissionsUserId represents a @ensnode/ensnode-sdk#PermissionsUserId.""" +scalar PermissionsUserId + +type Query { + """Identify an Account by Address.""" + account(address: Address!): Account + + """Identify a Domain by Name or DomainId""" + domain(by: DomainIdInput!): Domain + + """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 + + """TODO""" + registrations(after: String, before: String, first: Int, last: Int): QueryRegistrationsConnection + + """Identify a Registry by ID or AccountId.""" + registry(by: RegistryIdInput!): Registry + + """Identify a Resolver by ID or AccountId.""" + resolver(by: ResolverIdInput!): Resolver + + """TODO""" + resolvers(after: String, before: String, first: Int, last: Int): QueryResolversConnection + + """The ENSv2 Root Registry, if exists.""" + root: Registry + + """TODO""" + v1Domains(after: String, before: String, first: Int, last: Int): QueryV1DomainsConnection + + """TODO""" + v2Domains(after: String, before: String, first: Int, last: Int): QueryV2DomainsConnection +} + +type QueryDomainsConnection { + edges: [QueryDomainsConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type QueryDomainsConnectionEdge { + cursor: String! + node: Domain +} + +type QueryRegistrationsConnection { + edges: [QueryRegistrationsConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type QueryRegistrationsConnectionEdge { + cursor: String! + node: Registration +} + +type QueryResolversConnection { + edges: [QueryResolversConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type QueryResolversConnectionEdge { + cursor: String! + node: Resolver +} + +type QueryV1DomainsConnection { + edges: [QueryV1DomainsConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type QueryV1DomainsConnectionEdge { + cursor: String! + node: ENSv1Domain +} + +type QueryV2DomainsConnection { + edges: [QueryV2DomainsConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type QueryV2DomainsConnectionEdge { + cursor: String! + node: ENSv2Domain +} + +""" +A Registration represents a Domain's registration status within the various registries. +""" +interface Registration { + """The Domain for which this Registration exists.""" + domain: Domain! + + """The Event for which this Registration was created.""" + event: Event! + + """ + Indicates whether this Registration is expired. If the Registration is for an ENSv1Domain, a Registration is only considered `expired` after the Grace Period has elapsed. + """ + expired: Boolean! + + """A UnixTimestamp indicating the Registration's expiry, if exists.""" + expiry: BigInt + + """A unique reference to this Registration.""" + id: RegistrationId! + + """The extra `referrer` data provided with a Registration, if exists.""" + referrer: Hex + + """The Registrant of a Registration, if exists.""" + registrant: Account + + """The Registrar contract under which this Registration is managed.""" + registrar: AccountId! + + """ + Renewals that have occurred within this Registration's lifespan to extend its expiration. + """ + renewals(after: String, before: String, first: Int, last: Int): RegistrationRenewalsConnection + + """A UnixTimestamp indicating when this Registration was created.""" + start: BigInt! + + """The Unregistrant of a Registration, if exists.""" + unregistrant: Account +} + +"""RegistrationId represents a @ensnode/ensnode-sdk#RegistrationId.""" +scalar RegistrationId + +type RegistrationRenewalsConnection { + edges: [RegistrationRenewalsConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type RegistrationRenewalsConnectionEdge { + cursor: String! + node: Renewal +} + +"""A Registry represents an ENSv2 Registry contract.""" +type Registry { + """Contract metadata for this Registry""" + contract: AccountId! + + """The Domains managed by this Registry.""" + domains(after: String, before: String, first: Int, last: Int, order: DomainsOrderInput, where: RegistryDomainsWhereInput): RegistryDomainsConnection + + """A unique reference to this Registry.""" + id: RegistryId! + + """The Domains for which this Registry is a Subregistry.""" + parents(after: String, before: String, first: Int, last: Int): RegistryParentsConnection + + """The Permissions managed by this Registry.""" + permissions: Permissions +} + +type RegistryDomainsConnection { + edges: [RegistryDomainsConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type RegistryDomainsConnectionEdge { + cursor: String! + node: Domain +} + +"""Filter for Registry.domains query.""" +input RegistryDomainsWhereInput { + """ + A partial Interpreted Name by which to filter Domains in this Registry. + """ + name: String +} + +"""RegistryId represents a @ensnode/ensnode-sdk#RegistryId.""" +scalar RegistryId + +"""Address a Registry by ID or AccountId.""" +input RegistryIdInput @oneOf { + contract: AccountIdInput + id: RegistryId +} + +type RegistryParentsConnection { + edges: [RegistryParentsConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type RegistryParentsConnectionEdge { + cursor: String! + node: ENSv2Domain +} + +type RegistryPermissionsUser { + """A unique reference to this RegistryPermissionsUser.""" + id: PermissionsUserId! + + """The Registry in which this Permission is granted.""" + registry: Registry! + + """The Resource for which this Permission is granted.""" + resource: BigInt! + + """The Roles that this Permission grants.""" + roles: BigInt! + + """The User for whom these Roles are granted.""" + user: Account! +} + +"""A Renewal represents an extension of a Registration's expiry.""" +type Renewal { + """The `base` cost of a Renewal, in wei, if exists.""" + base: BigInt + + """The duration for which a Registration was extended.""" + duration: BigInt! + + """The Event for which this Renewal was created.""" + event: Event! + + """A unique reference to this Renewal.""" + id: RenewalId! + + """The `premium` cost of a Renewal, in wei, if exists.""" + premium: BigInt + + """The extra `referrer` data provided with a Renewal, if exists.""" + referrer: Hex +} + +"""RenewalId represents a @ensnode/ensnode-sdk#RenewalId.""" +scalar RenewalId + +"""A Resolver represents a Resolver contract on-chain.""" +type Resolver { + """Whether Resolver is a BridgedResolver.""" + bridged: AccountId + + """Contract metadata for this Resolver.""" + contract: AccountId! + + """All Events associated with this Resolver.""" + events(after: String, before: String, first: Int, last: Int, where: EventsWhereInput): ResolverEventsConnection + + """A unique reference to this Resolver.""" + id: ResolverId! + + """Permissions granted by this Resolver.""" + permissions: Permissions + + """ResolverRecords issued by this Resolver.""" + records(after: String, before: String, first: Int, last: Int): ResolverRecordsConnection + + """Identify a ResolverRecord by `name` or `node`.""" + records_(for: NameOrNodeInput!): ResolverRecords +} + +type ResolverEventsConnection { + edges: [ResolverEventsConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type ResolverEventsConnectionEdge { + cursor: String! + node: Event +} + +"""ResolverId represents a @ensnode/ensnode-sdk#ResolverId.""" +scalar ResolverId + +"""Address a Resolver by ID or AccountId.""" +input ResolverIdInput @oneOf { + contract: AccountIdInput + id: ResolverId +} + +type ResolverPermissionsUser { + """A unique reference to this ResolverPermissionsUser.""" + id: PermissionsUserId! + + """The Resolver in which this Permission is granted.""" + resolver: Resolver! + + """The Resource for which this Permission is granted.""" + resource: BigInt! + + """The Roles that this Permission grants.""" + roles: BigInt! + + """The User for whom these Roles are granted.""" + user: Account! +} + +"""ResolverRecords represents the _indexed_ records within a Resolver.""" +type ResolverRecords { + """Unique CoinTypes of `addr` records for this `node`.""" + coinTypes: [CoinType!]! + + """A unique reference to these ResolverRecords.""" + id: ResolverRecordsId! + + """Unique keys of `text` records for this `node`.""" + keys: [String!]! + + """The `name` record for this `node`, if any.""" + name: String + + """The Node for which these ResolverRecords are issued.""" + node: Node! +} + +type ResolverRecordsConnection { + edges: [ResolverRecordsConnectionEdge] + pageInfo: PageInfo! + totalCount: Int! +} + +type ResolverRecordsConnectionEdge { + cursor: String! + node: ResolverRecords +} + +"""ResolverRecordsId represents a @ensnode/ensnode-sdk#ResolverRecordsId.""" +scalar ResolverRecordsId + +"""Filter for Domain.subdomains query.""" +input SubdomainsWhereInput { + """A partial Interpreted Name by which to filter subdomains.""" + name: String +} + +"""ThreeDNSRegistration represents a Registration within ThreeDNSToken.""" +type ThreeDNSRegistration implements Registration { + """The Domain for which this Registration exists.""" + domain: Domain! + + """The Event for which this Registration was created.""" + event: Event! + + """ + Indicates whether this Registration is expired. If the Registration is for an ENSv1Domain, a Registration is only considered `expired` after the Grace Period has elapsed. + """ + expired: Boolean! + + """A UnixTimestamp indicating the Registration's expiry, if exists.""" + expiry: BigInt + + """A unique reference to this Registration.""" + id: RegistrationId! + + """The extra `referrer` data provided with a Registration, if exists.""" + referrer: Hex + + """The Registrant of a Registration, if exists.""" + registrant: Account + + """The Registrar contract under which this Registration is managed.""" + registrar: AccountId! + + """ + Renewals that have occurred within this Registration's lifespan to extend its expiration. + """ + renewals(after: String, before: String, first: Int, last: Int): RegistrationRenewalsConnection + + """A UnixTimestamp indicating when this Registration was created.""" + start: BigInt! + + """The Unregistrant of a Registration, if exists.""" + unregistrant: Account +} + +""" +Additional metadata for BaseRegistrar Registrations wrapped by the NameWrapper (i.e. in the case of a wrapped .eth name) +""" +type WrappedBaseRegistrarRegistration { + """The Fuses for this Registration's Domain in the NameWrapper.""" + fuses: Int! + + """The TokenID for this Domain in the NameWrapper.""" + tokenId: BigInt! +} \ No newline at end of file diff --git a/packages/enssdk/src/omnigraph/graphql.ts b/packages/enssdk/src/omnigraph/graphql.ts new file mode 100644 index 0000000000..75cbc89fca --- /dev/null +++ b/packages/enssdk/src/omnigraph/graphql.ts @@ -0,0 +1,23 @@ +import { initGraphQLTada } from "gql.tada"; + +import type { introspection } from "./generated/graphql-env"; + +// Semantic scalar types — these will eventually be imported from enssdk's +// own type definitions. For now, defined inline. +type Name = string; + +export const graphql = initGraphQLTada<{ + introspection: introspection; + scalars: { + Address: `0x${string}`; + BigInt: bigint; + ChainId: number; + Hex: `0x${string}`; + ID: string; + Name: Name; + Node: `0x${string}`; + }; +}>(); + +export type { FragmentOf, ResultOf, VariablesOf } from "gql.tada"; +export { readFragment } from "gql.tada"; diff --git a/packages/enssdk/src/omnigraph/index.ts b/packages/enssdk/src/omnigraph/index.ts new file mode 100644 index 0000000000..a5a833d95c --- /dev/null +++ b/packages/enssdk/src/omnigraph/index.ts @@ -0,0 +1,58 @@ +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>; + }, + }, + }; +} diff --git a/packages/enssdk/src/omnigraph/omnigraph.test.ts b/packages/enssdk/src/omnigraph/omnigraph.test.ts new file mode 100644 index 0000000000..62c2bbdbfe --- /dev/null +++ b/packages/enssdk/src/omnigraph/omnigraph.test.ts @@ -0,0 +1,93 @@ +import { parse } from "graphql"; +import { describe, expect, it, vi } from "vitest"; + +import { createEnsNodeClient } from "../core/index"; +import { omnigraph } from "./index"; + +function createMockClient(mockFetch: ReturnType) { + return createEnsNodeClient({ + url: "https://example.com", + fetch: mockFetch as unknown as typeof globalThis.fetch, + }).extend(omnigraph); +} + +describe("omnigraph module", () => { + it("attaches omnigraph namespace to client", () => { + const client = createEnsNodeClient({ url: "https://example.com" }).extend(omnigraph); + + expect(client.omnigraph).toBeDefined(); + expect(typeof client.omnigraph.query).toBe("function"); + }); + + it("sends a POST request with string query", async () => { + const mockResponse = { data: { domain: { name: "nick.eth" } } }; + const mockFetch = vi.fn().mockResolvedValue({ + json: () => Promise.resolve(mockResponse), + }); + + const client = createMockClient(mockFetch); + + const result = await client.omnigraph.query({ + query: 'query { domain(by: { name: "nick.eth" }) { name } }', + }); + + expect(mockFetch).toHaveBeenCalledWith("https://example.com/api/omnigraph", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + query: 'query { domain(by: { name: "nick.eth" }) { name } }', + variables: undefined, + }), + signal: undefined, + }); + + expect(result).toEqual(mockResponse); + }); + + it("sends variables when provided", async () => { + const mockFetch = vi.fn().mockResolvedValue({ + json: () => Promise.resolve({ data: null }), + }); + + const client = createMockClient(mockFetch); + + await client.omnigraph.query({ + query: "query($name: String!) { domain(by: { name: $name }) { name } }", + variables: { name: "nick.eth" }, + }); + + const body = JSON.parse(mockFetch.mock.calls[0][1].body); + expect(body.variables).toEqual({ name: "nick.eth" }); + }); + + it("passes signal for abort support", async () => { + const mockFetch = vi.fn().mockResolvedValue({ + json: () => Promise.resolve({ data: null }), + }); + const controller = new AbortController(); + + const client = createMockClient(mockFetch); + + await client.omnigraph.query({ + query: "query { domains { name } }", + signal: controller.signal, + }); + + expect(mockFetch.mock.calls[0][1].signal).toBe(controller.signal); + }); + + it("prints DocumentNode queries to string", async () => { + const mockFetch = vi.fn().mockResolvedValue({ + json: () => Promise.resolve({ data: null }), + }); + + const client = createMockClient(mockFetch); + const doc = parse('query { domain(by: { name: "nick.eth" }) { name } }'); + + await client.omnigraph.query({ query: doc }); + + const body = JSON.parse(mockFetch.mock.calls[0][1].body); + expect(body.query).toContain("domain"); + expect(body.query).toContain("nick.eth"); + }); +}); diff --git a/packages/enssdk/tsconfig.json b/packages/enssdk/tsconfig.json new file mode 100644 index 0000000000..6af4a81c9f --- /dev/null +++ b/packages/enssdk/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "@ensnode/shared-configs/tsconfig.lib.json", + "compilerOptions": { + "rootDir": ".", + "plugins": [ + { + "name": "gql.tada/ts-plugin", + "schema": "./src/omnigraph/generated/schema.graphql", + "tadaOutputLocation": "./src/omnigraph/generated/graphql-env.d.ts" + } + ] + }, + "include": ["src/**/*"], + "exclude": ["dist"] +} diff --git a/packages/enssdk/tsup.config.ts b/packages/enssdk/tsup.config.ts new file mode 100644 index 0000000000..4c0916ed86 --- /dev/null +++ b/packages/enssdk/tsup.config.ts @@ -0,0 +1,18 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: { + "core/index": "src/core/index.ts", + "omnigraph/index": "src/omnigraph/index.ts", + }, + platform: "neutral", + format: ["esm"], + target: "es2022", + bundle: true, + splitting: false, + sourcemap: true, + dts: true, + clean: true, + external: ["gql.tada", "graphql"], + outDir: "./dist", +}); diff --git a/packages/enssdk/vitest.config.ts b/packages/enssdk/vitest.config.ts new file mode 100644 index 0000000000..8e3d64e885 --- /dev/null +++ b/packages/enssdk/vitest.config.ts @@ -0,0 +1,15 @@ +import { resolve } from "node:path"; + +import { configDefaults, defineProject } from "vitest/config"; + +export default defineProject({ + resolve: { + alias: { + "@": resolve(__dirname, "./src"), + }, + }, + test: { + environment: "node", + exclude: [...configDefaults.exclude, "**/*.integration.test.ts"], + }, +}); diff --git a/packages/ensskills/LICENSE b/packages/ensskills/LICENSE new file mode 100644 index 0000000000..24d66814d7 --- /dev/null +++ b/packages/ensskills/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/packages/ensskills/README.md b/packages/ensskills/README.md new file mode 100644 index 0000000000..60cd87e96c --- /dev/null +++ b/packages/ensskills/README.md @@ -0,0 +1,5 @@ +# ensskills + +This package name is reserved for the [ENSNode](https://ensnode.io) project by [NameHash Labs](https://namehashlabs.org). + +For more information, visit [ensnode.io](https://ensnode.io). diff --git a/packages/ensskills/package.json b/packages/ensskills/package.json new file mode 100644 index 0000000000..76a04a0f69 --- /dev/null +++ b/packages/ensskills/package.json @@ -0,0 +1,12 @@ +{ + "name": "ensskills", + "version": "1.9.0", + "description": "Reserved for the ENSNode project by NameHash Labs. See https://ensnode.io", + "repository": { + "type": "git", + "url": "https://github.com/namehash/ensnode.git", + "directory": "packages/ensskills" + }, + "license": "MIT", + "homepage": "https://ensnode.io" +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f693c35fe5..39884f65b6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -842,6 +842,8 @@ 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/enscli: {} + packages/ensdb-sdk: devDependencies: '@ensnode/ensnode-sdk': @@ -872,6 +874,8 @@ 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/ensnode-react: dependencies: '@ensnode/ensnode-sdk': @@ -968,6 +972,30 @@ 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/enssdk: + dependencies: + 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) + typescript: + specifier: 'catalog:' + version: 5.9.3 + 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/ensskills: {} + packages/integration-test-env: dependencies: '@ensnode/datasources': @@ -1168,6 +1196,20 @@ importers: packages: + '@0no-co/graphql.web@1.2.0': + resolution: {integrity: sha512-/1iHy9TTr63gE1YcR5idjx8UREz1s0kFhydf3bBLCXyqjhkIc6igAzTOx3zPifCwFR87tsh/4Pa9cNts6d2otw==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 + peerDependenciesMeta: + graphql: + optional: true + + '@0no-co/graphqlsp@1.15.2': + resolution: {integrity: sha512-Ys031WnS3sTQQBtRTkQsYnw372OlW72ais4sp0oh2UMPRNyxxnq85zRfU4PIdoy9kWriysPT5BYAkgIxhbonFA==} + peerDependencies: + graphql: ^15.5.0 || ^16.0.0 || ^17.0.0 + typescript: ^5.0.0 + '@adraffy/ens-normalize@1.11.1': resolution: {integrity: sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==} @@ -2279,6 +2321,26 @@ packages: '@formkit/auto-animate@0.9.0': resolution: {integrity: sha512-VhP4zEAacXS3dfTpJpJ88QdLqMTcabMg0jwpOSxZ/VzfQVfl3GkZSCZThhGC5uhq/TxPHPzW0dzr4H9Bb1OgKA==} + '@gql.tada/cli-utils@1.7.2': + resolution: {integrity: sha512-Qbc7hbLvCz6IliIJpJuKJa9p05b2Jona7ov7+qofCsMRxHRZE1kpAmZMvL8JCI4c0IagpIlWNaMizXEQUe8XjQ==} + peerDependencies: + '@0no-co/graphqlsp': ^1.12.13 + '@gql.tada/svelte-support': 1.0.1 + '@gql.tada/vue-support': 1.0.1 + graphql: ^15.5.0 || ^16.0.0 || ^17.0.0 + typescript: ^5.0.0 + peerDependenciesMeta: + '@gql.tada/svelte-support': + optional: true + '@gql.tada/vue-support': + optional: true + + '@gql.tada/internal@1.0.8': + resolution: {integrity: sha512-XYdxJhtHC5WtZfdDqtKjcQ4d7R1s0d1rnlSs3OcBEUbYiPoJJfZU7tWsVXuv047Z6msvmr4ompJ7eLSK5Km57g==} + peerDependencies: + graphql: ^15.5.0 || ^16.0.0 || ^17.0.0 + typescript: ^5.0.0 + '@graphiql/plugin-doc-explorer@0.4.1': resolution: {integrity: sha512-+ram1dDDGMqJn/f9n5I8E6grTvxcM9JZYt/HhtYLuCvkN8kERI6/E3zBHBshhIUnQZoXioZ03fAzXg7JOn0Kyg==} peerDependencies: @@ -6250,6 +6312,12 @@ packages: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} + gql.tada@1.9.1: + resolution: {integrity: sha512-Ijtwgw08aE7l06wK5oj5Msgpk9SUe5FSVcuxU5dHyefdM7fDqLQpA76yHBoq8lPB3MNSir8tznodDknHkm2Z/w==} + hasBin: true + peerDependencies: + typescript: ^5.0.0 + graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -9403,6 +9471,16 @@ packages: snapshots: + '@0no-co/graphql.web@1.2.0(graphql@16.11.0)': + optionalDependencies: + graphql: 16.11.0 + + '@0no-co/graphqlsp@1.15.2(graphql@16.11.0)(typescript@5.9.3)': + dependencies: + '@gql.tada/internal': 1.0.8(graphql@16.11.0)(typescript@5.9.3) + graphql: 16.11.0 + typescript: 5.9.3 + '@adraffy/ens-normalize@1.11.1': {} '@alloc/quick-lru@5.2.0': {} @@ -10804,6 +10882,19 @@ snapshots: '@formkit/auto-animate@0.9.0': {} + '@gql.tada/cli-utils@1.7.2(@0no-co/graphqlsp@1.15.2(graphql@16.11.0)(typescript@5.9.3))(graphql@16.11.0)(typescript@5.9.3)': + dependencies: + '@0no-co/graphqlsp': 1.15.2(graphql@16.11.0)(typescript@5.9.3) + '@gql.tada/internal': 1.0.8(graphql@16.11.0)(typescript@5.9.3) + graphql: 16.11.0 + typescript: 5.9.3 + + '@gql.tada/internal@1.0.8(graphql@16.11.0)(typescript@5.9.3)': + dependencies: + '@0no-co/graphql.web': 1.2.0(graphql@16.11.0) + graphql: 16.11.0 + typescript: 5.9.3 + '@graphiql/plugin-doc-explorer@0.4.1(@graphiql/react@0.37.1(@types/node@24.10.9)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(graphql@16.11.0)(immer@9.0.21)(react-compiler-runtime@19.1.0-rc.1(react@19.2.1))(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(use-sync-external-store@1.6.0(react@19.2.1)))(@types/react@19.2.7)(graphql@16.11.0)(immer@9.0.21)(react-compiler-runtime@19.1.0-rc.1(react@19.2.1))(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(use-sync-external-store@1.6.0(react@19.2.1))': dependencies: '@graphiql/react': 0.37.1(@types/node@24.10.9)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(graphql@16.11.0)(immer@9.0.21)(react-compiler-runtime@19.1.0-rc.1(react@19.2.1))(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(use-sync-external-store@1.6.0(react@19.2.1)) @@ -15273,6 +15364,18 @@ snapshots: gopd@1.2.0: {} + gql.tada@1.9.1(graphql@16.11.0)(typescript@5.9.3): + dependencies: + '@0no-co/graphql.web': 1.2.0(graphql@16.11.0) + '@0no-co/graphqlsp': 1.15.2(graphql@16.11.0)(typescript@5.9.3) + '@gql.tada/cli-utils': 1.7.2(@0no-co/graphqlsp@1.15.2(graphql@16.11.0)(typescript@5.9.3))(graphql@16.11.0)(typescript@5.9.3) + '@gql.tada/internal': 1.0.8(graphql@16.11.0)(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - '@gql.tada/svelte-support' + - '@gql.tada/vue-support' + - graphql + graceful-fs@4.2.11: {} graphiql-explorer@0.9.0(graphql@16.11.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1):