From 0cc7c75031983f7b8975863f4e301f83631d74ed Mon Sep 17 00:00:00 2001 From: shrugs Date: Thu, 9 Apr 2026 11:49:39 -0500 Subject: [PATCH 01/60] refactor getParentInterpretedName and ENS_ROOT_NAME --- .../handlers/api/explore/name-tokens-api.ts | 10 +++++---- .../omnigraph-api/lib/get-canonical-path.ts | 4 ++-- .../src/lib/subgraph/subgraph-helpers.ts | 4 ++-- .../ensv2/handlers/ensv1/ENSv1Registry.ts | 8 +++---- .../plugins/subgraph/handlers/Registry.ts | 4 ++-- .../ensnode-sdk/src/tokenscope/name-token.ts | 5 +++-- packages/enssdk/src/lib/constants.ts | 22 ++++++++++++++++--- packages/enssdk/src/lib/names.test.ts | 19 ++++++++-------- packages/enssdk/src/lib/names.ts | 18 +++++---------- 9 files changed, 54 insertions(+), 40 deletions(-) diff --git a/apps/ensapi/src/handlers/api/explore/name-tokens-api.ts b/apps/ensapi/src/handlers/api/explore/name-tokens-api.ts index 490c41c5a..4dbcf9658 100644 --- a/apps/ensapi/src/handlers/api/explore/name-tokens-api.ts +++ b/apps/ensapi/src/handlers/api/explore/name-tokens-api.ts @@ -2,8 +2,8 @@ import config from "@/config"; import { asInterpretedName, - ENS_ROOT, - getParentNameFQDN, + ENS_ROOT_NAME, + getParentInterpretedName, type Node, namehashInterpretedName, } from "enssdk"; @@ -72,7 +72,7 @@ app.openapi(getNameTokensRoute, async (c) => { const name = asInterpretedName(request.name); // return 404 when the requested name was the ENS Root - if (name === ENS_ROOT) { + if (name === ENS_ROOT_NAME) { return c.json( serializeNameTokensResponse( makeNameTokensNotIndexedResponse( @@ -83,7 +83,9 @@ app.openapi(getNameTokensRoute, async (c) => { ); } - const parentNode = namehashInterpretedName(getParentNameFQDN(name)); + // biome-ignore lint/style/noNonNullAssertion: getParentInterpretedName only throws if name === ENS_ROOT_NAME but we handle that case above + const parentName = getParentInterpretedName(name)!; + const parentNode = namehashInterpretedName(parentName); const subregistry = indexedSubregistries.find((s) => s.node === parentNode); // Return 404 response with error code for Name Tokens Not Indexed when diff --git a/apps/ensapi/src/omnigraph-api/lib/get-canonical-path.ts b/apps/ensapi/src/omnigraph-api/lib/get-canonical-path.ts index b3ba0a107..5249a007b 100644 --- a/apps/ensapi/src/omnigraph-api/lib/get-canonical-path.ts +++ b/apps/ensapi/src/omnigraph-api/lib/get-canonical-path.ts @@ -4,10 +4,10 @@ import { sql } from "drizzle-orm"; import { type CanonicalPath, type DomainId, + ENS_ROOT_NODE, type ENSv1DomainId, type ENSv2DomainId, type RegistryId, - ROOT_NODE, } from "enssdk"; import { maybeGetENSv2RootRegistryId } from "@ensnode/ensnode-sdk"; @@ -63,7 +63,7 @@ export async function getV1CanonicalPath(domainId: ENSv1DomainId): Promise { const shouldIgnoreEvent = await shouldIgnoreRegistryOldEvents(context, event.args.node); - const isRootNode = event.args.node === ROOT_NODE; + const isRootNode = event.args.node === ENS_ROOT_NODE; // inverted logic of https://github.com/ensdomains/ens-subgraph/blob/c844791/src/ensRegistry.ts#L246 // NOTE: the subgraph must include an exception here for the root node because it starts out diff --git a/packages/ensnode-sdk/src/tokenscope/name-token.ts b/packages/ensnode-sdk/src/tokenscope/name-token.ts index 78de51b5b..68b3a2ab3 100644 --- a/packages/ensnode-sdk/src/tokenscope/name-token.ts +++ b/packages/ensnode-sdk/src/tokenscope/name-token.ts @@ -1,5 +1,5 @@ import type { AccountId, AssetId, InterpretedName } from "enssdk"; -import { getParentNameFQDN } from "enssdk"; +import { getParentInterpretedName } from "enssdk"; import { isAddressEqual, zeroAddress } from "viem"; import { DatasourceNames, type ENSNamespaceId } from "@ensnode/datasources"; @@ -219,7 +219,8 @@ export function getNameTokenOwnership( } satisfies NameTokenOwnershipBurned; } - const parentName = getParentNameFQDN(name); + const parentName = getParentInterpretedName(name); + if (parentName === null) throw new Error(`Invariant: '${name}' has no parent Name.`); // set ownershipType as 'fully-onchain' if `name` is a direct subname of .eth if (parentName === "eth") { diff --git a/packages/enssdk/src/lib/constants.ts b/packages/enssdk/src/lib/constants.ts index 595fa8525..aad1dc080 100644 --- a/packages/enssdk/src/lib/constants.ts +++ b/packages/enssdk/src/lib/constants.ts @@ -1,12 +1,28 @@ import { asInterpretedName } from "./interpreted-names-and-labels"; import { namehashInterpretedName } from "./namehash"; -import type { Node } from "./types"; +import type { EACResource, Node } from "./types"; -export const ROOT_NODE: Node = namehashInterpretedName(asInterpretedName("")); +/** + * Name for the ENS Root + */ +export const ENS_ROOT_NAME = asInterpretedName(""); + +/** + * The {@link Node} that identifies the ENS Root Name (""). + */ +export const ENS_ROOT_NODE: Node = namehashInterpretedName(asInterpretedName("")); + +/** + * The {@link Node} that identifies the ETH Name ("eth"). + */ export const ETH_NODE: Node = namehashInterpretedName(asInterpretedName("eth")); + +/** + * The {@link Node} that identifies the addr.reverse Name ("addr.reverse"). + */ export const ADDR_REVERSE_NODE: Node = namehashInterpretedName(asInterpretedName("addr.reverse")); /** * ROOT_RESOURCE represents the 'root' resource in an EnhancedAccessControl contract. */ -export const ROOT_RESOURCE = 0n; +export const ROOT_RESOURCE: EACResource = 0n; diff --git a/packages/enssdk/src/lib/names.test.ts b/packages/enssdk/src/lib/names.test.ts index d1ae24028..b17b69009 100644 --- a/packages/enssdk/src/lib/names.test.ts +++ b/packages/enssdk/src/lib/names.test.ts @@ -1,7 +1,8 @@ import { describe, expect, it } from "vitest"; +import { ENS_ROOT_NAME } from "./constants"; import { asInterpretedName } from "./interpreted-names-and-labels"; -import { beautifyName, ENS_ROOT, getNameHierarchy, getParentNameFQDN } from "./names"; +import { beautifyName, getNameHierarchy, getParentInterpretedName } from "./names"; import type { Name, NormalizedName } from "./types"; describe("names", () => { @@ -31,23 +32,23 @@ describe("names", () => { }); }); - describe("getParentNameFQDN", () => { - it("throws error for ENS Root", () => { - expect(() => getParentNameFQDN(ENS_ROOT)).toThrowError( - /There is no parent name for ENS Root/i, - ); + describe("getParentInterpretedName", () => { + it("returns null for ENS Root", () => { + expect(getParentInterpretedName(ENS_ROOT_NAME)).toBeNull(); }); it("returns ENS Root for top-level name", () => { - expect(getParentNameFQDN(asInterpretedName("eth"))).toStrictEqual(ENS_ROOT); + expect(getParentInterpretedName(asInterpretedName("eth"))).toStrictEqual(ENS_ROOT_NAME); }); it("returns FQDN for 2nd-level name", () => { - expect(getParentNameFQDN(asInterpretedName("base.eth"))).toStrictEqual("eth"); + expect(getParentInterpretedName(asInterpretedName("base.eth"))).toStrictEqual("eth"); }); it("returns FQDN for 3rd-level name", () => { - expect(getParentNameFQDN(asInterpretedName("test.base.eth"))).toStrictEqual("base.eth"); + expect(getParentInterpretedName(asInterpretedName("test.base.eth"))).toStrictEqual( + "base.eth", + ); }); }); diff --git a/packages/enssdk/src/lib/names.ts b/packages/enssdk/src/lib/names.ts index 6abe45865..e17f24fa6 100644 --- a/packages/enssdk/src/lib/names.ts +++ b/packages/enssdk/src/lib/names.ts @@ -1,18 +1,13 @@ import { ens_beautify } from "@adraffy/ens-normalize"; +import { ENS_ROOT_NAME } from "./constants"; import { - asInterpretedName, interpretedLabelsToInterpretedName, interpretedNameToInterpretedLabels, } from "./interpreted-names-and-labels"; import { isNormalizedLabel } from "./normalization"; import type { InterpretedName, Label, Name, NormalizedName } from "./types"; -/** - * Name for the ENS Root - */ -export const ENS_ROOT = asInterpretedName(""); - /** * Constructs a name hierarchy from a given NormalizedName. * @@ -28,16 +23,15 @@ export const getNameHierarchy = (name: NormalizedName): NormalizedName[] => name.split(".").map((_, i, labels) => labels.slice(i).join(".")) as NormalizedName[]; /** - * Get FQDN of parent for a name. + * Derives the parent's {@link InterpretedName} of the provided `name`, or null if there is none. */ -export const getParentNameFQDN = (name: InterpretedName): InterpretedName => { - // Invariant: name is not ENS root. - if (name === ENS_ROOT) throw new Error("There is no parent name for ENS Root."); +export const getParentInterpretedName = (name: InterpretedName): InterpretedName | null => { + if (name === ENS_ROOT_NAME) return null; const labels = interpretedNameToInterpretedLabels(name); - // For TLDs, return ENS_ROOT - if (labels.length === 1) return ENS_ROOT; + // For TLDs, return ENS_ROOT_NAME + if (labels.length === 1) return ENS_ROOT_NAME; // Strip off the child-most label in the name to get the FQDN of the parent return interpretedLabelsToInterpretedName(labels.slice(1)); From 9559c9194de0a05be29b89e0e93c6e0fa6c974f8 Mon Sep 17 00:00:00 2001 From: shrugs Date: Thu, 9 Apr 2026 11:56:52 -0500 Subject: [PATCH 02/60] refactor: no UnixTimestamp re-export --- .../src/components/indexing-status/backfill-status.tsx | 2 +- apps/ensapi/src/handlers/api/meta/realtime-api.test.ts | 2 +- .../src/lib/name-tokens/find-name-tokens-for-domain.ts | 3 +-- .../plugins/registrars/shared/lib/registrar-events.ts | 9 +++++++-- .../src/v1/award-models/rev-share-limit/leaderboard.ts | 10 ++-------- .../ensnode-sdk/src/ensapi/api/name-tokens/response.ts | 3 +-- .../src/ensapi/api/registrar-actions/filters.ts | 3 +-- .../src/ensapi/api/registrar-actions/request.ts | 3 +-- .../src/ensapi/api/registrar-actions/response.ts | 3 +-- .../indexing-status/chain-indexing-status-snapshot.ts | 4 ++-- .../cross-chain-indexing-status-snapshot.ts | 4 ++-- .../omnichain-indexing-status-snapshot.ts | 4 ++-- .../realtime-indexing-status-projection.ts | 4 +++- .../src/registrars/registration-lifecycle.ts | 3 +-- packages/ensnode-sdk/src/shared/cache/swr-cache.ts | 3 ++- packages/ensnode-sdk/src/shared/cache/ttl-cache.ts | 3 ++- packages/ensnode-sdk/src/shared/datetime.ts | 3 ++- packages/ensnode-sdk/src/shared/types.ts | 6 ++---- packages/ensnode-sdk/src/shared/zod-schemas.ts | 2 +- packages/enssdk/src/lib/normalization.ts | 4 ++-- .../registrar-actions/RegistrarActionCard.tsx | 3 +-- 21 files changed, 38 insertions(+), 43 deletions(-) diff --git a/apps/ensadmin/src/components/indexing-status/backfill-status.tsx b/apps/ensadmin/src/components/indexing-status/backfill-status.tsx index a4f5ff77a..a5a6bf0db 100644 --- a/apps/ensadmin/src/components/indexing-status/backfill-status.tsx +++ b/apps/ensadmin/src/components/indexing-status/backfill-status.tsx @@ -4,6 +4,7 @@ */ import { AbsoluteTime } from "@namehash/namehash-ui"; +import type { UnixTimestamp } from "enssdk"; import { Clock } from "lucide-react"; import { @@ -12,7 +13,6 @@ import { getTimestampForLowestOmnichainStartBlock, type RealtimeIndexingStatusProjection, sortChainStatusesByStartBlockAsc, - type UnixTimestamp, } from "@ensnode/ensnode-sdk"; import { diff --git a/apps/ensapi/src/handlers/api/meta/realtime-api.test.ts b/apps/ensapi/src/handlers/api/meta/realtime-api.test.ts index e59bd6458..afb303c42 100644 --- a/apps/ensapi/src/handlers/api/meta/realtime-api.test.ts +++ b/apps/ensapi/src/handlers/api/meta/realtime-api.test.ts @@ -1,9 +1,9 @@ +import type { UnixTimestamp } from "enssdk"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { type CrossChainIndexingStatusSnapshot, createRealtimeIndexingStatusProjection, - type UnixTimestamp, } from "@ensnode/ensnode-sdk"; import { createApp } from "@/lib/hono-factory"; diff --git a/apps/ensapi/src/lib/name-tokens/find-name-tokens-for-domain.ts b/apps/ensapi/src/lib/name-tokens/find-name-tokens-for-domain.ts index d60279020..3b4b6ca95 100644 --- a/apps/ensapi/src/lib/name-tokens/find-name-tokens-for-domain.ts +++ b/apps/ensapi/src/lib/name-tokens/find-name-tokens-for-domain.ts @@ -1,7 +1,7 @@ import config from "@/config"; import { eq } from "drizzle-orm/sql"; -import { type AccountId, asInterpretedName, type Node } from "enssdk"; +import { type AccountId, asInterpretedName, type Node, type UnixTimestamp } from "enssdk"; import { bigIntToNumber, @@ -11,7 +11,6 @@ import { type NFTMintStatus, parseAssetId, type RegisteredNameTokens, - type UnixTimestamp, } from "@ensnode/ensnode-sdk"; import { ensDb, ensIndexerSchema } from "@/lib/ensdb/singleton"; diff --git a/apps/ensindexer/src/plugins/registrars/shared/lib/registrar-events.ts b/apps/ensindexer/src/plugins/registrars/shared/lib/registrar-events.ts index 72c2777f4..79ad629f8 100644 --- a/apps/ensindexer/src/plugins/registrars/shared/lib/registrar-events.ts +++ b/apps/ensindexer/src/plugins/registrars/shared/lib/registrar-events.ts @@ -2,7 +2,13 @@ * This file contains handlers used in event handlers for a Registrar contract. */ -import { type AccountId, type Address, type Node, stringifyAccountId } from "enssdk"; +import { + type AccountId, + type Address, + type Node, + stringifyAccountId, + type UnixTimestamp, +} from "enssdk"; import type { Hash } from "viem"; import { @@ -10,7 +16,6 @@ import { bigIntToNumber, durationBetween, RegistrarActionTypes, - type UnixTimestamp, } from "@ensnode/ensnode-sdk"; import type { IndexingEngineContext, IndexingEngineEvent } from "@/lib/indexing-engines/ponder"; diff --git a/packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.ts b/packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.ts index 9c1e99418..77152d8b9 100644 --- a/packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.ts +++ b/packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.ts @@ -1,12 +1,6 @@ -import type { Address } from "enssdk"; +import type { Address, UnixTimestamp } from "enssdk"; -import { - type Duration, - priceEth, - priceUsdc, - scalePrice, - type UnixTimestamp, -} from "@ensnode/ensnode-sdk"; +import { type Duration, priceEth, priceUsdc, scalePrice } from "@ensnode/ensnode-sdk"; import { normalizeAddress } from "../../address"; import { buildReferrerMetrics } from "../../referrer-metrics"; diff --git a/packages/ensnode-sdk/src/ensapi/api/name-tokens/response.ts b/packages/ensnode-sdk/src/ensapi/api/name-tokens/response.ts index 7cd498a7a..b89170969 100644 --- a/packages/ensnode-sdk/src/ensapi/api/name-tokens/response.ts +++ b/packages/ensnode-sdk/src/ensapi/api/name-tokens/response.ts @@ -1,6 +1,5 @@ -import type { InterpretedName, Node } from "enssdk"; +import type { InterpretedName, Node, UnixTimestamp } from "enssdk"; -import type { UnixTimestamp } from "../../../shared/types"; import type { NameToken, NameTokenOwnershipTypes } from "../../../tokenscope/name-token"; import type { ErrorResponse } from "../shared/errors"; diff --git a/packages/ensnode-sdk/src/ensapi/api/registrar-actions/filters.ts b/packages/ensnode-sdk/src/ensapi/api/registrar-actions/filters.ts index e7a67a640..634e1393d 100644 --- a/packages/ensnode-sdk/src/ensapi/api/registrar-actions/filters.ts +++ b/packages/ensnode-sdk/src/ensapi/api/registrar-actions/filters.ts @@ -1,6 +1,5 @@ -import type { Address, Node } from "enssdk"; +import type { Address, Node, UnixTimestamp } from "enssdk"; -import type { UnixTimestamp } from "../../../shared/types"; import { type RegistrarActionsFilter, type RegistrarActionsFilterBeginTimestamp, diff --git a/packages/ensnode-sdk/src/ensapi/api/registrar-actions/request.ts b/packages/ensnode-sdk/src/ensapi/api/registrar-actions/request.ts index 9d777eba1..074fc5e86 100644 --- a/packages/ensnode-sdk/src/ensapi/api/registrar-actions/request.ts +++ b/packages/ensnode-sdk/src/ensapi/api/registrar-actions/request.ts @@ -1,6 +1,5 @@ -import type { Address, Node } from "enssdk"; +import type { Address, Node, UnixTimestamp } from "enssdk"; -import type { UnixTimestamp } from "../../../shared/types"; import type { RequestPageParams } from "../shared/pagination"; /** diff --git a/packages/ensnode-sdk/src/ensapi/api/registrar-actions/response.ts b/packages/ensnode-sdk/src/ensapi/api/registrar-actions/response.ts index f87c87c42..88d266ffb 100644 --- a/packages/ensnode-sdk/src/ensapi/api/registrar-actions/response.ts +++ b/packages/ensnode-sdk/src/ensapi/api/registrar-actions/response.ts @@ -1,7 +1,6 @@ -import type { InterpretedName } from "enssdk"; +import type { InterpretedName, UnixTimestamp } from "enssdk"; import type { RegistrarAction } from "../../../registrars/registrar-action"; -import type { UnixTimestamp } from "../../../shared/types"; import type { IndexingStatusResponseCodes } from "../indexing-status/response"; import type { ErrorResponse } from "../shared/errors"; import type { ResponsePageContext } from "../shared/pagination"; diff --git a/packages/ensnode-sdk/src/indexing-status/chain-indexing-status-snapshot.ts b/packages/ensnode-sdk/src/indexing-status/chain-indexing-status-snapshot.ts index 45451c46d..d670eda4e 100644 --- a/packages/ensnode-sdk/src/indexing-status/chain-indexing-status-snapshot.ts +++ b/packages/ensnode-sdk/src/indexing-status/chain-indexing-status-snapshot.ts @@ -1,4 +1,4 @@ -import type { ChainId } from "enssdk"; +import type { ChainId, UnixTimestamp } from "enssdk"; import { type BlockRefRangeBounded, @@ -6,7 +6,7 @@ import { type BlockRefRangeWithStartBlock, RangeTypeIds, } from "../shared/blockrange"; -import type { BlockRef, UnixTimestamp } from "../shared/types"; +import type { BlockRef } from "../shared/types"; /** * The status of indexing a chain at the time an indexing status snapshot diff --git a/packages/ensnode-sdk/src/indexing-status/cross-chain-indexing-status-snapshot.ts b/packages/ensnode-sdk/src/indexing-status/cross-chain-indexing-status-snapshot.ts index 5506706be..437a213eb 100644 --- a/packages/ensnode-sdk/src/indexing-status/cross-chain-indexing-status-snapshot.ts +++ b/packages/ensnode-sdk/src/indexing-status/cross-chain-indexing-status-snapshot.ts @@ -1,7 +1,7 @@ -import type { ChainId } from "enssdk"; +import type { ChainId, UnixTimestamp } from "enssdk"; import { RangeTypeIds } from "../shared/blockrange"; -import type { BlockRef, UnixTimestamp } from "../shared/types"; +import type { BlockRef } from "../shared/types"; import { ChainIndexingStatusIds, type ChainIndexingStatusSnapshot, diff --git a/packages/ensnode-sdk/src/indexing-status/omnichain-indexing-status-snapshot.ts b/packages/ensnode-sdk/src/indexing-status/omnichain-indexing-status-snapshot.ts index c475c72c6..b67f43987 100644 --- a/packages/ensnode-sdk/src/indexing-status/omnichain-indexing-status-snapshot.ts +++ b/packages/ensnode-sdk/src/indexing-status/omnichain-indexing-status-snapshot.ts @@ -1,6 +1,6 @@ -import type { ChainId } from "enssdk"; +import type { ChainId, UnixTimestamp } from "enssdk"; -import type { UnixTimestamp, Unvalidated } from "../shared/types"; +import type { Unvalidated } from "../shared/types"; import { ChainIndexingStatusIds, type ChainIndexingStatusSnapshot, diff --git a/packages/ensnode-sdk/src/indexing-status/realtime-indexing-status-projection.ts b/packages/ensnode-sdk/src/indexing-status/realtime-indexing-status-projection.ts index 7dcb1cf8c..000ecb75c 100644 --- a/packages/ensnode-sdk/src/indexing-status/realtime-indexing-status-projection.ts +++ b/packages/ensnode-sdk/src/indexing-status/realtime-indexing-status-projection.ts @@ -1,4 +1,6 @@ -import type { Duration, UnixTimestamp } from "../shared/types"; +import type { UnixTimestamp } from "enssdk"; + +import type { Duration } from "../shared/types"; import type { CrossChainIndexingStatusSnapshot } from "./cross-chain-indexing-status-snapshot"; /** diff --git a/packages/ensnode-sdk/src/registrars/registration-lifecycle.ts b/packages/ensnode-sdk/src/registrars/registration-lifecycle.ts index ee7993c98..9260593c3 100644 --- a/packages/ensnode-sdk/src/registrars/registration-lifecycle.ts +++ b/packages/ensnode-sdk/src/registrars/registration-lifecycle.ts @@ -1,6 +1,5 @@ -import type { Node } from "enssdk"; +import type { Node, UnixTimestamp } from "enssdk"; -import type { UnixTimestamp } from "../shared/types"; import type { Subregistry } from "./subregistry"; /** diff --git a/packages/ensnode-sdk/src/shared/cache/swr-cache.ts b/packages/ensnode-sdk/src/shared/cache/swr-cache.ts index 30f1d94d1..e3ca400a5 100644 --- a/packages/ensnode-sdk/src/shared/cache/swr-cache.ts +++ b/packages/ensnode-sdk/src/shared/cache/swr-cache.ts @@ -1,8 +1,9 @@ import { secondsToMilliseconds } from "date-fns"; import { getUnixTime } from "date-fns/getUnixTime"; +import type { UnixTimestamp } from "enssdk"; import { durationBetween } from "../datetime"; -import type { Duration, UnixTimestamp } from "../types"; +import type { Duration } from "../types"; /** * Data structure for a single cached result. diff --git a/packages/ensnode-sdk/src/shared/cache/ttl-cache.ts b/packages/ensnode-sdk/src/shared/cache/ttl-cache.ts index 3dd8e4b83..fcdb1888d 100644 --- a/packages/ensnode-sdk/src/shared/cache/ttl-cache.ts +++ b/packages/ensnode-sdk/src/shared/cache/ttl-cache.ts @@ -1,7 +1,8 @@ import { getUnixTime } from "date-fns/getUnixTime"; +import type { UnixTimestamp } from "enssdk"; import { addDuration } from "../datetime"; -import type { Duration, UnixTimestamp } from "../types"; +import type { Duration } from "../types"; import type { Cache } from "./cache"; interface CacheEntry { diff --git a/packages/ensnode-sdk/src/shared/datetime.ts b/packages/ensnode-sdk/src/shared/datetime.ts index 497c70e07..f59a27185 100644 --- a/packages/ensnode-sdk/src/shared/datetime.ts +++ b/packages/ensnode-sdk/src/shared/datetime.ts @@ -1,7 +1,8 @@ import { getUnixTime } from "date-fns/getUnixTime"; +import type { UnixTimestamp } from "enssdk"; import { deserializeDuration, deserializeUnixTimestamp } from "./deserialize"; -import type { Duration, UnixTimestamp } from "./types"; +import type { Duration } from "./types"; /** * Duration between two moments in time. diff --git a/packages/ensnode-sdk/src/shared/types.ts b/packages/ensnode-sdk/src/shared/types.ts index ea4e87184..8252b6d90 100644 --- a/packages/ensnode-sdk/src/shared/types.ts +++ b/packages/ensnode-sdk/src/shared/types.ts @@ -1,3 +1,5 @@ +import type { UnixTimestamp } from "enssdk"; + /** * Block Number * @@ -10,10 +12,6 @@ export type BlockNumber = number; */ export type Datetime = Date; -import type { UnixTimestamp } from "enssdk"; - -export type { UnixTimestamp } from "enssdk"; - /** * Represents a URL that is used for RPC endpoints. */ diff --git a/packages/ensnode-sdk/src/shared/zod-schemas.ts b/packages/ensnode-sdk/src/shared/zod-schemas.ts index 974d54936..a92c67ca6 100644 --- a/packages/ensnode-sdk/src/shared/zod-schemas.ts +++ b/packages/ensnode-sdk/src/shared/zod-schemas.ts @@ -30,7 +30,7 @@ import { type PriceEth, type PriceUsdc, } from "./currencies"; -import type { BlockRef, Datetime, Duration, UnixTimestamp } from "./types"; +import type { BlockRef, Datetime, Duration } from "./types"; /** * Parses a string value as a boolean. diff --git a/packages/enssdk/src/lib/normalization.ts b/packages/enssdk/src/lib/normalization.ts index 8130b599a..9a0ea1a94 100644 --- a/packages/enssdk/src/lib/normalization.ts +++ b/packages/enssdk/src/lib/normalization.ts @@ -18,8 +18,8 @@ export const normalizeName = (name: Name): InterpretedName => * @see https://docs.ens.domains/ensip/15 */ export const normalizeLabel = (label: Label): InterpretedLabel => { - // empty string cannot be a label - if (label === "") throw new Error("Empty string is not a valid Label."); + // empty string cannot be a normalized label + if (label === "") throw new Error("Empty string cannot be normalized."); // normalized labels do not contain periods if (label.includes(".")) { diff --git a/packages/namehash-ui/src/components/registrar-actions/RegistrarActionCard.tsx b/packages/namehash-ui/src/components/registrar-actions/RegistrarActionCard.tsx index e4b4315f1..dc377a896 100644 --- a/packages/namehash-ui/src/components/registrar-actions/RegistrarActionCard.tsx +++ b/packages/namehash-ui/src/components/registrar-actions/RegistrarActionCard.tsx @@ -1,4 +1,4 @@ -import type { Address, DefaultableChainId } from "enssdk"; +import type { Address, DefaultableChainId, UnixTimestamp } from "enssdk"; import { Info as InfoIcon, CircleQuestionMark as QuestionmarkIcon } from "lucide-react"; import { memo, type PropsWithChildren, type ReactNode } from "react"; import { zeroAddress } from "viem"; @@ -7,7 +7,6 @@ import type { ENSNamespaceId, NamedRegistrarAction, RegistrarActionReferral, - UnixTimestamp, } from "@ensnode/ensnode-sdk"; import { buildUnresolvedIdentity, From f5ac2dce568f6cb03fe7174397a0780cdaba82d1 Mon Sep 17 00:00:00 2001 From: shrugs Date: Thu, 9 Apr 2026 12:12:05 -0500 Subject: [PATCH 03/60] refactor: remove NormalizedName type in favor of InterpretedName across the board --- .../protocol-acceleration/find-resolver.ts | 8 +++---- .../src/lib/resolution/forward-resolution.ts | 13 ++++------ .../interpretation/interpret-record-values.ts | 12 +++++----- .../src/lib/interpreted-names-and-labels.ts | 4 ---- packages/enssdk/src/lib/names.test.ts | 24 +++++++++---------- packages/enssdk/src/lib/names.ts | 13 +++++----- packages/enssdk/src/lib/normalization.ts | 5 ++-- packages/enssdk/src/lib/types/ens.ts | 10 -------- 8 files changed, 36 insertions(+), 53 deletions(-) diff --git a/apps/ensapi/src/lib/protocol-acceleration/find-resolver.ts b/apps/ensapi/src/lib/protocol-acceleration/find-resolver.ts index 10a03464e..0c64fdb83 100644 --- a/apps/ensapi/src/lib/protocol-acceleration/find-resolver.ts +++ b/apps/ensapi/src/lib/protocol-acceleration/find-resolver.ts @@ -8,9 +8,9 @@ import { asInterpretedName, type DomainId, getNameHierarchy, + type InterpretedName, type Name, type Node, - type NormalizedName, namehashInterpretedName, } from "enssdk"; import { isAddressEqual, type PublicClient, toHex, zeroAddress } from "viem"; @@ -62,7 +62,7 @@ export async function findResolver({ publicClient, }: { registry: AccountId; - name: NormalizedName; + name: InterpretedName; accelerate: boolean; canAccelerate: boolean; publicClient: PublicClient; @@ -175,7 +175,7 @@ async function findResolverWithUniversalResolver( */ async function findResolverWithIndex( registry: AccountId, - name: NormalizedName, + name: InterpretedName, ): Promise { return withActiveSpanAsync( tracer, @@ -194,7 +194,7 @@ async function findResolverWithIndex( // 2. compute domainId of each node // NOTE: this is currently ENSv1-specific - const nodes = names.map((name) => namehashInterpretedName(asInterpretedName(name)) as Node); + const nodes = names.map((name) => namehashInterpretedName(name)); const domainIds = nodes as DomainId[]; // 3. for each domain, find its associated resolver in the selected registry diff --git a/apps/ensapi/src/lib/resolution/forward-resolution.ts b/apps/ensapi/src/lib/resolution/forward-resolution.ts index ccd2dec8b..457aeb540 100644 --- a/apps/ensapi/src/lib/resolution/forward-resolution.ts +++ b/apps/ensapi/src/lib/resolution/forward-resolution.ts @@ -5,7 +5,6 @@ import { replaceBigInts } from "@ponder/utils"; import { type AccountId, asInterpretedName, - isNormalizedName, type Node, namehashInterpretedName, normalizeName, @@ -108,10 +107,13 @@ export async function resolveForward * `registry`. */ async function _resolveForward( - name: ForwardResolutionArgs["name"], + _name: ForwardResolutionArgs["name"], selection: ForwardResolutionArgs["selection"], options: { registry: AccountId; accelerate: boolean; canAccelerate: boolean }, ): Promise> { + // Invariant: Name must be an InterpretedName + const name = asInterpretedName(_name); + const { registry: { chainId }, accelerate = false, @@ -141,12 +143,7 @@ async function _resolveForward( // Validate Input ////////////////////////////////////////////////// - // Invariant: Name must be normalized - if (!isNormalizedName(name)) { - throw new Error(`Invariant: Name "${name}" must be normalized.`); - } - - const node: Node = namehashInterpretedName(asInterpretedName(name)); + const node: Node = namehashInterpretedName(name); span.setAttribute("node", node); // if selection is empty, give them what they asked for diff --git a/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.ts b/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.ts index 2efd82ecf..c551f0954 100644 --- a/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.ts +++ b/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.ts @@ -1,5 +1,5 @@ -import type { NormalizedName } from "enssdk"; -import { asLowerCaseAddress, isNormalizedName } from "enssdk"; +import type { InterpretedName } from "enssdk"; +import { asLowerCaseAddress, isInterpretedName } from "enssdk"; import { isAddress, isAddressEqual, zeroAddress } from "viem"; import { hasNullByte } from "../null-bytes"; @@ -9,20 +9,20 @@ import { hasNullByte } from "../null-bytes"; * * The interpreted record value is either: * a) null, representing a non-existant or deletion of the record, or - * b) a normalized, non-empty-string Name. + * b) an {@link InterpretedName}. * * @param value - The name record value string to interpret. * @returns The interpreted name string, or null if deleted. */ -export function interpretNameRecordValue(value: string): NormalizedName | null { - // empty string is technically a normalized name, representing the ens root node, but in the +export function interpretNameRecordValue(value: string): InterpretedName | null { + // empty string is technically an InterpretedName, representing the ens root node, but in the // context of a name record value, empty string is emitted when the user un-sets the record (this // is because the abi of this event is only capable of expressing string values, so empty string // canonically represents the non-existence or deletion of the record value) if (value === "") return null; // if not normalized, is not valid `name` record value - if (!isNormalizedName(value)) return null; + if (!isInterpretedName(value)) return null; // otherwise, this is a non-empty-string normalized Name that can be used as a name() record value return value; diff --git a/packages/enssdk/src/lib/interpreted-names-and-labels.ts b/packages/enssdk/src/lib/interpreted-names-and-labels.ts index 7cba07420..5accfd78a 100644 --- a/packages/enssdk/src/lib/interpreted-names-and-labels.ts +++ b/packages/enssdk/src/lib/interpreted-names-and-labels.ts @@ -213,11 +213,7 @@ export function asInterpretedName(name: string): InterpretedName { /** * Validates and casts a string to a {@link LiteralLabel}. * A LiteralLabel is a label as it literally appears onchain. - * - * @throws if the input is empty */ export function asLiteralLabel(label: string): LiteralLabel { - if (label === "") throw new Error("LiteralLabel must not be empty"); - return label as LiteralLabel; } diff --git a/packages/enssdk/src/lib/names.test.ts b/packages/enssdk/src/lib/names.test.ts index b17b69009..de7655a96 100644 --- a/packages/enssdk/src/lib/names.test.ts +++ b/packages/enssdk/src/lib/names.test.ts @@ -3,30 +3,30 @@ import { describe, expect, it } from "vitest"; import { ENS_ROOT_NAME } from "./constants"; import { asInterpretedName } from "./interpreted-names-and-labels"; import { beautifyName, getNameHierarchy, getParentInterpretedName } from "./names"; -import type { Name, NormalizedName } from "./types"; +import type { Name } from "./types"; describe("names", () => { describe("getNameHierarchy", () => { it("should split name into hierarchy correctly", () => { - const name = "sub.example.eth" as NormalizedName; + const name = asInterpretedName("sub.example.eth"); const expected = ["sub.example.eth", "example.eth", "eth"]; expect(getNameHierarchy(name)).toEqual(expected); }); it("should handle single label names", () => { - const name = "eth" as NormalizedName; + const name = asInterpretedName("eth"); const expected = ["eth"]; expect(getNameHierarchy(name)).toEqual(expected); }); it("should handle empty string (root node)", () => { - const name = "" as NormalizedName; + const name = asInterpretedName(""); const expected = [""]; expect(getNameHierarchy(name)).toEqual(expected); }); it("should handle names with different TLDs", () => { - const name = "sub.example.com" as NormalizedName; + const name = asInterpretedName("sub.example.com"); const expected = ["sub.example.com", "example.com", "com"]; expect(getNameHierarchy(name)).toEqual(expected); }); @@ -41,11 +41,11 @@ describe("names", () => { expect(getParentInterpretedName(asInterpretedName("eth"))).toStrictEqual(ENS_ROOT_NAME); }); - it("returns FQDN for 2nd-level name", () => { + it("returns parent for 2nd-level name", () => { expect(getParentInterpretedName(asInterpretedName("base.eth"))).toStrictEqual("eth"); }); - it("returns FQDN for 3rd-level name", () => { + it("returns parent for 3rd-level name", () => { expect(getParentInterpretedName(asInterpretedName("test.base.eth"))).toStrictEqual( "base.eth", ); @@ -54,14 +54,14 @@ describe("names", () => { describe("beautifyName", () => { it("should beautify a name with no labels", () => { - const name = "" as Name; + const name = ""; const expected = ""; expect(beautifyName(name)).toEqual(expected); }); it("should beautify normalized labels", () => { - const name = "1\u20E32\u20E3.eth" as NormalizedName; - const expected = "1\uFE0F\u20E32\uFE0F\u20E3.eth"; + const name = "1⃣2⃣.eth"; + const expected = "1️⃣2️⃣.eth"; expect(beautifyName(name)).toEqual(expected); }); @@ -72,8 +72,8 @@ describe("names", () => { }); it("should selectively beautify labels where possible", () => { - const name = "1\u20E32\u20E3.ABC.eth" as Name; - const expected = "1\uFE0F\u20E32\uFE0F\u20E3.ABC.eth"; + const name = "1⃣2⃣.ABC.eth" as Name; + const expected = "1️⃣2️⃣.ABC.eth"; expect(beautifyName(name)).toEqual(expected); }); diff --git a/packages/enssdk/src/lib/names.ts b/packages/enssdk/src/lib/names.ts index e17f24fa6..40d4eacf5 100644 --- a/packages/enssdk/src/lib/names.ts +++ b/packages/enssdk/src/lib/names.ts @@ -6,21 +6,20 @@ import { interpretedNameToInterpretedLabels, } from "./interpreted-names-and-labels"; import { isNormalizedLabel } from "./normalization"; -import type { InterpretedName, Label, Name, NormalizedName } from "./types"; +import type { InterpretedName, Label, Name } from "./types"; /** - * Constructs a name hierarchy from a given NormalizedName. + * Constructs a name hierarchy from a given InterpretedName. * * @example * ``` * getNameHierarchy("sub.example.eth") -> ["sub.example.eth", "example.eth", "eth"] * ``` - * - * @dev by restricting the input type to NormalizedName we guarantee that we can split and join - * on '.' and receive NormalizedNames as a result */ -export const getNameHierarchy = (name: NormalizedName): NormalizedName[] => - name.split(".").map((_, i, labels) => labels.slice(i).join(".")) as NormalizedName[]; +export const getNameHierarchy = (name: InterpretedName): InterpretedName[] => + interpretedNameToInterpretedLabels(name).map((_, i, labels) => + interpretedLabelsToInterpretedName(labels.slice(i)), + ); /** * Derives the parent's {@link InterpretedName} of the provided `name`, or null if there is none. diff --git a/packages/enssdk/src/lib/normalization.ts b/packages/enssdk/src/lib/normalization.ts index 9a0ea1a94..93245d7b1 100644 --- a/packages/enssdk/src/lib/normalization.ts +++ b/packages/enssdk/src/lib/normalization.ts @@ -1,6 +1,6 @@ import { ens_normalize } from "@adraffy/ens-normalize"; -import type { InterpretedLabel, InterpretedName, Label, Name, NormalizedName } from "./types"; +import type { InterpretedLabel, InterpretedName, Label, Name } from "./types"; /** * Normalizes a Name according to ENS normalization rules (ENSIP-15), returning an InterpretedName. @@ -34,13 +34,14 @@ export const normalizeLabel = (label: Label): InterpretedLabel => { /** * Determines whether the Name is normalized according to ENSIP-15 normalization rules. */ -export function isNormalizedName(name: Name): name is NormalizedName { +export function isNormalizedName(name: Name): boolean { try { return name === normalizeName(name); } catch { return false; } } + /** * Determines whether the Label is normalized according to ENSIP-15 normalization rules. */ diff --git a/packages/enssdk/src/lib/types/ens.ts b/packages/enssdk/src/lib/types/ens.ts index cf5e94a9a..4d15420a7 100644 --- a/packages/enssdk/src/lib/types/ens.ts +++ b/packages/enssdk/src/lib/types/ens.ts @@ -22,16 +22,6 @@ export type Node = Hex; */ export type Name = string; -/** - * A Normalized Name is an ENS Name that is guaranteed to be normalized. - * - * @example vitalik.eth - * @see https://ensnode.io/docs/reference/terminology#name-node-namehash - * @see https://docs.ens.domains/ensip/15 - * @dev nominally typed to enforce usage & enhance codebase clarity - */ -export type NormalizedName = Name & { __brand: "NormalizedName" }; - /** * A LabelHash is the result of the labelhash function (which is just keccak256) on a Label. * From fe4c7db4977b6301a92ec0ac8570aa4bb6ba9649 Mon Sep 17 00:00:00 2001 From: shrugs Date: Thu, 9 Apr 2026 12:32:22 -0500 Subject: [PATCH 04/60] fix: ensure resolution lib works with interpreted name --- .../protocol-acceleration/find-resolver.ts | 9 ++-- .../src/lib/resolution/forward-resolution.ts | 13 +----- .../src/lib/resolution/packetToBytes.test.ts | 42 +++++++++++++++++++ .../resolution/resolve-calls-and-results.ts | 11 +++-- .../resolve-with-universal-resolver.ts | 4 +- packages/enssdk/src/lib/parse-reverse-name.ts | 4 +- 6 files changed, 56 insertions(+), 27 deletions(-) create mode 100644 apps/ensapi/src/lib/resolution/packetToBytes.test.ts diff --git a/apps/ensapi/src/lib/protocol-acceleration/find-resolver.ts b/apps/ensapi/src/lib/protocol-acceleration/find-resolver.ts index 0c64fdb83..e204835ca 100644 --- a/apps/ensapi/src/lib/protocol-acceleration/find-resolver.ts +++ b/apps/ensapi/src/lib/protocol-acceleration/find-resolver.ts @@ -9,8 +9,6 @@ import { type DomainId, getNameHierarchy, type InterpretedName, - type Name, - type Node, namehashInterpretedName, } from "enssdk"; import { isAddressEqual, type PublicClient, toHex, zeroAddress } from "viem"; @@ -29,7 +27,7 @@ type FindResolverResult = activeResolver: null; requiresWildcardSupport: undefined; } - | { activeName: Name; requiresWildcardSupport: boolean; activeResolver: Address }; + | { activeName: InterpretedName; requiresWildcardSupport: boolean; activeResolver: Address }; const NULL_RESULT: FindResolverResult = { activeName: null, @@ -94,7 +92,7 @@ export async function findResolver({ */ async function findResolverWithUniversalResolver( publicClient: PublicClient, - name: Name, + name: InterpretedName, ): Promise { return withActiveSpanAsync( tracer, @@ -147,7 +145,8 @@ async function findResolverWithUniversalResolver( } // UniversalResolver returns the offset in bytes within the DNS Encoded Name where the activeName begins - const activeName: Name = bytesToPacket(dnsEncodedNameBytes.slice(offset)); + // Invariant: the decoded name must be an InterpretedName + const activeName = asInterpretedName(bytesToPacket(dnsEncodedNameBytes.slice(offset))); return { activeName, diff --git a/apps/ensapi/src/lib/resolution/forward-resolution.ts b/apps/ensapi/src/lib/resolution/forward-resolution.ts index 457aeb540..c5fe018d6 100644 --- a/apps/ensapi/src/lib/resolution/forward-resolution.ts +++ b/apps/ensapi/src/lib/resolution/forward-resolution.ts @@ -7,7 +7,6 @@ import { asInterpretedName, type Node, namehashInterpretedName, - normalizeName, parseReverseName, } from "enssdk"; @@ -56,10 +55,6 @@ import { const logger = makeLogger("forward-resolution"); const tracer = trace.getTracer("forward-resolution"); -// NOTE: normalize generic name to force the normalization lib to lazy-load itself (otherwise the -// first trace generated here would be unusually slow) -normalizeName("example.eth"); - /** * Implements Forward Resolution of record values for a specified ENS Name. * @@ -147,9 +142,7 @@ async function _resolveForward( span.setAttribute("node", node); // if selection is empty, give them what they asked for - if (isSelectionEmpty(selection)) { - return makeEmptyResolverRecordsResponse(selection); - } + if (isSelectionEmpty(selection)) return makeEmptyResolverRecordsResponse(selection); // construct the set of resolve() calls indicated by selection const calls = makeResolveCalls(node, selection); @@ -221,9 +214,7 @@ async function _resolveForward( !!activeResolver, ); // we're unable to find an active resolver for this name, return empty response - if (!activeResolver) { - return makeEmptyResolverRecordsResponse(selection); - } + if (!activeResolver) return makeEmptyResolverRecordsResponse(selection); // set some attributes on the span for easy reference span.setAttribute("activeResolver", activeResolver); diff --git a/apps/ensapi/src/lib/resolution/packetToBytes.test.ts b/apps/ensapi/src/lib/resolution/packetToBytes.test.ts new file mode 100644 index 000000000..d30b0186f --- /dev/null +++ b/apps/ensapi/src/lib/resolution/packetToBytes.test.ts @@ -0,0 +1,42 @@ +import { + asInterpretedLabel, + asInterpretedName, + asLiteralLabel, + encodeLabelHash, + interpretedLabelsToInterpretedName, + labelhashLiteralLabel, +} from "enssdk"; +import { bytesToHex, stringToHex } from "viem"; +import { packetToBytes } from "viem/ens"; +import { describe, expect, it } from "vitest"; + +const TEST_LABEL = asLiteralLabel("test"); +const ENCODED_LABEL_HASH = asInterpretedLabel(encodeLabelHash(labelhashLiteralLabel(TEST_LABEL))); + +describe("packetToBytes", () => { + it("correctly DNS-encodes an InterpretedName containing an encoded labelhash label", () => { + const name = asInterpretedName( + interpretedLabelsToInterpretedName([ENCODED_LABEL_HASH, asInterpretedLabel("eth")]), + ); + const expectedLabelHex = stringToHex(ENCODED_LABEL_HASH).slice(2); + + // The encoded labelhash label (e.g. "[9c22ff...b658]") is 66 characters and should + // be DNS-encoded as a single label: length prefix 0x42 (66) followed by its UTF-8 bytes, + // followed by the 'eth' label with length (03 65 74 68) and null terminator (00) + const result = bytesToHex(packetToBytes(name)); + expect(result).toEqual(`0x42${expectedLabelHex}0365746800`); + }); + + it("encodes an encoded labelhash label differently from the plaintext label", () => { + const fromPlaintext = bytesToHex(packetToBytes(`${TEST_LABEL}.eth`)); + const fromEncodedLabelHash = bytesToHex(packetToBytes(`${ENCODED_LABEL_HASH}.eth`)); + + // The plaintext "test" label is 4 bytes (length prefix 0x04), while the encoded + // labelhash "[9c22ff...b658]" is 66 bytes (length prefix 0x42). These produce + // different DNS encodings because the resolver uses the labelhash to look up + // records when the original label is unknown. + expect(fromPlaintext).toMatch(/^0x04/); + expect(fromEncodedLabelHash).toMatch(/^0x42/); + expect(fromEncodedLabelHash).not.toEqual(fromPlaintext); + }); +}); diff --git a/apps/ensapi/src/lib/resolution/resolve-calls-and-results.ts b/apps/ensapi/src/lib/resolution/resolve-calls-and-results.ts index f9c57c6a9..4f6597121 100644 --- a/apps/ensapi/src/lib/resolution/resolve-calls-and-results.ts +++ b/apps/ensapi/src/lib/resolution/resolve-calls-and-results.ts @@ -96,9 +96,7 @@ export function makeResolveCalls( /** * Execute a set of ResolveCalls against the provided `resolverAddress`. * - * NOTE: viem#readContract implements CCIP-Read, so we get that behavior for free - * NOTE: viem#multicall _doesn't_ implement CCIP-Read so maybe this can be optimized further - * + * @dev viem#readContract implements CCIP-Read, so we get that behavior for free * TODO: CCIP-Read Gateways can fail, should likely implement retries? */ export async function executeResolveCalls({ @@ -194,14 +192,15 @@ export async function executeResolveCalls; publicClient: PublicClient; }): Promise> { diff --git a/packages/enssdk/src/lib/parse-reverse-name.ts b/packages/enssdk/src/lib/parse-reverse-name.ts index b49423e4a..dc1c412b5 100644 --- a/packages/enssdk/src/lib/parse-reverse-name.ts +++ b/packages/enssdk/src/lib/parse-reverse-name.ts @@ -21,9 +21,7 @@ const REVERSE_NAME_REGEX = /^([0-9a-fA-F]+)\.([0-9a-f]{1,64}|addr|default)\.reve const parseAddressLabel = (addressLabel: Label): Address => { const maybeAddress = `0x${addressLabel}`; - if (!isAddress(maybeAddress)) { - throw new Error(`Invalid EVM address "${maybeAddress}"`); - } + if (!isAddress(maybeAddress)) throw new Error(`Invalid EVM address "${maybeAddress}"`); return asLowerCaseAddress(maybeAddress); }; From 4b5fa3db89c84274d10f84a56bc797cfa88e8207 Mon Sep 17 00:00:00 2001 From: shrugs Date: Thu, 9 Apr 2026 16:42:03 -0500 Subject: [PATCH 05/60] refactor Address to NormalizedAddress where reasonable --- .../src/app/mock/display-identity/page.tsx | 4 +- .../explore/registrar-actions-api.routes.ts | 4 +- .../ensanalytics-api-v1.routes.ts | 4 +- .../ensanalytics/ensanalytics-api.routes.ts | 4 +- apps/ensapi/src/lib/handlers/params.schema.ts | 4 +- apps/ensapi/src/omnigraph-api/builder.ts | 3 +- .../schema/account.integration.test.ts | 17 ++-- .../schema/domain.integration.test.ts | 10 +-- .../schema/permissions.integration.test.ts | 55 +++++++------ .../src/omnigraph-api/schema/scalars.ts | 34 ++++---- apps/ensindexer/src/config/validations.ts | 4 +- .../lib/heal-addr-reverse-subname-label.ts | 4 +- .../src/lib/tokenscope/seaport-types.ts | 8 +- .../src/lib/trace-transaction-helpers.ts | 6 +- .../ensv2/handlers/ensv1/BaseRegistrar.ts | 8 +- .../ensv2/handlers/ensv1/ENSv1Registry.ts | 6 +- .../ensv2/handlers/ensv1/NameWrapper.ts | 12 +-- .../ensv2/handlers/ensv2/ENSv2Registry.ts | 14 ++-- .../ensv2/handlers/ensv2/ETHRegistrar.ts | 12 +-- .../handlers/ensv2/EnhancedAccessControl.ts | 4 +- .../handlers/ENSv1Registry.ts | 8 +- .../handlers/ENSv2Registry.ts | 4 +- .../handlers/ThreeDNSToken.ts | 3 +- .../registrars/shared/lib/registrar-action.ts | 2 + .../subgraph/shared-handlers/NameWrapper.ts | 9 ++- .../subgraph/shared-handlers/Registrar.ts | 10 ++- .../subgraph/shared-handlers/Registry.ts | 8 +- .../subgraph/shared-handlers/Resolver.ts | 8 +- .../subgraph/shared-handlers/ThreeDNSToken.ts | 7 +- .../enskit-react-example/src/DomainView.tsx | 48 ++++++++--- packages/datasources/src/invariants.test.ts | 3 +- packages/ens-referrals/src/address.ts | 4 - packages/ens-referrals/src/api/zod-schemas.ts | 6 +- .../ens-referrals/src/referrer-metrics.ts | 5 +- packages/ens-referrals/src/v1/address.ts | 4 - .../ens-referrals/src/v1/api/zod-schemas.ts | 4 +- .../award-models/pie-split/api/zod-schemas.ts | 6 +- .../rev-share-limit/api/zod-schemas.ts | 12 +-- .../rev-share-limit/leaderboard.ts | 4 +- .../v1/award-models/rev-share-limit/rules.ts | 5 +- .../ens-referrals/src/v1/referrer-metrics.ts | 5 +- .../components/ensure-interpreted-name.tsx | 34 ++++++++ .../src/react/omnigraph/components/index.tsx | 1 + packages/enskit/src/react/omnigraph/index.ts | 1 + .../src/omnigraph-api/example-queries.ts | 10 ++- .../ensnode-sdk/src/registrars/zod-schemas.ts | 6 +- .../interpretation/interpret-record-values.ts | 6 +- .../ensnode-sdk/src/shared/zod-schemas.ts | 10 +-- packages/enssdk/src/lib/address.test.ts | 79 ++++++++++++++++--- packages/enssdk/src/lib/address.ts | 36 +++++++-- .../src/lib/interpreted-names-and-labels.ts | 69 +++++++++++----- packages/enssdk/src/lib/parse-reverse-name.ts | 4 +- packages/enssdk/src/lib/types/evm.ts | 19 ++++- .../src/omnigraph/generated/schema.graphql | 32 ++++---- packages/enssdk/src/omnigraph/graphql.ts | 5 +- 55 files changed, 450 insertions(+), 244 deletions(-) create mode 100644 packages/enskit/src/react/omnigraph/components/ensure-interpreted-name.tsx create mode 100644 packages/enskit/src/react/omnigraph/components/index.tsx diff --git a/apps/ensadmin/src/app/mock/display-identity/page.tsx b/apps/ensadmin/src/app/mock/display-identity/page.tsx index 5ebe54dda..fe9ffe068 100644 --- a/apps/ensadmin/src/app/mock/display-identity/page.tsx +++ b/apps/ensadmin/src/app/mock/display-identity/page.tsx @@ -6,7 +6,7 @@ import { getEnsManagerAddressDetailsUrl, } from "@namehash/namehash-ui"; import type { Address, ChainId, DefaultableChainId, Name } from "enssdk"; -import { asLowerCaseAddress, DEFAULT_EVM_CHAIN_ID } from "enssdk"; +import { DEFAULT_EVM_CHAIN_ID, toNormalizedAddress } from "enssdk"; import { useState } from "react"; import { isAddress } from "viem"; @@ -76,7 +76,7 @@ export default function MockDisplayIdentityPage() { } // at a data-model level, we always represent addresses fully in lowercase. - selectedAddress = asLowerCaseAddress(selectedAddress); + selectedAddress = toNormalizedAddress(selectedAddress); // fallback to selecting the default name if // selectedRawName is an empty string diff --git a/apps/ensapi/src/handlers/api/explore/registrar-actions-api.routes.ts b/apps/ensapi/src/handlers/api/explore/registrar-actions-api.routes.ts index b9f70c983..6c42f2823 100644 --- a/apps/ensapi/src/handlers/api/explore/registrar-actions-api.routes.ts +++ b/apps/ensapi/src/handlers/api/explore/registrar-actions-api.routes.ts @@ -6,8 +6,8 @@ import { RegistrarActionsOrders, } from "@ensnode/ensnode-sdk"; import { - makeLowercaseAddressSchema, makeNodeSchema, + makeNormalizedAddressSchema, makePositiveIntegerSchema, makeUnixTimestampSchema, } from "@ensnode/ensnode-sdk/internal"; @@ -51,7 +51,7 @@ export const registrarActionsQuerySchema = z .describe("Filter to only include actions with referrals") .openapi({ default: false }), - decodedReferrer: makeLowercaseAddressSchema("decodedReferrer") + decodedReferrer: makeNormalizedAddressSchema("decodedReferrer") .optional() .describe("Filter by decoded referrer address"), diff --git a/apps/ensapi/src/handlers/ensanalytics/ensanalytics-api-v1.routes.ts b/apps/ensapi/src/handlers/ensanalytics/ensanalytics-api-v1.routes.ts index 003682e37..e2932c8b8 100644 --- a/apps/ensapi/src/handlers/ensanalytics/ensanalytics-api-v1.routes.ts +++ b/apps/ensapi/src/handlers/ensanalytics/ensanalytics-api-v1.routes.ts @@ -8,7 +8,7 @@ import { makeReferrerMetricsEditionsArraySchema, } from "@namehash/ens-referrals/v1/internal"; -import { makeLowercaseAddressSchema } from "@ensnode/ensnode-sdk/internal"; +import { makeNormalizedAddressSchema } from "@ensnode/ensnode-sdk/internal"; export const basePath = "/v1/ensanalytics"; @@ -39,7 +39,7 @@ const referrerLeaderboardPageQuerySchema = z.object({ // Referrer address parameter schema const referrerAddressSchema = z.object({ - referrer: makeLowercaseAddressSchema("Referrer address").describe("Referrer Ethereum address"), + referrer: makeNormalizedAddressSchema("Referrer address").describe("Referrer Ethereum address"), }); // Editions query parameter schema diff --git a/apps/ensapi/src/handlers/ensanalytics/ensanalytics-api.routes.ts b/apps/ensapi/src/handlers/ensanalytics/ensanalytics-api.routes.ts index cb14bac2b..15503d1d6 100644 --- a/apps/ensapi/src/handlers/ensanalytics/ensanalytics-api.routes.ts +++ b/apps/ensapi/src/handlers/ensanalytics/ensanalytics-api.routes.ts @@ -1,7 +1,7 @@ import { createRoute, z } from "@hono/zod-openapi"; import { REFERRERS_PER_LEADERBOARD_PAGE_MAX } from "@namehash/ens-referrals"; -import { makeLowercaseAddressSchema } from "@ensnode/ensnode-sdk/internal"; +import { makeNormalizedAddressSchema } from "@ensnode/ensnode-sdk/internal"; export const basePath = "/ensanalytics"; @@ -28,7 +28,7 @@ const paginationQuerySchema = z.object({ // Referrer address parameter schema const referrerAddressSchema = z.object({ - referrer: makeLowercaseAddressSchema("Referrer address").describe("Referrer Ethereum address"), + referrer: makeNormalizedAddressSchema("Referrer address").describe("Referrer Ethereum address"), }); export const getReferrerLeaderboardRoute = createRoute({ diff --git a/apps/ensapi/src/lib/handlers/params.schema.ts b/apps/ensapi/src/lib/handlers/params.schema.ts index 7c1550a56..36e78e24a 100644 --- a/apps/ensapi/src/lib/handlers/params.schema.ts +++ b/apps/ensapi/src/lib/handlers/params.schema.ts @@ -5,7 +5,7 @@ import { isSelectionEmpty, type ResolverRecordsSelection } from "@ensnode/ensnod import { makeCoinTypeStringSchema, makeDefaultableChainIdStringSchema, - makeLowercaseAddressSchema, + makeNormalizedAddressSchema, } from "@ensnode/ensnode-sdk/internal"; const excludingDefaultChainId = z @@ -36,7 +36,7 @@ const name = z const trace = z.optional(boolstring).default(false).openapi({ default: false }); const accelerate = z.optional(boolstring).default(false).openapi({ default: false }); -const address = makeLowercaseAddressSchema(); +const address = makeNormalizedAddressSchema(); const defaultableChainId = makeDefaultableChainIdStringSchema(); const coinType = makeCoinTypeStringSchema(); diff --git a/apps/ensapi/src/omnigraph-api/builder.ts b/apps/ensapi/src/omnigraph-api/builder.ts index 16b1097d1..8cb83130c 100644 --- a/apps/ensapi/src/omnigraph-api/builder.ts +++ b/apps/ensapi/src/omnigraph-api/builder.ts @@ -13,6 +13,7 @@ import type { InterpretedLabel, InterpretedName, Node, + NormalizedAddress, PermissionsId, PermissionsResourceId, PermissionsUserId, @@ -60,7 +61,7 @@ export const builder = new SchemaBuilder<{ Scalars: { // make sure to keep these scalars up to date with packages/enssdk/src/omnigraph/graphql.ts ! BigInt: { Input: bigint; Output: bigint }; - Address: { Input: Address; Output: Address }; + Address: { Input: Address; Output: NormalizedAddress }; Hex: { Input: Hex; Output: Hex }; ChainId: { Input: ChainId; Output: ChainId }; CoinType: { Input: CoinType; Output: CoinType }; diff --git a/apps/ensapi/src/omnigraph-api/schema/account.integration.test.ts b/apps/ensapi/src/omnigraph-api/schema/account.integration.test.ts index 82203b911..273224417 100644 --- a/apps/ensapi/src/omnigraph-api/schema/account.integration.test.ts +++ b/apps/ensapi/src/omnigraph-api/schema/account.integration.test.ts @@ -1,4 +1,4 @@ -import type { Address, Name } from "enssdk"; +import { type InterpretedName, toNormalizedAddress } from "enssdk"; import { beforeAll, describe, expect, it } from "vitest"; import { @@ -21,13 +21,13 @@ import { import { gql } from "@/test/integration/omnigraph-api-client"; // via devnet -const DEVNET_DEPLOYER: Address = "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"; -const DEFAULT_OWNER: Address = "0x70997970c51812dc3a010c7d01b50e0d17dc79c8"; -const NEW_OWNER_OWNER: Address = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC"; +const DEVNET_DEPLOYER = toNormalizedAddress("0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"); +const DEFAULT_OWNER = toNormalizedAddress("0x70997970c51812dc3a010c7d01b50e0d17dc79c8"); +const NEW_OWNER_OWNER = toNormalizedAddress("0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC"); describe("Account.domains", () => { type AccountDomainsResult = { - account: { domains: GraphQLConnection<{ name: Name | null }> }; + account: { domains: GraphQLConnection<{ name: InterpretedName | null }> }; }; const AccountDomains = gql` @@ -101,9 +101,8 @@ describe("Account.events", () => { expect(events.length).toBeGreaterThan(0); - // all events should have from === deployer address (case-insensitive) for (const event of events) { - expect(event.from.toLowerCase()).toBe(DEVNET_DEPLOYER.toLowerCase()); + expect(event.from).toBe(DEVNET_DEPLOYER); } }); }); @@ -150,7 +149,7 @@ describe("Account.events filtering (AccountEventsWhereInput)", () => { expect(events.length).toBeGreaterThan(0); for (const event of events) { - expect(event.topics[0]?.toLowerCase()).toBe(targetSelector.toLowerCase()); + expect(event.topics[0]).toBe(targetSelector); } }); @@ -236,7 +235,7 @@ describe("Account.events filtering (AccountEventsWhereInput)", () => { expect(events.length).toBeGreaterThan(0); expect(events.length).toBeLessThanOrEqual(allEvents.length); for (const event of events) { - expect(event.topics[0]?.toLowerCase()).toBe(targetSelector.toLowerCase()); + expect(event.topics[0]).toBe(targetSelector); expect(BigInt(event.timestamp)).toBeGreaterThanOrEqual(BigInt(midTimestamp)); } }); diff --git a/apps/ensapi/src/omnigraph-api/schema/domain.integration.test.ts b/apps/ensapi/src/omnigraph-api/schema/domain.integration.test.ts index 3b937066c..b9ee706b8 100644 --- a/apps/ensapi/src/omnigraph-api/schema/domain.integration.test.ts +++ b/apps/ensapi/src/omnigraph-api/schema/domain.integration.test.ts @@ -1,4 +1,4 @@ -import type { InterpretedLabel, Name } from "enssdk"; +import type { InterpretedLabel, InterpretedName } from "enssdk"; import { beforeAll, describe, expect, it } from "vitest"; import { DEVNET_ETH_LABELS } from "@/test/integration/devnet-names"; @@ -27,7 +27,7 @@ describe("Domain.subdomains", () => { type SubdomainsResult = { domain: { subdomains: GraphQLConnection<{ - name: Name | null; + name: InterpretedName | null; label: { interpreted: InterpretedLabel }; }>; }; @@ -135,7 +135,7 @@ describe("Domain.events filtering (EventsWhereInput)", () => { expect(events.length).toBeGreaterThan(0); for (const event of events) { - expect(event.topics[0]?.toLowerCase()).toBe(targetSelector.toLowerCase()); + expect(event.topics[0]).toBe(targetSelector); } }); @@ -215,7 +215,7 @@ describe("Domain.events filtering (EventsWhereInput)", () => { expect(events.length).toBeGreaterThan(0); for (const event of events) { - expect(event.from.toLowerCase()).toBe(targetFrom.toLowerCase()); + expect(event.from).toBe(targetFrom); } }); @@ -236,7 +236,7 @@ describe("Domain.events filtering (EventsWhereInput)", () => { expect(events.length).toBeGreaterThan(0); expect(events.length).toBeLessThanOrEqual(allEvents.length); for (const event of events) { - expect(event.topics[0]?.toLowerCase()).toBe(targetSelector.toLowerCase()); + expect(event.topics[0]).toBe(targetSelector); expect(BigInt(event.timestamp)).toBeGreaterThanOrEqual(BigInt(midTimestamp)); } }); diff --git a/apps/ensapi/src/omnigraph-api/schema/permissions.integration.test.ts b/apps/ensapi/src/omnigraph-api/schema/permissions.integration.test.ts index 44b1a1c38..2256978c4 100644 --- a/apps/ensapi/src/omnigraph-api/schema/permissions.integration.test.ts +++ b/apps/ensapi/src/omnigraph-api/schema/permissions.integration.test.ts @@ -1,4 +1,4 @@ -import type { Address } from "enssdk"; +import type { NormalizedAddress } from "enssdk"; import { toEventSelector } from "viem"; import { beforeAll, describe, expect, it } from "vitest"; @@ -19,9 +19,11 @@ import { } from "@/test/integration/graphql-utils"; import { gql } from "@/test/integration/omnigraph-api-client"; -const namespace = "ens-test-env"; - -const V2_ETH_REGISTRY = getDatasourceContract(namespace, DatasourceNames.ENSv2Root, "ETHRegistry"); +const V2_ETH_REGISTRY = getDatasourceContract( + "ens-test-env", + DatasourceNames.ENSv2Root, + "ETHRegistry", +); const NAME_WITH_RESOLVER = "example.eth"; @@ -35,14 +37,14 @@ describe("Permissions", () => { type PermissionsResult = { permissions: { id: string; - contract: { chainId: number; address: Address }; + contract: { chainId: number; address: NormalizedAddress }; root: { id: string; resource: string; users: GraphQLConnection<{ id: string; resource: string; - user: { address: Address }; + user: { address: NormalizedAddress }; roles: string; }>; }; @@ -52,7 +54,7 @@ describe("Permissions", () => { users: GraphQLConnection<{ id: string; resource: string; - user: { address: Address }; + user: { address: NormalizedAddress }; roles: string; }>; }>; @@ -126,7 +128,7 @@ describe("Registry.permissions", () => { it("resolves permissions from a registry", async () => { const result = await request<{ registry: { - permissions: { id: string; contract: { chainId: number; address: Address } }; + permissions: { id: string; contract: { chainId: number; address: NormalizedAddress } }; }; }>(RegistryPermissions, { contract: V2_ETH_REGISTRY }); @@ -141,7 +143,7 @@ describe("Domain.permissions", () => { permissions: GraphQLConnection<{ id: string; resource: string; - user: { address: Address }; + user: { address: NormalizedAddress }; roles: string; }>; }; @@ -157,7 +159,12 @@ describe("Domain.permissions", () => { } `; - let allUsers: { id: string; resource: string; user: { address: Address }; roles: string }[]; + let allUsers: { + id: string; + resource: string; + user: { address: NormalizedAddress }; + roles: string; + }[]; beforeAll(async () => { const result = await request(DomainPermissions, { @@ -199,7 +206,7 @@ describe("Domain.permissions", () => { expect(filteredUsers.length).toBeGreaterThan(0); for (const user of filteredUsers) { - expect(user.user.address.toLowerCase()).toBe(targetUser.toLowerCase()); + expect(user.user.address).toBe(targetUser); } }); }); @@ -229,12 +236,12 @@ describe("Account.permissions and Account.registryPermissions", () => { } `; - let targetAddress: Address; + let targetAddress: NormalizedAddress; beforeAll(async () => { const rootResult = await request<{ permissions: { - root: { users: GraphQLConnection<{ user: { address: Address } }> }; + root: { users: GraphQLConnection<{ user: { address: NormalizedAddress } }> }; }; }>(PermissionsRootUsers, { contract: V2_ETH_REGISTRY }); @@ -249,7 +256,7 @@ describe("Account.permissions and Account.registryPermissions", () => { permissions: GraphQLConnection<{ id: string; resource: string; - user: { address: Address }; + user: { address: NormalizedAddress }; roles: string; }>; }; @@ -259,7 +266,7 @@ describe("Account.permissions and Account.registryPermissions", () => { expect(permissions.length).toBeGreaterThan(0); for (const p of permissions) { - expect(p.user.address.toLowerCase()).toBe(targetAddress.toLowerCase()); + expect(p.user.address).toBe(targetAddress); } }); @@ -270,7 +277,7 @@ describe("Account.permissions and Account.registryPermissions", () => { id: string; registry: { id: string }; resource: string; - user: { address: Address }; + user: { address: NormalizedAddress }; roles: string; }>; }; @@ -281,7 +288,7 @@ describe("Account.permissions and Account.registryPermissions", () => { for (const p of permissions) { expect(p.registry.id).toBeTruthy(); - expect(p.user.address.toLowerCase()).toBe(targetAddress.toLowerCase()); + expect(p.user.address).toBe(targetAddress); } }); }); @@ -299,7 +306,7 @@ describe("Resolver.permissions", () => { const result = await request<{ domain: { resolver: { - permissions: { id: string; contract: { chainId: number; address: Address } }; + permissions: { id: string; contract: { chainId: number; address: NormalizedAddress } }; }; }; }>(ResolverPermissions, { name: NAME_WITH_RESOLVER }); @@ -340,14 +347,12 @@ describe("Permissions.events", () => { it("returns events scoped to the ETHRegistry contract", () => { for (const event of allEvents) { - expect(event.address.toLowerCase()).toBe(V2_ETH_REGISTRY.address); + expect(event.address).toBe(V2_ETH_REGISTRY.address); } }); it("includes EACRolesChanged events", () => { - const rolesChangedEvents = allEvents.filter( - (e) => e.topics[0]?.toLowerCase() === EAC_ROLES_CHANGED_SELECTOR, - ); + const rolesChangedEvents = allEvents.filter((e) => e.topics[0] === EAC_ROLES_CHANGED_SELECTOR); expect(rolesChangedEvents.length).toBeGreaterThan(0); }); }); @@ -394,7 +399,7 @@ describe("Permissions.events filtering (EventsWhereInput)", () => { expect(events.length).toBeGreaterThan(0); for (const event of events) { - expect(event.topics[0]?.toLowerCase()).toBe(EAC_ROLES_CHANGED_SELECTOR); + expect(event.topics[0]).toBe(EAC_ROLES_CHANGED_SELECTOR); } }); @@ -476,7 +481,7 @@ describe("Permissions.events filtering (EventsWhereInput)", () => { expect(events.length).toBeGreaterThan(0); for (const event of events) { - expect(event.from.toLowerCase()).toBe(targetFrom.toLowerCase()); + expect(event.from).toBe(targetFrom); } }); @@ -492,7 +497,7 @@ describe("Permissions.events filtering (EventsWhereInput)", () => { expect(events.length).toBeGreaterThan(0); expect(events.length).toBeLessThanOrEqual(allEvents.length); for (const event of events) { - expect(event.topics[0]?.toLowerCase()).toBe(EAC_ROLES_CHANGED_SELECTOR); + expect(event.topics[0]).toBe(EAC_ROLES_CHANGED_SELECTOR); expect(BigInt(event.timestamp)).toBeGreaterThanOrEqual(BigInt(midTimestamp)); } }); diff --git a/apps/ensapi/src/omnigraph-api/schema/scalars.ts b/apps/ensapi/src/omnigraph-api/schema/scalars.ts index 55b8f4337..9fd1efb60 100644 --- a/apps/ensapi/src/omnigraph-api/schema/scalars.ts +++ b/apps/ensapi/src/omnigraph-api/schema/scalars.ts @@ -25,7 +25,7 @@ import { z } from "zod/v4"; import { makeChainIdSchema, makeCoinTypeSchema, - makeLowercaseAddressSchema, + makeNormalizedAddressSchema, } from "@ensnode/ensnode-sdk/internal"; import { builder } from "@/omnigraph-api/builder"; @@ -37,9 +37,9 @@ builder.scalarType("BigInt", { }); builder.scalarType("Address", { - description: "Address represents a lowercase (unchecksummed) viem#Address.", + description: "Address represents an EVM Address in all lowercase.", serialize: (value: Address) => value.toString(), - parseValue: (value) => makeLowercaseAddressSchema("Address").parse(value), + parseValue: (value) => makeNormalizedAddressSchema("Address").parse(value), }); builder.scalarType("Hex", { @@ -62,19 +62,19 @@ builder.scalarType("Hex", { }); builder.scalarType("ChainId", { - description: "ChainId represents a @ensnode/ensnode-sdk#ChainId.", + description: "ChainId represents a enssdk#ChainId.", serialize: (value: ChainId) => value, parseValue: (value) => makeChainIdSchema("ChainId").parse(value), }); builder.scalarType("CoinType", { - description: "CoinType represents a @ensnode/ensnode-sdk#CoinType.", + description: "CoinType represents a enssdk#CoinType.", serialize: (value: CoinType) => value, parseValue: (value) => makeCoinTypeSchema("CoinType").parse(value), }); builder.scalarType("Node", { - description: "Node represents a @ensnode/ensnode-sdk#Node.", + description: "Node represents a enssdk#Node.", serialize: (value: Node) => value, parseValue: (value) => z.coerce @@ -93,7 +93,7 @@ builder.scalarType("Node", { }); builder.scalarType("InterpretedName", { - description: "InterpretedName represents a @ensnode/ensnode-sdk#InterpretedName.", + description: "InterpretedName represents a enssdk#InterpretedName.", serialize: (value: Name) => value, parseValue: (value) => z.coerce @@ -113,7 +113,7 @@ builder.scalarType("InterpretedName", { }); builder.scalarType("InterpretedLabel", { - description: "InterpretedLabel represents a @ensnode/ensnode-sdk#InterpretedLabel.", + description: "InterpretedLabel represents a enssdk#InterpretedLabel.", serialize: (value: Name) => value, parseValue: (value) => z.coerce @@ -132,7 +132,7 @@ builder.scalarType("InterpretedLabel", { }); builder.scalarType("DomainId", { - description: "DomainId represents a @ensnode/ensnode-sdk#DomainId.", + description: "DomainId represents a enssdk#DomainId.", serialize: (value: DomainId) => value, parseValue: (value) => z.coerce @@ -142,7 +142,7 @@ builder.scalarType("DomainId", { }); builder.scalarType("RegistryId", { - description: "RegistryId represents a @ensnode/ensnode-sdk#RegistryId.", + description: "RegistryId represents a enssdk#RegistryId.", serialize: (value: RegistryId) => value, parseValue: (value) => z.coerce @@ -152,7 +152,7 @@ builder.scalarType("RegistryId", { }); builder.scalarType("ResolverId", { - description: "ResolverId represents a @ensnode/ensnode-sdk#ResolverId.", + description: "ResolverId represents a enssdk#ResolverId.", serialize: (value: ResolverId) => value, parseValue: (value) => z.coerce @@ -162,7 +162,7 @@ builder.scalarType("ResolverId", { }); builder.scalarType("PermissionsId", { - description: "PermissionsId represents a @ensnode/ensnode-sdk#PermissionsId.", + description: "PermissionsId represents a enssdk#PermissionsId.", serialize: (value: PermissionsId) => value, parseValue: (value) => z.coerce @@ -172,7 +172,7 @@ builder.scalarType("PermissionsId", { }); builder.scalarType("PermissionsResourceId", { - description: "PermissionsResourceId represents a @ensnode/ensnode-sdk#PermissionsResourceId.", + description: "PermissionsResourceId represents a enssdk#PermissionsResourceId.", serialize: (value: PermissionsResourceId) => value, parseValue: (value) => z.coerce @@ -182,7 +182,7 @@ builder.scalarType("PermissionsResourceId", { }); builder.scalarType("PermissionsUserId", { - description: "PermissionsUserId represents a @ensnode/ensnode-sdk#PermissionsUserId.", + description: "PermissionsUserId represents a enssdk#PermissionsUserId.", serialize: (value: PermissionsUserId) => value, parseValue: (value) => z.coerce @@ -192,7 +192,7 @@ builder.scalarType("PermissionsUserId", { }); builder.scalarType("RegistrationId", { - description: "RegistrationId represents a @ensnode/ensnode-sdk#RegistrationId.", + description: "RegistrationId represents a enssdk#RegistrationId.", serialize: (value: RegistrationId) => value, parseValue: (value) => z.coerce @@ -202,7 +202,7 @@ builder.scalarType("RegistrationId", { }); builder.scalarType("RenewalId", { - description: "RenewalId represents a @ensnode/ensnode-sdk#RenewalId.", + description: "RenewalId represents a enssdk#RenewalId.", serialize: (value: RenewalId) => value, parseValue: (value) => z.coerce @@ -212,7 +212,7 @@ builder.scalarType("RenewalId", { }); builder.scalarType("ResolverRecordsId", { - description: "ResolverRecordsId represents a @ensnode/ensnode-sdk#ResolverRecordsId.", + description: "ResolverRecordsId represents a enssdk#ResolverRecordsId.", serialize: (value: ResolverRecordsId) => value, parseValue: (value) => z.coerce diff --git a/apps/ensindexer/src/config/validations.ts b/apps/ensindexer/src/config/validations.ts index 168c0d9ce..ac18dd5d4 100644 --- a/apps/ensindexer/src/config/validations.ts +++ b/apps/ensindexer/src/config/validations.ts @@ -1,5 +1,5 @@ import type { Address } from "enssdk"; -import { asLowerCaseAddress } from "enssdk"; +import { isNormalizedAddress } from "enssdk"; import { isAddress } from "viem"; import { type DatasourceName, type ENSNamespace, getENSNamespace } from "@ensnode/datasources"; @@ -129,7 +129,7 @@ export function invariant_validContractConfigs( // only ContractConfigs with `address` defined const isValidAddress = isAddress(contractConfig.address as Address, { strict: false }) && // must be a valid `Address` - contractConfig.address === asLowerCaseAddress(contractConfig.address); // and in lowercase format + isNormalizedAddress(contractConfig.address as Address); // and in lowercase format if (!isValidAddress) { throw new Error( diff --git a/apps/ensindexer/src/lib/heal-addr-reverse-subname-label.ts b/apps/ensindexer/src/lib/heal-addr-reverse-subname-label.ts index 2a8ad5138..6e21dce0c 100644 --- a/apps/ensindexer/src/lib/heal-addr-reverse-subname-label.ts +++ b/apps/ensindexer/src/lib/heal-addr-reverse-subname-label.ts @@ -1,6 +1,6 @@ import config from "@/config"; -import type { Address, LabelHash, LiteralLabel } from "enssdk"; +import type { LabelHash, LiteralLabel, NormalizedAddress } from "enssdk"; import { getENSRootChainId } from "@ensnode/datasources"; @@ -21,7 +21,7 @@ import { */ export async function healAddrReverseSubnameLabel( context: IndexingEngineContext, - event: EventWithArgs<{ owner: Address }>, + event: EventWithArgs<{ owner: NormalizedAddress }>, labelHash: LabelHash, ): Promise { if (context.chain.id !== getENSRootChainId(config.namespace)) { diff --git a/apps/ensindexer/src/lib/tokenscope/seaport-types.ts b/apps/ensindexer/src/lib/tokenscope/seaport-types.ts index 7bc523104..8c1bdbe2a 100644 --- a/apps/ensindexer/src/lib/tokenscope/seaport-types.ts +++ b/apps/ensindexer/src/lib/tokenscope/seaport-types.ts @@ -1,4 +1,4 @@ -import type { Address, Hex } from "enssdk"; +import type { Address, Hex, NormalizedAddress } from "enssdk"; import type { EventWithArgs } from "@/lib/ponder-helpers"; @@ -33,7 +33,7 @@ export type OrderFulfilledEvent = EventWithArgs<{ * The address of the account that created and signed the original order. * This is the party offering items for trade. */ - offerer: Address; + offerer: NormalizedAddress; /** * The address of the zone contract that implements custom validation rules. @@ -41,13 +41,13 @@ export type OrderFulfilledEvent = EventWithArgs<{ * or other custom logic before order fulfillment. Can be zero address if * no additional validation is required. */ - zone: Address; + zone: NormalizedAddress; /** * The address that receives the offered items from the order. * This is typically the order fulfiller or their designated recipient. */ - recipient: Address; + recipient: NormalizedAddress; /** * Array of items that the offerer is giving up in this order. diff --git a/apps/ensindexer/src/lib/trace-transaction-helpers.ts b/apps/ensindexer/src/lib/trace-transaction-helpers.ts index b847b6a68..eed892e28 100644 --- a/apps/ensindexer/src/lib/trace-transaction-helpers.ts +++ b/apps/ensindexer/src/lib/trace-transaction-helpers.ts @@ -1,4 +1,4 @@ -import { type Address, asLowerCaseAddress, type Hex } from "enssdk"; +import { type Address, type Hex, toNormalizedAddress } from "enssdk"; import { type Hash, isAddress } from "viem"; /** @@ -86,7 +86,7 @@ export function getAddressesFromTrace(trace: Trace): Set
{ for (const maybeAddress of matches) { if (isAddress(maybeAddress)) { // Normalize the address - const normalizedAddr = asLowerCaseAddress(maybeAddress); + const normalizedAddr = toNormalizedAddress(maybeAddress); // Add the normalized address to the set uniqueAddresses.add(normalizedAddr); } else { @@ -118,7 +118,7 @@ export function getAddressesFromTrace(trace: Trace): Set
{ if (isAddress(maybeAddress)) { // Add 0x prefix and normalize the address - const normalizedAddr = asLowerCaseAddress(maybeAddress); + const normalizedAddr = toNormalizedAddress(maybeAddress); // Add the normalized address to the set uniqueAddresses.add(normalizedAddr); } else { diff --git a/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/BaseRegistrar.ts b/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/BaseRegistrar.ts index 041706dbd..61af2c703 100644 --- a/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/BaseRegistrar.ts +++ b/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/BaseRegistrar.ts @@ -1,9 +1,9 @@ import { GRACE_PERIOD_SECONDS } from "@ensdomains/ensjs/utils"; import { - type Address, interpretTokenIdAsLabelHash, makeENSv1DomainId, makeSubdomainNode, + type NormalizedAddress, } from "enssdk"; import { isAddressEqual, zeroAddress } from "viem"; @@ -52,8 +52,8 @@ export default function () { }: { context: IndexingEngineContext; event: EventWithArgs<{ - from: Address; - to: Address; + from: NormalizedAddress; + to: NormalizedAddress; tokenId: bigint; }>; }) => { @@ -98,7 +98,7 @@ export default function () { context: IndexingEngineContext; event: EventWithArgs<{ id: bigint; - owner: Address; + owner: NormalizedAddress; expires: bigint; }>; }) { diff --git a/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/ENSv1Registry.ts b/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/ENSv1Registry.ts index c5b455f2a..cfa08dd33 100644 --- a/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/ENSv1Registry.ts +++ b/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/ENSv1Registry.ts @@ -2,12 +2,12 @@ import config from "@/config"; import { ADDR_REVERSE_NODE, - type Address, ENS_ROOT_NODE, type LabelHash, makeENSv1DomainId, makeSubdomainNode, type Node, + type NormalizedAddress, } from "enssdk"; import { isAddressEqual, zeroAddress } from "viem"; @@ -46,7 +46,7 @@ export default function () { node: Node; // NOTE: `label` event arg represents a `LabelHash` for the sub-node under `node` label: LabelHash; - owner: Address; + owner: NormalizedAddress; }>; }) { const { label: labelHash, node: parentNode, owner } = event.args; @@ -104,7 +104,7 @@ export default function () { event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ node: Node; owner: Address }>; + event: EventWithArgs<{ node: Node; owner: NormalizedAddress }>; }) { const { node, owner } = event.args; diff --git a/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/NameWrapper.ts b/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/NameWrapper.ts index 0431da02f..c18c274d7 100644 --- a/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/NameWrapper.ts +++ b/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/NameWrapper.ts @@ -1,5 +1,4 @@ import { - type Address, type DNSEncodedLiteralName, type DNSEncodedName, decodeDNSEncodedLiteralName, @@ -9,6 +8,7 @@ import { makeENSv1DomainId, makeSubdomainNode, type Node, + type NormalizedAddress, } from "enssdk"; import { isAddressEqual, zeroAddress } from "viem"; @@ -98,9 +98,9 @@ export default function () { }: { context: IndexingEngineContext; event: EventWithArgs<{ - operator: Address; - from: Address; - to: Address; + operator: NormalizedAddress; + from: NormalizedAddress; + to: NormalizedAddress; id: bigint; }>; }) { @@ -155,7 +155,7 @@ export default function () { event: EventWithArgs<{ node: Node; name: DNSEncodedName; - owner: Address; + owner: NormalizedAddress; fuses: number; expiry: bigint; }>; @@ -272,7 +272,7 @@ export default function () { event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ node: Node; owner: Address }>; + event: EventWithArgs<{ node: Node; owner: NormalizedAddress }>; }) => { const { node } = event.args; diff --git a/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts b/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts index 1b88a4d5a..395b3a2b2 100644 --- a/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts +++ b/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts @@ -1,12 +1,12 @@ import { type AccountId, - type Address, asLiteralLabel, type LabelHash, labelhashLiteralLabel, makeENSv2DomainId, makeRegistryId, makeStorageId, + type NormalizedAddress, } from "enssdk"; import { hexToBigInt } from "viem"; @@ -46,9 +46,9 @@ export default function () { labelHash: LabelHash; label: string; // NOTE: marking `owner` as optional to handle both LabelRegistered and LabelReserved events - owner?: Address; + owner?: NormalizedAddress; expiry: bigint; - sender: Address; + sender: NormalizedAddress; }>; }) { const { tokenId, labelHash, owner, expiry, sender: registrant } = event.args; @@ -156,7 +156,7 @@ export default function () { context: IndexingEngineContext; event: EventWithArgs<{ tokenId: bigint; - sender: Address; + sender: NormalizedAddress; }>; }) => { const { tokenId, sender: unregistrant } = event.args; @@ -205,7 +205,7 @@ export default function () { event: EventWithArgs<{ tokenId: bigint; newExpiry: bigint; - sender: Address; + sender: NormalizedAddress; }>; }) => { // biome-ignore lint/correctness/noUnusedVariables: not sure if we care to index sender @@ -248,7 +248,7 @@ export default function () { context: IndexingEngineContext; event: EventWithArgs<{ tokenId: bigint; - subregistry: Address; + subregistry: NormalizedAddress; }>; }) => { const { tokenId, subregistry: _subregistry } = event.args; @@ -332,7 +332,7 @@ export default function () { event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ id: bigint; to: Address }>; + event: EventWithArgs<{ id: bigint; to: NormalizedAddress }>; }) { const { id: tokenId, to: owner } = event.args; diff --git a/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ETHRegistrar.ts b/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ETHRegistrar.ts index 038d0d998..4e9e78599 100644 --- a/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ETHRegistrar.ts +++ b/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ETHRegistrar.ts @@ -1,8 +1,8 @@ import { type AccountId, - type Address, makeENSv2DomainId, makeStorageId, + type NormalizedAddress, type TokenId, } from "enssdk"; @@ -54,12 +54,12 @@ export default function () { event: EventWithArgs<{ tokenId: TokenId; label: string; - owner: Address; - subregistry: Address; - resolver: Address; + owner: NormalizedAddress; + subregistry: NormalizedAddress; + resolver: NormalizedAddress; duration: bigint; referrer: EncodedReferrer; - paymentToken: Address; + paymentToken: NormalizedAddress; base: bigint; premium: bigint; }>; @@ -136,7 +136,7 @@ export default function () { duration: bigint; newExpiry: bigint; referrer: EncodedReferrer; - paymentToken: Address; + paymentToken: NormalizedAddress; base: bigint; }>; }) => { diff --git a/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/EnhancedAccessControl.ts b/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/EnhancedAccessControl.ts index 2ee4ee0d9..b039a7f28 100644 --- a/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/EnhancedAccessControl.ts +++ b/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/EnhancedAccessControl.ts @@ -1,10 +1,10 @@ import { - type Address, type EACResource, type EACRoleBitmap, makePermissionsId, makePermissionsResourceId, makePermissionsUserId, + type NormalizedAddress, } from "enssdk"; import { isAddressEqual, zeroAddress } from "viem"; @@ -62,7 +62,7 @@ export default function () { context: IndexingEngineContext; event: EventWithArgs<{ resource: EACResource; - account: Address; + account: NormalizedAddress; oldRoleBitmap: EACRoleBitmap; newRoleBitmap: EACRoleBitmap; }>; diff --git a/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ENSv1Registry.ts b/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ENSv1Registry.ts index a6737a654..2055bcd23 100644 --- a/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ENSv1Registry.ts +++ b/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ENSv1Registry.ts @@ -1,11 +1,11 @@ import config from "@/config"; import { - type Address, type LabelHash, makeENSv1DomainId, makeSubdomainNode, type Node, + type NormalizedAddress, } from "enssdk"; import { getENSRootChainId } from "@ensnode/datasources"; @@ -33,7 +33,7 @@ export default function () { event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ node: Node; resolver: Address }>; + event: EventWithArgs<{ node: Node; resolver: NormalizedAddress }>; }) { const { node, resolver } = event.args; @@ -59,7 +59,7 @@ export default function () { node: Node; // NOTE: `label` event arg represents a `LabelHash` for the sub-node under `node` label: LabelHash; - owner: Address; + owner: NormalizedAddress; }>; }) => { // no-op because we only track registry migration status on ENS Root Chain @@ -82,7 +82,7 @@ export default function () { event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ node: Node; resolver: Address }>; + event: EventWithArgs<{ node: Node; resolver: NormalizedAddress }>; }) => { // ignore the event on ENSv1RegistryOld if node is migrated to new Registry const shouldIgnoreEvent = await nodeIsMigrated(context, event.args.node); diff --git a/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ENSv2Registry.ts b/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ENSv2Registry.ts index 27570f739..eec246efe 100644 --- a/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ENSv2Registry.ts +++ b/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ENSv2Registry.ts @@ -1,4 +1,4 @@ -import { type Address, makeENSv2DomainId, makeStorageId } from "enssdk"; +import { makeENSv2DomainId, makeStorageId, type NormalizedAddress } from "enssdk"; import { PluginName } from "@ensnode/ensnode-sdk"; @@ -20,7 +20,7 @@ export default function () { context: IndexingEngineContext; event: EventWithArgs<{ tokenId: bigint; - resolver: Address; + resolver: NormalizedAddress; }>; }) => { const { tokenId, resolver } = event.args; diff --git a/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ThreeDNSToken.ts b/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ThreeDNSToken.ts index 1dc82f3da..3d680f067 100644 --- a/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ThreeDNSToken.ts +++ b/apps/ensindexer/src/plugins/protocol-acceleration/handlers/ThreeDNSToken.ts @@ -7,6 +7,7 @@ import { makeENSv1DomainId, makeSubdomainNode, type Node, + type NormalizedAddress, } from "enssdk"; import { DatasourceNames, maybeGetDatasource } from "@ensnode/datasources"; @@ -50,7 +51,7 @@ export default function () { node: Node; // NOTE: `label` event arg represents a `LabelHash` for the sub-node under `node` label: LabelHash; - owner: Address; + owner: NormalizedAddress; }>; }) => { const { label: labelHash, node: parentNode } = event.args; diff --git a/apps/ensindexer/src/plugins/registrars/shared/lib/registrar-action.ts b/apps/ensindexer/src/plugins/registrars/shared/lib/registrar-action.ts index ea6b3ce70..a140e00f5 100644 --- a/apps/ensindexer/src/plugins/registrars/shared/lib/registrar-action.ts +++ b/apps/ensindexer/src/plugins/registrars/shared/lib/registrar-action.ts @@ -18,6 +18,8 @@ export type LogicalEventKey = string; /** * Make a logical event key for a "logical registrar action". + * + * @dev the .toLowerCase() is just a sanity check */ export function makeLogicalEventKey({ node, diff --git a/apps/ensindexer/src/plugins/subgraph/shared-handlers/NameWrapper.ts b/apps/ensindexer/src/plugins/subgraph/shared-handlers/NameWrapper.ts index 812d98ae7..e1510621a 100644 --- a/apps/ensindexer/src/plugins/subgraph/shared-handlers/NameWrapper.ts +++ b/apps/ensindexer/src/plugins/subgraph/shared-handlers/NameWrapper.ts @@ -26,6 +26,7 @@ import { literalLabelsToInterpretedName, literalLabelToInterpretedLabel, type Node, + type NormalizedAddress, type SubgraphInterpretedLabel, type SubgraphInterpretedName, } from "enssdk"; @@ -174,7 +175,7 @@ export const makeNameWrapperHandlers = () => { context: IndexingEngineContext; event: EventWithArgs<{ node: Node; - owner: Address; + owner: NormalizedAddress; fuses: number; expiry: bigint; name: DNSEncodedName; @@ -237,7 +238,7 @@ export const makeNameWrapperHandlers = () => { event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ node: Node; owner: Address }>; + event: EventWithArgs<{ node: Node; owner: NormalizedAddress }>; }) { const { node, owner } = event.args; @@ -334,7 +335,7 @@ export const makeNameWrapperHandlers = () => { event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ id: bigint; to: Address }>; + event: EventWithArgs<{ id: bigint; to: NormalizedAddress }>; }) { const { id: tokenId, to } = event.args; @@ -356,7 +357,7 @@ export const makeNameWrapperHandlers = () => { event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ ids: readonly bigint[]; to: Address }>; + event: EventWithArgs<{ ids: readonly bigint[]; to: NormalizedAddress }>; }) { const { ids: tokenIds, to } = event.args; diff --git a/apps/ensindexer/src/plugins/subgraph/shared-handlers/Registrar.ts b/apps/ensindexer/src/plugins/subgraph/shared-handlers/Registrar.ts index c70744c9d..98798c1e5 100644 --- a/apps/ensindexer/src/plugins/subgraph/shared-handlers/Registrar.ts +++ b/apps/ensindexer/src/plugins/subgraph/shared-handlers/Registrar.ts @@ -1,7 +1,6 @@ import config from "@/config"; import { - type Address, asInterpretedLabel, asLiteralLabel, constructSubInterpretedName, @@ -13,6 +12,7 @@ import { type LiteralLabel, literalLabelToInterpretedLabel, makeSubdomainNode, + type NormalizedAddress, type SubgraphInterpretedLabel, type SubgraphInterpretedName, } from "enssdk"; @@ -94,7 +94,7 @@ export const makeRegistrarHandlers = ({ pluginName }: { pluginName: PluginName } context: IndexingEngineContext; event: EventWithArgs<{ labelHash: LabelHash; - owner: Address; + owner: NormalizedAddress; expires: bigint; }>; }) { @@ -287,7 +287,11 @@ export const makeRegistrarHandlers = ({ pluginName }: { pluginName: PluginName } event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ labelHash: LabelHash; from: Address; to: Address }>; + event: EventWithArgs<{ + labelHash: LabelHash; + from: NormalizedAddress; + to: NormalizedAddress; + }>; }) { const { labelHash, to } = event.args; diff --git a/apps/ensindexer/src/plugins/subgraph/shared-handlers/Registry.ts b/apps/ensindexer/src/plugins/subgraph/shared-handlers/Registry.ts index ac04ed6c1..6a996a350 100644 --- a/apps/ensindexer/src/plugins/subgraph/shared-handlers/Registry.ts +++ b/apps/ensindexer/src/plugins/subgraph/shared-handlers/Registry.ts @@ -2,7 +2,6 @@ import config from "@/config"; import { ADDR_REVERSE_NODE, - type Address, asInterpretedLabel, constructSubInterpretedName, encodeLabelHash, @@ -12,6 +11,7 @@ import { literalLabelToInterpretedLabel, makeSubdomainNode, type Node, + type NormalizedAddress, type SubgraphInterpretedLabel, type SubgraphInterpretedName, } from "enssdk"; @@ -44,7 +44,7 @@ export const handleNewOwner = node: Node; // NOTE: `label` event arg represents a `LabelHash` for the sub-node under `node` label: LabelHash; - owner: Address; + owner: NormalizedAddress; }>; }) => { const { label: labelHash, node: parentNode, owner } = event.args; @@ -178,7 +178,7 @@ export async function handleTransfer({ event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ node: Node; owner: Address }>; + event: EventWithArgs<{ node: Node; owner: NormalizedAddress }>; }) { const { node, owner } = event.args; @@ -231,7 +231,7 @@ export async function handleNewResolver({ event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ node: Node; resolver: Address }>; + event: EventWithArgs<{ node: Node; resolver: NormalizedAddress }>; }) { const { node, resolver: resolverAddress } = event.args; diff --git a/apps/ensindexer/src/plugins/subgraph/shared-handlers/Resolver.ts b/apps/ensindexer/src/plugins/subgraph/shared-handlers/Resolver.ts index e1f288acb..ec1394616 100644 --- a/apps/ensindexer/src/plugins/subgraph/shared-handlers/Resolver.ts +++ b/apps/ensindexer/src/plugins/subgraph/shared-handlers/Resolver.ts @@ -1,6 +1,6 @@ import config from "@/config"; -import type { Address, Hex, Node } from "enssdk"; +import type { Hex, Node, NormalizedAddress } from "enssdk"; import type { Hash } from "viem"; import { hasNullByte, stripNullBytes, uniq } from "@ensnode/ensnode-sdk"; @@ -26,7 +26,7 @@ export async function handleAddrChanged({ event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ node: Node; a: Address }>; + event: EventWithArgs<{ node: Node; a: NormalizedAddress }>; }) { const { a: address, node } = event.args; await upsertAccount(context, address); @@ -60,7 +60,7 @@ export async function handleAddressChanged({ event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ node: Node; coinType: bigint; newAddress: Address }>; + event: EventWithArgs<{ node: Node; coinType: bigint; newAddress: NormalizedAddress }>; }) { const { node, coinType, newAddress } = event.args; @@ -265,7 +265,7 @@ export async function handleAuthorisationChanged({ context: IndexingEngineContext; event: EventWithArgs<{ node: Node; - owner: Address; + owner: NormalizedAddress; target: Hex; isAuthorised: boolean; }>; diff --git a/apps/ensindexer/src/plugins/subgraph/shared-handlers/ThreeDNSToken.ts b/apps/ensindexer/src/plugins/subgraph/shared-handlers/ThreeDNSToken.ts index fca6a120f..2b608fafe 100644 --- a/apps/ensindexer/src/plugins/subgraph/shared-handlers/ThreeDNSToken.ts +++ b/apps/ensindexer/src/plugins/subgraph/shared-handlers/ThreeDNSToken.ts @@ -15,6 +15,7 @@ import { literalLabelToInterpretedLabel, makeSubdomainNode, type Node, + type NormalizedAddress, } from "enssdk"; import { isAddressEqual, zeroAddress, zeroHash } from "viem"; @@ -110,7 +111,7 @@ export async function handleNewOwner({ node: Node; // NOTE: `label` event arg represents a `LabelHash` for the sub-node under `node` label: LabelHash; - owner: Address; + owner: NormalizedAddress; }>; }) { const { label: labelHash, node: parentNode, owner } = event.args; @@ -210,7 +211,7 @@ export async function handleTransfer({ event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ node: Node; owner: Address }>; + event: EventWithArgs<{ node: Node; owner: NormalizedAddress }>; }) { const { node, owner } = event.args; @@ -245,7 +246,7 @@ export async function handleRegistrationCreated({ // NOTE: `tld` event arg represents a `Node` that is the parent of `node` tld: Node; fqdn: DNSEncodedName; - registrant: Address; + registrant: NormalizedAddress; controlBitmap: number; expiry: bigint; }>; diff --git a/examples/enskit-react-example/src/DomainView.tsx b/examples/enskit-react-example/src/DomainView.tsx index 2e6c4ed77..68988bc80 100644 --- a/examples/enskit-react-example/src/DomainView.tsx +++ b/examples/enskit-react-example/src/DomainView.tsx @@ -1,6 +1,12 @@ -import { type FragmentOf, graphql, readFragment, useOmnigraphQuery } from "enskit/react/omnigraph"; -import { asInterpretedName } from "enssdk"; -import { Link, useParams } from "react-router"; +import { + EnsureInterpretedName, + type FragmentOf, + graphql, + readFragment, + useOmnigraphQuery, +} from "enskit/react/omnigraph"; +import { getParentInterpretedName, type InterpretedName } from "enssdk"; +import { Link, Navigate, useParams } from "react-router"; const DomainFragment = graphql(` fragment DomainFragment on Domain { @@ -39,10 +45,7 @@ function SubdomainLink({ data }: { data: FragmentOf }) { ); } -export function DomainView() { - const params = useParams(); - const name = asInterpretedName(params.name ?? "eth"); - +function RenderDomain({ name }: { name: InterpretedName }) { const [result] = useOmnigraphQuery({ query: DomainByNameQuery, variables: { name }, @@ -52,14 +55,14 @@ export function DomainView() { if (fetching) return

Loading...

; if (error) return

Error: {error.message}

; - if (!data?.domain) return

Not found

; + if (!data?.domain) return

A Domain with InterpretedName '{name}' was not found.

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

{domain.name}

+

{domain.name ?? name}

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

{parentName && ( @@ -78,3 +81,28 @@ export function DomainView() {
); } + +export function DomainView() { + const params = useParams(); + + // if a user accesses /domain directly, redirec to /domain/etc + if (params.name === undefined || params.name === "") return ; + + // here we ensure that the provided /domain/:name parameter is an InterpretedName + return ( + } + // this name can't conform to InterpretedName: it is malformed or contains unnormalizable Labels + malformed={(name) => ( +
+

{name} is malformed

+ Back to 'eth' Domain. +
+ )} + > + {(name) => } +
+ ); +} diff --git a/packages/datasources/src/invariants.test.ts b/packages/datasources/src/invariants.test.ts index 5da2fcf5b..44205fbc3 100644 --- a/packages/datasources/src/invariants.test.ts +++ b/packages/datasources/src/invariants.test.ts @@ -19,8 +19,9 @@ describe("datasource invariants", () => { `The ContractConfig '${namespace}' > '${datasourceName}' > '${contractName}' > '${contractConfig.address}' is not a viem#Address. This occurs if the address property of any ContractConfig in the Datasource is malformed (i.e. not a viem#Address).`, ).toBe(true); - // must be lowercase adddress + // must be lowercase expect( + // TODO: could use enssdk#isNormalizedAddress here contractConfig.address === contractConfig.address.toLowerCase(), `The ContractConfig '${namespace}' > '${datasourceName}' > '${contractName}' > '${contractConfig.address}' is not is lowercase format.`, ).toBe(true); diff --git a/packages/ens-referrals/src/address.ts b/packages/ens-referrals/src/address.ts index bcc9b4fc2..37276b11a 100644 --- a/packages/ens-referrals/src/address.ts +++ b/packages/ens-referrals/src/address.ts @@ -10,7 +10,3 @@ export const validateLowercaseAddress = (address: Address): void => { throw new Error(`Invalid address: ${address}. Address must be in lowercase format.`); } }; - -export const normalizeAddress = (address: Address): Address => { - return address.toLowerCase() as Address; -}; diff --git a/packages/ens-referrals/src/api/zod-schemas.ts b/packages/ens-referrals/src/api/zod-schemas.ts index d025ab1eb..d8a4d58b2 100644 --- a/packages/ens-referrals/src/api/zod-schemas.ts +++ b/packages/ens-referrals/src/api/zod-schemas.ts @@ -13,8 +13,8 @@ import { makeAccountIdSchema, makeDurationSchema, makeFiniteNonNegativeNumberSchema, - makeLowercaseAddressSchema, makeNonNegativeIntegerSchema, + makeNormalizedAddressSchema, makePositiveIntegerSchema, makeUnixTimestampSchema, } from "@ensnode/ensnode-sdk/internal"; @@ -53,7 +53,7 @@ export const makeReferralProgramRulesSchema = (valueLabel: string = "ReferralPro */ export const makeAwardedReferrerMetricsSchema = (valueLabel: string = "AwardedReferrerMetrics") => z.object({ - referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`), + referrer: makeNormalizedAddressSchema(`${valueLabel}.referrer`), totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`), totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`), totalRevenueContribution: makeRevenueContributionSchema( @@ -79,7 +79,7 @@ export const makeAwardedReferrerMetricsSchema = (valueLabel: string = "AwardedRe */ export const makeUnrankedReferrerMetricsSchema = (valueLabel: string = "UnrankedReferrerMetrics") => z.object({ - referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`), + referrer: makeNormalizedAddressSchema(`${valueLabel}.referrer`), totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`), totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`), totalRevenueContribution: makeRevenueContributionSchema( diff --git a/packages/ens-referrals/src/referrer-metrics.ts b/packages/ens-referrals/src/referrer-metrics.ts index 837dce6a3..2ff859d48 100644 --- a/packages/ens-referrals/src/referrer-metrics.ts +++ b/packages/ens-referrals/src/referrer-metrics.ts @@ -1,8 +1,9 @@ import type { Address } from "enssdk"; +import { toNormalizedAddress } from "enssdk"; import type { Duration } from "@ensnode/ensnode-sdk"; -import { normalizeAddress, validateLowercaseAddress } from "./address"; +import { validateLowercaseAddress } from "./address"; import type { AggregatedReferrerMetrics } from "./aggregations"; import type { USDQuantity } from "./currency"; import { validateNonNegativeInteger } from "./number"; @@ -63,7 +64,7 @@ export const buildReferrerMetrics = ( totalRevenueContribution: RevenueContribution, ): ReferrerMetrics => { const result = { - referrer: normalizeAddress(referrer), + referrer: toNormalizedAddress(referrer), totalReferrals, totalIncrementalDuration, totalRevenueContribution, diff --git a/packages/ens-referrals/src/v1/address.ts b/packages/ens-referrals/src/v1/address.ts index bcc9b4fc2..37276b11a 100644 --- a/packages/ens-referrals/src/v1/address.ts +++ b/packages/ens-referrals/src/v1/address.ts @@ -10,7 +10,3 @@ export const validateLowercaseAddress = (address: Address): void => { throw new Error(`Invalid address: ${address}. Address must be in lowercase format.`); } }; - -export const normalizeAddress = (address: Address): Address => { - return address.toLowerCase() as Address; -}; diff --git a/packages/ens-referrals/src/v1/api/zod-schemas.ts b/packages/ens-referrals/src/v1/api/zod-schemas.ts index 83cdb042e..8fa402dc7 100644 --- a/packages/ens-referrals/src/v1/api/zod-schemas.ts +++ b/packages/ens-referrals/src/v1/api/zod-schemas.ts @@ -9,7 +9,7 @@ import z from "zod/v4"; -import { makeLowercaseAddressSchema } from "@ensnode/ensnode-sdk/internal"; +import { makeNormalizedAddressSchema } from "@ensnode/ensnode-sdk/internal"; import { makeReferralProgramEditionSummaryPieSplitSchema, @@ -243,7 +243,7 @@ export const makeReferrerMetricsEditionsRequestSchema = ( valueLabel: string = "ReferrerMetricsEditionsRequest", ) => z.object({ - referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`), + referrer: makeNormalizedAddressSchema(`${valueLabel}.referrer`), editions: makeReferrerMetricsEditionsArraySchema(`${valueLabel}.editions`), }); diff --git a/packages/ens-referrals/src/v1/award-models/pie-split/api/zod-schemas.ts b/packages/ens-referrals/src/v1/award-models/pie-split/api/zod-schemas.ts index ab03f5376..457e5bcc1 100644 --- a/packages/ens-referrals/src/v1/award-models/pie-split/api/zod-schemas.ts +++ b/packages/ens-referrals/src/v1/award-models/pie-split/api/zod-schemas.ts @@ -3,8 +3,8 @@ import z from "zod/v4"; import { makeDurationSchema, makeFiniteNonNegativeNumberSchema, - makeLowercaseAddressSchema, makeNonNegativeIntegerSchema, + makeNormalizedAddressSchema, makePositiveIntegerSchema, makePriceEthSchema, makePriceUsdcSchema, @@ -39,7 +39,7 @@ export const makeAwardedReferrerMetricsPieSplitSchema = ( valueLabel: string = "AwardedReferrerMetricsPieSplit", ) => z.object({ - referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`), + referrer: makeNormalizedAddressSchema(`${valueLabel}.referrer`), totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`), totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`), totalRevenueContribution: makePriceEthSchema(`${valueLabel}.totalRevenueContribution`), @@ -65,7 +65,7 @@ export const makeUnrankedReferrerMetricsPieSplitSchema = ( valueLabel: string = "UnrankedReferrerMetricsPieSplit", ) => z.object({ - referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`), + referrer: makeNormalizedAddressSchema(`${valueLabel}.referrer`), totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`), totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`), totalRevenueContribution: makePriceEthSchema(`${valueLabel}.totalRevenueContribution`), diff --git a/packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts b/packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts index 0d55dfb51..febf03708 100644 --- a/packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts +++ b/packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts @@ -1,17 +1,17 @@ +import { toNormalizedAddress } from "enssdk"; import z from "zod/v4"; import { makeDurationSchema, makeFiniteNonNegativeNumberSchema, - makeLowercaseAddressSchema, makeNonNegativeIntegerSchema, + makeNormalizedAddressSchema, makePositiveIntegerSchema, makePriceEthSchema, makePriceUsdcSchema, makeUnixTimestampSchema, } from "@ensnode/ensnode-sdk/internal"; -import { normalizeAddress } from "../../../address"; import { makeBaseReferralProgramEditionSummarySchema, makeBaseReferralProgramRulesSchema, @@ -28,7 +28,7 @@ export const makeReferralProgramEditionDisqualificationSchema = ( valueLabel = "ReferralProgramEditionDisqualification", ) => z.object({ - referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`), + referrer: makeNormalizedAddressSchema(`${valueLabel}.referrer`), reason: z.string().trim().min(1, `${valueLabel}.reason must not be empty`), }); @@ -55,7 +55,7 @@ export const makeReferralProgramRulesRevShareLimitSchema = ( ) .refine( (items) => { - const addresses = items.map((item) => normalizeAddress(item.referrer)); + const addresses = items.map((item) => toNormalizedAddress(item.referrer)); return new Set(addresses).size === addresses.length; }, { @@ -73,7 +73,7 @@ export const makeAwardedReferrerMetricsRevShareLimitSchema = ( ) => z .object({ - referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`), + referrer: makeNormalizedAddressSchema(`${valueLabel}.referrer`), totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`), totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`), totalRevenueContribution: makePriceEthSchema(`${valueLabel}.totalRevenueContribution`), @@ -120,7 +120,7 @@ export const makeUnrankedReferrerMetricsRevShareLimitSchema = ( ) => z .object({ - referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`), + referrer: makeNormalizedAddressSchema(`${valueLabel}.referrer`), totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`), totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`), totalRevenueContribution: makePriceEthSchema(`${valueLabel}.totalRevenueContribution`), diff --git a/packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.ts b/packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.ts index 77152d8b9..ae6258ec9 100644 --- a/packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.ts +++ b/packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.ts @@ -1,8 +1,8 @@ import type { Address, UnixTimestamp } from "enssdk"; +import { toNormalizedAddress } from "enssdk"; import { type Duration, priceEth, priceUsdc, scalePrice } from "@ensnode/ensnode-sdk"; -import { normalizeAddress } from "../../address"; import { buildReferrerMetrics } from "../../referrer-metrics"; import { SECONDS_PER_YEAR } from "../../time"; import type { ReferralProgramAwardModels } from "../shared/rules"; @@ -101,7 +101,7 @@ export const buildReferrerLeaderboardRevShareLimit = ( let awardPoolRemaining = rules.awardPool.amount; for (const event of sortedEvents) { - const referrer = normalizeAddress(event.referrer); + const referrer = toNormalizedAddress(event.referrer); let state = referrerStates.get(referrer); if (!state) { diff --git a/packages/ens-referrals/src/v1/award-models/rev-share-limit/rules.ts b/packages/ens-referrals/src/v1/award-models/rev-share-limit/rules.ts index f914916b9..d9554f970 100644 --- a/packages/ens-referrals/src/v1/award-models/rev-share-limit/rules.ts +++ b/packages/ens-referrals/src/v1/award-models/rev-share-limit/rules.ts @@ -1,9 +1,10 @@ import type { AccountId, Address, UnixTimestamp } from "enssdk"; +import { toNormalizedAddress } from "enssdk"; import type { PriceUsdc } from "@ensnode/ensnode-sdk"; import { makePriceUsdcSchema } from "@ensnode/ensnode-sdk/internal"; -import { normalizeAddress, validateLowercaseAddress } from "../../address"; +import { validateLowercaseAddress } from "../../address"; import { type BaseReferralProgramRules, ReferralProgramAwardModels, @@ -162,7 +163,7 @@ export function isReferrerQualifiedRevShareLimit( totalBaseRevenueContribution: PriceUsdc, rules: ReferralProgramRulesRevShareLimit, ): boolean { - const normalizedReferrer = normalizeAddress(referrer); + const normalizedReferrer = toNormalizedAddress(referrer); const isAdminDisqualified = rules.disqualifications.some( (d) => d.referrer === normalizedReferrer, ); diff --git a/packages/ens-referrals/src/v1/referrer-metrics.ts b/packages/ens-referrals/src/v1/referrer-metrics.ts index e447e7b6f..ae7d4f10a 100644 --- a/packages/ens-referrals/src/v1/referrer-metrics.ts +++ b/packages/ens-referrals/src/v1/referrer-metrics.ts @@ -1,9 +1,10 @@ import type { Address } from "enssdk"; +import { toNormalizedAddress } from "enssdk"; import type { Duration, PriceEth } from "@ensnode/ensnode-sdk"; import { makePriceEthSchema } from "@ensnode/ensnode-sdk/internal"; -import { normalizeAddress, validateLowercaseAddress } from "./address"; +import { validateLowercaseAddress } from "./address"; import { validateNonNegativeInteger } from "./number"; import { ReferralProgramRules } from "./rules"; import { validateDuration } from "./time"; @@ -52,7 +53,7 @@ export const buildReferrerMetrics = ( totalRevenueContribution: PriceEth, ): ReferrerMetrics => { const result = { - referrer: normalizeAddress(referrer), + referrer: toNormalizedAddress(referrer), totalReferrals, totalIncrementalDuration, totalRevenueContribution, diff --git a/packages/enskit/src/react/omnigraph/components/ensure-interpreted-name.tsx b/packages/enskit/src/react/omnigraph/components/ensure-interpreted-name.tsx new file mode 100644 index 000000000..16081a37b --- /dev/null +++ b/packages/enskit/src/react/omnigraph/components/ensure-interpreted-name.tsx @@ -0,0 +1,34 @@ +import { type InterpretedName, isInterpretedName, type Name, nameToInterpretedName } from "enssdk"; +import type { ReactNode } from "react"; + +type MalformedNameRenderer = (name: string) => ReactNode; +type InterpretedNameRenderer = (name: InterpretedName) => ReactNode; + +/** + * Renders a Name by ensuring it is an InterpretedName. If the name is already + * interpreted, renders via `children`. If not, attempts to interpret it and + * renders via `interpreted` (enabling e.g. a redirect). If interpretation + * fails (malformed or unnormalizable), renders via `malformed`. + */ +export function EnsureInterpretedName({ + name, + children, + interpreted, + malformed, +}: { + name: Name; + children: InterpretedNameRenderer; + interpreted: InterpretedNameRenderer; + malformed: MalformedNameRenderer; +}) { + if (isInterpretedName(name)) return children(name); + + try { + // this isn't an InterpretedName, let's try to redirect the user to the InterpretedName + // which ensures that our app only ever operates on InterpretedNames + return interpreted(nameToInterpretedName(name)); + } catch { + // this name can't conform to InterpretedName: it is malformed or contains unnormalizable Labels + return malformed(name); + } +} diff --git a/packages/enskit/src/react/omnigraph/components/index.tsx b/packages/enskit/src/react/omnigraph/components/index.tsx new file mode 100644 index 000000000..6d57c3771 --- /dev/null +++ b/packages/enskit/src/react/omnigraph/components/index.tsx @@ -0,0 +1 @@ +export * from "./ensure-interpreted-name"; diff --git a/packages/enskit/src/react/omnigraph/index.ts b/packages/enskit/src/react/omnigraph/index.ts index 24f3c8750..7646f062c 100644 --- a/packages/enskit/src/react/omnigraph/index.ts +++ b/packages/enskit/src/react/omnigraph/index.ts @@ -2,5 +2,6 @@ export type { FragmentOf, ResultOf, VariablesOf } from "enssdk/omnigraph"; export { graphql, readFragment } from "enssdk/omnigraph"; +export * from "./components"; export * from "./hooks"; export * from "./provider"; diff --git a/packages/ensnode-sdk/src/omnigraph-api/example-queries.ts b/packages/ensnode-sdk/src/omnigraph-api/example-queries.ts index 27edd4a48..af85cc747 100644 --- a/packages/ensnode-sdk/src/omnigraph-api/example-queries.ts +++ b/packages/ensnode-sdk/src/omnigraph-api/example-queries.ts @@ -1,3 +1,5 @@ +import { toNormalizedAddress } from "enssdk"; + import { DatasourceNames, ENSNamespaceIds } from "@ensnode/datasources"; import { maybeGetDatasourceContract } from "../shared/datasource-contract"; @@ -28,12 +30,12 @@ const ENS_TEST_ENV_V2_ETH_REGISTRAR = maybeGetDatasourceContract( ); // these addresses are from the devnet accounts output -const DEVNET_DEPLOYER = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"; -const DEVNET_OWNER = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"; +const DEVNET_DEPLOYER = toNormalizedAddress("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"); +const DEVNET_OWNER = toNormalizedAddress("0x70997970C51812dc3A010C7d01b50e0d17dc79C8"); // biome-ignore lint/correctness/noUnusedVariables: keeping it around for the future -const DEVNET_USER = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC"; +const DEVNET_USER = toNormalizedAddress("0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC"); -const VITALIK_ADDRESS = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"; +const VITALIK_ADDRESS = toNormalizedAddress("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"); const DEVNET_NAME_WITH_OWNED_RESOLVER = "example.eth"; diff --git a/packages/ensnode-sdk/src/registrars/zod-schemas.ts b/packages/ensnode-sdk/src/registrars/zod-schemas.ts index f2b12c6eb..aa7054359 100644 --- a/packages/ensnode-sdk/src/registrars/zod-schemas.ts +++ b/packages/ensnode-sdk/src/registrars/zod-schemas.ts @@ -8,8 +8,8 @@ import { makeBlockRefSchema, makeDurationSchema, makeHexStringSchema, - makeLowercaseAddressSchema, makeNodeSchema, + makeNormalizedAddressSchema, makePriceEthSchema, makeTransactionHashSchema, makeUnixTimestampSchema, @@ -127,7 +127,7 @@ const makeRegistrarActionReferralSchema = (valueLabel: string = "Registrar Actio { bytesCount: ENCODED_REFERRER_BYTE_LENGTH }, `${valueLabel} Encoded Referrer`, ), - decodedReferrer: makeLowercaseAddressSchema(`${valueLabel} Decoded Referrer`), + decodedReferrer: makeNormalizedAddressSchema(`${valueLabel} Decoded Referrer`), }) .check(invariant_registrarActionDecodedReferrerBasedOnRawReferrer), @@ -164,7 +164,7 @@ export const makeBaseRegistrarActionSchema = (valueLabel: string = "Base Registr .object({ id: EventIdSchema, incrementalDuration: makeDurationSchema(`${valueLabel} Incremental Duration`), - registrant: makeLowercaseAddressSchema(`${valueLabel} Registrant`), + registrant: makeNormalizedAddressSchema(`${valueLabel} Registrant`), registrationLifecycle: makeRegistrationLifecycleSchema( `${valueLabel} Registration Lifecycle`, ), diff --git a/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.ts b/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.ts index c551f0954..005e2b00a 100644 --- a/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.ts +++ b/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.ts @@ -1,5 +1,5 @@ import type { InterpretedName } from "enssdk"; -import { asLowerCaseAddress, isInterpretedName } from "enssdk"; +import { isInterpretedName, toNormalizedAddress } from "enssdk"; import { isAddress, isAddressEqual, zeroAddress } from "viem"; import { hasNullByte } from "../null-bytes"; @@ -60,8 +60,8 @@ export function interpretAddressRecordValue(value: string): string | null { // interpret zeroAddress as deletion if (isAddressEqual(value, zeroAddress)) return null; - // otherwise convert to lowercase - return asLowerCaseAddress(value); + // otherwise normalize and return + return toNormalizedAddress(value); } /** diff --git a/packages/ensnode-sdk/src/shared/zod-schemas.ts b/packages/ensnode-sdk/src/shared/zod-schemas.ts index a92c67ca6..1c730ae60 100644 --- a/packages/ensnode-sdk/src/shared/zod-schemas.ts +++ b/packages/ensnode-sdk/src/shared/zod-schemas.ts @@ -10,7 +10,7 @@ import type { InterpretedName, Node, } from "enssdk"; -import { asLowerCaseAddress, reinterpretName } from "enssdk"; +import { reinterpretName, toNormalizedAddress } from "enssdk"; import { isAddress, isHex, size } from "viem"; /** * All zod schemas we define must remain internal implementation details. @@ -149,9 +149,9 @@ export const makeCoinTypeStringSchema = (valueLabel: string = "Coin Type String" .pipe(makeCoinTypeSchema(`The numeric value represented by ${valueLabel}`)); /** - * Parses a serialized representation of an EVM address into a lowercase Address. + * Parses a serialized representation of an EVM address into a {@link NormalizedAddress}. */ -export const makeLowercaseAddressSchema = (valueLabel: string = "EVM address") => +export const makeNormalizedAddressSchema = (valueLabel: string = "EVM address") => z .string() .check((ctx) => { @@ -163,7 +163,7 @@ export const makeLowercaseAddressSchema = (valueLabel: string = "EVM address") = }); } }) - .transform((val) => asLowerCaseAddress(val as Address)); + .transform((val) => toNormalizedAddress(val as Address)); /** * Parses an ISO 8601 string representations of {@link Datetime} @@ -290,7 +290,7 @@ export const makePriceDaiSchema = (valueLabel: string = "Price DAI") => export const makeAccountIdSchema = (valueLabel: string = "AccountId") => z.strictObject({ chainId: makeChainIdSchema(`${valueLabel} chain ID`), - address: makeLowercaseAddressSchema(`${valueLabel} address`), + address: makeNormalizedAddressSchema(`${valueLabel} address`), }); /** diff --git a/packages/enssdk/src/lib/address.test.ts b/packages/enssdk/src/lib/address.test.ts index 58264d42d..a8a3a9c35 100644 --- a/packages/enssdk/src/lib/address.test.ts +++ b/packages/enssdk/src/lib/address.test.ts @@ -1,16 +1,77 @@ import { describe, expect, it } from "vitest"; -import { asLowerCaseAddress } from "./address"; +import { asNormalizedAddress, isNormalizedAddress, toNormalizedAddress } from "./address"; -describe("asLowerCaseAddress", () => { - it("should convert a valid EVM address to lowercase", () => { - // arrange - const input = "0x6bD421B6e762d6AD89780EB54B9255f9ab5840BF"; +describe("isNormalizedAddress", () => { + it("should return true for a lowercase address", () => { + expect(isNormalizedAddress("0x6bd421b6e762d6ad89780eb54b9255f9ab5840bf")).toBe(true); + }); + + it("should return true for the zero address", () => { + expect(isNormalizedAddress("0x0000000000000000000000000000000000000000")).toBe(true); + }); + + it("should return false for a checksummed address", () => { + expect(isNormalizedAddress("0x6bD421B6e762d6AD89780EB54B9255f9ab5840BF")).toBe(false); + }); + + it("should return false for a short hex string", () => { + expect(isNormalizedAddress("0xdeaf")).toBe(false); + }); + + it("should return false for a non-hex string", () => { + expect(isNormalizedAddress("not-an-address")).toBe(false); + }); +}); + +describe("toNormalizedAddress", () => { + it("should convert a checksummed address to lowercase", () => { + expect(toNormalizedAddress("0x6bD421B6e762d6AD89780EB54B9255f9ab5840BF")).toBe( + "0x6bd421b6e762d6ad89780eb54b9255f9ab5840bf", + ); + }); + + it("should return an already-lowercase address unchanged", () => { + expect(toNormalizedAddress("0x6bd421b6e762d6ad89780eb54b9255f9ab5840bf")).toBe( + "0x6bd421b6e762d6ad89780eb54b9255f9ab5840bf", + ); + }); + + it("should normalize the zero address", () => { + expect(toNormalizedAddress("0x0000000000000000000000000000000000000000")).toBe( + "0x0000000000000000000000000000000000000000", + ); + }); - // act - const result = asLowerCaseAddress(input); + it("should throw for a partial address", () => { + expect(() => toNormalizedAddress("0xdeaf")).toThrow(/does not/); + }); + + it("should throw for a non-hex string", () => { + expect(() => toNormalizedAddress("not-an-address")).toThrow(/does not/); + }); +}); + +describe("asNormalizedAddress", () => { + it("should return the address if already normalized", () => { + expect(asNormalizedAddress("0x6bd421b6e762d6ad89780eb54b9255f9ab5840bf")).toBe( + "0x6bd421b6e762d6ad89780eb54b9255f9ab5840bf", + ); + }); + + it("should return the zero address", () => { + expect(asNormalizedAddress("0x0000000000000000000000000000000000000000")).toBe( + "0x0000000000000000000000000000000000000000", + ); + }); + + it("should throw for a checksummed address", () => { + expect(() => asNormalizedAddress("0x6bD421B6e762d6AD89780EB54B9255f9ab5840BF")).toThrow( + "Not a NormalizedAddress", + ); + }); - // assert - expect(result).toBe("0x6bd421b6e762d6ad89780eb54b9255f9ab5840bf"); + it("should throw for a short hex string", () => { + expect(() => asNormalizedAddress("0xdeaf")).toThrow("Not a NormalizedAddress"); }); }); diff --git a/packages/enssdk/src/lib/address.ts b/packages/enssdk/src/lib/address.ts index 2c4e2b5ce..7e0a7fc13 100644 --- a/packages/enssdk/src/lib/address.ts +++ b/packages/enssdk/src/lib/address.ts @@ -1,11 +1,35 @@ -import type { Address } from "./types"; +import { isAddress } from "viem"; + +import type { Address, NormalizedAddress } from "./types"; + +/** + * Determines whether an {@link Address} is a {@link NormalizedAddress}. + */ +export function isNormalizedAddress(address: Address): address is NormalizedAddress { + const isNormalized = address === address.toLowerCase(); + return isNormalized && isAddress(address, { strict: false }); +} + +/** + * Converts an {@link Address} to a {@link NormalizedAddress}. + * + * @throws if `address` does not represent an EVM Address + */ +export function toNormalizedAddress(address: Address): NormalizedAddress { + if (!isAddress(address, { strict: false })) { + throw new Error(`'${address}' does not represent an EVM Address.`); + } + + return address.toLowerCase() as NormalizedAddress; +} /** - * Converts an EVM address to its lowercase representation. + * Validates that an {@link Address} is already a {@link NormalizedAddress}. * - * @param address - EVM address to convert. - * @returns The lowercase representation of the EVM address. + * @throws if the address is not already normalized */ -export function asLowerCaseAddress(address: Address): Address { - return address.toLowerCase() as Address; +export function asNormalizedAddress(address: Address): NormalizedAddress { + if (isNormalizedAddress(address)) return address; + + throw new Error(`Not a NormalizedAddress: '${address}'`); } diff --git a/packages/enssdk/src/lib/interpreted-names-and-labels.ts b/packages/enssdk/src/lib/interpreted-names-and-labels.ts index 5accfd78a..200bbf040 100644 --- a/packages/enssdk/src/lib/interpreted-names-and-labels.ts +++ b/packages/enssdk/src/lib/interpreted-names-and-labels.ts @@ -1,6 +1,11 @@ import { isHex } from "viem"; -import { encodeLabelHash, labelhashInterpretedLabel, labelhashLiteralLabel } from "./labelhash"; +import { + encodeLabelHash, + isEncodedLabelHash, + labelhashInterpretedLabel, + labelhashLiteralLabel, +} from "./labelhash"; import { isNormalizedLabel } from "./normalization"; import type { InterpretedLabel, @@ -13,6 +18,27 @@ import type { Name, } from "./types"; +/** + * Interprets a Name as an InterpretedName. + * @throws if the provided `name` cannot conform to InterpretedName. + * + * @dev encodes unnormalized labels in `name` to make it InterpretedName. + * @dev this is similar to the concept of Reinterpretation (packages/enssdk/src/lib/reinterpretation.ts) + * but is distinct. + */ +export function nameToInterpretedName(name: Name): InterpretedName { + return interpretedLabelsToInterpretedName( + name + .split(".") + .map((label) => { + if (isEncodedLabelHash(label)) return label; + if (isNormalizedLabel(label)) return label; + return encodeLabelHash(labelhashLiteralLabel(asLiteralLabel(label))); + }) + .map(asInterpretedLabel), + ); +} + /** * Interprets a Literal Label, producing an Interpreted Label. * @@ -161,6 +187,12 @@ export function ensureInterpretedLabel( /** * Parses a Partial InterpretedName into concrete InterpretedLabels and the partial Label. * + * @example + * ```ts + * const result = parsePartialInterpretedName("example.et") + * // { concrete: ["example"], partial: "et" } + * ``` + * * @throws if the provided `partialInterpretedName` is not composed of concrete InterpretedLabels. */ export function parsePartialInterpretedName(partialInterpretedName: Name): { @@ -170,6 +202,7 @@ export function parsePartialInterpretedName(partialInterpretedName: Name): { if (partialInterpretedName === "") return { concrete: [], partial: "" }; const concrete = partialInterpretedName.split("."); + // note that the concrete.pop mutates `concrete` to exclude the last element // biome-ignore lint/style/noNonNullAssertion: there's always at least one element after a .split const partial = concrete.pop()!; @@ -182,38 +215,34 @@ export function parsePartialInterpretedName(partialInterpretedName: Name): { return { concrete, partial }; } +/** + * Validates and casts a string to a {@link LiteralLabel}. + * A LiteralLabel is a label as it literally appears onchain. + */ +export function asLiteralLabel(label: Label): LiteralLabel { + return label as LiteralLabel; +} + /** * Validates and casts a string to an {@link InterpretedLabel}. * An InterpretedLabel is either a normalized label or an EncodedLabelHash. * * @throws if the input is not a valid InterpretedLabel */ -export function asInterpretedLabel(label: string): InterpretedLabel { - if (!isInterpetedLabel(label as Label)) { - throw new Error(`Not a valid InterpretedLabel: '${label}'`); - } +export function asInterpretedLabel(label: Label): InterpretedLabel { + if (isInterpetedLabel(label)) return label; - return label as InterpretedLabel; + throw new Error(`Not a valid InterpretedLabel: '${label}'`); } /** * Validates and casts a string to an {@link InterpretedName}. * An InterpretedName is composed entirely of InterpretedLabels joined by dots. * - * @throws if the input is not a valid InterpretedName + * @throws if the input cannot be interpreted into an InterpretedName */ -export function asInterpretedName(name: string): InterpretedName { - if (!isInterpretedName(name as Name)) { - throw new Error(`Not a valid InterpretedName: '${name}'`); - } - - return name as InterpretedName; -} +export function asInterpretedName(name: Name): InterpretedName { + if (isInterpretedName(name)) return name; -/** - * Validates and casts a string to a {@link LiteralLabel}. - * A LiteralLabel is a label as it literally appears onchain. - */ -export function asLiteralLabel(label: string): LiteralLabel { - return label as LiteralLabel; + throw new Error(`Not a valid InterpretedName: '${name}'`); } diff --git a/packages/enssdk/src/lib/parse-reverse-name.ts b/packages/enssdk/src/lib/parse-reverse-name.ts index dc1c412b5..79ed74cc9 100644 --- a/packages/enssdk/src/lib/parse-reverse-name.ts +++ b/packages/enssdk/src/lib/parse-reverse-name.ts @@ -1,6 +1,6 @@ import { hexToBigInt, isAddress } from "viem"; -import { asLowerCaseAddress } from "./address"; +import { toNormalizedAddress } from "./address"; import { bigintToCoinType, DEFAULT_EVM_COIN_TYPE, ETH_COIN_TYPE } from "./coin-type"; import type { Address, CoinType, Label, Name } from "./types"; @@ -23,7 +23,7 @@ const parseAddressLabel = (addressLabel: Label): Address => { if (!isAddress(maybeAddress)) throw new Error(`Invalid EVM address "${maybeAddress}"`); - return asLowerCaseAddress(maybeAddress); + return toNormalizedAddress(maybeAddress); }; /** diff --git a/packages/enssdk/src/lib/types/evm.ts b/packages/enssdk/src/lib/types/evm.ts index 16d2c8805..56ba5aefe 100644 --- a/packages/enssdk/src/lib/types/evm.ts +++ b/packages/enssdk/src/lib/types/evm.ts @@ -1,9 +1,26 @@ import type { Address as ViemAddress, Hex as ViemHex } from "viem"; -// re-export viem Address/Hex for consistency +/** + * Represents an Hex string, in the format `0x{string}`. + */ export type Hex = ViemHex; + +/** + * Represents an EVM Address, in the format `0x{string}`, which may or may not be checksummed. + */ export type Address = ViemAddress; +/** + * Represents a normalized (non-checksummed) EVM Address, in the format `0x{string}`, where all + * characters are lowercase and length is exactly 42. + * + * @dev because the Address type is so widely used, nominally typing it would involve a _ton_ of + * asNormalizedAddress() casts across the codebase. By avoiding the __brand, we can easily use + * EventWithArgs<{ address: NormalizedAddress }> in all of the Ponder event handler args to + * declare that the incoming event.args.address is a NormalizedAddress. + */ +export type NormalizedAddress = Address; + /** * Chain ID * diff --git a/packages/enssdk/src/omnigraph/generated/schema.graphql b/packages/enssdk/src/omnigraph/generated/schema.graphql index 25aee8d99..b3283c854 100644 --- a/packages/enssdk/src/omnigraph/generated/schema.graphql +++ b/packages/enssdk/src/omnigraph/generated/schema.graphql @@ -128,7 +128,7 @@ type AccountResolverPermissionsConnectionEdge { node: ResolverPermissionsUser! } -"""Address represents a lowercase (unchecksummed) viem#Address.""" +"""Address represents an EVM Address in all lowercase.""" scalar Address """ @@ -192,10 +192,10 @@ type BaseRegistrarRegistration implements Registration { """BigInt represents non-fractional signed whole numeric values.""" scalar BigInt -"""ChainId represents a @ensnode/ensnode-sdk#ChainId.""" +"""ChainId represents a enssdk#ChainId.""" scalar ChainId -"""CoinType represents a @ensnode/ensnode-sdk#CoinType.""" +"""CoinType represents a enssdk#CoinType.""" scalar CoinType """ @@ -252,7 +252,7 @@ type DomainEventsConnectionEdge { node: Event! } -"""DomainId represents a @ensnode/ensnode-sdk#DomainId.""" +"""DomainId represents a enssdk#DomainId.""" scalar DomainId """Reference a specific Domain.""" @@ -585,10 +585,10 @@ input EventsWhereInput { """Hex represents viem#Hex.""" scalar Hex -"""InterpretedLabel represents a @ensnode/ensnode-sdk#InterpretedLabel.""" +"""InterpretedLabel represents a enssdk#InterpretedLabel.""" scalar InterpretedLabel -"""InterpretedName represents a @ensnode/ensnode-sdk#InterpretedName.""" +"""InterpretedName represents a enssdk#InterpretedName.""" scalar InterpretedName """ @@ -659,7 +659,7 @@ type NameWrapperRegistration implements Registration { unregistrant: Account } -"""Node represents a @ensnode/ensnode-sdk#Node.""" +"""Node represents a enssdk#Node.""" scalar Node """Sort direction""" @@ -704,7 +704,7 @@ type PermissionsEventsConnectionEdge { node: Event! } -"""PermissionsId represents a @ensnode/ensnode-sdk#PermissionsId.""" +"""PermissionsId represents a enssdk#PermissionsId.""" scalar PermissionsId """Address Permissions by ID or AccountId.""" @@ -731,9 +731,7 @@ type PermissionsResource { users(after: String, before: String, first: Int, last: Int): PermissionsResourceUsersConnection } -""" -PermissionsResourceId represents a @ensnode/ensnode-sdk#PermissionsResourceId. -""" +"""PermissionsResourceId represents a enssdk#PermissionsResourceId.""" scalar PermissionsResourceId type PermissionsResourceUsersConnection { @@ -776,7 +774,7 @@ type PermissionsUser { user: Account! } -"""PermissionsUserId represents a @ensnode/ensnode-sdk#PermissionsUserId.""" +"""PermissionsUserId represents a enssdk#PermissionsUserId.""" scalar PermissionsUserId type Query { @@ -911,7 +909,7 @@ interface Registration { unregistrant: Account } -"""RegistrationId represents a @ensnode/ensnode-sdk#RegistrationId.""" +"""RegistrationId represents a enssdk#RegistrationId.""" scalar RegistrationId type RegistrationRenewalsConnection { @@ -962,7 +960,7 @@ input RegistryDomainsWhereInput { name: String } -"""RegistryId represents a @ensnode/ensnode-sdk#RegistryId.""" +"""RegistryId represents a enssdk#RegistryId.""" scalar RegistryId """Address a Registry by ID or AccountId.""" @@ -1020,7 +1018,7 @@ type Renewal { referrer: Hex } -"""RenewalId represents a @ensnode/ensnode-sdk#RenewalId.""" +"""RenewalId represents a enssdk#RenewalId.""" scalar RenewalId """A Resolver represents a Resolver contract on-chain.""" @@ -1058,7 +1056,7 @@ type ResolverEventsConnectionEdge { node: Event! } -"""ResolverId represents a @ensnode/ensnode-sdk#ResolverId.""" +"""ResolverId represents a enssdk#ResolverId.""" scalar ResolverId """Address a Resolver by ID or AccountId.""" @@ -1113,7 +1111,7 @@ type ResolverRecordsConnectionEdge { node: ResolverRecords! } -"""ResolverRecordsId represents a @ensnode/ensnode-sdk#ResolverRecordsId.""" +"""ResolverRecordsId represents a enssdk#ResolverRecordsId.""" scalar ResolverRecordsId """Filter for Domain.subdomains query.""" diff --git a/packages/enssdk/src/omnigraph/graphql.ts b/packages/enssdk/src/omnigraph/graphql.ts index a67c4102f..4e6f6c304 100644 --- a/packages/enssdk/src/omnigraph/graphql.ts +++ b/packages/enssdk/src/omnigraph/graphql.ts @@ -1,13 +1,14 @@ import { initGraphQLTada } from "gql.tada"; -import type { Address, Hex } from "viem"; import type { ChainId, CoinType, DomainId, + Hex, InterpretedLabel, InterpretedName, Node, + NormalizedAddress, PermissionsId, PermissionsResourceId, PermissionsUserId, @@ -28,7 +29,7 @@ export const graphql = initGraphQLTada<{ BigInt: `${bigint}`; // NOTE: keep these semantic scalar types in sync with the scalars in apps/ensapi/src/omnigraph-api/builder.ts // (i.e. excluding the BigInt scalar, which we handle above) - Address: Address; + Address: NormalizedAddress; Hex: Hex; ChainId: ChainId; CoinType: CoinType; From b49bcdf0bcd19f71c088f9337b8af428f8e0d4d2 Mon Sep 17 00:00:00 2001 From: shrugs Date: Thu, 9 Apr 2026 16:59:49 -0500 Subject: [PATCH 06/60] refactor validateAddress --- .../ensapi/src/lib/resolution/forward-resolution.ts | 13 +++++++------ apps/ensindexer/src/config/validations.ts | 12 +++--------- examples/enskit-react-example/src/DomainView.tsx | 3 ++- packages/ens-referrals/src/address.ts | 12 ++++-------- packages/ens-referrals/src/referrer-metrics.ts | 4 ++-- packages/ens-referrals/src/v1/address.ts | 12 ++++-------- .../src/v1/award-models/rev-share-limit/rules.ts | 4 ++-- packages/ens-referrals/src/v1/referrer-metrics.ts | 4 ++-- .../enssdk/src/lib/interpreted-names-and-labels.ts | 3 ++- 9 files changed, 28 insertions(+), 39 deletions(-) diff --git a/apps/ensapi/src/lib/resolution/forward-resolution.ts b/apps/ensapi/src/lib/resolution/forward-resolution.ts index c5fe018d6..259c47dd3 100644 --- a/apps/ensapi/src/lib/resolution/forward-resolution.ts +++ b/apps/ensapi/src/lib/resolution/forward-resolution.ts @@ -5,6 +5,7 @@ import { replaceBigInts } from "@ponder/utils"; import { type AccountId, asInterpretedName, + type InterpretedName, type Node, namehashInterpretedName, parseReverseName, @@ -89,9 +90,12 @@ export async function resolveForward selection: ForwardResolutionArgs["selection"], options: Omit[2], "registry">, ): Promise> { + // Invariant: Name must be an InterpretedName + const interpretedName = asInterpretedName(name); + // NOTE: `resolveForward` is just `_resolveForward` with the enforcement that `registry` must - // initially be ENS Root Chain's Registry: see `_resolveForward` for additional context. - return _resolveForward(name, selection, { + // initially be ENS Root Registry: see `_resolveForward` for additional context. + return _resolveForward(interpretedName, selection, { ...options, registry: getENSv1Registry(config.namespace), }); @@ -102,13 +106,10 @@ export async function resolveForward * `registry`. */ async function _resolveForward( - _name: ForwardResolutionArgs["name"], + name: InterpretedName, selection: ForwardResolutionArgs["selection"], options: { registry: AccountId; accelerate: boolean; canAccelerate: boolean }, ): Promise> { - // Invariant: Name must be an InterpretedName - const name = asInterpretedName(_name); - const { registry: { chainId }, accelerate = false, diff --git a/apps/ensindexer/src/config/validations.ts b/apps/ensindexer/src/config/validations.ts index ac18dd5d4..c85782fcb 100644 --- a/apps/ensindexer/src/config/validations.ts +++ b/apps/ensindexer/src/config/validations.ts @@ -1,6 +1,4 @@ -import type { Address } from "enssdk"; import { isNormalizedAddress } from "enssdk"; -import { isAddress } from "viem"; import { type DatasourceName, type ENSNamespace, getENSNamespace } from "@ensnode/datasources"; import { PluginName } from "@ensnode/ensnode-sdk"; @@ -125,15 +123,11 @@ export function invariant_validContractConfigs( // Invariant: `contracts` must provide valid addresses if a filter is not provided for (const [contractName, contractConfig] of Object.entries(datasource.contracts)) { + // only ContractConfigs with `address` defined if ("address" in contractConfig && typeof contractConfig.address === "string") { - // only ContractConfigs with `address` defined - const isValidAddress = - isAddress(contractConfig.address as Address, { strict: false }) && // must be a valid `Address` - isNormalizedAddress(contractConfig.address as Address); // and in lowercase format - - if (!isValidAddress) { + if (!isNormalizedAddress(contractConfig.address)) { throw new Error( - `The '${config.namespace}' namespace's '${datasourceName}' Datasource does not define a valid address for ${contractName}: '${contractConfig.address}'. This occurs if the address property of any ContractConfig in the Datasource is malformed (i.e. not a lowercase viem#Address). This is only likely to occur if you are actively editing the Datasource and typo'd an address.`, + `The '${config.namespace}' namespace's '${datasourceName}' Datasource does not define a valid address for ${contractName}: '${contractConfig.address}'. This occurs if the address property of any ContractConfig in the Datasource is malformed (i.e. not a enssdk#NormalizedAddress). This is only likely to occur if you are actively editing the Datasource and typo'd an address.`, ); } } diff --git a/examples/enskit-react-example/src/DomainView.tsx b/examples/enskit-react-example/src/DomainView.tsx index 68988bc80..79df47e07 100644 --- a/examples/enskit-react-example/src/DomainView.tsx +++ b/examples/enskit-react-example/src/DomainView.tsx @@ -85,7 +85,8 @@ function RenderDomain({ name }: { name: InterpretedName }) { export function DomainView() { const params = useParams(); - // if a user accesses /domain directly, redirec to /domain/etc + // if a user accesses '/domain' directly, redirect to '/domain/eth' + // TODO: render the set of tlds if (params.name === undefined || params.name === "") return ; // here we ensure that the provided /domain/:name parameter is an InterpretedName diff --git a/packages/ens-referrals/src/address.ts b/packages/ens-referrals/src/address.ts index 37276b11a..22e865c95 100644 --- a/packages/ens-referrals/src/address.ts +++ b/packages/ens-referrals/src/address.ts @@ -1,12 +1,8 @@ import type { Address } from "enssdk"; -import { isAddress } from "viem"; +import { isNormalizedAddress } from "enssdk"; -export const validateLowercaseAddress = (address: Address): void => { - if (!isAddress(address, { strict: false })) { - throw new Error(`Invalid address: ${address}. Address must be a valid EVM address.`); - } - - if (address !== address.toLowerCase()) { - throw new Error(`Invalid address: ${address}. Address must be in lowercase format.`); +export const validateAddress = (address: Address): void => { + if (!isNormalizedAddress(address)) { + throw new Error(`Invalid address: '${address}'. Address must be a lowercase EVM Address.`); } }; diff --git a/packages/ens-referrals/src/referrer-metrics.ts b/packages/ens-referrals/src/referrer-metrics.ts index 2ff859d48..e770b8b1d 100644 --- a/packages/ens-referrals/src/referrer-metrics.ts +++ b/packages/ens-referrals/src/referrer-metrics.ts @@ -3,7 +3,7 @@ import { toNormalizedAddress } from "enssdk"; import type { Duration } from "@ensnode/ensnode-sdk"; -import { validateLowercaseAddress } from "./address"; +import { validateAddress } from "./address"; import type { AggregatedReferrerMetrics } from "./aggregations"; import type { USDQuantity } from "./currency"; import { validateNonNegativeInteger } from "./number"; @@ -75,7 +75,7 @@ export const buildReferrerMetrics = ( }; export const validateReferrerMetrics = (metrics: ReferrerMetrics): void => { - validateLowercaseAddress(metrics.referrer); + validateAddress(metrics.referrer); validateNonNegativeInteger(metrics.totalReferrals); validateDuration(metrics.totalIncrementalDuration); validateRevenueContribution(metrics.totalRevenueContribution); diff --git a/packages/ens-referrals/src/v1/address.ts b/packages/ens-referrals/src/v1/address.ts index 37276b11a..3c182284d 100644 --- a/packages/ens-referrals/src/v1/address.ts +++ b/packages/ens-referrals/src/v1/address.ts @@ -1,12 +1,8 @@ import type { Address } from "enssdk"; -import { isAddress } from "viem"; +import { isNormalizedAddress } from "enssdk"; -export const validateLowercaseAddress = (address: Address): void => { - if (!isAddress(address, { strict: false })) { - throw new Error(`Invalid address: ${address}. Address must be a valid EVM address.`); - } - - if (address !== address.toLowerCase()) { - throw new Error(`Invalid address: ${address}. Address must be in lowercase format.`); +export const validateAddress = (address: Address): void => { + if (!isNormalizedAddress(address)) { + throw new Error(`Invalid address: '${address}'. Address must be a NormalizedAddress.`); } }; diff --git a/packages/ens-referrals/src/v1/award-models/rev-share-limit/rules.ts b/packages/ens-referrals/src/v1/award-models/rev-share-limit/rules.ts index d9554f970..56e90d189 100644 --- a/packages/ens-referrals/src/v1/award-models/rev-share-limit/rules.ts +++ b/packages/ens-referrals/src/v1/award-models/rev-share-limit/rules.ts @@ -4,7 +4,7 @@ import { toNormalizedAddress } from "enssdk"; import type { PriceUsdc } from "@ensnode/ensnode-sdk"; import { makePriceUsdcSchema } from "@ensnode/ensnode-sdk/internal"; -import { validateLowercaseAddress } from "../../address"; +import { validateAddress } from "../../address"; import { type BaseReferralProgramRules, ReferralProgramAwardModels, @@ -99,7 +99,7 @@ export const validateReferralProgramRulesRevShareLimit = ( } for (const d of rules.disqualifications) { - validateLowercaseAddress(d.referrer); + validateAddress(d.referrer); if (d.reason.trim().length === 0) { throw new Error( "ReferralProgramRulesRevShareLimit: disqualification reason must not be empty.", diff --git a/packages/ens-referrals/src/v1/referrer-metrics.ts b/packages/ens-referrals/src/v1/referrer-metrics.ts index ae7d4f10a..e03ed8245 100644 --- a/packages/ens-referrals/src/v1/referrer-metrics.ts +++ b/packages/ens-referrals/src/v1/referrer-metrics.ts @@ -4,7 +4,7 @@ import { toNormalizedAddress } from "enssdk"; import type { Duration, PriceEth } from "@ensnode/ensnode-sdk"; import { makePriceEthSchema } from "@ensnode/ensnode-sdk/internal"; -import { validateLowercaseAddress } from "./address"; +import { validateAddress } from "./address"; import { validateNonNegativeInteger } from "./number"; import { ReferralProgramRules } from "./rules"; import { validateDuration } from "./time"; @@ -64,7 +64,7 @@ export const buildReferrerMetrics = ( }; export const validateReferrerMetrics = (metrics: ReferrerMetrics): void => { - validateLowercaseAddress(metrics.referrer); + validateAddress(metrics.referrer); validateNonNegativeInteger(metrics.totalReferrals); validateDuration(metrics.totalIncrementalDuration); diff --git a/packages/enssdk/src/lib/interpreted-names-and-labels.ts b/packages/enssdk/src/lib/interpreted-names-and-labels.ts index 200bbf040..d0f3dbea2 100644 --- a/packages/enssdk/src/lib/interpreted-names-and-labels.ts +++ b/packages/enssdk/src/lib/interpreted-names-and-labels.ts @@ -24,7 +24,8 @@ import type { * * @dev encodes unnormalized labels in `name` to make it InterpretedName. * @dev this is similar to the concept of Reinterpretation (packages/enssdk/src/lib/reinterpretation.ts) - * but is distinct. + * but is distinct in that we're interpreting a Name (i.e. from user input) rather than a previously + * interpreted InterpretedName. */ export function nameToInterpretedName(name: Name): InterpretedName { return interpretedLabelsToInterpretedName( From 5d4e6c97ff46a5f6b3c2863fd685738f0314beaa Mon Sep 17 00:00:00 2001 From: shrugs Date: Thu, 9 Apr 2026 17:17:52 -0500 Subject: [PATCH 07/60] fix: documentation for InterpretedNames in schema --- .../protocol-acceleration.schema.ts | 29 +++++++++---------- packages/enssdk/src/lib/address.test.ts | 5 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/ensdb-sdk/src/ensindexer-abstract/protocol-acceleration.schema.ts b/packages/ensdb-sdk/src/ensindexer-abstract/protocol-acceleration.schema.ts index 223081391..a1b335f1b 100644 --- a/packages/ensdb-sdk/src/ensindexer-abstract/protocol-acceleration.schema.ts +++ b/packages/ensdb-sdk/src/ensindexer-abstract/protocol-acceleration.schema.ts @@ -2,7 +2,15 @@ * Schema Definitions that power Protocol Acceleration in the Resolution API. */ -import type { Address, ChainId, DomainId, Node, ResolverId, ResolverRecordsId } from "enssdk"; +import type { + Address, + ChainId, + DomainId, + InterpretedName, + Node, + ResolverId, + ResolverRecordsId, +} from "enssdk"; import { onchainTable, primaryKey, relations, uniqueIndex } from "ponder"; /** @@ -28,13 +36,9 @@ export const reverseNameRecord = onchainTable( /** * Represents the ENSIP-19 Reverse Name Record for a given (address, coinType). * - * The value of this field is guaranteed to be a non-empty-string normalized ENS name (see - * `interpretNameRecordValue` for additional context and specific guarantees). Unnormalized - * names and empty string values are interpreted as a deletion of the associated Reverse Name - * Record entity (represented in the schema as the _absence_ of a relevant Reverse Name Record - * entity). + * The value of this field is guaranteed to be a non-empty {@link InterpretedName}. */ - value: t.text().notNull(), + value: t.text().notNull().$type(), }), (t) => ({ pk: primaryKey({ columns: [t.address, t.coinType] }), @@ -124,14 +128,9 @@ export const resolverRecords = onchainTable( /** * Represents the value of the reverse-resolution (ENSIP-3) name() record, used for Reverse Resolution. * - * The emitted record values are interpreted according to `interpretNameRecordValue` — unnormalized - * names and empty string values are interpreted as a deletion of the associated record (represented - * here as `null`). - * - * If set, the value of this field is guaranteed to be a non-empty-string normalized ENS name - * (see `interpretNameRecordValue` for additional context and specific guarantees). + * If present, the value of this field is guaranteed to be a non-empty {@link InterpretedName}. */ - name: t.text(), + name: t.text().$type(), }), (t) => ({ byId: uniqueIndex().on(t.chainId, t.address, t.node), @@ -257,5 +256,5 @@ export const resolverTextRecordRelations = relations(resolverTextRecord, ({ one * Registry migration logic. */ export const migratedNode = onchainTable("migrated_nodes", (t) => ({ - node: t.hex().primaryKey(), + node: t.hex().primaryKey().$type(), })); diff --git a/packages/enssdk/src/lib/address.test.ts b/packages/enssdk/src/lib/address.test.ts index a8a3a9c35..c0d0ce2e5 100644 --- a/packages/enssdk/src/lib/address.test.ts +++ b/packages/enssdk/src/lib/address.test.ts @@ -1,6 +1,7 @@ import { describe, expect, it } from "vitest"; import { asNormalizedAddress, isNormalizedAddress, toNormalizedAddress } from "./address"; +import type { Address } from "./types"; describe("isNormalizedAddress", () => { it("should return true for a lowercase address", () => { @@ -20,7 +21,7 @@ describe("isNormalizedAddress", () => { }); it("should return false for a non-hex string", () => { - expect(isNormalizedAddress("not-an-address")).toBe(false); + expect(isNormalizedAddress("not-an-address" as Address)).toBe(false); }); }); @@ -48,7 +49,7 @@ describe("toNormalizedAddress", () => { }); it("should throw for a non-hex string", () => { - expect(() => toNormalizedAddress("not-an-address")).toThrow(/does not/); + expect(() => toNormalizedAddress("not-an-address" as Address)).toThrow(/does not/); }); }); From 6fb27e319f70c0aefa12139d934378511bbe1d25 Mon Sep 17 00:00:00 2001 From: shrugs Date: Thu, 9 Apr 2026 17:22:06 -0500 Subject: [PATCH 08/60] refactor: clean up expects in ensrainbow tests --- .../src/commands/convert-csv-command.test.ts | 136 ++++++------------ 1 file changed, 41 insertions(+), 95 deletions(-) diff --git a/apps/ensrainbow/src/commands/convert-csv-command.test.ts b/apps/ensrainbow/src/commands/convert-csv-command.test.ts index 1ac1f42bb..6a781dcec 100644 --- a/apps/ensrainbow/src/commands/convert-csv-command.test.ts +++ b/apps/ensrainbow/src/commands/convert-csv-command.test.ts @@ -12,6 +12,11 @@ import { ENSRainbowDB } from "@/lib/database"; import { convertCsvCommand } from "./convert-csv-command"; +/** Shorthand: compute the labelhash bytes for a given label string. */ +function hashLabel(label: string) { + return labelHashToBytes(labelhashLiteralLabel(asLiteralLabel(label))); +} + // Path to test fixtures const TEST_FIXTURES_DIR = join(__dirname, "..", "..", "test", "fixtures"); @@ -53,21 +58,12 @@ describe("convert-csv-command", () => { await cli.parse(["ingest-ensrainbow", "--input-file", outputFile, "--data-dir", dataDir]); const db = await ENSRainbowDB.open(dataDir); - expect(await db.validate()).toBe(true); - const recordsCount = await db.getPrecalculatedRainbowRecordCount(); - expect(recordsCount).toBe(11); - expect( - ( - await db.getVersionedRainbowRecord( - labelHashToBytes(labelhashLiteralLabel(asLiteralLabel("123"))), - ) - )?.label, - ).toBe("123"); - expect( - await db.getVersionedRainbowRecord( - labelHashToBytes(labelhashLiteralLabel(asLiteralLabel("1234"))), - ), - ).toBe(null); + await expect(db.validate()).resolves.toBe(true); + await expect(db.getPrecalculatedRainbowRecordCount()).resolves.toBe(11); + await expect(db.getVersionedRainbowRecord(hashLabel("123"))).resolves.toMatchObject({ + label: "123", + }); + await expect(db.getVersionedRainbowRecord(hashLabel("1234"))).resolves.toBe(null); await db.close(); }); @@ -94,9 +90,8 @@ describe("convert-csv-command", () => { await cli.parse(["ingest-ensrainbow", "--input-file", outputFile, "--data-dir", dataDir]); const db = await ENSRainbowDB.open(dataDir); - expect(await db.validate()).toBe(true); - const recordsCount = await db.getPrecalculatedRainbowRecordCount(); - expect(recordsCount).toBe(10); + await expect(db.validate()).resolves.toBe(true); + await expect(db.getPrecalculatedRainbowRecordCount()).resolves.toBe(10); const labels = [ "🔥emoji-label🚀", 'special"quotes"inside', @@ -104,16 +99,11 @@ describe("convert-csv-command", () => { "label-with-null\0byte", // null byte ].map(asLiteralLabel); for (const label of labels) { - expect( - (await db.getVersionedRainbowRecord(labelHashToBytes(labelhashLiteralLabel(label)))) - ?.label, - ).toBe(label); + await expect(db.getVersionedRainbowRecord(hashLabel(label))).resolves.toMatchObject({ + label, + }); } - expect( - await db.getVersionedRainbowRecord( - labelHashToBytes(labelhashLiteralLabel(asLiteralLabel("1234"))), - ), - ).toBe(null); + await expect(db.getVersionedRainbowRecord(hashLabel("1234"))).resolves.toBe(null); await db.close(); }); }); @@ -193,9 +183,8 @@ describe("convert-csv-command", () => { // Verify initial database const db = await ENSRainbowDB.open(dataDir); - expect(await db.validate()).toBe(true); - const initialCount = await db.getPrecalculatedRainbowRecordCount(); - expect(initialCount).toBe(11); + await expect(db.validate()).resolves.toBe(true); + await expect(db.getPrecalculatedRainbowRecordCount()).resolves.toBe(11); await db.close(); // Now convert the same CSV file again, but with filtering enabled @@ -251,41 +240,14 @@ describe("convert-csv-command", () => { await cli.parse(["ingest-ensrainbow", "--input-file", outputFile, "--data-dir", dataDir]); const db = await ENSRainbowDB.open(dataDir); - expect(await db.validate()).toBe(true); - - // Should have 4 unique labels (label1, label2, label3, label4) - const recordsCount = await db.getPrecalculatedRainbowRecordCount(); - expect(recordsCount).toBe(4); - - // Verify specific labels exist - expect( - ( - await db.getVersionedRainbowRecord( - labelHashToBytes(labelhashLiteralLabel(asLiteralLabel("label1"))), - ) - )?.label, - ).toBe("label1"); - expect( - ( - await db.getVersionedRainbowRecord( - labelHashToBytes(labelhashLiteralLabel(asLiteralLabel("label2"))), - ) - )?.label, - ).toBe("label2"); - expect( - ( - await db.getVersionedRainbowRecord( - labelHashToBytes(labelhashLiteralLabel(asLiteralLabel("label3"))), - ) - )?.label, - ).toBe("label3"); - expect( - ( - await db.getVersionedRainbowRecord( - labelHashToBytes(labelhashLiteralLabel(asLiteralLabel("label4"))), - ) - )?.label, - ).toBe("label4"); + await expect(db.validate()).resolves.toBe(true); + await expect(db.getPrecalculatedRainbowRecordCount()).resolves.toBe(4); + + for (const label of ["label1", "label2", "label3", "label4"]) { + await expect(db.getVersionedRainbowRecord(hashLabel(label))).resolves.toMatchObject({ + label, + }); + } await db.close(); }); @@ -332,9 +294,8 @@ describe("convert-csv-command", () => { // Verify initial database was created const db = await ENSRainbowDB.open(dataDir); - expect(await db.validate()).toBe(true); - const labelSet = await db.getLabelSet(); - expect(labelSet.labelSetId).toBe("test-label-set-a"); + await expect(db.validate()).resolves.toBe(true); + await expect(db.getLabelSet()).resolves.toMatchObject({ labelSetId: "test-label-set-a" }); await db.close(); // Now try to convert with a different label set ID and the existing database path @@ -501,9 +462,8 @@ describe("convert-csv-command", () => { await cli.parse(["ingest-ensrainbow", "--input-file", outputFile, "--data-dir", dataDir]); const db = await ENSRainbowDB.open(dataDir); - expect(await db.validate()).toBe(true); - const recordsCount = await db.getPrecalculatedRainbowRecordCount(); - expect(recordsCount).toBe(0); + await expect(db.validate()).resolves.toBe(true); + await expect(db.getPrecalculatedRainbowRecordCount()).resolves.toBe(0); await db.close(); }); @@ -550,10 +510,9 @@ describe("convert-csv-command", () => { await cli.parse(["ingest-ensrainbow", "--input-file", outputFile, "--data-dir", dataDir]); const db = await ENSRainbowDB.open(dataDir); - expect(await db.validate()).toBe(true); - const recordsCount = await db.getPrecalculatedRainbowRecordCount(); + await expect(db.validate()).resolves.toBe(true); // Should have 3 records: "label", "label1", "label2" - expect(recordsCount).toBe(3); + await expect(db.getPrecalculatedRainbowRecordCount()).resolves.toBe(3); await db.close(); }); @@ -603,27 +562,14 @@ describe("convert-csv-command", () => { await cli.parse(["ingest-ensrainbow", "--input-file", outputFile, "--data-dir", dataDir]); const db = await ENSRainbowDB.open(dataDir); - expect(await db.validate()).toBe(true); - const recordsCount = await db.getPrecalculatedRainbowRecordCount(); - expect(recordsCount).toBe(2); - - // Verify the labels were stored correctly - const label1 = "label,with,commas"; - const label2 = "another,label"; - expect( - ( - await db.getVersionedRainbowRecord( - labelHashToBytes(labelhashLiteralLabel(asLiteralLabel(label1))), - ) - )?.label, - ).toBe(label1); - expect( - ( - await db.getVersionedRainbowRecord( - labelHashToBytes(labelhashLiteralLabel(asLiteralLabel(label2))), - ) - )?.label, - ).toBe(label2); + await expect(db.validate()).resolves.toBe(true); + await expect(db.getPrecalculatedRainbowRecordCount()).resolves.toBe(2); + + for (const label of ["label,with,commas", "another,label"]) { + await expect(db.getVersionedRainbowRecord(hashLabel(label))).resolves.toMatchObject({ + label, + }); + } await db.close(); }); From ec5cac16e7a7edf429f04509fc8cd3207a2ee455 Mon Sep 17 00:00:00 2001 From: shrugs Date: Fri, 10 Apr 2026 16:15:41 -0500 Subject: [PATCH 09/60] fix: use lazy for UR1 as well --- ...ith-universal-resolver.integration.test.ts | 72 +++++++++++++++++++ .../resolve-with-universal-resolver.ts | 8 +-- 2 files changed, 75 insertions(+), 5 deletions(-) create mode 100644 apps/ensapi/src/lib/resolution/resolve-with-universal-resolver.integration.test.ts diff --git a/apps/ensapi/src/lib/resolution/resolve-with-universal-resolver.integration.test.ts b/apps/ensapi/src/lib/resolution/resolve-with-universal-resolver.integration.test.ts new file mode 100644 index 000000000..d8c59d69d --- /dev/null +++ b/apps/ensapi/src/lib/resolution/resolve-with-universal-resolver.integration.test.ts @@ -0,0 +1,72 @@ +import { vi } from "vitest"; + +// we're testing a function specifically, not fetching through the running ensapi instance, so +// we need to mock the config when this worker process attempts to import ./resolve-with-universal-resolver +vi.mock("@/config", () => ({ + default: { + namespace: "ens-test-env", + rpcConfigs: new Map([[ensTestEnvChain.id, { httpRPCs: [new URL("http://localhost:8545")] }]]), + }, +})); + +import { + asInterpretedLabel, + asInterpretedName, + asLiteralLabel, + encodeLabelHash, + interpretedLabelsToInterpretedName, + labelhashLiteralLabel, + namehashInterpretedName, +} from "enssdk"; +import { describe, expect, it } from "vitest"; + +import { ensTestEnvChain } from "@ensnode/datasources"; + +import { getPublicClient } from "@/lib/public-client"; +import { makeResolveCalls } from "@/lib/resolution/resolve-calls-and-results"; + +import { executeResolveCallsWithUniversalResolver } from "./resolve-with-universal-resolver"; + +const NAME = asInterpretedName("example.eth"); +const NAME_WITH_ENCODED_LABELHASHES = interpretedLabelsToInterpretedName([ + asInterpretedLabel(encodeLabelHash(labelhashLiteralLabel(asLiteralLabel("example")))), + asInterpretedLabel("eth"), +]); + +const EXPECTED_DESCRIPTION = "example.eth"; + +const CALLS = makeResolveCalls(namehashInterpretedName(NAME), { texts: ["description"] }); +const publicClient = getPublicClient(ensTestEnvChain.id); + +describe("executeResolveCallsWithUniversalResolver", () => { + it("should resolve interpreted name without encoded labelhashes", async () => { + await expect( + executeResolveCallsWithUniversalResolver({ + name: NAME, + calls: CALLS, + publicClient, + }), + ).resolves.toMatchObject([{ result: EXPECTED_DESCRIPTION }]); + }); + + /** + * NOTE(shrugs): This was contrary to my expectations, but the NameCoder (in both ENSv1 and ENSv2) + * is NOT EncodedLabelHash-aware: all label segments are hashed indiscriminately as LiteralLabels + * to traverse the nametree, meaning that InterpretedNames (which may include EncodedLabelHash + * segments for labels that are unknown, too long, or unnormalized) are explicitly unresolvable! + * + * Or, more technically, they resolve to an incorrect name, one addressed by, for example: + * [root, labelhash("eth"), labelhash("[6fd43e7cffc31bb581d7421c8698e29aa2bd8e7186a394b85299908b4eb9b175]")] + * + * Which likely doesn't have the appropriate records set. + */ + it("should NOT resolve interpreted name with encoded labelhashes", async () => { + await expect( + executeResolveCallsWithUniversalResolver({ + name: NAME_WITH_ENCODED_LABELHASHES, + calls: CALLS, + publicClient, + }), + ).resolves.toMatchObject([{ result: null }]); + }); +}); diff --git a/apps/ensapi/src/lib/resolution/resolve-with-universal-resolver.ts b/apps/ensapi/src/lib/resolution/resolve-with-universal-resolver.ts index 19a9acd98..0965ce984 100644 --- a/apps/ensapi/src/lib/resolution/resolve-with-universal-resolver.ts +++ b/apps/ensapi/src/lib/resolution/resolve-with-universal-resolver.ts @@ -19,15 +19,13 @@ import { type ResolverRecordsSelection, } from "@ensnode/ensnode-sdk"; -import { lazy, lazyProxy } from "@/lib/lazy"; +import { lazy } from "@/lib/lazy"; import type { ResolveCalls, ResolveCallsAndRawResults, } from "@/lib/resolution/resolve-calls-and-results"; -// lazyProxy defers construction until first use so that this module can be -// imported without env vars being present (e.g. during OpenAPI generation). -const universalResolver = lazyProxy(() => +const getUniversalResolverV1 = lazy(() => getDatasourceContract(config.namespace, DatasourceNames.ENSRoot, "UniversalResolver"), ); @@ -60,7 +58,7 @@ export async function executeResolveCallsWithUniversalResolver< abi: UniversalResolverABI, // NOTE(ensv2-transition): if UniversalResolverV2 is defined, prefer it over UniversalResolver // TODO(ensv2-transition): confirm this is correct - address: getUniversalResolverV2()?.address ?? universalResolver.address, + address: getUniversalResolverV2()?.address ?? getUniversalResolverV1().address, functionName: "resolve", args: [encodedName, encodedMethod], }); From ad94a8cc8c711193f71bb7f407e99d6850d804e3 Mon Sep 17 00:00:00 2001 From: shrugs Date: Fri, 10 Apr 2026 16:26:14 -0500 Subject: [PATCH 10/60] fix: use ENS_ROOT_NODE in comments --- apps/ensapi/src/omnigraph-api/lib/get-canonical-path.ts | 2 +- .../plugins/subgraph/plugins/subgraph/handlers/Registry.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/ensapi/src/omnigraph-api/lib/get-canonical-path.ts b/apps/ensapi/src/omnigraph-api/lib/get-canonical-path.ts index 5249a007b..1fc25c60f 100644 --- a/apps/ensapi/src/omnigraph-api/lib/get-canonical-path.ts +++ b/apps/ensapi/src/omnigraph-api/lib/get-canonical-path.ts @@ -61,7 +61,7 @@ export async function getV1CanonicalPath(domainId: ENSv1DomainId): Promise { - // NOTE: this logic derived from the subgraph introduces a bug for queries with a blockheight + // NOTE: this logic derived from the subgraph introduces a minor bug for queries with a blockheight // below 9380380, when the new Registry was deployed, as it implicitly ignores Transfer events - // of the ROOT_NODE. as a result, the root node's owner is always zeroAddress until the new + // of the ENS_ROOT_NODE. as a result, the root node's owner is always zeroAddress until the new // Registry events are picked up. for backwards compatibility this beahvior is re-implemented // here. From 6b7fc4f6c3a4ba68b3b0275473ab416881f9d3d7 Mon Sep 17 00:00:00 2001 From: shrugs Date: Fri, 10 Apr 2026 16:31:13 -0500 Subject: [PATCH 11/60] fix: use semantic types in ensapi integration tests --- .../schema/permissions.integration.test.ts | 35 +++++++++++-------- .../schema/query.integration.test.ts | 4 +-- .../find-domains/domain-pagination-queries.ts | 4 +-- .../find-events/event-pagination-queries.ts | 18 +++++----- 4 files changed, 35 insertions(+), 26 deletions(-) diff --git a/apps/ensapi/src/omnigraph-api/schema/permissions.integration.test.ts b/apps/ensapi/src/omnigraph-api/schema/permissions.integration.test.ts index 2256978c4..0b720a608 100644 --- a/apps/ensapi/src/omnigraph-api/schema/permissions.integration.test.ts +++ b/apps/ensapi/src/omnigraph-api/schema/permissions.integration.test.ts @@ -1,4 +1,11 @@ -import type { NormalizedAddress } from "enssdk"; +import type { + ChainId, + NormalizedAddress, + PermissionsId, + PermissionsResourceId, + PermissionsUserId, + RegistryId, +} from "enssdk"; import { toEventSelector } from "viem"; import { beforeAll, describe, expect, it } from "vitest"; @@ -36,23 +43,23 @@ const EAC_ROLES_CHANGED_SELECTOR = toEventSelector( describe("Permissions", () => { type PermissionsResult = { permissions: { - id: string; - contract: { chainId: number; address: NormalizedAddress }; + id: PermissionsId; + contract: { chainId: ChainId; address: NormalizedAddress }; root: { - id: string; + id: PermissionsResourceId; resource: string; users: GraphQLConnection<{ - id: string; + id: PermissionsUserId; resource: string; user: { address: NormalizedAddress }; roles: string; }>; }; resources: GraphQLConnection<{ - id: string; + id: PermissionsResourceId; resource: string; users: GraphQLConnection<{ - id: string; + id: PermissionsUserId; resource: string; user: { address: NormalizedAddress }; roles: string; @@ -128,7 +135,7 @@ describe("Registry.permissions", () => { it("resolves permissions from a registry", async () => { const result = await request<{ registry: { - permissions: { id: string; contract: { chainId: number; address: NormalizedAddress } }; + permissions: { id: PermissionsId; contract: { chainId: ChainId; address: NormalizedAddress } }; }; }>(RegistryPermissions, { contract: V2_ETH_REGISTRY }); @@ -141,7 +148,7 @@ describe("Domain.permissions", () => { type DomainPermissionsResult = { domain: { permissions: GraphQLConnection<{ - id: string; + id: PermissionsUserId; resource: string; user: { address: NormalizedAddress }; roles: string; @@ -160,7 +167,7 @@ describe("Domain.permissions", () => { `; let allUsers: { - id: string; + id: PermissionsUserId; resource: string; user: { address: NormalizedAddress }; roles: string; @@ -254,7 +261,7 @@ describe("Account.permissions and Account.registryPermissions", () => { const result = await request<{ account: { permissions: GraphQLConnection<{ - id: string; + id: PermissionsUserId; resource: string; user: { address: NormalizedAddress }; roles: string; @@ -274,8 +281,8 @@ describe("Account.permissions and Account.registryPermissions", () => { const result = await request<{ account: { registryPermissions: GraphQLConnection<{ - id: string; - registry: { id: string }; + id: PermissionsUserId; + registry: { id: RegistryId }; resource: string; user: { address: NormalizedAddress }; roles: string; @@ -306,7 +313,7 @@ describe("Resolver.permissions", () => { const result = await request<{ domain: { resolver: { - permissions: { id: string; contract: { chainId: number; address: NormalizedAddress } }; + permissions: { id: PermissionsId; contract: { chainId: ChainId; address: NormalizedAddress } }; }; }; }>(ResolverPermissions, { name: NAME_WITH_RESOLVER }); diff --git a/apps/ensapi/src/omnigraph-api/schema/query.integration.test.ts b/apps/ensapi/src/omnigraph-api/schema/query.integration.test.ts index 267ceec9f..91aae1816 100644 --- a/apps/ensapi/src/omnigraph-api/schema/query.integration.test.ts +++ b/apps/ensapi/src/omnigraph-api/schema/query.integration.test.ts @@ -1,5 +1,4 @@ import { - type Address, asInterpretedLabel, asInterpretedName, type DomainId, @@ -10,6 +9,7 @@ import { makeStorageId, type Name, namehashInterpretedName, + type NormalizedAddress, } from "enssdk"; import { describe, expect, it } from "vitest"; @@ -59,7 +59,7 @@ describe("Query.domains", () => { id: DomainId; name: Name; label: { interpreted: InterpretedLabel }; - owner: { address: Address }; + owner: { address: NormalizedAddress }; }>; }; diff --git a/apps/ensapi/src/test/integration/find-domains/domain-pagination-queries.ts b/apps/ensapi/src/test/integration/find-domains/domain-pagination-queries.ts index ea4fcc26a..4a251fa84 100644 --- a/apps/ensapi/src/test/integration/find-domains/domain-pagination-queries.ts +++ b/apps/ensapi/src/test/integration/find-domains/domain-pagination-queries.ts @@ -1,4 +1,4 @@ -import type { InterpretedLabel, Name } from "enssdk"; +import type { DomainId, InterpretedLabel, Name } from "enssdk"; import { gql } from "@/test/integration/omnigraph-api-client"; @@ -24,7 +24,7 @@ const PaginatedDomainFragment = gql` `; export type PaginatedDomainResult = { - id: string; + id: DomainId; name: Name | null; label: { interpreted: InterpretedLabel }; registration: { diff --git a/apps/ensapi/src/test/integration/find-events/event-pagination-queries.ts b/apps/ensapi/src/test/integration/find-events/event-pagination-queries.ts index 89b54f6ed..265515ec7 100644 --- a/apps/ensapi/src/test/integration/find-events/event-pagination-queries.ts +++ b/apps/ensapi/src/test/integration/find-events/event-pagination-queries.ts @@ -1,3 +1,5 @@ +import type { ChainId, Hex, NormalizedAddress } from "enssdk"; + import { gql } from "@/test/integration/omnigraph-api-client"; const PageInfoFragment = gql` @@ -29,18 +31,18 @@ export const EventFragment = gql` export type EventResult = { id: string; - chainId: number; + chainId: ChainId; blockNumber: string; - blockHash: string; + blockHash: Hex; timestamp: string; - transactionHash: string; + transactionHash: Hex; transactionIndex: number; - from: string; - to: string | null; - address: string; + from: NormalizedAddress; + to: NormalizedAddress | null; + address: NormalizedAddress; logIndex: number; - topics: string[]; - data: string; + topics: Hex[]; + data: Hex; }; export const DomainEventsPaginated = gql` From aae29f4686389080efe306e92fe0c4685be2b09a Mon Sep 17 00:00:00 2001 From: shrugs Date: Fri, 10 Apr 2026 16:55:14 -0500 Subject: [PATCH 12/60] refactor: more semantic scalars, and move Duration to enssdk --- .../src/app/mock/registrar-actions/mocks.ts | 3 +- .../indexing-status/projection-info.tsx | 4 +-- .../use-indexing-status-with-swr.ts | 2 +- .../handlers/api/meta/realtime-api.routes.ts | 2 +- .../handlers/api/resolution/resolution-api.ts | 3 +- .../src/handlers/subgraph/subgraph-api.ts | 3 +- .../referrer-leaderboard/closeout.ts | 4 +-- .../src/middleware/is-realtime.middleware.ts | 2 +- .../schema/permissions.integration.test.ts | 10 ++++-- .../schema/query.integration.test.ts | 2 +- .../ensdb-writer-worker.ts | 2 +- .../ensv2/handlers/ensv1/BaseRegistrar.ts | 10 +++--- .../ensv2/handlers/ensv1/NameWrapper.ts | 11 +++--- .../ensv2/handlers/ensv2/ENSv2Registry.ts | 20 ++++++----- .../ensv2/handlers/ensv2/ETHRegistrar.ts | 15 ++++---- .../subgraph/shared-handlers/NameWrapper.ts | 10 +++--- .../subgraph/shared-handlers/Registrar.ts | 12 ++++--- .../subgraph/shared-handlers/ThreeDNSToken.ts | 6 ++-- packages/ens-referrals/src/aggregations.ts | 2 +- packages/ens-referrals/src/rank.ts | 4 +-- .../ens-referrals/src/referrer-metrics.ts | 4 +-- packages/ens-referrals/src/score.ts | 2 +- packages/ens-referrals/src/time.ts | 4 +-- .../v1/award-models/pie-split/aggregations.ts | 4 ++- .../src/v1/award-models/pie-split/rank.ts | 2 +- .../src/v1/award-models/pie-split/score.ts | 2 +- .../rev-share-limit/aggregations.ts | 4 ++- .../rev-share-limit/leaderboard.ts | 4 +-- .../rev-share-limit/referral-event.ts | 4 +-- .../src/v1/award-models/shared/rank.ts | 4 +-- .../ens-referrals/src/v1/referrer-metrics.ts | 4 +-- packages/ens-referrals/src/v1/time.ts | 4 +-- .../realtime-indexing-status-projection.ts | 3 +- .../src/registrars/registrar-action.ts | 4 +-- .../ensnode-sdk/src/shared/cache/swr-cache.ts | 3 +- .../ensnode-sdk/src/shared/cache/ttl-cache.ts | 3 +- packages/ensnode-sdk/src/shared/datetime.ts | 3 +- .../ensnode-sdk/src/shared/deserialize.ts | 4 +-- packages/ensnode-sdk/src/shared/types.ts | 9 ----- .../ensnode-sdk/src/shared/zod-schemas.ts | 3 +- packages/enssdk/src/lib/types/evm.ts | 36 +++++++++++++------ packages/enssdk/src/lib/types/shared.ts | 20 +++++++++++ .../components/datetime/DisplayDuration.tsx | 3 +- packages/namehash-ui/src/hooks/useNow.ts | 4 +-- 44 files changed, 150 insertions(+), 114 deletions(-) diff --git a/apps/ensadmin/src/app/mock/registrar-actions/mocks.ts b/apps/ensadmin/src/app/mock/registrar-actions/mocks.ts index c7e40fa2c..41a7e4fe6 100644 --- a/apps/ensadmin/src/app/mock/registrar-actions/mocks.ts +++ b/apps/ensadmin/src/app/mock/registrar-actions/mocks.ts @@ -1,6 +1,7 @@ +import type { Duration } from "enssdk"; import { asInterpretedName } from "enssdk"; -import { type Duration, type NamedRegistrarAction } from "@ensnode/ensnode-sdk"; +import { type NamedRegistrarAction } from "@ensnode/ensnode-sdk"; export const registrationWithReferral = { action: { diff --git a/apps/ensadmin/src/components/indexing-status/projection-info.tsx b/apps/ensadmin/src/components/indexing-status/projection-info.tsx index 9c18b1b37..519fd2277 100644 --- a/apps/ensadmin/src/components/indexing-status/projection-info.tsx +++ b/apps/ensadmin/src/components/indexing-status/projection-info.tsx @@ -1,11 +1,9 @@ "use client"; import { formatRelativeTime, RelativeTime, useNow } from "@namehash/namehash-ui"; -import type { UnixTimestamp } from "enssdk"; +import type { Duration, UnixTimestamp } from "enssdk"; import { InfoIcon } from "lucide-react"; -import type { Duration } from "@ensnode/ensnode-sdk"; - import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; /** diff --git a/apps/ensadmin/src/components/indexing-status/use-indexing-status-with-swr.ts b/apps/ensadmin/src/components/indexing-status/use-indexing-status-with-swr.ts index ba9d80cc2..0ae81e942 100644 --- a/apps/ensadmin/src/components/indexing-status/use-indexing-status-with-swr.ts +++ b/apps/ensadmin/src/components/indexing-status/use-indexing-status-with-swr.ts @@ -2,6 +2,7 @@ import { useNow } from "@namehash/namehash-ui"; import { secondsToMilliseconds } from "date-fns"; +import type { Duration } from "enssdk"; import { useCallback, useMemo } from "react"; import { @@ -15,7 +16,6 @@ import { import { CrossChainIndexingStatusSnapshotOmnichain, createRealtimeIndexingStatusProjection, - Duration, type IndexingStatusRequest, IndexingStatusResponseCodes, IndexingStatusResponseOk, diff --git a/apps/ensapi/src/handlers/api/meta/realtime-api.routes.ts b/apps/ensapi/src/handlers/api/meta/realtime-api.routes.ts index 56fd2f541..91fc7f3cf 100644 --- a/apps/ensapi/src/handlers/api/meta/realtime-api.routes.ts +++ b/apps/ensapi/src/handlers/api/meta/realtime-api.routes.ts @@ -1,7 +1,7 @@ import { createRoute, z } from "@hono/zod-openapi"; import { minutesToSeconds } from "date-fns"; +import type { Duration } from "enssdk"; -import type { Duration } from "@ensnode/ensnode-sdk"; import { makeDurationSchema } from "@ensnode/ensnode-sdk/internal"; import { params } from "@/lib/handlers/params.schema"; diff --git a/apps/ensapi/src/handlers/api/resolution/resolution-api.ts b/apps/ensapi/src/handlers/api/resolution/resolution-api.ts index 9aabc9bd8..edfce5611 100644 --- a/apps/ensapi/src/handlers/api/resolution/resolution-api.ts +++ b/apps/ensapi/src/handlers/api/resolution/resolution-api.ts @@ -1,5 +1,6 @@ +import type { Duration } from "enssdk"; + import type { - Duration, ResolvePrimaryNameResponse, ResolvePrimaryNamesResponse, ResolveRecordsResponse, diff --git a/apps/ensapi/src/handlers/subgraph/subgraph-api.ts b/apps/ensapi/src/handlers/subgraph/subgraph-api.ts index 2a8390960..b0b01929c 100644 --- a/apps/ensapi/src/handlers/subgraph/subgraph-api.ts +++ b/apps/ensapi/src/handlers/subgraph/subgraph-api.ts @@ -1,5 +1,6 @@ import config from "@/config"; +import type { Duration } from "enssdk"; import { createDocumentationMiddleware } from "ponder-enrich-gql-docs-middleware"; // FIXME: use the import from: @@ -7,7 +8,7 @@ import { createDocumentationMiddleware } from "ponder-enrich-gql-docs-middleware // Once the lazy proxy implemented for `ensIndexerSchema` export is improved // to support Drizzle ORM in `ponder-subgraph` package. import * as ensIndexerSchema from "@ensnode/ensdb-sdk/ensindexer-abstract"; -import { type Duration, hasSubgraphApiConfigSupport } from "@ensnode/ensnode-sdk"; +import { hasSubgraphApiConfigSupport } from "@ensnode/ensnode-sdk"; import { subgraphGraphQLMiddleware } from "@ensnode/ponder-subgraph"; import { createApp } from "@/lib/hono-factory"; diff --git a/apps/ensapi/src/lib/ensanalytics/referrer-leaderboard/closeout.ts b/apps/ensapi/src/lib/ensanalytics/referrer-leaderboard/closeout.ts index 33226faf8..5d8fe2ece 100644 --- a/apps/ensapi/src/lib/ensanalytics/referrer-leaderboard/closeout.ts +++ b/apps/ensapi/src/lib/ensanalytics/referrer-leaderboard/closeout.ts @@ -1,8 +1,8 @@ import type { ReferralProgramRules } from "@namehash/ens-referrals/v1"; import { minutesToSeconds } from "date-fns"; -import type { UnixTimestamp } from "enssdk"; +import type { Duration, UnixTimestamp } from "enssdk"; -import { addDuration, type Duration } from "@ensnode/ensnode-sdk"; +import { addDuration } from "@ensnode/ensnode-sdk"; /** * Duration after which we assume a closed edition is safe from chain reorganizations. diff --git a/apps/ensapi/src/middleware/is-realtime.middleware.ts b/apps/ensapi/src/middleware/is-realtime.middleware.ts index 7490799db..272e97180 100644 --- a/apps/ensapi/src/middleware/is-realtime.middleware.ts +++ b/apps/ensapi/src/middleware/is-realtime.middleware.ts @@ -1,4 +1,4 @@ -import type { Duration } from "@ensnode/ensnode-sdk"; +import type { Duration } from "enssdk"; import { factory, producing } from "@/lib/hono-factory"; import { makeLogger } from "@/lib/logger"; diff --git a/apps/ensapi/src/omnigraph-api/schema/permissions.integration.test.ts b/apps/ensapi/src/omnigraph-api/schema/permissions.integration.test.ts index 0b720a608..631daa86a 100644 --- a/apps/ensapi/src/omnigraph-api/schema/permissions.integration.test.ts +++ b/apps/ensapi/src/omnigraph-api/schema/permissions.integration.test.ts @@ -135,7 +135,10 @@ describe("Registry.permissions", () => { it("resolves permissions from a registry", async () => { const result = await request<{ registry: { - permissions: { id: PermissionsId; contract: { chainId: ChainId; address: NormalizedAddress } }; + permissions: { + id: PermissionsId; + contract: { chainId: ChainId; address: NormalizedAddress }; + }; }; }>(RegistryPermissions, { contract: V2_ETH_REGISTRY }); @@ -313,7 +316,10 @@ describe("Resolver.permissions", () => { const result = await request<{ domain: { resolver: { - permissions: { id: PermissionsId; contract: { chainId: ChainId; address: NormalizedAddress } }; + permissions: { + id: PermissionsId; + contract: { chainId: ChainId; address: NormalizedAddress }; + }; }; }; }>(ResolverPermissions, { name: NAME_WITH_RESOLVER }); diff --git a/apps/ensapi/src/omnigraph-api/schema/query.integration.test.ts b/apps/ensapi/src/omnigraph-api/schema/query.integration.test.ts index 91aae1816..20a3da699 100644 --- a/apps/ensapi/src/omnigraph-api/schema/query.integration.test.ts +++ b/apps/ensapi/src/omnigraph-api/schema/query.integration.test.ts @@ -8,8 +8,8 @@ import { makeENSv2DomainId, makeStorageId, type Name, - namehashInterpretedName, type NormalizedAddress, + namehashInterpretedName, } from "enssdk"; import { describe, expect, it } from "vitest"; diff --git a/apps/ensindexer/src/lib/ensdb-writer-worker/ensdb-writer-worker.ts b/apps/ensindexer/src/lib/ensdb-writer-worker/ensdb-writer-worker.ts index 7204dd535..38aa6d12d 100644 --- a/apps/ensindexer/src/lib/ensdb-writer-worker/ensdb-writer-worker.ts +++ b/apps/ensindexer/src/lib/ensdb-writer-worker/ensdb-writer-worker.ts @@ -1,11 +1,11 @@ import { getUnixTime, secondsToMilliseconds } from "date-fns"; +import type { Duration } from "enssdk"; import pRetry from "p-retry"; import type { EnsDbWriter } from "@ensnode/ensdb-sdk"; import { buildCrossChainIndexingStatusSnapshotOmnichain, type CrossChainIndexingStatusSnapshot, - type Duration, type EnsIndexerPublicConfig, OmnichainIndexingStatusIds, type OmnichainIndexingStatusSnapshot, diff --git a/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/BaseRegistrar.ts b/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/BaseRegistrar.ts index 61af2c703..396774865 100644 --- a/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/BaseRegistrar.ts +++ b/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/BaseRegistrar.ts @@ -4,6 +4,8 @@ import { makeENSv1DomainId, makeSubdomainNode, type NormalizedAddress, + type TokenId, + type UnixTimestampBigInt, } from "enssdk"; import { isAddressEqual, zeroAddress } from "viem"; @@ -54,7 +56,7 @@ export default function () { event: EventWithArgs<{ from: NormalizedAddress; to: NormalizedAddress; - tokenId: bigint; + tokenId: TokenId; }>; }) => { const { from, to, tokenId } = event.args; @@ -97,9 +99,9 @@ export default function () { }: { context: IndexingEngineContext; event: EventWithArgs<{ - id: bigint; + id: TokenId; owner: NormalizedAddress; - expires: bigint; + expires: UnixTimestampBigInt; }>; }) { const { id: tokenId, owner, expires: expiry } = event.args; @@ -161,7 +163,7 @@ export default function () { event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ id: bigint; expires: bigint }>; + event: EventWithArgs<{ id: TokenId; expires: UnixTimestampBigInt }>; }) => { const { id: tokenId, expires: expiry } = event.args; diff --git a/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/NameWrapper.ts b/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/NameWrapper.ts index c18c274d7..2002c49a4 100644 --- a/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/NameWrapper.ts +++ b/apps/ensindexer/src/plugins/ensv2/handlers/ensv1/NameWrapper.ts @@ -9,6 +9,8 @@ import { makeSubdomainNode, type Node, type NormalizedAddress, + type TokenId, + type UnixTimestampBigInt, } from "enssdk"; import { isAddressEqual, zeroAddress } from "viem"; @@ -47,7 +49,8 @@ const pluginName = PluginName.ENSv2; /** * NameWrapper emits expiry as 0 to mean 'doesn't expire', so we interpret as null. */ -const interpretExpiry = (expiry: bigint): bigint | null => (expiry === 0n ? null : expiry); +const interpretExpiry = (expiry: UnixTimestampBigInt): UnixTimestampBigInt | null => + expiry === 0n ? null : expiry; // registrar is source of truth for expiry if eth 2LD // otherwise namewrapper is registrar and source of truth for expiry @@ -101,7 +104,7 @@ export default function () { operator: NormalizedAddress; from: NormalizedAddress; to: NormalizedAddress; - id: bigint; + id: TokenId; }>; }) { const { from, to, id: tokenId } = event.args; @@ -157,7 +160,7 @@ export default function () { name: DNSEncodedName; owner: NormalizedAddress; fuses: number; - expiry: bigint; + expiry: UnixTimestampBigInt; }>; }) => { const { node, name: _name, owner, fuses, expiry: _expiry } = event.args; @@ -349,7 +352,7 @@ export default function () { event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ node: Node; expiry: bigint }>; + event: EventWithArgs<{ node: Node; expiry: UnixTimestampBigInt }>; }) => { const { node, expiry: _expiry } = event.args; const expiry = interpretExpiry(_expiry); diff --git a/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts b/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts index 395b3a2b2..a2d20d6fb 100644 --- a/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts +++ b/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ENSv2Registry.ts @@ -7,6 +7,8 @@ import { makeRegistryId, makeStorageId, type NormalizedAddress, + type TokenId, + type UnixTimestampBigInt, } from "enssdk"; import { hexToBigInt } from "viem"; @@ -42,12 +44,12 @@ export default function () { }: { context: IndexingEngineContext; event: EventWithArgs<{ - tokenId: bigint; + tokenId: TokenId; labelHash: LabelHash; label: string; // NOTE: marking `owner` as optional to handle both LabelRegistered and LabelReserved events owner?: NormalizedAddress; - expiry: bigint; + expiry: UnixTimestampBigInt; sender: NormalizedAddress; }>; }) { @@ -155,7 +157,7 @@ export default function () { }: { context: IndexingEngineContext; event: EventWithArgs<{ - tokenId: bigint; + tokenId: TokenId; sender: NormalizedAddress; }>; }) => { @@ -203,8 +205,8 @@ export default function () { }: { context: IndexingEngineContext; event: EventWithArgs<{ - tokenId: bigint; - newExpiry: bigint; + tokenId: TokenId; + newExpiry: UnixTimestampBigInt; sender: NormalizedAddress; }>; }) => { @@ -247,7 +249,7 @@ export default function () { }: { context: IndexingEngineContext; event: EventWithArgs<{ - tokenId: bigint; + tokenId: TokenId; subregistry: NormalizedAddress; }>; }) => { @@ -303,8 +305,8 @@ export default function () { }: { context: IndexingEngineContext; event: EventWithArgs<{ - oldTokenId: bigint; - newTokenId: bigint; + oldTokenId: TokenId; + newTokenId: TokenId; }>; }) => { const { oldTokenId, newTokenId } = event.args; @@ -332,7 +334,7 @@ export default function () { event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ id: bigint; to: NormalizedAddress }>; + event: EventWithArgs<{ id: TokenId; to: NormalizedAddress }>; }) { const { id: tokenId, to: owner } = event.args; diff --git a/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ETHRegistrar.ts b/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ETHRegistrar.ts index 4e9e78599..d484bdf90 100644 --- a/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ETHRegistrar.ts +++ b/apps/ensindexer/src/plugins/ensv2/handlers/ensv2/ETHRegistrar.ts @@ -1,9 +1,12 @@ import { type AccountId, + type DurationBigInt, makeENSv2DomainId, makeStorageId, type NormalizedAddress, type TokenId, + type UnixTimestampBigInt, + type Wei, } from "enssdk"; import { @@ -57,11 +60,11 @@ export default function () { owner: NormalizedAddress; subregistry: NormalizedAddress; resolver: NormalizedAddress; - duration: bigint; + duration: DurationBigInt; referrer: EncodedReferrer; paymentToken: NormalizedAddress; - base: bigint; - premium: bigint; + base: Wei; + premium: Wei; }>; }) => { // biome-ignore lint/correctness/noUnusedVariables: TODO(paymentToken) @@ -133,11 +136,11 @@ export default function () { event: EventWithArgs<{ tokenId: TokenId; label: string; - duration: bigint; - newExpiry: bigint; + duration: DurationBigInt; + newExpiry: UnixTimestampBigInt; referrer: EncodedReferrer; paymentToken: NormalizedAddress; - base: bigint; + base: Wei; }>; }) => { // biome-ignore lint/correctness/noUnusedVariables: TODO(paymentToken) diff --git a/apps/ensindexer/src/plugins/subgraph/shared-handlers/NameWrapper.ts b/apps/ensindexer/src/plugins/subgraph/shared-handlers/NameWrapper.ts index e1510621a..e600df696 100644 --- a/apps/ensindexer/src/plugins/subgraph/shared-handlers/NameWrapper.ts +++ b/apps/ensindexer/src/plugins/subgraph/shared-handlers/NameWrapper.ts @@ -29,6 +29,8 @@ import { type NormalizedAddress, type SubgraphInterpretedLabel, type SubgraphInterpretedName, + type TokenId, + type UnixTimestampBigInt, } from "enssdk"; import { subgraph_decodeDNSEncodedLiteralName } from "@/lib/dns-helpers"; @@ -177,7 +179,7 @@ export const makeNameWrapperHandlers = () => { node: Node; owner: NormalizedAddress; fuses: number; - expiry: bigint; + expiry: UnixTimestampBigInt; name: DNSEncodedName; }>; }) { @@ -304,7 +306,7 @@ export const makeNameWrapperHandlers = () => { event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ node: Node; expiry: bigint }>; + event: EventWithArgs<{ node: Node; expiry: UnixTimestampBigInt }>; }) { const { node, expiry } = event.args; @@ -335,7 +337,7 @@ export const makeNameWrapperHandlers = () => { event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ id: bigint; to: NormalizedAddress }>; + event: EventWithArgs<{ id: TokenId; to: NormalizedAddress }>; }) { const { id: tokenId, to } = event.args; @@ -357,7 +359,7 @@ export const makeNameWrapperHandlers = () => { event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ ids: readonly bigint[]; to: NormalizedAddress }>; + event: EventWithArgs<{ ids: readonly TokenId[]; to: NormalizedAddress }>; }) { const { ids: tokenIds, to } = event.args; diff --git a/apps/ensindexer/src/plugins/subgraph/shared-handlers/Registrar.ts b/apps/ensindexer/src/plugins/subgraph/shared-handlers/Registrar.ts index 98798c1e5..c8f12af0b 100644 --- a/apps/ensindexer/src/plugins/subgraph/shared-handlers/Registrar.ts +++ b/apps/ensindexer/src/plugins/subgraph/shared-handlers/Registrar.ts @@ -15,6 +15,8 @@ import { type NormalizedAddress, type SubgraphInterpretedLabel, type SubgraphInterpretedName, + type UnixTimestampBigInt, + type Wei, } from "enssdk"; import type { PluginName } from "@ensnode/ensnode-sdk"; @@ -43,7 +45,7 @@ export const makeRegistrarHandlers = ({ pluginName }: { pluginName: PluginName } event: EventWithArgs<{ label: LiteralLabel; labelHash: LabelHash; - cost: bigint; + cost: Wei; }>, ) { const { label, labelHash, cost } = event.args; @@ -95,7 +97,7 @@ export const makeRegistrarHandlers = ({ pluginName }: { pluginName: PluginName } event: EventWithArgs<{ labelHash: LabelHash; owner: NormalizedAddress; - expires: bigint; + expires: UnixTimestampBigInt; }>; }) { const { labelHash, owner, expires } = event.args; @@ -225,7 +227,7 @@ export const makeRegistrarHandlers = ({ pluginName }: { pluginName: PluginName } event: EventWithArgs<{ label: Label; labelHash: LabelHash; - cost: bigint; + cost: Wei; }>; }) { const { labelHash, cost } = event.args; @@ -242,7 +244,7 @@ export const makeRegistrarHandlers = ({ pluginName }: { pluginName: PluginName } event: EventWithArgs<{ label: Label; labelHash: LabelHash; - cost: bigint; + cost: Wei; }>; }) { const { labelHash, cost } = event.args; @@ -256,7 +258,7 @@ export const makeRegistrarHandlers = ({ pluginName }: { pluginName: PluginName } event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ labelHash: LabelHash; expires: bigint }>; + event: EventWithArgs<{ labelHash: LabelHash; expires: UnixTimestampBigInt }>; }) { const { labelHash, expires } = event.args; diff --git a/apps/ensindexer/src/plugins/subgraph/shared-handlers/ThreeDNSToken.ts b/apps/ensindexer/src/plugins/subgraph/shared-handlers/ThreeDNSToken.ts index 2b608fafe..634ec5c4a 100644 --- a/apps/ensindexer/src/plugins/subgraph/shared-handlers/ThreeDNSToken.ts +++ b/apps/ensindexer/src/plugins/subgraph/shared-handlers/ThreeDNSToken.ts @@ -4,6 +4,7 @@ import { constructSubInterpretedName, type DNSEncodedLiteralName, type DNSEncodedName, + type DurationBigInt, decodeDNSEncodedLiteralName, encodeLabelHash, type InterpretedLabel, @@ -16,6 +17,7 @@ import { makeSubdomainNode, type Node, type NormalizedAddress, + type UnixTimestampBigInt, } from "enssdk"; import { isAddressEqual, zeroAddress, zeroHash } from "viem"; @@ -248,7 +250,7 @@ export async function handleRegistrationCreated({ fqdn: DNSEncodedName; registrant: NormalizedAddress; controlBitmap: number; - expiry: bigint; + expiry: UnixTimestampBigInt; }>; }) { const { node, tld, fqdn, registrant, expiry } = event.args; @@ -307,7 +309,7 @@ export async function handleRegistrationExtended({ event, }: { context: IndexingEngineContext; - event: EventWithArgs<{ node: Node; duration: bigint; newExpiry: bigint }>; + event: EventWithArgs<{ node: Node; duration: DurationBigInt; newExpiry: UnixTimestampBigInt }>; }) { const { node, newExpiry } = event.args; diff --git a/packages/ens-referrals/src/aggregations.ts b/packages/ens-referrals/src/aggregations.ts index 3ab23edc9..1cde5b507 100644 --- a/packages/ens-referrals/src/aggregations.ts +++ b/packages/ens-referrals/src/aggregations.ts @@ -1,4 +1,4 @@ -import type { Duration } from "@ensnode/ensnode-sdk"; +import type { Duration } from "enssdk"; import { validateNonNegativeInteger } from "./number"; import type { RankedReferrerMetrics } from "./referrer-metrics"; diff --git a/packages/ens-referrals/src/rank.ts b/packages/ens-referrals/src/rank.ts index d2d3d9557..1a416f308 100644 --- a/packages/ens-referrals/src/rank.ts +++ b/packages/ens-referrals/src/rank.ts @@ -1,6 +1,4 @@ -import type { Address } from "enssdk"; - -import type { Duration } from "@ensnode/ensnode-sdk"; +import type { Address, Duration } from "enssdk"; import { isPositiveInteger } from "./number"; import type { ReferralProgramRules } from "./rules"; diff --git a/packages/ens-referrals/src/referrer-metrics.ts b/packages/ens-referrals/src/referrer-metrics.ts index e770b8b1d..30cd07dc0 100644 --- a/packages/ens-referrals/src/referrer-metrics.ts +++ b/packages/ens-referrals/src/referrer-metrics.ts @@ -1,8 +1,6 @@ -import type { Address } from "enssdk"; +import type { Address, Duration } from "enssdk"; import { toNormalizedAddress } from "enssdk"; -import type { Duration } from "@ensnode/ensnode-sdk"; - import { validateAddress } from "./address"; import type { AggregatedReferrerMetrics } from "./aggregations"; import type { USDQuantity } from "./currency"; diff --git a/packages/ens-referrals/src/score.ts b/packages/ens-referrals/src/score.ts index 5995b6e1d..6690e0f30 100644 --- a/packages/ens-referrals/src/score.ts +++ b/packages/ens-referrals/src/score.ts @@ -1,4 +1,4 @@ -import type { Duration } from "@ensnode/ensnode-sdk"; +import type { Duration } from "enssdk"; import { SECONDS_PER_YEAR } from "./time"; diff --git a/packages/ens-referrals/src/time.ts b/packages/ens-referrals/src/time.ts index 228465341..a72b180ca 100644 --- a/packages/ens-referrals/src/time.ts +++ b/packages/ens-referrals/src/time.ts @@ -1,6 +1,4 @@ -import type { UnixTimestamp } from "enssdk"; - -import type { Duration } from "@ensnode/ensnode-sdk"; +import type { Duration, UnixTimestamp } from "enssdk"; import { isInteger, isNonNegativeInteger } from "./number"; diff --git a/packages/ens-referrals/src/v1/award-models/pie-split/aggregations.ts b/packages/ens-referrals/src/v1/award-models/pie-split/aggregations.ts index 072bbc2f5..d363fe0d9 100644 --- a/packages/ens-referrals/src/v1/award-models/pie-split/aggregations.ts +++ b/packages/ens-referrals/src/v1/award-models/pie-split/aggregations.ts @@ -1,4 +1,6 @@ -import { type Duration, type PriceEth, priceEth } from "@ensnode/ensnode-sdk"; +import type { Duration } from "enssdk"; + +import { type PriceEth, priceEth } from "@ensnode/ensnode-sdk"; import { makePriceEthSchema } from "@ensnode/ensnode-sdk/internal"; import { validateNonNegativeInteger } from "../../number"; diff --git a/packages/ens-referrals/src/v1/award-models/pie-split/rank.ts b/packages/ens-referrals/src/v1/award-models/pie-split/rank.ts index 652af4f47..d4aac8695 100644 --- a/packages/ens-referrals/src/v1/award-models/pie-split/rank.ts +++ b/packages/ens-referrals/src/v1/award-models/pie-split/rank.ts @@ -1,4 +1,4 @@ -import type { Duration } from "@ensnode/ensnode-sdk"; +import type { Duration } from "enssdk"; import type { ReferrerRank } from "../shared/rank"; import type { ReferrerScore } from "../shared/score"; diff --git a/packages/ens-referrals/src/v1/award-models/pie-split/score.ts b/packages/ens-referrals/src/v1/award-models/pie-split/score.ts index 755ad8976..369add2d9 100644 --- a/packages/ens-referrals/src/v1/award-models/pie-split/score.ts +++ b/packages/ens-referrals/src/v1/award-models/pie-split/score.ts @@ -1,4 +1,4 @@ -import type { Duration } from "@ensnode/ensnode-sdk"; +import type { Duration } from "enssdk"; import { SECONDS_PER_YEAR } from "../../time"; import type { ReferrerScore } from "../shared/score"; diff --git a/packages/ens-referrals/src/v1/award-models/rev-share-limit/aggregations.ts b/packages/ens-referrals/src/v1/award-models/rev-share-limit/aggregations.ts index 91f142526..aa4126d8d 100644 --- a/packages/ens-referrals/src/v1/award-models/rev-share-limit/aggregations.ts +++ b/packages/ens-referrals/src/v1/award-models/rev-share-limit/aggregations.ts @@ -1,4 +1,6 @@ -import { type Duration, type PriceEth, type PriceUsdc, priceEth } from "@ensnode/ensnode-sdk"; +import type { Duration } from "enssdk"; + +import { type PriceEth, type PriceUsdc, priceEth } from "@ensnode/ensnode-sdk"; import { makePriceEthSchema, makePriceUsdcSchema } from "@ensnode/ensnode-sdk/internal"; import { validateNonNegativeInteger } from "../../number"; diff --git a/packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.ts b/packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.ts index ae6258ec9..d01798cb4 100644 --- a/packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.ts +++ b/packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.ts @@ -1,7 +1,7 @@ -import type { Address, UnixTimestamp } from "enssdk"; +import type { Address, Duration, UnixTimestamp } from "enssdk"; import { toNormalizedAddress } from "enssdk"; -import { type Duration, priceEth, priceUsdc, scalePrice } from "@ensnode/ensnode-sdk"; +import { priceEth, priceUsdc, scalePrice } from "@ensnode/ensnode-sdk"; import { buildReferrerMetrics } from "../../referrer-metrics"; import { SECONDS_PER_YEAR } from "../../time"; diff --git a/packages/ens-referrals/src/v1/award-models/rev-share-limit/referral-event.ts b/packages/ens-referrals/src/v1/award-models/rev-share-limit/referral-event.ts index 5570dcb10..e32b5e42b 100644 --- a/packages/ens-referrals/src/v1/award-models/rev-share-limit/referral-event.ts +++ b/packages/ens-referrals/src/v1/award-models/rev-share-limit/referral-event.ts @@ -1,6 +1,6 @@ -import type { Address, UnixTimestamp } from "enssdk"; +import type { Address, Duration, UnixTimestamp } from "enssdk"; -import type { Duration, PriceEth } from "@ensnode/ensnode-sdk"; +import type { PriceEth } from "@ensnode/ensnode-sdk"; /** * Represents a single raw referral event. diff --git a/packages/ens-referrals/src/v1/award-models/shared/rank.ts b/packages/ens-referrals/src/v1/award-models/shared/rank.ts index 6f25960e5..9ac0a75aa 100644 --- a/packages/ens-referrals/src/v1/award-models/shared/rank.ts +++ b/packages/ens-referrals/src/v1/award-models/shared/rank.ts @@ -1,6 +1,4 @@ -import type { Address } from "enssdk"; - -import type { Duration } from "@ensnode/ensnode-sdk"; +import type { Address, Duration } from "enssdk"; import { isPositiveInteger } from "../../number"; import type { ReferrerMetrics } from "../../referrer-metrics"; diff --git a/packages/ens-referrals/src/v1/referrer-metrics.ts b/packages/ens-referrals/src/v1/referrer-metrics.ts index e03ed8245..1087a6583 100644 --- a/packages/ens-referrals/src/v1/referrer-metrics.ts +++ b/packages/ens-referrals/src/v1/referrer-metrics.ts @@ -1,7 +1,7 @@ -import type { Address } from "enssdk"; +import type { Address, Duration } from "enssdk"; import { toNormalizedAddress } from "enssdk"; -import type { Duration, PriceEth } from "@ensnode/ensnode-sdk"; +import type { PriceEth } from "@ensnode/ensnode-sdk"; import { makePriceEthSchema } from "@ensnode/ensnode-sdk/internal"; import { validateAddress } from "./address"; diff --git a/packages/ens-referrals/src/v1/time.ts b/packages/ens-referrals/src/v1/time.ts index 228465341..a72b180ca 100644 --- a/packages/ens-referrals/src/v1/time.ts +++ b/packages/ens-referrals/src/v1/time.ts @@ -1,6 +1,4 @@ -import type { UnixTimestamp } from "enssdk"; - -import type { Duration } from "@ensnode/ensnode-sdk"; +import type { Duration, UnixTimestamp } from "enssdk"; import { isInteger, isNonNegativeInteger } from "./number"; diff --git a/packages/ensnode-sdk/src/indexing-status/realtime-indexing-status-projection.ts b/packages/ensnode-sdk/src/indexing-status/realtime-indexing-status-projection.ts index 000ecb75c..6ba2f1cd0 100644 --- a/packages/ensnode-sdk/src/indexing-status/realtime-indexing-status-projection.ts +++ b/packages/ensnode-sdk/src/indexing-status/realtime-indexing-status-projection.ts @@ -1,6 +1,5 @@ -import type { UnixTimestamp } from "enssdk"; +import type { Duration, UnixTimestamp } from "enssdk"; -import type { Duration } from "../shared/types"; import type { CrossChainIndexingStatusSnapshot } from "./cross-chain-indexing-status-snapshot"; /** diff --git a/packages/ensnode-sdk/src/registrars/registrar-action.ts b/packages/ensnode-sdk/src/registrars/registrar-action.ts index 86b2f9a03..c6edbdd1f 100644 --- a/packages/ensnode-sdk/src/registrars/registrar-action.ts +++ b/packages/ensnode-sdk/src/registrars/registrar-action.ts @@ -1,4 +1,4 @@ -import type { Address } from "enssdk"; +import type { Address, Duration } from "enssdk"; import type { Hash } from "viem"; import type { EncodedReferrer } from "./encoded-referrer"; @@ -8,7 +8,7 @@ export { decodeEncodedReferrer, ZERO_ENCODED_REFERRER } from "./encoded-referrer import type { PriceEth, SerializedPriceEth } from "../shared/currencies"; import { serializePriceEth } from "../shared/serialize"; -import type { BlockRef, Duration } from "../shared/types"; +import type { BlockRef } from "../shared/types"; import type { RegistrationLifecycle } from "./registration-lifecycle"; /** diff --git a/packages/ensnode-sdk/src/shared/cache/swr-cache.ts b/packages/ensnode-sdk/src/shared/cache/swr-cache.ts index e3ca400a5..a7be2064f 100644 --- a/packages/ensnode-sdk/src/shared/cache/swr-cache.ts +++ b/packages/ensnode-sdk/src/shared/cache/swr-cache.ts @@ -1,9 +1,8 @@ import { secondsToMilliseconds } from "date-fns"; import { getUnixTime } from "date-fns/getUnixTime"; -import type { UnixTimestamp } from "enssdk"; +import type { Duration, UnixTimestamp } from "enssdk"; import { durationBetween } from "../datetime"; -import type { Duration } from "../types"; /** * Data structure for a single cached result. diff --git a/packages/ensnode-sdk/src/shared/cache/ttl-cache.ts b/packages/ensnode-sdk/src/shared/cache/ttl-cache.ts index fcdb1888d..8030df05f 100644 --- a/packages/ensnode-sdk/src/shared/cache/ttl-cache.ts +++ b/packages/ensnode-sdk/src/shared/cache/ttl-cache.ts @@ -1,8 +1,7 @@ import { getUnixTime } from "date-fns/getUnixTime"; -import type { UnixTimestamp } from "enssdk"; +import type { Duration, UnixTimestamp } from "enssdk"; import { addDuration } from "../datetime"; -import type { Duration } from "../types"; import type { Cache } from "./cache"; interface CacheEntry { diff --git a/packages/ensnode-sdk/src/shared/datetime.ts b/packages/ensnode-sdk/src/shared/datetime.ts index f59a27185..8636c1fc9 100644 --- a/packages/ensnode-sdk/src/shared/datetime.ts +++ b/packages/ensnode-sdk/src/shared/datetime.ts @@ -1,8 +1,7 @@ import { getUnixTime } from "date-fns/getUnixTime"; -import type { UnixTimestamp } from "enssdk"; +import type { Duration, UnixTimestamp } from "enssdk"; import { deserializeDuration, deserializeUnixTimestamp } from "./deserialize"; -import type { Duration } from "./types"; /** * Duration between two moments in time. diff --git a/packages/ensnode-sdk/src/shared/deserialize.ts b/packages/ensnode-sdk/src/shared/deserialize.ts index 8c81416a5..4e2d5d2d6 100644 --- a/packages/ensnode-sdk/src/shared/deserialize.ts +++ b/packages/ensnode-sdk/src/shared/deserialize.ts @@ -1,8 +1,8 @@ -import type { AccountId, ChainId, ChainIdString, UrlString } from "enssdk"; +import type { AccountId, ChainId, ChainIdString, Duration, UrlString } from "enssdk"; import z, { prettifyError } from "zod/v4"; import type { PriceDai, PriceEth, PriceUsdc } from "./currencies"; -import type { BlockNumber, BlockRef, Datetime, Duration } from "./types"; +import type { BlockNumber, BlockRef, Datetime } from "./types"; import { makeAccountIdStringSchema, makeBlockNumberSchema, diff --git a/packages/ensnode-sdk/src/shared/types.ts b/packages/ensnode-sdk/src/shared/types.ts index 8252b6d90..980ff7e7f 100644 --- a/packages/ensnode-sdk/src/shared/types.ts +++ b/packages/ensnode-sdk/src/shared/types.ts @@ -33,15 +33,6 @@ export interface BlockRef { timestamp: UnixTimestamp; } -/** - * Duration - * - * Representing a duration in seconds. - * - * Guaranteed to be a non-negative integer. - */ -export type Duration = number; - /** * A utility type that makes all properties of a type optional recursively, * including nested objects and arrays. diff --git a/packages/ensnode-sdk/src/shared/zod-schemas.ts b/packages/ensnode-sdk/src/shared/zod-schemas.ts index 1c730ae60..8a8d1d5e4 100644 --- a/packages/ensnode-sdk/src/shared/zod-schemas.ts +++ b/packages/ensnode-sdk/src/shared/zod-schemas.ts @@ -6,6 +6,7 @@ import type { Address, ChainId, DefaultableChainId, + Duration, Hex, InterpretedName, Node, @@ -30,7 +31,7 @@ import { type PriceEth, type PriceUsdc, } from "./currencies"; -import type { BlockRef, Datetime, Duration } from "./types"; +import type { BlockRef, Datetime } from "./types"; /** * Parses a string value as a boolean. diff --git a/packages/enssdk/src/lib/types/evm.ts b/packages/enssdk/src/lib/types/evm.ts index 56ba5aefe..5f72ba49d 100644 --- a/packages/enssdk/src/lib/types/evm.ts +++ b/packages/enssdk/src/lib/types/evm.ts @@ -21,6 +21,31 @@ export type Address = ViemAddress; */ export type NormalizedAddress = Address; +/** + * Unix timestamp value as bigint. + * + * Represents the number of seconds that have elapsed + * since January 1, 1970 (midnight UTC/GMT). + * + * Guaranteed to be an integer. May be zero or negative to represent a time at or + * before Jan 1, 1970. + */ +export type UnixTimestampBigInt = bigint; + +/** + * Duration value as bigint. + * + * Representing a duration in seconds. + * + * Guaranteed to be a non-negative integer. + */ +export type DurationBigInt = bigint; + +/** + * A value denominated in wei, the smallest unit of Ether (1 ETH = 10^18 wei). + */ +export type Wei = bigint; + /** * Chain ID * @@ -65,17 +90,6 @@ export const AssetNamespaces = { export type AssetNamespace = (typeof AssetNamespaces)[keyof typeof AssetNamespaces]; -/** - * Unix timestamp value - * - * Represents the number of seconds that have elapsed - * since January 1, 1970 (midnight UTC/GMT). - * - * Guaranteed to be an integer. May be zero or negative to represent a time at or - * before Jan 1, 1970. - */ -export type UnixTimestamp = number; - /** * A uint256 value that identifies a specific NFT within a NFT contract. */ diff --git a/packages/enssdk/src/lib/types/shared.ts b/packages/enssdk/src/lib/types/shared.ts index 06265d9ff..21837dad7 100644 --- a/packages/enssdk/src/lib/types/shared.ts +++ b/packages/enssdk/src/lib/types/shared.ts @@ -1,3 +1,23 @@ +/** + * Unix timestamp value + * + * Represents the number of seconds that have elapsed + * since January 1, 1970 (midnight UTC/GMT). + * + * Guaranteed to be an integer. May be zero or negative to represent a time at or + * before Jan 1, 1970. + */ +export type UnixTimestamp = number; + +/** + * Duration + * + * Representing a duration in seconds. + * + * Guaranteed to be a non-negative integer. + */ +export type Duration = number; + /** * Serialized representation of {@link ChainId}. **/ diff --git a/packages/namehash-ui/src/components/datetime/DisplayDuration.tsx b/packages/namehash-ui/src/components/datetime/DisplayDuration.tsx index 134cade25..7ab117477 100644 --- a/packages/namehash-ui/src/components/datetime/DisplayDuration.tsx +++ b/packages/namehash-ui/src/components/datetime/DisplayDuration.tsx @@ -1,8 +1,7 @@ import { formatDistanceStrict, fromUnixTime } from "date-fns"; +import type { Duration } from "enssdk"; import { useEffect, useState } from "react"; -import type { Duration } from "@ensnode/ensnode-sdk"; - /** * Display Duration component */ diff --git a/packages/namehash-ui/src/hooks/useNow.ts b/packages/namehash-ui/src/hooks/useNow.ts index 832e4d09f..6d523236c 100644 --- a/packages/namehash-ui/src/hooks/useNow.ts +++ b/packages/namehash-ui/src/hooks/useNow.ts @@ -1,8 +1,6 @@ -import type { UnixTimestamp } from "enssdk"; +import type { Duration, UnixTimestamp } from "enssdk"; import { useEffect, useState } from "react"; -import type { Duration } from "@ensnode/ensnode-sdk"; - import { useSystemClock } from "./useSystemClock"; /** Default time to refresh: `1` second. */ From 597fa4c0c672a7309b6c1ed29e9d3976f3fc2a80 Mon Sep 17 00:00:00 2001 From: shrugs Date: Fri, 10 Apr 2026 18:24:57 -0500 Subject: [PATCH 13/60] refactor: local resolvers, add bigint deserialization resolvers --- apps/ensapi/src/omnigraph-api/builder.test.ts | 14 + apps/ensapi/src/omnigraph-api/builder.ts | 42 +- .../omnigraph-api/lib/write-graphql-schema.ts | 8 +- packages/enskit/biome.jsonc | 2 +- .../enskit/src/react/omnigraph/_lib/README.md | 1 + .../omnigraph/_lib/by-id-lookup-resolvers.ts | 68 + .../react/omnigraph/_lib/cache-exchange.ts | 43 + .../omnigraph/_lib/introspection-helpers.ts | 26 + .../_lib/local-bigint-resolvers.test.ts | 54 + .../omnigraph/_lib/local-bigint-resolvers.ts | 35 + .../local-connection-resolvers.ts | 27 +- .../omnigraph/_lib/merge-resolver-maps.ts | 16 + packages/enskit/src/react/omnigraph/client.ts | 8 +- .../enskit/src/react/omnigraph/graphql.ts | 13 + packages/enskit/src/react/omnigraph/index.ts | 3 +- .../src/react/omnigraph/lib/cache-exchange.ts | 104 - .../src/omnigraph/generated/graphql-env.d.ts | 136 - .../src/omnigraph/generated/graphql-env.ts | 5767 +++++++++++++++++ .../src/omnigraph/generated/introspection.ts | 2 +- packages/enssdk/src/omnigraph/graphql.ts | 56 +- .../enssdk/src/omnigraph/introspection.ts | 3 +- packages/enssdk/tsconfig.json | 2 +- 22 files changed, 6108 insertions(+), 322 deletions(-) create mode 100644 apps/ensapi/src/omnigraph-api/builder.test.ts create mode 100644 packages/enskit/src/react/omnigraph/_lib/README.md create mode 100644 packages/enskit/src/react/omnigraph/_lib/by-id-lookup-resolvers.ts create mode 100644 packages/enskit/src/react/omnigraph/_lib/cache-exchange.ts create mode 100644 packages/enskit/src/react/omnigraph/_lib/introspection-helpers.ts create mode 100644 packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.test.ts create mode 100644 packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.ts rename packages/enskit/src/react/omnigraph/{lib => _lib}/local-connection-resolvers.ts (56%) create mode 100644 packages/enskit/src/react/omnigraph/_lib/merge-resolver-maps.ts create mode 100644 packages/enskit/src/react/omnigraph/graphql.ts delete mode 100644 packages/enskit/src/react/omnigraph/lib/cache-exchange.ts delete mode 100644 packages/enssdk/src/omnigraph/generated/graphql-env.d.ts create mode 100644 packages/enssdk/src/omnigraph/generated/graphql-env.ts diff --git a/apps/ensapi/src/omnigraph-api/builder.test.ts b/apps/ensapi/src/omnigraph-api/builder.test.ts new file mode 100644 index 000000000..1677aa71e --- /dev/null +++ b/apps/ensapi/src/omnigraph-api/builder.test.ts @@ -0,0 +1,14 @@ +import type { OmnigraphScalars } from "enssdk/omnigraph"; +import { assertType, describe, it } from "vitest"; + +import type { BuilderScalars } from "./builder"; + +type BuilderScalarNames = Record; +type OmnigraphScalarNames = Record; + +describe("BuilderScalars", () => { + it("defines the same scalar names as OmnigraphScalars from enssdk", () => { + assertType({} as OmnigraphScalarNames); + assertType({} as BuilderScalarNames); + }); +}); diff --git a/apps/ensapi/src/omnigraph-api/builder.ts b/apps/ensapi/src/omnigraph-api/builder.ts index 8cb83130c..9eebd9b44 100644 --- a/apps/ensapi/src/omnigraph-api/builder.ts +++ b/apps/ensapi/src/omnigraph-api/builder.ts @@ -56,28 +56,30 @@ const createSpan = createOpenTelemetryWrapper(tracer, { }, }); +export type BuilderScalars = { + ID: { Input: string; Output: string }; + BigInt: { Input: bigint; Output: bigint }; + Address: { Input: Address; Output: NormalizedAddress }; + Hex: { Input: Hex; Output: Hex }; + ChainId: { Input: ChainId; Output: ChainId }; + CoinType: { Input: CoinType; Output: CoinType }; + Node: { Input: Node; Output: Node }; + InterpretedName: { Input: InterpretedName; Output: InterpretedName }; + InterpretedLabel: { Input: InterpretedLabel; Output: InterpretedLabel }; + DomainId: { Input: DomainId; Output: DomainId }; + RegistryId: { Input: RegistryId; Output: RegistryId }; + ResolverId: { Input: ResolverId; Output: ResolverId }; + PermissionsId: { Input: PermissionsId; Output: PermissionsId }; + PermissionsResourceId: { Input: PermissionsResourceId; Output: PermissionsResourceId }; + PermissionsUserId: { Input: PermissionsUserId; Output: PermissionsUserId }; + RegistrationId: { Input: RegistrationId; Output: RegistrationId }; + RenewalId: { Input: RenewalId; Output: RenewalId }; + ResolverRecordsId: { Input: ResolverRecordsId; Output: ResolverRecordsId }; +}; + export const builder = new SchemaBuilder<{ Context: ReturnType; - Scalars: { - // make sure to keep these scalars up to date with packages/enssdk/src/omnigraph/graphql.ts ! - BigInt: { Input: bigint; Output: bigint }; - Address: { Input: Address; Output: NormalizedAddress }; - Hex: { Input: Hex; Output: Hex }; - ChainId: { Input: ChainId; Output: ChainId }; - CoinType: { Input: CoinType; Output: CoinType }; - Node: { Input: Node; Output: Node }; - InterpretedName: { Input: InterpretedName; Output: InterpretedName }; - InterpretedLabel: { Input: InterpretedLabel; Output: InterpretedLabel }; - DomainId: { Input: DomainId; Output: DomainId }; - RegistryId: { Input: RegistryId; Output: RegistryId }; - ResolverId: { Input: ResolverId; Output: ResolverId }; - PermissionsId: { Input: PermissionsId; Output: PermissionsId }; - PermissionsResourceId: { Input: PermissionsResourceId; Output: PermissionsResourceId }; - PermissionsUserId: { Input: PermissionsUserId; Output: PermissionsUserId }; - RegistrationId: { Input: RegistrationId; Output: RegistrationId }; - RenewalId: { Input: RenewalId; Output: RenewalId }; - ResolverRecordsId: { Input: ResolverRecordsId; Output: ResolverRecordsId }; - }; + Scalars: BuilderScalars; // the following ensures via typechecker that every t.connection returns a totalCount field Connection: { diff --git a/apps/ensapi/src/omnigraph-api/lib/write-graphql-schema.ts b/apps/ensapi/src/omnigraph-api/lib/write-graphql-schema.ts index 4ab24b471..a1f1e4f0d 100644 --- a/apps/ensapi/src/omnigraph-api/lib/write-graphql-schema.ts +++ b/apps/ensapi/src/omnigraph-api/lib/write-graphql-schema.ts @@ -17,7 +17,13 @@ async function _writeGraphQLSchema() { const { schema: unsortedSchema } = await import("@/omnigraph-api/schema"); const schema = lexicographicSortSchema(unsortedSchema); const sdl = printSchema(schema); - const introspection = minifyIntrospectionQuery(introspectionFromSchema(schema)); + const introspection = minifyIntrospectionQuery(introspectionFromSchema(schema), { + /** + * We include Scalar types in the introspection in order to power automatic bigint deserialization + * within the Omnigraph's urql GraphCache. + */ + includeScalars: true, + }); await Promise.all([ writeFile(resolve(GENERATED_DIR, "schema.graphql"), sdl), diff --git a/packages/enskit/biome.jsonc b/packages/enskit/biome.jsonc index 3bac83229..e28987dc5 100644 --- a/packages/enskit/biome.jsonc +++ b/packages/enskit/biome.jsonc @@ -4,7 +4,7 @@ "overrides": [ // ignore unused resolver args { - "includes": ["src/react/omnigraph/lib/cache-exchange.ts"], + "includes": ["src/react/omnigraph/_lib/*.ts"], "linter": { "rules": { "correctness": { diff --git a/packages/enskit/src/react/omnigraph/_lib/README.md b/packages/enskit/src/react/omnigraph/_lib/README.md new file mode 100644 index 000000000..42a3c5f88 --- /dev/null +++ b/packages/enskit/src/react/omnigraph/_lib/README.md @@ -0,0 +1 @@ +enskit/react/omnigraph libs or helpers not meant for export to consumers diff --git a/packages/enskit/src/react/omnigraph/_lib/by-id-lookup-resolvers.ts b/packages/enskit/src/react/omnigraph/_lib/by-id-lookup-resolvers.ts new file mode 100644 index 000000000..5a1d9686b --- /dev/null +++ b/packages/enskit/src/react/omnigraph/_lib/by-id-lookup-resolvers.ts @@ -0,0 +1,68 @@ +import type { Cache, ResolveInfo, Resolver, Variables } from "@urql/exchange-graphcache"; +import { + type AccountId, + type Address, + makePermissionsId, + makeRegistryId, + makeResolverId, + type PermissionsId, + type RegistryId, + type ResolverId, +} from "enssdk"; + +/** + * This local resolver delegates to graphcache's built-in cache resolution with the full argument set, + * effectively telling urql 'not found locally' and to fetch from the network. + */ +const passthrough = (args: Variables, cache: Cache, info: ResolveInfo) => + cache.resolve(info.parentTypeName, info.fieldName, args); + +export const byIdLookupResolvers: Record> = { + Query: { + domain(parent, args, cache, info) { + const by = args.by as { id?: string; name?: string }; + + if (by.id) { + const v1Key = cache.keyOfEntity({ __typename: "ENSv1Domain", id: by.id }); + if (v1Key && cache.resolve(v1Key, "id")) return v1Key; + + const v2Key = cache.keyOfEntity({ __typename: "ENSv2Domain", id: by.id }); + if (v2Key && cache.resolve(v2Key, "id")) return v2Key; + } + + return passthrough(args, cache, info); + }, + account(parent, args, cache, info) { + const by = args.by as { id?: Address; address?: Address }; + + if (by.id) return { __typename: "Account", id: by.id }; + if (by.address) return { __typename: "Account", id: by.address }; + + throw new Error("never"); + }, + registry(parent, args, cache, info) { + const by = args.by as { id?: RegistryId; contract?: AccountId }; + + if (by.id) return { __typename: "Registry", id: by.id }; + if (by.contract) return { __typename: "Registry", id: makeRegistryId(by.contract) }; + + throw new Error("never"); + }, + resolver(parent, args, cache, info) { + const by = args.by as { id?: ResolverId; contract?: AccountId }; + + if (by.id) return { __typename: "Resolver", id: by.id }; + if (by.contract) return { __typename: "Resolver", id: makeResolverId(by.contract) }; + + throw new Error("never"); + }, + permissions(parent, args, cache, info) { + const by = args.by as { id?: PermissionsId; contract?: AccountId }; + + if (by.id) return { __typename: "Permissions", id: by.id }; + if (by.contract) return { __typename: "Permissions", id: makePermissionsId(by.contract) }; + + throw new Error("never"); + }, + }, +}; diff --git a/packages/enskit/src/react/omnigraph/_lib/cache-exchange.ts b/packages/enskit/src/react/omnigraph/_lib/cache-exchange.ts new file mode 100644 index 000000000..31d563d4a --- /dev/null +++ b/packages/enskit/src/react/omnigraph/_lib/cache-exchange.ts @@ -0,0 +1,43 @@ +import { cacheExchange } from "@urql/exchange-graphcache"; +import type { AccountId } from "enssdk"; +import { stringifyAccountId } from "enssdk"; +import { introspection } from "enssdk/omnigraph"; + +import { byIdLookupResolvers } from "./by-id-lookup-resolvers"; +import { localBigIntResolvers } from "./local-bigint-resolvers"; +import { localConnectionResolvers } from "./local-connection-resolvers"; +import { mergeResolverMaps } from "./merge-resolver-maps"; + +/** + * Entities without keys are 'Embedded Data', and we tell graphcache about them to avoid warnings + * about the inability to normalize them. + * + * @see https://nearform.com/open-source/urql/docs/graphcache/normalized-caching/#custom-keys-and-non-keyable-entities + */ +const EMBEDDED_DATA = () => null; + +export const omnigraphCacheExchange = cacheExchange({ + schema: introspection, + keys: { + // by default, all Entities are assumed to match the Relay spec, and graphcache treats + // them as keyable by `id`. if it encounters an Entity with no `id` field and no other + // special handling here in the cacheExchange.keys definitions, it will issue a warning. + + // AccountIds are keyable by stringifying them + AccountId: (data) => stringifyAccountId(data as unknown as AccountId), + + // These entities are Embedded Data and don't have a relevant key + Label: EMBEDDED_DATA, + WrappedBaseRegistrarRegistration: EMBEDDED_DATA, + }, + resolvers: mergeResolverMaps( + // produce relayPagination() local resolvers for each t.connection in the schema + localConnectionResolvers(introspection), + + // produce local resolvers that parse BigInt scalar fields from cached strings into native bigint + localBigIntResolvers(introspection), + + // produce local cache resolvers for the Query.entity(by: { }) lookups + byIdLookupResolvers, + ), +}); diff --git a/packages/enskit/src/react/omnigraph/_lib/introspection-helpers.ts b/packages/enskit/src/react/omnigraph/_lib/introspection-helpers.ts new file mode 100644 index 000000000..a2540383a --- /dev/null +++ b/packages/enskit/src/react/omnigraph/_lib/introspection-helpers.ts @@ -0,0 +1,26 @@ +export interface IntrospectionTypeRef { + readonly kind: string; + readonly name?: string; + readonly ofType?: IntrospectionTypeRef | null; +} + +export interface IntrospectionField { + readonly name: string; + readonly type: IntrospectionTypeRef; +} + +export interface IntrospectionType { + readonly kind: string; + readonly name: string; + readonly fields?: readonly IntrospectionField[] | null; +} + +export interface IntrospectionSchema { + readonly __schema: { + readonly types: readonly IntrospectionType[]; + }; +} + +export function unwrapType(type: IntrospectionTypeRef): IntrospectionTypeRef { + return type.ofType ? unwrapType(type.ofType) : type; +} diff --git a/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.test.ts b/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.test.ts new file mode 100644 index 000000000..e3d5d80d6 --- /dev/null +++ b/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.test.ts @@ -0,0 +1,54 @@ +import { describe, expect, expectTypeOf, it, vi } from "vitest"; + +import { createOmnigraphUrqlClient } from "../client"; +import { graphql } from "../graphql"; + +const mockFetch = vi.fn(); +const client = createOmnigraphUrqlClient({ url: "http://whatever", fetch: mockFetch }); + +const BIGINT_VALUE = 1234567890n; +const BIGINT_STRING = BIGINT_VALUE.toString(); + +describe("localBigIntResolvers", () => { + it("deserialized BigInt scalars as bigint", async () => { + mockFetch.mockResolvedValueOnce( + new Response( + JSON.stringify({ + data: { + domain: { + __typename: "ENSv1Domain", + id: "test-domain-id", + registration: { + __typename: "BaseRegistrarRegistration", + id: "test-registration-id", + start: BIGINT_STRING, + }, + }, + }, + }), + { + status: 200, + headers: { "content-type": "application/json" }, + }, + ), + ); + + const { data } = await client.query( + graphql(` + query localBigIntResolvers { + domain(by: { name: "example.eth" }) { + id + registration { + id + start + } + } + } + `), + {}, + ); + + expect(data!.domain!.registration!.start).toEqual(BIGINT_VALUE); + expectTypeOf(data!.domain!.registration!.start).toEqualTypeOf(); + }); +}); diff --git a/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.ts b/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.ts new file mode 100644 index 000000000..f66f2a49e --- /dev/null +++ b/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.ts @@ -0,0 +1,35 @@ +import type { Resolver, ScalarObject } from "@urql/exchange-graphcache"; + +import { type IntrospectionSchema, unwrapType } from "./introspection-helpers"; + +// graphcache's ResolverResult type doesn't include bigint, but the value is stored +// in the normalized cache and returned to the consumer as-is, so bigint works at runtime +// the load-bearing piece of +const toBigInt: Resolver = (parent, args, cache, info) => { + const value = parent[info.fieldName]; + if (value == null) return value; + return BigInt(value as string) as unknown as ScalarObject; +}; + +/** + * Derives local resolvers that parse BigInt scalar fields from cached strings into native bigint. + */ +export function localBigIntResolvers( + schema: IntrospectionSchema, +): Record> { + const resolvers: Record> = {}; + + for (const type of schema.__schema.types) { + if (type.kind !== "OBJECT" || type.name.startsWith("__")) continue; + + for (const field of type.fields ?? []) { + const leaf = unwrapType(field.type); + if (leaf.name === "BigInt") { + resolvers[type.name] ??= {}; + resolvers[type.name][field.name] = toBigInt; + } + } + } + + return resolvers; +} diff --git a/packages/enskit/src/react/omnigraph/lib/local-connection-resolvers.ts b/packages/enskit/src/react/omnigraph/_lib/local-connection-resolvers.ts similarity index 56% rename from packages/enskit/src/react/omnigraph/lib/local-connection-resolvers.ts rename to packages/enskit/src/react/omnigraph/_lib/local-connection-resolvers.ts index 2b777bae2..abc49a5c8 100644 --- a/packages/enskit/src/react/omnigraph/lib/local-connection-resolvers.ts +++ b/packages/enskit/src/react/omnigraph/_lib/local-connection-resolvers.ts @@ -1,32 +1,7 @@ import type { Resolver } from "@urql/exchange-graphcache"; import { relayPagination } from "@urql/exchange-graphcache/extras"; -interface IntrospectionTypeRef { - readonly kind: string; - readonly name?: string; - readonly ofType?: IntrospectionTypeRef | null; -} - -interface IntrospectionField { - readonly name: string; - readonly type: IntrospectionTypeRef; -} - -interface IntrospectionType { - readonly kind: string; - readonly name: string; - readonly fields?: readonly IntrospectionField[] | null; -} - -interface IntrospectionSchema { - readonly __schema: { - readonly types: readonly IntrospectionType[]; - }; -} - -function unwrapType(type: IntrospectionTypeRef): IntrospectionTypeRef { - return type.ofType ? unwrapType(type.ofType) : type; -} +import { type IntrospectionSchema, unwrapType } from "./introspection-helpers"; /** * Derives `relayPagination()` local resolvers for all connection fields in the schema. diff --git a/packages/enskit/src/react/omnigraph/_lib/merge-resolver-maps.ts b/packages/enskit/src/react/omnigraph/_lib/merge-resolver-maps.ts new file mode 100644 index 000000000..67447ceb6 --- /dev/null +++ b/packages/enskit/src/react/omnigraph/_lib/merge-resolver-maps.ts @@ -0,0 +1,16 @@ +import type { Resolver } from "@urql/exchange-graphcache"; + +/** + * deep-merge resolver maps so types appearing in both get all their field resolvers + */ +export function mergeResolverMaps( + ...maps: Record>[] +): Record> { + const result: Record> = {}; + for (const map of maps) { + for (const [typeName, fields] of Object.entries(map)) { + result[typeName] = { ...result[typeName], ...fields }; + } + } + return result; +} diff --git a/packages/enskit/src/react/omnigraph/client.ts b/packages/enskit/src/react/omnigraph/client.ts index 0438d7bda..f405eb6ef 100644 --- a/packages/enskit/src/react/omnigraph/client.ts +++ b/packages/enskit/src/react/omnigraph/client.ts @@ -1,13 +1,11 @@ import { Client, fetchExchange } from "@urql/core"; import type { EnsNodeClientConfig } from "enssdk/core"; -import { omnigraphCacheExchange } from "./lib/cache-exchange"; - -export function createOmnigraphUrqlClient(config: EnsNodeClientConfig): Client { - const url = new URL("/api/omnigraph", config.url).href; +import { omnigraphCacheExchange } from "./_lib/cache-exchange"; +export function createOmnigraphUrqlClient(config: EnsNodeClientConfig) { return new Client({ - url, + url: new URL("/api/omnigraph", config.url).href, fetch: config.fetch, exchanges: [omnigraphCacheExchange, fetchExchange], }); diff --git a/packages/enskit/src/react/omnigraph/graphql.ts b/packages/enskit/src/react/omnigraph/graphql.ts new file mode 100644 index 000000000..2b8fa1881 --- /dev/null +++ b/packages/enskit/src/react/omnigraph/graphql.ts @@ -0,0 +1,13 @@ +import type { introspection, OmnigraphScalars } from "enssdk/omnigraph"; +import { initGraphQLTada } from "gql.tada"; + +export const graphql = initGraphQLTada<{ + introspection: typeof introspection; + scalars: Omit & { + // override the default Omnigraph Scalar definitions to include a deserialized BigInt (see cache-exchange.ts) + BigInt: bigint; + }; +}>(); + +export type { FragmentOf, ResultOf, VariablesOf } from "gql.tada"; +export { readFragment } from "gql.tada"; diff --git a/packages/enskit/src/react/omnigraph/index.ts b/packages/enskit/src/react/omnigraph/index.ts index 7646f062c..c1af1b7ee 100644 --- a/packages/enskit/src/react/omnigraph/index.ts +++ b/packages/enskit/src/react/omnigraph/index.ts @@ -1,7 +1,8 @@ // export the gql.tada subset of enssdk/omnigraph so consumers only need the one dependency export type { FragmentOf, ResultOf, VariablesOf } from "enssdk/omnigraph"; -export { graphql, readFragment } from "enssdk/omnigraph"; +export { readFragment } from "enssdk/omnigraph"; export * from "./components"; +export * from "./graphql"; export * from "./hooks"; export * from "./provider"; diff --git a/packages/enskit/src/react/omnigraph/lib/cache-exchange.ts b/packages/enskit/src/react/omnigraph/lib/cache-exchange.ts deleted file mode 100644 index dfcc3ff6b..000000000 --- a/packages/enskit/src/react/omnigraph/lib/cache-exchange.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { - type Cache, - cacheExchange, - type ResolveInfo, - type Variables, -} from "@urql/exchange-graphcache"; -import type { AccountId, Address, PermissionsId, RegistryId, ResolverId } from "enssdk"; -import { makePermissionsId, makeRegistryId, makeResolverId, stringifyAccountId } from "enssdk"; -import { introspection } from "enssdk/omnigraph"; - -import { localConnectionResolvers } from "./local-connection-resolvers"; - -/** - * Entities without keys are 'Embedded Data', and we tell graphcache about them to avoid warnings - * about the inability to normalize them. - * - * @see https://nearform.com/open-source/urql/docs/graphcache/normalized-caching/#custom-keys-and-non-keyable-entities - */ -const EMBEDDED_DATA = () => null; - -/** - * This local resolver delegates to graphcache's built-in cache resolution with the full argument set, - * effectively telling urql 'not found locally' and to fetch from the network. - */ -const passthrough = (args: Variables, cache: Cache, info: ResolveInfo) => - cache.resolve(info.parentTypeName, info.fieldName, args); - -// produce relayPagination() local resolvers for each t.connection in the schema -const connectionResolvers = localConnectionResolvers(introspection); - -// TODO: add bigint parsing to the relevant scalar fields ala localConnectionResolvers -// @see https://nearform.com/open-source/urql/docs/graphcache/local-resolvers/#transforming-records - -export const omnigraphCacheExchange = cacheExchange({ - schema: introspection, - keys: { - // by default, all Entities are assumed to match the Relay spec, and graphcache treats - // them as keyable by `id`. if it encounters an Entity with no `id` field and no other - // special handling here in the cacheExchange.keys definitions, it will issue a warning. - - // AccountIds are keyable by stringifying them - AccountId: (data) => stringifyAccountId(data as unknown as AccountId), - - // These entities are Embedded Data and don't have a relevant key - Label: EMBEDDED_DATA, - WrappedBaseRegistrarRegistration: EMBEDDED_DATA, - }, - resolvers: { - // TODO: maybe there's a better way to import/cast the type of args in these local resolvers? - - // derive relayPagination() resolvers for all connection fields in the schema - ...connectionResolvers, - - Query: { - ...connectionResolvers.Query, - - domain(parent, args, cache, info) { - const by = args.by as { id?: string; name?: string }; - - if (by.id) { - const v1Key = cache.keyOfEntity({ __typename: "ENSv1Domain", id: by.id }); - if (v1Key && cache.resolve(v1Key, "id")) return v1Key; - - const v2Key = cache.keyOfEntity({ __typename: "ENSv2Domain", id: by.id }); - if (v2Key && cache.resolve(v2Key, "id")) return v2Key; - } - - return passthrough(args, cache, info); - }, - account(parent, args, cache, info) { - const by = args.by as { id?: Address; address?: Address }; - - if (by.id) return { __typename: "Account", id: by.id }; - if (by.address) return { __typename: "Account", id: by.address }; - - throw new Error("never"); - }, - registry(parent, args, cache, info) { - const by = args.by as { id?: RegistryId; contract?: AccountId }; - - if (by.id) return { __typename: "Registry", id: by.id }; - if (by.contract) return { __typename: "Registry", id: makeRegistryId(by.contract) }; - - throw new Error("never"); - }, - resolver(parent, args, cache, info) { - const by = args.by as { id?: ResolverId; contract?: AccountId }; - - if (by.id) return { __typename: "Resolver", id: by.id }; - if (by.contract) return { __typename: "Resolver", id: makeResolverId(by.contract) }; - - throw new Error("never"); - }, - permissions(parent, args, cache, info) { - const by = args.by as { id?: PermissionsId; contract?: AccountId }; - - if (by.id) return { __typename: "Permissions", id: by.id }; - if (by.contract) return { __typename: "Permissions", id: makePermissionsId(by.contract) }; - - throw new Error("never"); - }, - }, - }, -}); diff --git a/packages/enssdk/src/omnigraph/generated/graphql-env.d.ts b/packages/enssdk/src/omnigraph/generated/graphql-env.d.ts deleted file mode 100644 index 48f752368..000000000 --- a/packages/enssdk/src/omnigraph/generated/graphql-env.d.ts +++ /dev/null @@ -1,136 +0,0 @@ -/* 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; } }; }; }; - 'AccountByInput': { kind: 'INPUT_OBJECT'; name: 'AccountByInput'; isOneOf: true; inputFields: [{ name: 'address'; type: { kind: 'SCALAR'; name: 'Address'; ofType: null; }; defaultValue: null }, { name: 'id'; type: { kind: 'SCALAR'; name: 'Address'; ofType: null; }; defaultValue: null }]; }; - 'AccountDomainsConnection': { kind: 'OBJECT'; name: 'AccountDomainsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountDomainsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'AccountDomainsConnectionEdge': { kind: 'OBJECT'; name: 'AccountDomainsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; } }; }; }; - 'AccountDomainsWhereInput': { kind: 'INPUT_OBJECT'; name: 'AccountDomainsWhereInput'; isOneOf: false; inputFields: [{ name: 'canonical'; type: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; defaultValue: "false" }, { name: 'name'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; }; defaultValue: null }]; }; - 'AccountEventsConnection': { kind: 'OBJECT'; name: 'AccountEventsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountEventsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'AccountEventsConnectionEdge': { kind: 'OBJECT'; name: 'AccountEventsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Event'; ofType: null; }; } }; }; }; - 'AccountEventsWhereInput': { kind: 'INPUT_OBJECT'; name: 'AccountEventsWhereInput'; isOneOf: false; inputFields: [{ name: 'selector_in'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Hex'; ofType: null; }; }; }; defaultValue: null }, { name: 'timestamp_gte'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; defaultValue: null }, { name: 'timestamp_lte'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; defaultValue: null }]; }; - 'AccountId': { kind: 'OBJECT'; name: 'AccountId'; fields: { 'address': { name: 'address'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Address'; ofType: null; }; } }; 'chainId': { name: 'chainId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ChainId'; ofType: null; }; } }; }; }; - 'AccountIdInput': { kind: 'INPUT_OBJECT'; name: 'AccountIdInput'; isOneOf: false; inputFields: [{ name: 'address'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Address'; ofType: null; }; }; defaultValue: null }, { name: 'chainId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ChainId'; ofType: null; }; }; defaultValue: null }]; }; - 'AccountPermissionsConnection': { kind: 'OBJECT'; name: 'AccountPermissionsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountPermissionsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'AccountPermissionsConnectionEdge': { kind: 'OBJECT'; name: 'AccountPermissionsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PermissionsUser'; ofType: null; }; } }; }; }; - 'AccountRegistryPermissionsConnection': { kind: 'OBJECT'; name: 'AccountRegistryPermissionsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountRegistryPermissionsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'AccountRegistryPermissionsConnectionEdge': { kind: 'OBJECT'; name: 'AccountRegistryPermissionsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'RegistryPermissionsUser'; ofType: null; }; } }; }; }; - 'AccountResolverPermissionsConnection': { kind: 'OBJECT'; name: 'AccountResolverPermissionsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountResolverPermissionsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'AccountResolverPermissionsConnectionEdge': { kind: 'OBJECT'; name: 'AccountResolverPermissionsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'ResolverPermissionsUser'; ofType: null; }; } }; }; }; - 'Address': unknown; - 'BaseRegistrarRegistration': { kind: 'OBJECT'; name: 'BaseRegistrarRegistration'; fields: { 'baseCost': { name: 'baseCost'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'domain': { name: 'domain'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; } }; 'event': { name: 'event'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Event'; ofType: null; }; } }; 'expired': { name: 'expired'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'expiry': { name: 'expiry'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'RegistrationId'; ofType: null; }; } }; 'isInGracePeriod': { name: 'isInGracePeriod'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'premium': { name: 'premium'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'referrer': { name: 'referrer'; type: { kind: 'SCALAR'; name: 'Hex'; ofType: null; } }; 'registrant': { name: 'registrant'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'registrar': { name: 'registrar'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; }; } }; 'renewals': { name: 'renewals'; type: { kind: 'OBJECT'; name: 'RegistrationRenewalsConnection'; ofType: null; } }; 'start': { name: 'start'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'unregistrant': { name: 'unregistrant'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'wrapped': { name: 'wrapped'; type: { kind: 'OBJECT'; name: 'WrappedBaseRegistrarRegistration'; ofType: null; } }; }; }; - 'BigInt': unknown; - 'Boolean': unknown; - 'ChainId': unknown; - 'CoinType': unknown; - 'Domain': { kind: 'INTERFACE'; name: 'Domain'; fields: { 'events': { name: 'events'; type: { kind: 'OBJECT'; name: 'DomainEventsConnection'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'DomainId'; ofType: null; }; } }; 'label': { name: 'label'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Label'; ofType: null; }; } }; 'name': { name: 'name'; type: { kind: 'SCALAR'; name: 'InterpretedName'; ofType: null; } }; 'owner': { name: 'owner'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'path': { name: 'path'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; }; } }; 'registration': { name: 'registration'; type: { kind: 'INTERFACE'; name: 'Registration'; ofType: null; } }; 'registrations': { name: 'registrations'; type: { kind: 'OBJECT'; name: 'DomainRegistrationsConnection'; ofType: null; } }; 'resolver': { name: 'resolver'; type: { kind: 'OBJECT'; name: 'Resolver'; ofType: null; } }; 'subdomains': { name: 'subdomains'; type: { kind: 'OBJECT'; name: 'DomainSubdomainsConnection'; ofType: null; } }; }; possibleTypes: 'ENSv1Domain' | 'ENSv2Domain'; }; - 'DomainEventsConnection': { kind: 'OBJECT'; name: 'DomainEventsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'DomainEventsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'DomainEventsConnectionEdge': { kind: 'OBJECT'; name: 'DomainEventsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Event'; ofType: null; }; } }; }; }; - 'DomainId': unknown; - 'DomainIdInput': { kind: 'INPUT_OBJECT'; name: 'DomainIdInput'; isOneOf: true; inputFields: [{ name: 'id'; type: { kind: 'SCALAR'; name: 'DomainId'; ofType: null; }; defaultValue: null }, { name: 'name'; type: { kind: 'SCALAR'; name: 'InterpretedName'; ofType: null; }; defaultValue: null }]; }; - 'DomainPermissionsWhereInput': { kind: 'INPUT_OBJECT'; name: 'DomainPermissionsWhereInput'; isOneOf: false; inputFields: [{ name: 'user'; type: { kind: 'SCALAR'; name: 'Address'; ofType: null; }; defaultValue: null }]; }; - 'DomainRegistrationsConnection': { kind: 'OBJECT'; name: 'DomainRegistrationsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'DomainRegistrationsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'DomainRegistrationsConnectionEdge': { kind: 'OBJECT'; name: 'DomainRegistrationsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Registration'; ofType: null; }; } }; }; }; - 'DomainSubdomainsConnection': { kind: 'OBJECT'; name: 'DomainSubdomainsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'DomainSubdomainsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'DomainSubdomainsConnectionEdge': { kind: 'OBJECT'; name: 'DomainSubdomainsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; } }; }; }; - 'DomainsOrderBy': { name: 'DomainsOrderBy'; enumValues: 'NAME' | 'REGISTRATION_EXPIRY' | 'REGISTRATION_TIMESTAMP'; }; - 'DomainsOrderInput': { kind: 'INPUT_OBJECT'; name: 'DomainsOrderInput'; isOneOf: false; inputFields: [{ name: 'by'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'ENUM'; name: 'DomainsOrderBy'; ofType: null; }; }; defaultValue: null }, { name: 'dir'; type: { kind: 'ENUM'; name: 'OrderDirection'; ofType: null; }; defaultValue: "ASC" }]; }; - 'DomainsWhereInput': { kind: 'INPUT_OBJECT'; name: 'DomainsWhereInput'; isOneOf: false; inputFields: [{ name: 'canonical'; type: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; defaultValue: "false" }, { name: 'name'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; }; defaultValue: null }]; }; - 'ENSv1Domain': { kind: 'OBJECT'; name: 'ENSv1Domain'; fields: { 'events': { name: 'events'; type: { kind: 'OBJECT'; name: 'DomainEventsConnection'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'DomainId'; ofType: null; }; } }; 'label': { name: 'label'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Label'; ofType: null; }; } }; 'name': { name: 'name'; type: { kind: 'SCALAR'; name: 'InterpretedName'; ofType: null; } }; 'owner': { name: 'owner'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'parent': { name: 'parent'; type: { kind: 'OBJECT'; name: 'ENSv1Domain'; ofType: null; } }; 'path': { name: 'path'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; }; } }; 'registration': { name: 'registration'; type: { kind: 'INTERFACE'; name: 'Registration'; ofType: null; } }; 'registrations': { name: 'registrations'; type: { kind: 'OBJECT'; name: 'DomainRegistrationsConnection'; ofType: null; } }; 'resolver': { name: 'resolver'; type: { kind: 'OBJECT'; name: 'Resolver'; ofType: null; } }; 'rootRegistryOwner': { name: 'rootRegistryOwner'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'subdomains': { name: 'subdomains'; type: { kind: 'OBJECT'; name: 'DomainSubdomainsConnection'; ofType: null; } }; }; }; - 'ENSv2Domain': { kind: 'OBJECT'; name: 'ENSv2Domain'; fields: { 'events': { name: 'events'; type: { kind: 'OBJECT'; name: 'DomainEventsConnection'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'DomainId'; ofType: null; }; } }; 'label': { name: 'label'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Label'; ofType: null; }; } }; 'name': { name: 'name'; type: { kind: 'SCALAR'; name: 'InterpretedName'; ofType: null; } }; 'owner': { name: 'owner'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'path': { name: 'path'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; }; } }; 'permissions': { name: 'permissions'; type: { kind: 'OBJECT'; name: 'ENSv2DomainPermissionsConnection'; ofType: null; } }; 'registration': { name: 'registration'; type: { kind: 'INTERFACE'; name: 'Registration'; ofType: null; } }; 'registrations': { name: 'registrations'; type: { kind: 'OBJECT'; name: 'DomainRegistrationsConnection'; ofType: null; } }; 'registry': { name: 'registry'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Registry'; ofType: null; }; } }; 'resolver': { name: 'resolver'; type: { kind: 'OBJECT'; name: 'Resolver'; ofType: null; } }; 'subdomains': { name: 'subdomains'; type: { kind: 'OBJECT'; name: 'DomainSubdomainsConnection'; ofType: null; } }; 'subregistry': { name: 'subregistry'; type: { kind: 'OBJECT'; name: 'Registry'; ofType: null; } }; 'tokenId': { name: 'tokenId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; }; }; - 'ENSv2DomainPermissionsConnection': { kind: 'OBJECT'; name: 'ENSv2DomainPermissionsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'ENSv2DomainPermissionsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'ENSv2DomainPermissionsConnectionEdge': { kind: 'OBJECT'; name: 'ENSv2DomainPermissionsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PermissionsUser'; ofType: null; }; } }; }; }; - 'ENSv2RegistryRegistration': { kind: 'OBJECT'; name: 'ENSv2RegistryRegistration'; fields: { 'domain': { name: 'domain'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; } }; 'event': { name: 'event'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Event'; ofType: null; }; } }; 'expired': { name: 'expired'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'expiry': { name: 'expiry'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'RegistrationId'; ofType: null; }; } }; 'referrer': { name: 'referrer'; type: { kind: 'SCALAR'; name: 'Hex'; ofType: null; } }; 'registrant': { name: 'registrant'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'registrar': { name: 'registrar'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; }; } }; 'renewals': { name: 'renewals'; type: { kind: 'OBJECT'; name: 'RegistrationRenewalsConnection'; ofType: null; } }; 'start': { name: 'start'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'unregistrant': { name: 'unregistrant'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; }; }; - 'ENSv2RegistryReservation': { kind: 'OBJECT'; name: 'ENSv2RegistryReservation'; fields: { 'domain': { name: 'domain'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; } }; 'event': { name: 'event'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Event'; ofType: null; }; } }; 'expired': { name: 'expired'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'expiry': { name: 'expiry'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'RegistrationId'; ofType: null; }; } }; 'referrer': { name: 'referrer'; type: { kind: 'SCALAR'; name: 'Hex'; ofType: null; } }; 'registrant': { name: 'registrant'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'registrar': { name: 'registrar'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; }; } }; 'renewals': { name: 'renewals'; type: { kind: 'OBJECT'; name: 'RegistrationRenewalsConnection'; ofType: null; } }; 'start': { name: 'start'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'unregistrant': { name: 'unregistrant'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; }; }; - 'Event': { kind: 'OBJECT'; name: 'Event'; fields: { 'address': { name: 'address'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Address'; ofType: null; }; } }; 'blockHash': { name: 'blockHash'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Hex'; ofType: null; }; } }; 'blockNumber': { name: 'blockNumber'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'chainId': { name: 'chainId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ChainId'; ofType: null; }; } }; 'data': { name: 'data'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Hex'; ofType: null; }; } }; 'from': { name: 'from'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Address'; ofType: null; }; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ID'; ofType: null; }; } }; 'logIndex': { name: 'logIndex'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; 'timestamp': { name: 'timestamp'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'to': { name: 'to'; type: { kind: 'SCALAR'; name: 'Address'; ofType: null; } }; 'topics': { name: 'topics'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Hex'; ofType: null; }; }; }; } }; 'transactionHash': { name: 'transactionHash'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Hex'; ofType: null; }; } }; 'transactionIndex': { name: 'transactionIndex'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - '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; - 'InterpretedLabel': unknown; - 'InterpretedName': unknown; - 'Label': { kind: 'OBJECT'; name: 'Label'; fields: { 'hash': { name: 'hash'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Hex'; ofType: null; }; } }; 'interpreted': { name: 'interpreted'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'InterpretedLabel'; ofType: null; }; } }; }; }; - 'NameOrNodeInput': { kind: 'INPUT_OBJECT'; name: 'NameOrNodeInput'; isOneOf: true; inputFields: [{ name: 'name'; type: { kind: 'SCALAR'; name: 'InterpretedName'; ofType: null; }; defaultValue: null }, { name: 'node'; type: { kind: 'SCALAR'; name: 'Node'; ofType: null; }; defaultValue: null }]; }; - 'NameWrapperRegistration': { kind: 'OBJECT'; name: 'NameWrapperRegistration'; fields: { 'domain': { name: 'domain'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; } }; 'event': { name: 'event'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Event'; ofType: null; }; } }; 'expired': { name: 'expired'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'expiry': { name: 'expiry'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'fuses': { name: 'fuses'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'RegistrationId'; ofType: null; }; } }; 'referrer': { name: 'referrer'; type: { kind: 'SCALAR'; name: 'Hex'; ofType: null; } }; 'registrant': { name: 'registrant'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'registrar': { name: 'registrar'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; }; } }; 'renewals': { name: 'renewals'; type: { kind: 'OBJECT'; name: 'RegistrationRenewalsConnection'; ofType: null; } }; 'start': { name: 'start'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'unregistrant': { name: 'unregistrant'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; }; }; - 'Node': unknown; - 'OrderDirection': { name: 'OrderDirection'; enumValues: 'ASC' | 'DESC'; }; - 'PageInfo': { kind: 'OBJECT'; name: 'PageInfo'; fields: { 'endCursor': { name: 'endCursor'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'hasNextPage': { name: 'hasNextPage'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'hasPreviousPage': { name: 'hasPreviousPage'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'startCursor': { name: 'startCursor'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; }; }; - 'Permissions': { kind: 'OBJECT'; name: 'Permissions'; fields: { 'contract': { name: 'contract'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; }; } }; 'events': { name: 'events'; type: { kind: 'OBJECT'; name: 'PermissionsEventsConnection'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'PermissionsId'; ofType: null; }; } }; 'resources': { name: 'resources'; type: { kind: 'OBJECT'; name: 'PermissionsResourcesConnection'; ofType: null; } }; 'root': { name: 'root'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PermissionsResource'; ofType: null; }; } }; }; }; - 'PermissionsEventsConnection': { kind: 'OBJECT'; name: 'PermissionsEventsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PermissionsEventsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'PermissionsEventsConnectionEdge': { kind: 'OBJECT'; name: 'PermissionsEventsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Event'; ofType: null; }; } }; }; }; - 'PermissionsId': unknown; - 'PermissionsIdInput': { kind: 'INPUT_OBJECT'; name: 'PermissionsIdInput'; isOneOf: true; inputFields: [{ name: 'contract'; type: { kind: 'INPUT_OBJECT'; name: 'AccountIdInput'; ofType: null; }; defaultValue: null }, { name: 'id'; type: { kind: 'SCALAR'; name: 'PermissionsId'; ofType: null; }; defaultValue: null }]; }; - 'PermissionsResource': { kind: 'OBJECT'; name: 'PermissionsResource'; fields: { 'contract': { name: 'contract'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; }; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'PermissionsResourceId'; ofType: null; }; } }; 'permissions': { name: 'permissions'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Permissions'; ofType: null; }; } }; 'resource': { name: 'resource'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'users': { name: 'users'; type: { kind: 'OBJECT'; name: 'PermissionsResourceUsersConnection'; ofType: null; } }; }; }; - 'PermissionsResourceId': unknown; - 'PermissionsResourceUsersConnection': { kind: 'OBJECT'; name: 'PermissionsResourceUsersConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PermissionsResourceUsersConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'PermissionsResourceUsersConnectionEdge': { kind: 'OBJECT'; name: 'PermissionsResourceUsersConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PermissionsUser'; ofType: null; }; } }; }; }; - 'PermissionsResourcesConnection': { kind: 'OBJECT'; name: 'PermissionsResourcesConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PermissionsResourcesConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'PermissionsResourcesConnectionEdge': { kind: 'OBJECT'; name: 'PermissionsResourcesConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PermissionsResource'; ofType: null; }; } }; }; }; - 'PermissionsUser': { kind: 'OBJECT'; name: 'PermissionsUser'; fields: { 'contract': { name: 'contract'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; }; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'PermissionsUserId'; ofType: null; }; } }; 'resource': { name: 'resource'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'roles': { name: 'roles'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'user': { name: 'user'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Account'; ofType: null; }; } }; }; }; - 'PermissionsUserId': unknown; - 'Query': { kind: 'OBJECT'; name: 'Query'; fields: { 'account': { name: 'account'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'domain': { name: 'domain'; type: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; } }; 'domains': { name: 'domains'; type: { kind: 'OBJECT'; name: 'QueryDomainsConnection'; ofType: null; } }; 'permissions': { name: 'permissions'; type: { kind: 'OBJECT'; name: 'Permissions'; ofType: null; } }; 'registrations': { name: 'registrations'; type: { kind: 'OBJECT'; name: 'QueryRegistrationsConnection'; ofType: null; } }; 'registry': { name: 'registry'; type: { kind: 'OBJECT'; name: 'Registry'; ofType: null; } }; 'resolver': { name: 'resolver'; type: { kind: 'OBJECT'; name: 'Resolver'; ofType: null; } }; 'resolvers': { name: 'resolvers'; type: { kind: 'OBJECT'; name: 'QueryResolversConnection'; ofType: null; } }; 'root': { name: 'root'; type: { kind: 'OBJECT'; name: 'Registry'; ofType: null; } }; 'v1Domains': { name: 'v1Domains'; type: { kind: 'OBJECT'; name: 'QueryV1DomainsConnection'; ofType: null; } }; 'v2Domains': { name: 'v2Domains'; type: { kind: 'OBJECT'; name: 'QueryV2DomainsConnection'; ofType: null; } }; }; }; - 'QueryDomainsConnection': { kind: 'OBJECT'; name: 'QueryDomainsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'QueryDomainsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'QueryDomainsConnectionEdge': { kind: 'OBJECT'; name: 'QueryDomainsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; } }; }; }; - 'QueryRegistrationsConnection': { kind: 'OBJECT'; name: 'QueryRegistrationsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'QueryRegistrationsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'QueryRegistrationsConnectionEdge': { kind: 'OBJECT'; name: 'QueryRegistrationsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Registration'; ofType: null; }; } }; }; }; - 'QueryResolversConnection': { kind: 'OBJECT'; name: 'QueryResolversConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'QueryResolversConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'QueryResolversConnectionEdge': { kind: 'OBJECT'; name: 'QueryResolversConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Resolver'; ofType: null; }; } }; }; }; - 'QueryV1DomainsConnection': { kind: 'OBJECT'; name: 'QueryV1DomainsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'QueryV1DomainsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'QueryV1DomainsConnectionEdge': { kind: 'OBJECT'; name: 'QueryV1DomainsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'ENSv1Domain'; ofType: null; }; } }; }; }; - 'QueryV2DomainsConnection': { kind: 'OBJECT'; name: 'QueryV2DomainsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'QueryV2DomainsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'QueryV2DomainsConnectionEdge': { kind: 'OBJECT'; name: 'QueryV2DomainsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'ENSv2Domain'; ofType: null; }; } }; }; }; - 'Registration': { kind: 'INTERFACE'; name: 'Registration'; fields: { 'domain': { name: 'domain'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; } }; 'event': { name: 'event'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Event'; ofType: null; }; } }; 'expired': { name: 'expired'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'expiry': { name: 'expiry'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'RegistrationId'; ofType: null; }; } }; 'referrer': { name: 'referrer'; type: { kind: 'SCALAR'; name: 'Hex'; ofType: null; } }; 'registrant': { name: 'registrant'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; 'registrar': { name: 'registrar'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; }; } }; 'renewals': { name: 'renewals'; type: { kind: 'OBJECT'; name: 'RegistrationRenewalsConnection'; ofType: null; } }; 'start': { name: 'start'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'unregistrant': { name: 'unregistrant'; type: { kind: 'OBJECT'; name: 'Account'; ofType: null; } }; }; possibleTypes: 'BaseRegistrarRegistration' | 'ENSv2RegistryRegistration' | 'ENSv2RegistryReservation' | 'NameWrapperRegistration' | 'ThreeDNSRegistration'; }; - 'RegistrationId': unknown; - 'RegistrationRenewalsConnection': { kind: 'OBJECT'; name: 'RegistrationRenewalsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'RegistrationRenewalsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'RegistrationRenewalsConnectionEdge': { kind: 'OBJECT'; name: 'RegistrationRenewalsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Renewal'; ofType: null; }; } }; }; }; - 'Registry': { kind: 'OBJECT'; name: 'Registry'; fields: { 'contract': { name: 'contract'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; }; } }; 'domains': { name: 'domains'; type: { kind: 'OBJECT'; name: 'RegistryDomainsConnection'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'RegistryId'; ofType: null; }; } }; 'parents': { name: 'parents'; type: { kind: 'OBJECT'; name: 'RegistryParentsConnection'; ofType: null; } }; 'permissions': { name: 'permissions'; type: { kind: 'OBJECT'; name: 'Permissions'; ofType: null; } }; }; }; - 'RegistryDomainsConnection': { kind: 'OBJECT'; name: 'RegistryDomainsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'RegistryDomainsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'RegistryDomainsConnectionEdge': { kind: 'OBJECT'; name: 'RegistryDomainsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'Domain'; ofType: null; }; } }; }; }; - 'RegistryDomainsWhereInput': { kind: 'INPUT_OBJECT'; name: 'RegistryDomainsWhereInput'; isOneOf: false; inputFields: [{ name: 'name'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; }; defaultValue: null }]; }; - 'RegistryId': unknown; - 'RegistryIdInput': { kind: 'INPUT_OBJECT'; name: 'RegistryIdInput'; isOneOf: true; inputFields: [{ name: 'contract'; type: { kind: 'INPUT_OBJECT'; name: 'AccountIdInput'; ofType: null; }; defaultValue: null }, { name: 'id'; type: { kind: 'SCALAR'; name: 'RegistryId'; ofType: null; }; defaultValue: null }]; }; - 'RegistryParentsConnection': { kind: 'OBJECT'; name: 'RegistryParentsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'RegistryParentsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'RegistryParentsConnectionEdge': { kind: 'OBJECT'; name: 'RegistryParentsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'ENSv2Domain'; ofType: null; }; } }; }; }; - 'RegistryPermissionsUser': { kind: 'OBJECT'; name: 'RegistryPermissionsUser'; fields: { 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'PermissionsUserId'; ofType: null; }; } }; 'registry': { name: 'registry'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Registry'; ofType: null; }; } }; 'resource': { name: 'resource'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'roles': { name: 'roles'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'user': { name: 'user'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Account'; ofType: null; }; } }; }; }; - 'Renewal': { kind: 'OBJECT'; name: 'Renewal'; fields: { 'base': { name: 'base'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'duration': { name: 'duration'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'event': { name: 'event'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Event'; ofType: null; }; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'RenewalId'; ofType: null; }; } }; 'premium': { name: 'premium'; type: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; } }; 'referrer': { name: 'referrer'; type: { kind: 'SCALAR'; name: 'Hex'; ofType: null; } }; }; }; - 'RenewalId': unknown; - 'Resolver': { kind: 'OBJECT'; name: 'Resolver'; fields: { 'bridged': { name: 'bridged'; type: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; } }; 'contract': { name: 'contract'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'AccountId'; ofType: null; }; } }; 'events': { name: 'events'; type: { kind: 'OBJECT'; name: 'ResolverEventsConnection'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ResolverId'; ofType: null; }; } }; 'permissions': { name: 'permissions'; type: { kind: 'OBJECT'; name: 'Permissions'; ofType: null; } }; 'records': { name: 'records'; type: { kind: 'OBJECT'; name: 'ResolverRecordsConnection'; ofType: null; } }; 'records_': { name: 'records_'; type: { kind: 'OBJECT'; name: 'ResolverRecords'; ofType: null; } }; }; }; - 'ResolverEventsConnection': { kind: 'OBJECT'; name: 'ResolverEventsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'ResolverEventsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'ResolverEventsConnectionEdge': { kind: 'OBJECT'; name: 'ResolverEventsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Event'; ofType: null; }; } }; }; }; - 'ResolverId': unknown; - 'ResolverIdInput': { kind: 'INPUT_OBJECT'; name: 'ResolverIdInput'; isOneOf: true; inputFields: [{ name: 'contract'; type: { kind: 'INPUT_OBJECT'; name: 'AccountIdInput'; ofType: null; }; defaultValue: null }, { name: 'id'; type: { kind: 'SCALAR'; name: 'ResolverId'; ofType: null; }; defaultValue: null }]; }; - 'ResolverPermissionsUser': { kind: 'OBJECT'; name: 'ResolverPermissionsUser'; fields: { 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'PermissionsUserId'; ofType: null; }; } }; 'resolver': { name: 'resolver'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Resolver'; ofType: null; }; } }; 'resource': { name: 'resource'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'roles': { name: 'roles'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'BigInt'; ofType: null; }; } }; 'user': { name: 'user'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Account'; ofType: null; }; } }; }; }; - 'ResolverRecords': { kind: 'OBJECT'; name: 'ResolverRecords'; fields: { 'coinTypes': { name: 'coinTypes'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'CoinType'; ofType: null; }; }; }; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ResolverRecordsId'; ofType: null; }; } }; 'keys': { name: 'keys'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; }; }; } }; 'name': { name: 'name'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Node'; ofType: null; }; } }; }; }; - 'ResolverRecordsConnection': { kind: 'OBJECT'; name: 'ResolverRecordsConnection'; fields: { 'edges': { name: 'edges'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'ResolverRecordsConnectionEdge'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; - 'ResolverRecordsConnectionEdge': { kind: 'OBJECT'; name: 'ResolverRecordsConnectionEdge'; fields: { 'cursor': { name: 'cursor'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'node': { name: 'node'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'ResolverRecords'; ofType: null; }; } }; }; }; - 'ResolverRecordsId': unknown; - 'String': unknown; - 'SubdomainsWhereInput': { kind: 'INPUT_OBJECT'; name: 'SubdomainsWhereInput'; isOneOf: false; inputFields: [{ name: 'name'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; }; defaultValue: null }]; }; - '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/graphql-env.ts b/packages/enssdk/src/omnigraph/generated/graphql-env.ts new file mode 100644 index 000000000..5b128d151 --- /dev/null +++ b/packages/enssdk/src/omnigraph/generated/graphql-env.ts @@ -0,0 +1,5767 @@ +/* eslint-disable */ +/* prettier-ignore */ + +/** An IntrospectionQuery representation of your schema. + * + * @remarks + * This is an introspection of your schema saved as a file by GraphQLSP. + * You may import it to create a `graphql()` tag function with `gql.tada` + * by importing it and passing it to `initGraphQLTada<>()`. + * + * @example + * ``` + * import { initGraphQLTada } from 'gql.tada'; + * import type { introspection } from './introspection'; + * + * export const graphql = initGraphQLTada<{ + * introspection: typeof introspection; + * scalars: { + * DateTime: string; + * Json: any; + * }; + * }>(); + * ``` + */ +const introspection = { + "__schema": { + "queryType": { + "name": "Query" + }, + "mutationType": null, + "subscriptionType": null, + "types": [ + { + "kind": "OBJECT", + "name": "Account", + "fields": [ + { + "name": "address", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Address" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "domains", + "type": { + "kind": "OBJECT", + "name": "AccountDomainsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "order", + "type": { + "kind": "INPUT_OBJECT", + "name": "DomainsOrderInput" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "AccountDomainsWhereInput" + } + } + ], + "isDeprecated": false + }, + { + "name": "events", + "type": { + "kind": "OBJECT", + "name": "AccountEventsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "AccountEventsWhereInput" + } + } + ], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Address" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "permissions", + "type": { + "kind": "OBJECT", + "name": "AccountPermissionsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "in", + "type": { + "kind": "INPUT_OBJECT", + "name": "AccountIdInput" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "registryPermissions", + "type": { + "kind": "OBJECT", + "name": "AccountRegistryPermissionsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "resolverPermissions", + "type": { + "kind": "OBJECT", + "name": "AccountResolverPermissionsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "INPUT_OBJECT", + "name": "AccountByInput", + "inputFields": [ + { + "name": "address", + "type": { + "kind": "SCALAR", + "name": "Address" + } + }, + { + "name": "id", + "type": { + "kind": "SCALAR", + "name": "Address" + } + } + ], + "isOneOf": true + }, + { + "kind": "OBJECT", + "name": "AccountDomainsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountDomainsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "AccountDomainsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "INPUT_OBJECT", + "name": "AccountDomainsWhereInput", + "inputFields": [ + { + "name": "canonical", + "type": { + "kind": "SCALAR", + "name": "Boolean" + }, + "defaultValue": "false" + }, + { + "name": "name", + "type": { + "kind": "SCALAR", + "name": "String" + } + } + ], + "isOneOf": false + }, + { + "kind": "OBJECT", + "name": "AccountEventsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountEventsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "AccountEventsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "INPUT_OBJECT", + "name": "AccountEventsWhereInput", + "inputFields": [ + { + "name": "selector_in", + "type": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Hex" + } + } + } + }, + { + "name": "timestamp_gte", + "type": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + { + "name": "timestamp_lte", + "type": { + "kind": "SCALAR", + "name": "BigInt" + } + } + ], + "isOneOf": false + }, + { + "kind": "OBJECT", + "name": "AccountId", + "fields": [ + { + "name": "address", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Address" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "chainId", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "ChainId" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "INPUT_OBJECT", + "name": "AccountIdInput", + "inputFields": [ + { + "name": "address", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Address" + } + } + }, + { + "name": "chainId", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "ChainId" + } + } + } + ], + "isOneOf": false + }, + { + "kind": "OBJECT", + "name": "AccountPermissionsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountPermissionsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "AccountPermissionsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PermissionsUser" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "AccountRegistryPermissionsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountRegistryPermissionsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "AccountRegistryPermissionsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "RegistryPermissionsUser" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "AccountResolverPermissionsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountResolverPermissionsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "AccountResolverPermissionsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "ResolverPermissionsUser" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "SCALAR", + "name": "Address" + }, + { + "kind": "OBJECT", + "name": "BaseRegistrarRegistration", + "fields": [ + { + "name": "baseCost", + "type": { + "kind": "SCALAR", + "name": "BigInt" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "domain", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "event", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expired", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Boolean" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expiry", + "type": { + "kind": "SCALAR", + "name": "BigInt" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "RegistrationId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "isInGracePeriod", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Boolean" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "premium", + "type": { + "kind": "SCALAR", + "name": "BigInt" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "referrer", + "type": { + "kind": "SCALAR", + "name": "Hex" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrar", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "renewals", + "type": { + "kind": "OBJECT", + "name": "RegistrationRenewalsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "start", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "unregistrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "wrapped", + "type": { + "kind": "OBJECT", + "name": "WrappedBaseRegistrarRegistration" + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Registration" + } + ] + }, + { + "kind": "SCALAR", + "name": "BigInt" + }, + { + "kind": "SCALAR", + "name": "Boolean" + }, + { + "kind": "SCALAR", + "name": "ChainId" + }, + { + "kind": "SCALAR", + "name": "CoinType" + }, + { + "kind": "INTERFACE", + "name": "Domain", + "fields": [ + { + "name": "events", + "type": { + "kind": "OBJECT", + "name": "DomainEventsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EventsWhereInput" + } + } + ], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "DomainId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "label", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Label" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "name", + "type": { + "kind": "SCALAR", + "name": "InterpretedName" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "owner", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "path", + "type": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registration", + "type": { + "kind": "INTERFACE", + "name": "Registration" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrations", + "type": { + "kind": "OBJECT", + "name": "DomainRegistrationsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "resolver", + "type": { + "kind": "OBJECT", + "name": "Resolver" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "subdomains", + "type": { + "kind": "OBJECT", + "name": "DomainSubdomainsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "order", + "type": { + "kind": "INPUT_OBJECT", + "name": "DomainsOrderInput" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "SubdomainsWhereInput" + } + } + ], + "isDeprecated": false + } + ], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "ENSv1Domain" + }, + { + "kind": "OBJECT", + "name": "ENSv2Domain" + } + ] + }, + { + "kind": "OBJECT", + "name": "DomainEventsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "DomainEventsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "DomainEventsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "SCALAR", + "name": "DomainId" + }, + { + "kind": "INPUT_OBJECT", + "name": "DomainIdInput", + "inputFields": [ + { + "name": "id", + "type": { + "kind": "SCALAR", + "name": "DomainId" + } + }, + { + "name": "name", + "type": { + "kind": "SCALAR", + "name": "InterpretedName" + } + } + ], + "isOneOf": true + }, + { + "kind": "INPUT_OBJECT", + "name": "DomainPermissionsWhereInput", + "inputFields": [ + { + "name": "user", + "type": { + "kind": "SCALAR", + "name": "Address" + } + } + ], + "isOneOf": false + }, + { + "kind": "OBJECT", + "name": "DomainRegistrationsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "DomainRegistrationsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "DomainRegistrationsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Registration" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "DomainSubdomainsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "DomainSubdomainsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "DomainSubdomainsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "ENUM", + "name": "DomainsOrderBy", + "enumValues": [ + { + "name": "NAME", + "isDeprecated": false + }, + { + "name": "REGISTRATION_EXPIRY", + "isDeprecated": false + }, + { + "name": "REGISTRATION_TIMESTAMP", + "isDeprecated": false + } + ] + }, + { + "kind": "INPUT_OBJECT", + "name": "DomainsOrderInput", + "inputFields": [ + { + "name": "by", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "ENUM", + "name": "DomainsOrderBy" + } + } + }, + { + "name": "dir", + "type": { + "kind": "ENUM", + "name": "OrderDirection" + }, + "defaultValue": "ASC" + } + ], + "isOneOf": false + }, + { + "kind": "INPUT_OBJECT", + "name": "DomainsWhereInput", + "inputFields": [ + { + "name": "canonical", + "type": { + "kind": "SCALAR", + "name": "Boolean" + }, + "defaultValue": "false" + }, + { + "name": "name", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + } + } + ], + "isOneOf": false + }, + { + "kind": "OBJECT", + "name": "ENSv1Domain", + "fields": [ + { + "name": "events", + "type": { + "kind": "OBJECT", + "name": "DomainEventsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EventsWhereInput" + } + } + ], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "DomainId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "label", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Label" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "name", + "type": { + "kind": "SCALAR", + "name": "InterpretedName" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "owner", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "parent", + "type": { + "kind": "OBJECT", + "name": "ENSv1Domain" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "path", + "type": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registration", + "type": { + "kind": "INTERFACE", + "name": "Registration" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrations", + "type": { + "kind": "OBJECT", + "name": "DomainRegistrationsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "resolver", + "type": { + "kind": "OBJECT", + "name": "Resolver" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "rootRegistryOwner", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "subdomains", + "type": { + "kind": "OBJECT", + "name": "DomainSubdomainsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "order", + "type": { + "kind": "INPUT_OBJECT", + "name": "DomainsOrderInput" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "SubdomainsWhereInput" + } + } + ], + "isDeprecated": false + } + ], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Domain" + } + ] + }, + { + "kind": "OBJECT", + "name": "ENSv2Domain", + "fields": [ + { + "name": "events", + "type": { + "kind": "OBJECT", + "name": "DomainEventsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EventsWhereInput" + } + } + ], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "DomainId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "label", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Label" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "name", + "type": { + "kind": "SCALAR", + "name": "InterpretedName" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "owner", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "path", + "type": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "permissions", + "type": { + "kind": "OBJECT", + "name": "ENSv2DomainPermissionsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "DomainPermissionsWhereInput" + } + } + ], + "isDeprecated": false + }, + { + "name": "registration", + "type": { + "kind": "INTERFACE", + "name": "Registration" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrations", + "type": { + "kind": "OBJECT", + "name": "DomainRegistrationsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "registry", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Registry" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "resolver", + "type": { + "kind": "OBJECT", + "name": "Resolver" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "subdomains", + "type": { + "kind": "OBJECT", + "name": "DomainSubdomainsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "order", + "type": { + "kind": "INPUT_OBJECT", + "name": "DomainsOrderInput" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "SubdomainsWhereInput" + } + } + ], + "isDeprecated": false + }, + { + "name": "subregistry", + "type": { + "kind": "OBJECT", + "name": "Registry" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "tokenId", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Domain" + } + ] + }, + { + "kind": "OBJECT", + "name": "ENSv2DomainPermissionsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "ENSv2DomainPermissionsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "ENSv2DomainPermissionsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PermissionsUser" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "ENSv2RegistryRegistration", + "fields": [ + { + "name": "domain", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "event", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expired", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Boolean" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expiry", + "type": { + "kind": "SCALAR", + "name": "BigInt" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "RegistrationId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "referrer", + "type": { + "kind": "SCALAR", + "name": "Hex" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrar", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "renewals", + "type": { + "kind": "OBJECT", + "name": "RegistrationRenewalsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "start", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "unregistrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Registration" + } + ] + }, + { + "kind": "OBJECT", + "name": "ENSv2RegistryReservation", + "fields": [ + { + "name": "domain", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "event", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expired", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Boolean" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expiry", + "type": { + "kind": "SCALAR", + "name": "BigInt" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "RegistrationId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "referrer", + "type": { + "kind": "SCALAR", + "name": "Hex" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrar", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "renewals", + "type": { + "kind": "OBJECT", + "name": "RegistrationRenewalsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "start", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "unregistrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Registration" + } + ] + }, + { + "kind": "OBJECT", + "name": "Event", + "fields": [ + { + "name": "address", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Address" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "blockHash", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Hex" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "blockNumber", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "chainId", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "ChainId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "data", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Hex" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "from", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Address" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "ID" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "logIndex", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "timestamp", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "to", + "type": { + "kind": "SCALAR", + "name": "Address" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "topics", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Hex" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "transactionHash", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Hex" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "transactionIndex", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "INPUT_OBJECT", + "name": "EventsWhereInput", + "inputFields": [ + { + "name": "from", + "type": { + "kind": "SCALAR", + "name": "Address" + } + }, + { + "name": "selector_in", + "type": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Hex" + } + } + } + }, + { + "name": "timestamp_gte", + "type": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + { + "name": "timestamp_lte", + "type": { + "kind": "SCALAR", + "name": "BigInt" + } + } + ], + "isOneOf": false + }, + { + "kind": "SCALAR", + "name": "Hex" + }, + { + "kind": "SCALAR", + "name": "ID" + }, + { + "kind": "SCALAR", + "name": "Int" + }, + { + "kind": "SCALAR", + "name": "InterpretedLabel" + }, + { + "kind": "SCALAR", + "name": "InterpretedName" + }, + { + "kind": "OBJECT", + "name": "Label", + "fields": [ + { + "name": "hash", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Hex" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "interpreted", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "InterpretedLabel" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "INPUT_OBJECT", + "name": "NameOrNodeInput", + "inputFields": [ + { + "name": "name", + "type": { + "kind": "SCALAR", + "name": "InterpretedName" + } + }, + { + "name": "node", + "type": { + "kind": "SCALAR", + "name": "Node" + } + } + ], + "isOneOf": true + }, + { + "kind": "OBJECT", + "name": "NameWrapperRegistration", + "fields": [ + { + "name": "domain", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "event", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expired", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Boolean" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expiry", + "type": { + "kind": "SCALAR", + "name": "BigInt" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "fuses", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "RegistrationId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "referrer", + "type": { + "kind": "SCALAR", + "name": "Hex" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrar", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "renewals", + "type": { + "kind": "OBJECT", + "name": "RegistrationRenewalsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "start", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "unregistrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Registration" + } + ] + }, + { + "kind": "SCALAR", + "name": "Node" + }, + { + "kind": "ENUM", + "name": "OrderDirection", + "enumValues": [ + { + "name": "ASC", + "isDeprecated": false + }, + { + "name": "DESC", + "isDeprecated": false + } + ] + }, + { + "kind": "OBJECT", + "name": "PageInfo", + "fields": [ + { + "name": "endCursor", + "type": { + "kind": "SCALAR", + "name": "String" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "hasNextPage", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Boolean" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "hasPreviousPage", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Boolean" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "startCursor", + "type": { + "kind": "SCALAR", + "name": "String" + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "Permissions", + "fields": [ + { + "name": "contract", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "events", + "type": { + "kind": "OBJECT", + "name": "PermissionsEventsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EventsWhereInput" + } + } + ], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "PermissionsId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "resources", + "type": { + "kind": "OBJECT", + "name": "PermissionsResourcesConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "root", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PermissionsResource" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "PermissionsEventsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PermissionsEventsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "PermissionsEventsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "SCALAR", + "name": "PermissionsId" + }, + { + "kind": "INPUT_OBJECT", + "name": "PermissionsIdInput", + "inputFields": [ + { + "name": "contract", + "type": { + "kind": "INPUT_OBJECT", + "name": "AccountIdInput" + } + }, + { + "name": "id", + "type": { + "kind": "SCALAR", + "name": "PermissionsId" + } + } + ], + "isOneOf": true + }, + { + "kind": "OBJECT", + "name": "PermissionsResource", + "fields": [ + { + "name": "contract", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "PermissionsResourceId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "permissions", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Permissions" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "resource", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "users", + "type": { + "kind": "OBJECT", + "name": "PermissionsResourceUsersConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "SCALAR", + "name": "PermissionsResourceId" + }, + { + "kind": "OBJECT", + "name": "PermissionsResourceUsersConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PermissionsResourceUsersConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "PermissionsResourceUsersConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PermissionsUser" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "PermissionsResourcesConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PermissionsResourcesConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "PermissionsResourcesConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PermissionsResource" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "PermissionsUser", + "fields": [ + { + "name": "contract", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "PermissionsUserId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "resource", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "roles", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "user", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Account" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "SCALAR", + "name": "PermissionsUserId" + }, + { + "kind": "OBJECT", + "name": "Query", + "fields": [ + { + "name": "account", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [ + { + "name": "by", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INPUT_OBJECT", + "name": "AccountByInput" + } + } + } + ], + "isDeprecated": false + }, + { + "name": "domain", + "type": { + "kind": "INTERFACE", + "name": "Domain" + }, + "args": [ + { + "name": "by", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INPUT_OBJECT", + "name": "DomainIdInput" + } + } + } + ], + "isDeprecated": false + }, + { + "name": "domains", + "type": { + "kind": "OBJECT", + "name": "QueryDomainsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "order", + "type": { + "kind": "INPUT_OBJECT", + "name": "DomainsOrderInput" + } + }, + { + "name": "where", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INPUT_OBJECT", + "name": "DomainsWhereInput" + } + } + } + ], + "isDeprecated": false + }, + { + "name": "permissions", + "type": { + "kind": "OBJECT", + "name": "Permissions" + }, + "args": [ + { + "name": "by", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INPUT_OBJECT", + "name": "PermissionsIdInput" + } + } + } + ], + "isDeprecated": false + }, + { + "name": "registrations", + "type": { + "kind": "OBJECT", + "name": "QueryRegistrationsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "registry", + "type": { + "kind": "OBJECT", + "name": "Registry" + }, + "args": [ + { + "name": "by", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INPUT_OBJECT", + "name": "RegistryIdInput" + } + } + } + ], + "isDeprecated": false + }, + { + "name": "resolver", + "type": { + "kind": "OBJECT", + "name": "Resolver" + }, + "args": [ + { + "name": "by", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INPUT_OBJECT", + "name": "ResolverIdInput" + } + } + } + ], + "isDeprecated": false + }, + { + "name": "resolvers", + "type": { + "kind": "OBJECT", + "name": "QueryResolversConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "root", + "type": { + "kind": "OBJECT", + "name": "Registry" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "v1Domains", + "type": { + "kind": "OBJECT", + "name": "QueryV1DomainsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "v2Domains", + "type": { + "kind": "OBJECT", + "name": "QueryV2DomainsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "QueryDomainsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "QueryDomainsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "QueryDomainsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "QueryRegistrationsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "QueryRegistrationsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "QueryRegistrationsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Registration" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "QueryResolversConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "QueryResolversConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "QueryResolversConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Resolver" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "QueryV1DomainsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "QueryV1DomainsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "QueryV1DomainsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "ENSv1Domain" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "QueryV2DomainsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "QueryV2DomainsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "QueryV2DomainsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "ENSv2Domain" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "INTERFACE", + "name": "Registration", + "fields": [ + { + "name": "domain", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "event", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expired", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Boolean" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expiry", + "type": { + "kind": "SCALAR", + "name": "BigInt" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "RegistrationId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "referrer", + "type": { + "kind": "SCALAR", + "name": "Hex" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrar", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "renewals", + "type": { + "kind": "OBJECT", + "name": "RegistrationRenewalsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "start", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "unregistrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "BaseRegistrarRegistration" + }, + { + "kind": "OBJECT", + "name": "ENSv2RegistryRegistration" + }, + { + "kind": "OBJECT", + "name": "ENSv2RegistryReservation" + }, + { + "kind": "OBJECT", + "name": "NameWrapperRegistration" + }, + { + "kind": "OBJECT", + "name": "ThreeDNSRegistration" + } + ] + }, + { + "kind": "SCALAR", + "name": "RegistrationId" + }, + { + "kind": "OBJECT", + "name": "RegistrationRenewalsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "RegistrationRenewalsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "RegistrationRenewalsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Renewal" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "Registry", + "fields": [ + { + "name": "contract", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "domains", + "type": { + "kind": "OBJECT", + "name": "RegistryDomainsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "order", + "type": { + "kind": "INPUT_OBJECT", + "name": "DomainsOrderInput" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "RegistryDomainsWhereInput" + } + } + ], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "RegistryId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "parents", + "type": { + "kind": "OBJECT", + "name": "RegistryParentsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "permissions", + "type": { + "kind": "OBJECT", + "name": "Permissions" + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "RegistryDomainsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "RegistryDomainsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "RegistryDomainsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "INPUT_OBJECT", + "name": "RegistryDomainsWhereInput", + "inputFields": [ + { + "name": "name", + "type": { + "kind": "SCALAR", + "name": "String" + } + } + ], + "isOneOf": false + }, + { + "kind": "SCALAR", + "name": "RegistryId" + }, + { + "kind": "INPUT_OBJECT", + "name": "RegistryIdInput", + "inputFields": [ + { + "name": "contract", + "type": { + "kind": "INPUT_OBJECT", + "name": "AccountIdInput" + } + }, + { + "name": "id", + "type": { + "kind": "SCALAR", + "name": "RegistryId" + } + } + ], + "isOneOf": true + }, + { + "kind": "OBJECT", + "name": "RegistryParentsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "RegistryParentsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "RegistryParentsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "ENSv2Domain" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "RegistryPermissionsUser", + "fields": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "PermissionsUserId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registry", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Registry" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "resource", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "roles", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "user", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Account" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "Renewal", + "fields": [ + { + "name": "base", + "type": { + "kind": "SCALAR", + "name": "BigInt" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "duration", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "event", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "RenewalId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "premium", + "type": { + "kind": "SCALAR", + "name": "BigInt" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "referrer", + "type": { + "kind": "SCALAR", + "name": "Hex" + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "SCALAR", + "name": "RenewalId" + }, + { + "kind": "OBJECT", + "name": "Resolver", + "fields": [ + { + "name": "bridged", + "type": { + "kind": "OBJECT", + "name": "AccountId" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "contract", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "events", + "type": { + "kind": "OBJECT", + "name": "ResolverEventsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EventsWhereInput" + } + } + ], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "ResolverId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "permissions", + "type": { + "kind": "OBJECT", + "name": "Permissions" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "records", + "type": { + "kind": "OBJECT", + "name": "ResolverRecordsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "records_", + "type": { + "kind": "OBJECT", + "name": "ResolverRecords" + }, + "args": [ + { + "name": "for", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NameOrNodeInput" + } + } + } + ], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "ResolverEventsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "ResolverEventsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "ResolverEventsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "SCALAR", + "name": "ResolverId" + }, + { + "kind": "INPUT_OBJECT", + "name": "ResolverIdInput", + "inputFields": [ + { + "name": "contract", + "type": { + "kind": "INPUT_OBJECT", + "name": "AccountIdInput" + } + }, + { + "name": "id", + "type": { + "kind": "SCALAR", + "name": "ResolverId" + } + } + ], + "isOneOf": true + }, + { + "kind": "OBJECT", + "name": "ResolverPermissionsUser", + "fields": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "PermissionsUserId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "resolver", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Resolver" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "resource", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "roles", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "user", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Account" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "ResolverRecords", + "fields": [ + { + "name": "coinTypes", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "CoinType" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "ResolverRecordsId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "keys", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "name", + "type": { + "kind": "SCALAR", + "name": "String" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Node" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "ResolverRecordsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "ResolverRecordsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "ResolverRecordsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "ResolverRecords" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "SCALAR", + "name": "ResolverRecordsId" + }, + { + "kind": "SCALAR", + "name": "String" + }, + { + "kind": "INPUT_OBJECT", + "name": "SubdomainsWhereInput", + "inputFields": [ + { + "name": "name", + "type": { + "kind": "SCALAR", + "name": "String" + } + } + ], + "isOneOf": false + }, + { + "kind": "OBJECT", + "name": "ThreeDNSRegistration", + "fields": [ + { + "name": "domain", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "event", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expired", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Boolean" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expiry", + "type": { + "kind": "SCALAR", + "name": "BigInt" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "RegistrationId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "referrer", + "type": { + "kind": "SCALAR", + "name": "Hex" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrar", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "renewals", + "type": { + "kind": "OBJECT", + "name": "RegistrationRenewalsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "start", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "unregistrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Registration" + } + ] + }, + { + "kind": "OBJECT", + "name": "WrappedBaseRegistrarRegistration", + "fields": [ + { + "name": "fuses", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "tokenId", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + } + ], + "directives": [] + } +} as const; + +export { introspection }; \ No newline at end of file diff --git a/packages/enssdk/src/omnigraph/generated/introspection.ts b/packages/enssdk/src/omnigraph/generated/introspection.ts index 2c0c938fc..d37c822cf 100644 --- a/packages/enssdk/src/omnigraph/generated/introspection.ts +++ b/packages/enssdk/src/omnigraph/generated/introspection.ts @@ -1 +1 @@ -export const introspection = {"__schema":{"queryType":{"name":"Query","kind":"OBJECT"},"mutationType":null,"subscriptionType":null,"types":[{"kind":"OBJECT","name":"Account","fields":[{"name":"address","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"domains","type":{"kind":"OBJECT","name":"AccountDomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"events","type":{"kind":"OBJECT","name":"AccountEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"permissions","type":{"kind":"OBJECT","name":"AccountPermissionsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"in","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"registryPermissions","type":{"kind":"OBJECT","name":"AccountRegistryPermissionsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"resolverPermissions","type":{"kind":"OBJECT","name":"AccountResolverPermissionsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountDomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountDomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountDomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountEventsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountEventsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountEventsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountId","fields":[{"name":"address","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"chainId","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountPermissionsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountPermissionsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountPermissionsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsUser","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountRegistryPermissionsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountRegistryPermissionsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountRegistryPermissionsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"RegistryPermissionsUser","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountResolverPermissionsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountResolverPermissionsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountResolverPermissionsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ResolverPermissionsUser","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"BaseRegistrarRegistration","fields":[{"name":"baseCost","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"isInGracePeriod","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"premium","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"wrapped","type":{"kind":"OBJECT","name":"WrappedBaseRegistrarRegistration","ofType":null},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Registration"}]},{"kind":"INTERFACE","name":"Domain","fields":[{"name":"events","type":{"kind":"OBJECT","name":"DomainEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"label","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Label","ofType":null}},"args":[]},{"name":"name","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"owner","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"path","type":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}}},"args":[]},{"name":"registration","type":{"kind":"INTERFACE","name":"Registration","ofType":null},"args":[]},{"name":"registrations","type":{"kind":"OBJECT","name":"DomainRegistrationsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"resolver","type":{"kind":"OBJECT","name":"Resolver","ofType":null},"args":[]},{"name":"subdomains","type":{"kind":"OBJECT","name":"DomainSubdomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]}],"interfaces":[],"possibleTypes":[{"kind":"OBJECT","name":"ENSv1Domain"},{"kind":"OBJECT","name":"ENSv2Domain"}]},{"kind":"OBJECT","name":"DomainEventsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"DomainEventsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"DomainEventsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"DomainRegistrationsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"DomainRegistrationsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"DomainRegistrationsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Registration","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"DomainSubdomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"DomainSubdomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"DomainSubdomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ENSv1Domain","fields":[{"name":"events","type":{"kind":"OBJECT","name":"DomainEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"label","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Label","ofType":null}},"args":[]},{"name":"name","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"owner","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"parent","type":{"kind":"OBJECT","name":"ENSv1Domain","ofType":null},"args":[]},{"name":"path","type":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}}},"args":[]},{"name":"registration","type":{"kind":"INTERFACE","name":"Registration","ofType":null},"args":[]},{"name":"registrations","type":{"kind":"OBJECT","name":"DomainRegistrationsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"resolver","type":{"kind":"OBJECT","name":"Resolver","ofType":null},"args":[]},{"name":"rootRegistryOwner","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"subdomains","type":{"kind":"OBJECT","name":"DomainSubdomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]}],"interfaces":[{"kind":"INTERFACE","name":"Domain"}]},{"kind":"OBJECT","name":"ENSv2Domain","fields":[{"name":"events","type":{"kind":"OBJECT","name":"DomainEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"label","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Label","ofType":null}},"args":[]},{"name":"name","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"owner","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"path","type":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}}},"args":[]},{"name":"permissions","type":{"kind":"OBJECT","name":"ENSv2DomainPermissionsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"registration","type":{"kind":"INTERFACE","name":"Registration","ofType":null},"args":[]},{"name":"registrations","type":{"kind":"OBJECT","name":"DomainRegistrationsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"registry","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Registry","ofType":null}},"args":[]},{"name":"resolver","type":{"kind":"OBJECT","name":"Resolver","ofType":null},"args":[]},{"name":"subdomains","type":{"kind":"OBJECT","name":"DomainSubdomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"subregistry","type":{"kind":"OBJECT","name":"Registry","ofType":null},"args":[]},{"name":"tokenId","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Domain"}]},{"kind":"OBJECT","name":"ENSv2DomainPermissionsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ENSv2DomainPermissionsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ENSv2DomainPermissionsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsUser","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ENSv2RegistryRegistration","fields":[{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Registration"}]},{"kind":"OBJECT","name":"ENSv2RegistryReservation","fields":[{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Registration"}]},{"kind":"OBJECT","name":"Event","fields":[{"name":"address","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"blockHash","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"blockNumber","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"chainId","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"data","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"from","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"logIndex","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"timestamp","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"to","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"topics","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}},"args":[]},{"name":"transactionHash","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"transactionIndex","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"Label","fields":[{"name":"hash","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"interpreted","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"NameWrapperRegistration","fields":[{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"fuses","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Registration"}]},{"kind":"OBJECT","name":"PageInfo","fields":[{"name":"endCursor","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"hasNextPage","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"hasPreviousPage","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"startCursor","type":{"kind":"SCALAR","name":"Any"},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"Permissions","fields":[{"name":"contract","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"events","type":{"kind":"OBJECT","name":"PermissionsEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"resources","type":{"kind":"OBJECT","name":"PermissionsResourcesConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"root","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsResource","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsEventsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsEventsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsEventsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsResource","fields":[{"name":"contract","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"permissions","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Permissions","ofType":null}},"args":[]},{"name":"resource","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"users","type":{"kind":"OBJECT","name":"PermissionsResourceUsersConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsResourceUsersConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsResourceUsersConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsResourceUsersConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsUser","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsResourcesConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsResourcesConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsResourcesConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsResource","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsUser","fields":[{"name":"contract","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"resource","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"roles","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"user","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Account","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"Query","fields":[{"name":"account","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[{"name":"by","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"domain","type":{"kind":"INTERFACE","name":"Domain","ofType":null},"args":[{"name":"by","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"domains","type":{"kind":"OBJECT","name":"QueryDomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"permissions","type":{"kind":"OBJECT","name":"Permissions","ofType":null},"args":[{"name":"by","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"registrations","type":{"kind":"OBJECT","name":"QueryRegistrationsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"registry","type":{"kind":"OBJECT","name":"Registry","ofType":null},"args":[{"name":"by","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"resolver","type":{"kind":"OBJECT","name":"Resolver","ofType":null},"args":[{"name":"by","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"resolvers","type":{"kind":"OBJECT","name":"QueryResolversConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"root","type":{"kind":"OBJECT","name":"Registry","ofType":null},"args":[]},{"name":"v1Domains","type":{"kind":"OBJECT","name":"QueryV1DomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"v2Domains","type":{"kind":"OBJECT","name":"QueryV2DomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryDomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"QueryDomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryDomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryRegistrationsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"QueryRegistrationsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryRegistrationsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Registration","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryResolversConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"QueryResolversConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryResolversConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Resolver","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryV1DomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"QueryV1DomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryV1DomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ENSv1Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryV2DomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"QueryV2DomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryV2DomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ENSv2Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"INTERFACE","name":"Registration","fields":[{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]}],"interfaces":[],"possibleTypes":[{"kind":"OBJECT","name":"BaseRegistrarRegistration"},{"kind":"OBJECT","name":"ENSv2RegistryRegistration"},{"kind":"OBJECT","name":"ENSv2RegistryReservation"},{"kind":"OBJECT","name":"NameWrapperRegistration"},{"kind":"OBJECT","name":"ThreeDNSRegistration"}]},{"kind":"OBJECT","name":"RegistrationRenewalsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"RegistrationRenewalsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistrationRenewalsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Renewal","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"Registry","fields":[{"name":"contract","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"domains","type":{"kind":"OBJECT","name":"RegistryDomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"parents","type":{"kind":"OBJECT","name":"RegistryParentsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"permissions","type":{"kind":"OBJECT","name":"Permissions","ofType":null},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistryDomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"RegistryDomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistryDomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistryParentsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"RegistryParentsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistryParentsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ENSv2Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistryPermissionsUser","fields":[{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"registry","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Registry","ofType":null}},"args":[]},{"name":"resource","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"roles","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"user","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Account","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"Renewal","fields":[{"name":"base","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"duration","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"premium","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Any"},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"Resolver","fields":[{"name":"bridged","type":{"kind":"OBJECT","name":"AccountId","ofType":null},"args":[]},{"name":"contract","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"events","type":{"kind":"OBJECT","name":"ResolverEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"permissions","type":{"kind":"OBJECT","name":"Permissions","ofType":null},"args":[]},{"name":"records","type":{"kind":"OBJECT","name":"ResolverRecordsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"records_","type":{"kind":"OBJECT","name":"ResolverRecords","ofType":null},"args":[{"name":"for","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverEventsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ResolverEventsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverEventsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverPermissionsUser","fields":[{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"resolver","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Resolver","ofType":null}},"args":[]},{"name":"resource","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"roles","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"user","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Account","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverRecords","fields":[{"name":"coinTypes","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"keys","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}},"args":[]},{"name":"name","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverRecordsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ResolverRecordsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverRecordsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ResolverRecords","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ThreeDNSRegistration","fields":[{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Any"},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"Any"}},{"name":"before","type":{"kind":"SCALAR","name":"Any"}},{"name":"first","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Registration"}]},{"kind":"OBJECT","name":"WrappedBaseRegistrarRegistration","fields":[{"name":"fuses","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]},{"name":"tokenId","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"Any"}],"directives":[]}} as const; +export const introspection = {"__schema":{"queryType":{"name":"Query","kind":"OBJECT"},"mutationType":null,"subscriptionType":null,"types":[{"kind":"OBJECT","name":"Account","fields":[{"name":"address","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Address","ofType":null}},"args":[]},{"name":"domains","type":{"kind":"OBJECT","name":"AccountDomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"events","type":{"kind":"OBJECT","name":"AccountEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Address","ofType":null}},"args":[]},{"name":"permissions","type":{"kind":"OBJECT","name":"AccountPermissionsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"in","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"registryPermissions","type":{"kind":"OBJECT","name":"AccountRegistryPermissionsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"resolverPermissions","type":{"kind":"OBJECT","name":"AccountResolverPermissionsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountDomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountDomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountDomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountEventsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountEventsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountEventsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountId","fields":[{"name":"address","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Address","ofType":null}},"args":[]},{"name":"chainId","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"ChainId","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountPermissionsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountPermissionsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountPermissionsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsUser","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountRegistryPermissionsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountRegistryPermissionsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountRegistryPermissionsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"RegistryPermissionsUser","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountResolverPermissionsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountResolverPermissionsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountResolverPermissionsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ResolverPermissionsUser","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"Address"},{"kind":"OBJECT","name":"BaseRegistrarRegistration","fields":[{"name":"baseCost","type":{"kind":"SCALAR","name":"BigInt","ofType":null},"args":[]},{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"BigInt","ofType":null},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"RegistrationId","ofType":null}},"args":[]},{"name":"isInGracePeriod","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"args":[]},{"name":"premium","type":{"kind":"SCALAR","name":"BigInt","ofType":null},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Hex","ofType":null},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"wrapped","type":{"kind":"OBJECT","name":"WrappedBaseRegistrarRegistration","ofType":null},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Registration"}]},{"kind":"SCALAR","name":"BigInt"},{"kind":"SCALAR","name":"Boolean"},{"kind":"SCALAR","name":"ChainId"},{"kind":"SCALAR","name":"CoinType"},{"kind":"INTERFACE","name":"Domain","fields":[{"name":"events","type":{"kind":"OBJECT","name":"DomainEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"DomainId","ofType":null}},"args":[]},{"name":"label","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Label","ofType":null}},"args":[]},{"name":"name","type":{"kind":"SCALAR","name":"InterpretedName","ofType":null},"args":[]},{"name":"owner","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"path","type":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}}},"args":[]},{"name":"registration","type":{"kind":"INTERFACE","name":"Registration","ofType":null},"args":[]},{"name":"registrations","type":{"kind":"OBJECT","name":"DomainRegistrationsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"resolver","type":{"kind":"OBJECT","name":"Resolver","ofType":null},"args":[]},{"name":"subdomains","type":{"kind":"OBJECT","name":"DomainSubdomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]}],"interfaces":[],"possibleTypes":[{"kind":"OBJECT","name":"ENSv1Domain"},{"kind":"OBJECT","name":"ENSv2Domain"}]},{"kind":"OBJECT","name":"DomainEventsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"DomainEventsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"DomainEventsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"DomainId"},{"kind":"OBJECT","name":"DomainRegistrationsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"DomainRegistrationsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"DomainRegistrationsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Registration","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"DomainSubdomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"DomainSubdomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"DomainSubdomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ENSv1Domain","fields":[{"name":"events","type":{"kind":"OBJECT","name":"DomainEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"DomainId","ofType":null}},"args":[]},{"name":"label","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Label","ofType":null}},"args":[]},{"name":"name","type":{"kind":"SCALAR","name":"InterpretedName","ofType":null},"args":[]},{"name":"owner","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"parent","type":{"kind":"OBJECT","name":"ENSv1Domain","ofType":null},"args":[]},{"name":"path","type":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}}},"args":[]},{"name":"registration","type":{"kind":"INTERFACE","name":"Registration","ofType":null},"args":[]},{"name":"registrations","type":{"kind":"OBJECT","name":"DomainRegistrationsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"resolver","type":{"kind":"OBJECT","name":"Resolver","ofType":null},"args":[]},{"name":"rootRegistryOwner","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"subdomains","type":{"kind":"OBJECT","name":"DomainSubdomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]}],"interfaces":[{"kind":"INTERFACE","name":"Domain"}]},{"kind":"OBJECT","name":"ENSv2Domain","fields":[{"name":"events","type":{"kind":"OBJECT","name":"DomainEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"DomainId","ofType":null}},"args":[]},{"name":"label","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Label","ofType":null}},"args":[]},{"name":"name","type":{"kind":"SCALAR","name":"InterpretedName","ofType":null},"args":[]},{"name":"owner","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"path","type":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}}},"args":[]},{"name":"permissions","type":{"kind":"OBJECT","name":"ENSv2DomainPermissionsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"registration","type":{"kind":"INTERFACE","name":"Registration","ofType":null},"args":[]},{"name":"registrations","type":{"kind":"OBJECT","name":"DomainRegistrationsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"registry","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Registry","ofType":null}},"args":[]},{"name":"resolver","type":{"kind":"OBJECT","name":"Resolver","ofType":null},"args":[]},{"name":"subdomains","type":{"kind":"OBJECT","name":"DomainSubdomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"subregistry","type":{"kind":"OBJECT","name":"Registry","ofType":null},"args":[]},{"name":"tokenId","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Domain"}]},{"kind":"OBJECT","name":"ENSv2DomainPermissionsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ENSv2DomainPermissionsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ENSv2DomainPermissionsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsUser","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ENSv2RegistryRegistration","fields":[{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"BigInt","ofType":null},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"RegistrationId","ofType":null}},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Hex","ofType":null},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Registration"}]},{"kind":"OBJECT","name":"ENSv2RegistryReservation","fields":[{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"BigInt","ofType":null},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"RegistrationId","ofType":null}},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Hex","ofType":null},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Registration"}]},{"kind":"OBJECT","name":"Event","fields":[{"name":"address","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Address","ofType":null}},"args":[]},{"name":"blockHash","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Hex","ofType":null}},"args":[]},{"name":"blockNumber","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"chainId","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"ChainId","ofType":null}},"args":[]},{"name":"data","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Hex","ofType":null}},"args":[]},{"name":"from","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Address","ofType":null}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"args":[]},{"name":"logIndex","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]},{"name":"timestamp","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"to","type":{"kind":"SCALAR","name":"Address","ofType":null},"args":[]},{"name":"topics","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Hex","ofType":null}}}},"args":[]},{"name":"transactionHash","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Hex","ofType":null}},"args":[]},{"name":"transactionIndex","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"Float"},{"kind":"SCALAR","name":"Hex"},{"kind":"SCALAR","name":"ID"},{"kind":"SCALAR","name":"Int"},{"kind":"SCALAR","name":"InterpretedLabel"},{"kind":"SCALAR","name":"InterpretedName"},{"kind":"OBJECT","name":"Label","fields":[{"name":"hash","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Hex","ofType":null}},"args":[]},{"name":"interpreted","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"InterpretedLabel","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"NameWrapperRegistration","fields":[{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"BigInt","ofType":null},"args":[]},{"name":"fuses","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"RegistrationId","ofType":null}},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Hex","ofType":null},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Registration"}]},{"kind":"SCALAR","name":"Node"},{"kind":"OBJECT","name":"PageInfo","fields":[{"name":"endCursor","type":{"kind":"SCALAR","name":"String","ofType":null},"args":[]},{"name":"hasNextPage","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"args":[]},{"name":"hasPreviousPage","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"args":[]},{"name":"startCursor","type":{"kind":"SCALAR","name":"String","ofType":null},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"Permissions","fields":[{"name":"contract","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"events","type":{"kind":"OBJECT","name":"PermissionsEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"PermissionsId","ofType":null}},"args":[]},{"name":"resources","type":{"kind":"OBJECT","name":"PermissionsResourcesConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"root","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsResource","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsEventsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsEventsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsEventsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"PermissionsId"},{"kind":"OBJECT","name":"PermissionsResource","fields":[{"name":"contract","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"PermissionsResourceId","ofType":null}},"args":[]},{"name":"permissions","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Permissions","ofType":null}},"args":[]},{"name":"resource","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"users","type":{"kind":"OBJECT","name":"PermissionsResourceUsersConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]}],"interfaces":[]},{"kind":"SCALAR","name":"PermissionsResourceId"},{"kind":"OBJECT","name":"PermissionsResourceUsersConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsResourceUsersConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsResourceUsersConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsUser","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsResourcesConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsResourcesConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsResourcesConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsResource","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsUser","fields":[{"name":"contract","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"PermissionsUserId","ofType":null}},"args":[]},{"name":"resource","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"roles","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"user","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Account","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"PermissionsUserId"},{"kind":"OBJECT","name":"Query","fields":[{"name":"account","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[{"name":"by","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"domain","type":{"kind":"INTERFACE","name":"Domain","ofType":null},"args":[{"name":"by","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"domains","type":{"kind":"OBJECT","name":"QueryDomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"permissions","type":{"kind":"OBJECT","name":"Permissions","ofType":null},"args":[{"name":"by","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"registrations","type":{"kind":"OBJECT","name":"QueryRegistrationsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"registry","type":{"kind":"OBJECT","name":"Registry","ofType":null},"args":[{"name":"by","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"resolver","type":{"kind":"OBJECT","name":"Resolver","ofType":null},"args":[{"name":"by","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"resolvers","type":{"kind":"OBJECT","name":"QueryResolversConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"root","type":{"kind":"OBJECT","name":"Registry","ofType":null},"args":[]},{"name":"v1Domains","type":{"kind":"OBJECT","name":"QueryV1DomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"v2Domains","type":{"kind":"OBJECT","name":"QueryV2DomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryDomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"QueryDomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryDomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryRegistrationsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"QueryRegistrationsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryRegistrationsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Registration","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryResolversConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"QueryResolversConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryResolversConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Resolver","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryV1DomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"QueryV1DomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryV1DomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ENSv1Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryV2DomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"QueryV2DomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryV2DomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ENSv2Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"INTERFACE","name":"Registration","fields":[{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"BigInt","ofType":null},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"RegistrationId","ofType":null}},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Hex","ofType":null},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]}],"interfaces":[],"possibleTypes":[{"kind":"OBJECT","name":"BaseRegistrarRegistration"},{"kind":"OBJECT","name":"ENSv2RegistryRegistration"},{"kind":"OBJECT","name":"ENSv2RegistryReservation"},{"kind":"OBJECT","name":"NameWrapperRegistration"},{"kind":"OBJECT","name":"ThreeDNSRegistration"}]},{"kind":"SCALAR","name":"RegistrationId"},{"kind":"OBJECT","name":"RegistrationRenewalsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"RegistrationRenewalsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistrationRenewalsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Renewal","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"Registry","fields":[{"name":"contract","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"domains","type":{"kind":"OBJECT","name":"RegistryDomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"RegistryId","ofType":null}},"args":[]},{"name":"parents","type":{"kind":"OBJECT","name":"RegistryParentsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"permissions","type":{"kind":"OBJECT","name":"Permissions","ofType":null},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistryDomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"RegistryDomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistryDomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"RegistryId"},{"kind":"OBJECT","name":"RegistryParentsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"RegistryParentsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistryParentsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ENSv2Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistryPermissionsUser","fields":[{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"PermissionsUserId","ofType":null}},"args":[]},{"name":"registry","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Registry","ofType":null}},"args":[]},{"name":"resource","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"roles","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"user","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Account","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"Renewal","fields":[{"name":"base","type":{"kind":"SCALAR","name":"BigInt","ofType":null},"args":[]},{"name":"duration","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"RenewalId","ofType":null}},"args":[]},{"name":"premium","type":{"kind":"SCALAR","name":"BigInt","ofType":null},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Hex","ofType":null},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"RenewalId"},{"kind":"OBJECT","name":"Resolver","fields":[{"name":"bridged","type":{"kind":"OBJECT","name":"AccountId","ofType":null},"args":[]},{"name":"contract","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"events","type":{"kind":"OBJECT","name":"ResolverEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"ResolverId","ofType":null}},"args":[]},{"name":"permissions","type":{"kind":"OBJECT","name":"Permissions","ofType":null},"args":[]},{"name":"records","type":{"kind":"OBJECT","name":"ResolverRecordsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"records_","type":{"kind":"OBJECT","name":"ResolverRecords","ofType":null},"args":[{"name":"for","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverEventsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ResolverEventsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverEventsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"ResolverId"},{"kind":"OBJECT","name":"ResolverPermissionsUser","fields":[{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"PermissionsUserId","ofType":null}},"args":[]},{"name":"resolver","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Resolver","ofType":null}},"args":[]},{"name":"resource","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"roles","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"user","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Account","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverRecords","fields":[{"name":"coinTypes","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"CoinType","ofType":null}}}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"ResolverRecordsId","ofType":null}},"args":[]},{"name":"keys","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}}}},"args":[]},{"name":"name","type":{"kind":"SCALAR","name":"String","ofType":null},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Node","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverRecordsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ResolverRecordsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverRecordsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ResolverRecords","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"ResolverRecordsId"},{"kind":"SCALAR","name":"String"},{"kind":"OBJECT","name":"ThreeDNSRegistration","fields":[{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"BigInt","ofType":null},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"RegistrationId","ofType":null}},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Hex","ofType":null},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Registration"}]},{"kind":"OBJECT","name":"WrappedBaseRegistrarRegistration","fields":[{"name":"fuses","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]},{"name":"tokenId","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"Any"}],"directives":[]}} as const; diff --git a/packages/enssdk/src/omnigraph/graphql.ts b/packages/enssdk/src/omnigraph/graphql.ts index 4e6f6c304..a8edd6647 100644 --- a/packages/enssdk/src/omnigraph/graphql.ts +++ b/packages/enssdk/src/omnigraph/graphql.ts @@ -20,32 +20,38 @@ import type { } from "../lib/types"; import type { introspection } from "./generated/graphql-env"; +/** + * Scalar type mappings for the Omnigraph schema, representing the type of the serialized response + * from the Omnigraph API. + * + * Keep in sync with the scalars in apps/ensapi/src/omnigraph-api/builder.ts. + */ +export type OmnigraphScalars = { + ID: string; + // the omnigraph returns serialized bigint values from the api; further deserialization is + // handled by enskit's graphcache local resolvers (see cache-exchange.ts) + BigInt: `${bigint}`; + Address: NormalizedAddress; + Hex: Hex; + ChainId: ChainId; + CoinType: CoinType; + InterpretedName: InterpretedName; + InterpretedLabel: InterpretedLabel; + Node: Node; + DomainId: DomainId; + RegistryId: RegistryId; + ResolverId: ResolverId; + PermissionsId: PermissionsId; + PermissionsResourceId: PermissionsResourceId; + PermissionsUserId: PermissionsUserId; + RegistrationId: RegistrationId; + RenewalId: RenewalId; + ResolverRecordsId: ResolverRecordsId; +}; + export const graphql = initGraphQLTada<{ - introspection: introspection; - scalars: { - ID: string; - // NOTE: graphql clients don't really do deserialization of scalars like bigint, so instead we - // just helpfully type the string as 'a stringified bigint' - BigInt: `${bigint}`; - // NOTE: keep these semantic scalar types in sync with the scalars in apps/ensapi/src/omnigraph-api/builder.ts - // (i.e. excluding the BigInt scalar, which we handle above) - Address: NormalizedAddress; - Hex: Hex; - ChainId: ChainId; - CoinType: CoinType; - InterpretedName: InterpretedName; - InterpretedLabel: InterpretedLabel; - Node: Node; - DomainId: DomainId; - RegistryId: RegistryId; - ResolverId: ResolverId; - PermissionsId: PermissionsId; - PermissionsResourceId: PermissionsResourceId; - PermissionsUserId: PermissionsUserId; - RegistrationId: RegistrationId; - RenewalId: RenewalId; - ResolverRecordsId: ResolverRecordsId; - }; + introspection: typeof introspection; + scalars: OmnigraphScalars; }>(); export type { FragmentOf, ResultOf, VariablesOf } from "gql.tada"; diff --git a/packages/enssdk/src/omnigraph/introspection.ts b/packages/enssdk/src/omnigraph/introspection.ts index f25a9a828..23ef3090f 100644 --- a/packages/enssdk/src/omnigraph/introspection.ts +++ b/packages/enssdk/src/omnigraph/introspection.ts @@ -1 +1,2 @@ -export { introspection } from "./generated/introspection"; +export { introspection } from "./generated/graphql-env"; +// export { introspection } from "./generated/introspection"; diff --git a/packages/enssdk/tsconfig.json b/packages/enssdk/tsconfig.json index 6af4a81c9..760b1d5fb 100644 --- a/packages/enssdk/tsconfig.json +++ b/packages/enssdk/tsconfig.json @@ -6,7 +6,7 @@ { "name": "gql.tada/ts-plugin", "schema": "./src/omnigraph/generated/schema.graphql", - "tadaOutputLocation": "./src/omnigraph/generated/graphql-env.d.ts" + "tadaOutputLocation": "./src/omnigraph/generated/graphql-env.ts" } ] }, From a2442ddf004ba2d11a5264cf4fa442da1884d44f Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 11:08:50 -0500 Subject: [PATCH 14/60] fix: add constraint that name be normalized in forward resolution --- apps/ensapi/src/lib/resolution/forward-resolution.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apps/ensapi/src/lib/resolution/forward-resolution.ts b/apps/ensapi/src/lib/resolution/forward-resolution.ts index 259c47dd3..cb88dbae9 100644 --- a/apps/ensapi/src/lib/resolution/forward-resolution.ts +++ b/apps/ensapi/src/lib/resolution/forward-resolution.ts @@ -6,6 +6,7 @@ import { type AccountId, asInterpretedName, type InterpretedName, + isNormalizedName, type Node, namehashInterpretedName, parseReverseName, @@ -139,6 +140,14 @@ async function _resolveForward( // Validate Input ////////////////////////////////////////////////// + // TODO: technically InterpretedNames are not resolvable, since ENS contracts are not + // encoded-labelhash-aware; so we add a temporary additional constraint on name that it + // must be fully normalized (and therefore not contain encoded labelhash segments) + // (this will be improved in a future pr) + if (!isNormalizedName(name)) { + throw new Error(`'${name} must be normalized to be resolvable.'`); + } + const node: Node = namehashInterpretedName(name); span.setAttribute("node", node); From 87de64f31781b13c68d5db0a744a3d87b2ec285f Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 11:26:46 -0500 Subject: [PATCH 15/60] fix: circular import, fix nameToInterpretedName helper, add tests, update agents.md for running test files --- AGENTS.md | 5 +-- packages/enssdk/src/lib/constants.ts | 17 ++++++---- .../lib/interpreted-names-and-labels.test.ts | 31 +++++++++++++++++++ .../src/lib/interpreted-names-and-labels.ts | 11 ++++++- 4 files changed, 55 insertions(+), 9 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 26a094ee1..3cf464727 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -39,10 +39,11 @@ Runnable commands for validating changes; lint and format with Biome. - Install dependencies: `pnpm install` - Run all tests: `pnpm test` -- Run tests for a single package/app: `pnpm --filter test` (e.g. `pnpm --filter ensapi test`) + - Run tests for a single project: `pnpm test --project [:project]` (e.g. `pnpm test --project ensapi`) + - Run tests for a single file: `pnpm test [:path]` - Lint and format: `pnpm lint` (fixes where applicable); CI lint: `pnpm lint:ci` - Type checking: `pnpm typecheck` (runs typecheck in all workspaces) - - Always prefer `pnpm -F typecheck` over `tsc` + - Always use `pnpm -F typecheck`, never call `tsc` or `tsgo` directly ## Testing diff --git a/packages/enssdk/src/lib/constants.ts b/packages/enssdk/src/lib/constants.ts index aad1dc080..cf00184f8 100644 --- a/packages/enssdk/src/lib/constants.ts +++ b/packages/enssdk/src/lib/constants.ts @@ -1,26 +1,31 @@ -import { asInterpretedName } from "./interpreted-names-and-labels"; import { namehashInterpretedName } from "./namehash"; -import type { EACResource, Node } from "./types"; +import type { EACResource, InterpretedName, Node } from "./types"; /** * Name for the ENS Root + * + * @dev manually cast to InterpretedName to avoid circular import */ -export const ENS_ROOT_NAME = asInterpretedName(""); +export const ENS_ROOT_NAME = "" as InterpretedName; /** * The {@link Node} that identifies the ENS Root Name (""). */ -export const ENS_ROOT_NODE: Node = namehashInterpretedName(asInterpretedName("")); +export const ENS_ROOT_NODE: Node = namehashInterpretedName(ENS_ROOT_NAME); /** * The {@link Node} that identifies the ETH Name ("eth"). + * + * @dev manually cast to InterpretedName to avoid circular import */ -export const ETH_NODE: Node = namehashInterpretedName(asInterpretedName("eth")); +export const ETH_NODE: Node = namehashInterpretedName("eth" as InterpretedName); /** * The {@link Node} that identifies the addr.reverse Name ("addr.reverse"). + * + * @dev manually cast to InterpretedName to avoid circular import */ -export const ADDR_REVERSE_NODE: Node = namehashInterpretedName(asInterpretedName("addr.reverse")); +export const ADDR_REVERSE_NODE: Node = namehashInterpretedName("addr.reverse" as InterpretedName); /** * ROOT_RESOURCE represents the 'root' resource in an EnhancedAccessControl contract. diff --git a/packages/enssdk/src/lib/interpreted-names-and-labels.test.ts b/packages/enssdk/src/lib/interpreted-names-and-labels.test.ts index 31356601b..d29456aae 100644 --- a/packages/enssdk/src/lib/interpreted-names-and-labels.test.ts +++ b/packages/enssdk/src/lib/interpreted-names-and-labels.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it } from "vitest"; +import { ENS_ROOT_NAME } from "./constants"; import { asInterpretedLabel, asLiteralLabel, @@ -7,6 +8,7 @@ import { interpretedLabelsToInterpretedName, literalLabelsToInterpretedName, literalLabelToInterpretedLabel, + nameToInterpretedName, parsePartialInterpretedName, } from "./interpreted-names-and-labels"; import { encodeLabelHash, labelhashLiteralLabel } from "./labelhash"; @@ -202,4 +204,33 @@ describe("interpretation", () => { }, ); }); + + describe("nameToInterpretedName", () => { + it("returns ENS_ROOT_NAME unchanged", () => { + expect(nameToInterpretedName(ENS_ROOT_NAME)).toBe(ENS_ROOT_NAME); + }); + + it("works for tlds", () => { + expect(nameToInterpretedName("eth")).toBe("eth"); + }); + + it("throws for a name with an empty label segment", () => { + expect(() => nameToInterpretedName("example..eth")).toThrow(/empty label segment/); + }); + + it("preserves a pre-encoded labelhash label", () => { + expect(nameToInterpretedName(`${EXAMPLE_ENCODED_LABEL_HASH}.eth`)).toEqual( + `${EXAMPLE_ENCODED_LABEL_HASH}.eth`, + ); + }); + + it("preserves a normalized label", () => { + expect(nameToInterpretedName("vitalik.eth")).toEqual("vitalik.eth"); + }); + + it("encodes a non-normalized label as an encoded labelhash", () => { + const expectedEncoded = encodeLabelHash(labelhashLiteralLabel(asLiteralLabel("Vitalik"))); + expect(nameToInterpretedName("Vitalik.eth")).toEqual(`${expectedEncoded}.eth`); + }); + }); }); diff --git a/packages/enssdk/src/lib/interpreted-names-and-labels.ts b/packages/enssdk/src/lib/interpreted-names-and-labels.ts index d0f3dbea2..7fa6a0d16 100644 --- a/packages/enssdk/src/lib/interpreted-names-and-labels.ts +++ b/packages/enssdk/src/lib/interpreted-names-and-labels.ts @@ -1,5 +1,6 @@ import { isHex } from "viem"; +import { ENS_ROOT_NAME } from "./constants"; import { encodeLabelHash, isEncodedLabelHash, @@ -28,10 +29,18 @@ import type { * interpreted InterpretedName. */ export function nameToInterpretedName(name: Name): InterpretedName { + if (name === ENS_ROOT_NAME) return ENS_ROOT_NAME; + return interpretedLabelsToInterpretedName( name .split(".") .map((label) => { + if (label === "") { + throw new Error( + `Name '${name}' cannot conform to InterpretedName because it contains an empty label segment, which is not a valid label.`, + ); + } + if (isEncodedLabelHash(label)) return label; if (isNormalizedLabel(label)) return label; return encodeLabelHash(labelhashLiteralLabel(asLiteralLabel(label))); @@ -217,7 +226,7 @@ export function parsePartialInterpretedName(partialInterpretedName: Name): { } /** - * Validates and casts a string to a {@link LiteralLabel}. + * Casts a string to a {@link LiteralLabel}. * A LiteralLabel is a label as it literally appears onchain. */ export function asLiteralLabel(label: Label): LiteralLabel { From cf6216fcd39cdad5b675e50597f725bdb2e940e7 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 12:02:48 -0500 Subject: [PATCH 16/60] fix: decodeEncodedReferrer returns NormalizedAddress, fix normalized address usage at runtime --- .../src/lib/trace-transaction-helpers.ts | 4 +--- packages/datasources/src/invariants.test.ts | 2 +- .../rev-share-limit/api/zod-schemas.ts | 13 ++++------- .../src/registrars/encoded-referrer.test.ts | 4 ++-- .../src/registrars/encoded-referrer.ts | 22 ++++++++----------- .../ensnode-sdk/src/registrars/zod-schemas.ts | 4 +--- .../ensnode-sdk/src/shared/zod-schemas.ts | 4 ++-- 7 files changed, 20 insertions(+), 33 deletions(-) diff --git a/apps/ensindexer/src/lib/trace-transaction-helpers.ts b/apps/ensindexer/src/lib/trace-transaction-helpers.ts index eed892e28..d85bfdd77 100644 --- a/apps/ensindexer/src/lib/trace-transaction-helpers.ts +++ b/apps/ensindexer/src/lib/trace-transaction-helpers.ts @@ -85,10 +85,8 @@ export function getAddressesFromTrace(trace: Trace): Set
{ if (matches) { for (const maybeAddress of matches) { if (isAddress(maybeAddress)) { - // Normalize the address - const normalizedAddr = toNormalizedAddress(maybeAddress); // Add the normalized address to the set - uniqueAddresses.add(normalizedAddr); + uniqueAddresses.add(toNormalizedAddress(maybeAddress)); } else { // Ignore invalid addresses } diff --git a/packages/datasources/src/invariants.test.ts b/packages/datasources/src/invariants.test.ts index 44205fbc3..5c9627164 100644 --- a/packages/datasources/src/invariants.test.ts +++ b/packages/datasources/src/invariants.test.ts @@ -23,7 +23,7 @@ describe("datasource invariants", () => { expect( // TODO: could use enssdk#isNormalizedAddress here contractConfig.address === contractConfig.address.toLowerCase(), - `The ContractConfig '${namespace}' > '${datasourceName}' > '${contractName}' > '${contractConfig.address}' is not is lowercase format.`, + `The Address '${namespace}' > '${datasourceName}' > '${contractName}' > '${contractConfig.address}' is not a enssdk#NormalizedAddress (i.e. is not fully lowercase).`, ).toBe(true); } } diff --git a/packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts b/packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts index febf03708..f9e2772ca 100644 --- a/packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts +++ b/packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts @@ -53,15 +53,10 @@ export const makeReferralProgramRulesRevShareLimitSchema = ( .array( makeReferralProgramEditionDisqualificationSchema(`${valueLabel}.disqualifications[item]`), ) - .refine( - (items) => { - const addresses = items.map((item) => toNormalizedAddress(item.referrer)); - return new Set(addresses).size === addresses.length; - }, - { - message: `${valueLabel}.disqualifications must not contain duplicate referrer addresses`, - }, - ) + // NOTE: addresses are already normalized, so string equivalence here is accurate + .refine((addresses) => new Set(addresses).size === addresses.length, { + message: `${valueLabel}.disqualifications must not contain duplicate referrer addresses`, + }) .default([]), }); diff --git a/packages/ensnode-sdk/src/registrars/encoded-referrer.test.ts b/packages/ensnode-sdk/src/registrars/encoded-referrer.test.ts index 992107496..a3fbbed20 100644 --- a/packages/ensnode-sdk/src/registrars/encoded-referrer.test.ts +++ b/packages/ensnode-sdk/src/registrars/encoded-referrer.test.ts @@ -1,4 +1,4 @@ -import type { Address } from "enssdk"; +import { type Address, toNormalizedAddress } from "enssdk"; import { concat, getAddress, pad, zeroAddress } from "viem"; import { describe, expect, it } from "vitest"; @@ -67,7 +67,7 @@ describe("encoded referrer", () => { size: ENCODED_REFERRER_BYTE_LENGTH, dir: "left", }); // all lowercase hex - const expectedDecodedReferrer = getAddress(address); // checksummed EVM address + const expectedDecodedReferrer = toNormalizedAddress(address); const encodedReferrer = buildEncodedReferrer(address); const decodedReferrer = decodeEncodedReferrer(encodedReferrer); diff --git a/packages/ensnode-sdk/src/registrars/encoded-referrer.ts b/packages/ensnode-sdk/src/registrars/encoded-referrer.ts index 399ed8615..2a8b66dcd 100644 --- a/packages/ensnode-sdk/src/registrars/encoded-referrer.ts +++ b/packages/ensnode-sdk/src/registrars/encoded-referrer.ts @@ -1,4 +1,4 @@ -import type { Address, Hex } from "enssdk"; +import { type Address, type Hex, type NormalizedAddress, toNormalizedAddress } from "enssdk"; import { getAddress, pad, size, slice, zeroAddress } from "viem"; /** @@ -49,21 +49,19 @@ export const ZERO_ENCODED_REFERRER: EncodedReferrer = pad("0x", { }); /** - * Build an {@link EncodedReferrer} value for the given {@link Address} + * Build an {@link EncodedReferrer} value for the given {@link NormalizedAddress} * according to the referrer encoding with left-zero-padding. */ -export function buildEncodedReferrer(address: Address): EncodedReferrer { - const lowercaseAddress = address.toLowerCase() as Address; - - return pad(lowercaseAddress, { size: ENCODED_REFERRER_BYTE_LENGTH, dir: "left" }); +export function buildEncodedReferrer(address: NormalizedAddress): EncodedReferrer { + return pad(address, { size: ENCODED_REFERRER_BYTE_LENGTH, dir: "left" }); } /** - * Decode an {@link EncodedReferrer} value into a checksummed {@link Address} + * Decode an {@link EncodedReferrer} value into a {@link NormalizedAddress} * according to the referrer encoding with left-zero-padding. * * @param encodedReferrer - The "raw" {@link EncodedReferrer} value to decode. - * @returns The decoded referrer checksummed address. + * @returns The decoded referrer address. * @throws when encodedReferrer value is not represented by * {@link ENCODED_REFERRER_BYTE_LENGTH} bytes. * @throws when decodedReferrer is not a valid EVM address. @@ -80,15 +78,13 @@ export function decodeEncodedReferrer(encodedReferrer: EncodedReferrer): Address // strict validation: padding must be all zeros // if any byte in the padding is non-zero, treat as Zero Encoded Referrer - if (padding !== EXPECTED_ENCODED_REFERRER_PADDING) { - return zeroAddress; - } + if (padding !== EXPECTED_ENCODED_REFERRER_PADDING) return zeroAddress; const decodedReferrer = slice(encodedReferrer, ENCODED_REFERRER_BYTE_OFFSET); try { - // return checksummed address - return getAddress(decodedReferrer); + // return normalized address + return toNormalizedAddress(decodedReferrer); } catch { throw new Error(`Decoded referrer value must be a valid EVM address.`); } diff --git a/packages/ensnode-sdk/src/registrars/zod-schemas.ts b/packages/ensnode-sdk/src/registrars/zod-schemas.ts index aa7054359..ea239f3c0 100644 --- a/packages/ensnode-sdk/src/registrars/zod-schemas.ts +++ b/packages/ensnode-sdk/src/registrars/zod-schemas.ts @@ -94,9 +94,7 @@ function invariant_registrarActionDecodedReferrerBasedOnRawReferrer( const { encodedReferrer, decodedReferrer } = ctx.value; try { - // decodeEncodedReferrer returns checksummed address, but ENSNode work on lowercase address values - // so we lowercase the result before using for checks - const expectedDecodedReferrer = decodeEncodedReferrer(encodedReferrer).toLowerCase() as Address; + const expectedDecodedReferrer = decodeEncodedReferrer(encodedReferrer); if (decodedReferrer !== expectedDecodedReferrer) { ctx.issues.push({ diff --git a/packages/ensnode-sdk/src/shared/zod-schemas.ts b/packages/ensnode-sdk/src/shared/zod-schemas.ts index 8a8d1d5e4..dce327785 100644 --- a/packages/ensnode-sdk/src/shared/zod-schemas.ts +++ b/packages/ensnode-sdk/src/shared/zod-schemas.ts @@ -11,7 +11,7 @@ import type { InterpretedName, Node, } from "enssdk"; -import { reinterpretName, toNormalizedAddress } from "enssdk"; +import { isNormalizedAddress, reinterpretName, toNormalizedAddress } from "enssdk"; import { isAddress, isHex, size } from "viem"; /** * All zod schemas we define must remain internal implementation details. @@ -156,7 +156,7 @@ export const makeNormalizedAddressSchema = (valueLabel: string = "EVM address") z .string() .check((ctx) => { - if (!isAddress(ctx.value)) { + if (!isNormalizedAddress(ctx.value as Address)) { ctx.issues.push({ code: "custom", message: `${valueLabel} must be a valid EVM address`, From e438eb244fab8a90efa5417ca953003cdb18e13a Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 15:18:56 -0500 Subject: [PATCH 17/60] tidy up isAddress usage, fix normalized address schema --- .../src/lib/resolution/reverse-resolution.ts | 2 +- apps/ensindexer/src/config/validations.ts | 2 +- .../src/lib/trace-transaction-helpers.ts | 8 +++----- .../shared/lib/registrar-controller-events.ts | 4 ++-- examples/enskit-react-example/src/DomainView.tsx | 2 +- .../rev-share-limit/api/zod-schemas.ts | 1 - .../src/ensindexer-abstract/registrars.schema.ts | 3 ++- .../src/registrars/encoded-referrer.test.ts | 14 ++++++++------ .../ensnode-sdk/src/registrars/encoded-referrer.ts | 12 ++++++++++-- packages/ensnode-sdk/src/registrars/zod-schemas.ts | 1 - .../interpretation/interpret-record-values.ts | 2 +- packages/ensnode-sdk/src/shared/zod-schemas.ts | 6 ++++-- packages/enssdk/src/lib/parse-reverse-name.ts | 4 +++- 13 files changed, 36 insertions(+), 25 deletions(-) diff --git a/apps/ensapi/src/lib/resolution/reverse-resolution.ts b/apps/ensapi/src/lib/resolution/reverse-resolution.ts index b9cc05b8a..677d16188 100644 --- a/apps/ensapi/src/lib/resolution/reverse-resolution.ts +++ b/apps/ensapi/src/lib/resolution/reverse-resolution.ts @@ -126,7 +126,7 @@ export async function resolveReverse( span.setAttribute("resolvedAddress", resolvedAddress); // Step 8.2 — if the resolvedAddress is not an EVM address, no Primary Name - const resolvedAddressIsEVMAddress = isAddress(resolvedAddress); + const resolvedAddressIsEVMAddress = isAddress(resolvedAddress, { strict: false }); if (!resolvedAddressIsEVMAddress) { addProtocolStepEvent( protocolTracingSpan, diff --git a/apps/ensindexer/src/config/validations.ts b/apps/ensindexer/src/config/validations.ts index c85782fcb..5b95c7499 100644 --- a/apps/ensindexer/src/config/validations.ts +++ b/apps/ensindexer/src/config/validations.ts @@ -127,7 +127,7 @@ export function invariant_validContractConfigs( if ("address" in contractConfig && typeof contractConfig.address === "string") { if (!isNormalizedAddress(contractConfig.address)) { throw new Error( - `The '${config.namespace}' namespace's '${datasourceName}' Datasource does not define a valid address for ${contractName}: '${contractConfig.address}'. This occurs if the address property of any ContractConfig in the Datasource is malformed (i.e. not a enssdk#NormalizedAddress). This is only likely to occur if you are actively editing the Datasource and typo'd an address.`, + `The '${config.namespace}' namespace's '${datasourceName}' Datasource does not define a valid address for ${contractName}: '${contractConfig.address}'. This occurs if the address property of any ContractConfig in the Datasource is malformed (i.e. not an enssdk#NormalizedAddress). This is only likely to occur if you are actively editing the Datasource and typo'd an address.`, ); } } diff --git a/apps/ensindexer/src/lib/trace-transaction-helpers.ts b/apps/ensindexer/src/lib/trace-transaction-helpers.ts index d85bfdd77..956e93693 100644 --- a/apps/ensindexer/src/lib/trace-transaction-helpers.ts +++ b/apps/ensindexer/src/lib/trace-transaction-helpers.ts @@ -84,7 +84,7 @@ export function getAddressesFromTrace(trace: Trace): Set
{ // if matches are found, normalize them and return unique addresses if (matches) { for (const maybeAddress of matches) { - if (isAddress(maybeAddress)) { + if (isAddress(maybeAddress, { strict: false })) { // Add the normalized address to the set uniqueAddresses.add(toNormalizedAddress(maybeAddress)); } else { @@ -114,11 +114,9 @@ export function getAddressesFromTrace(trace: Trace): Set
{ const maybeAddress = `0x${maybePartialAddress}`; - if (isAddress(maybeAddress)) { - // Add 0x prefix and normalize the address - const normalizedAddr = toNormalizedAddress(maybeAddress); + if (isAddress(maybeAddress, { strict: false })) { // Add the normalized address to the set - uniqueAddresses.add(normalizedAddr); + uniqueAddresses.add(toNormalizedAddress(maybeAddress)); } else { // Ignore invalid addresses } diff --git a/apps/ensindexer/src/plugins/registrars/shared/lib/registrar-controller-events.ts b/apps/ensindexer/src/plugins/registrars/shared/lib/registrar-controller-events.ts index 61913d1e9..d8e756e92 100644 --- a/apps/ensindexer/src/plugins/registrars/shared/lib/registrar-controller-events.ts +++ b/apps/ensindexer/src/plugins/registrars/shared/lib/registrar-controller-events.ts @@ -1,4 +1,4 @@ -import type { Address, Node } from "enssdk"; +import type { Node, NormalizedAddress } from "enssdk"; import type { Hash } from "viem"; import { @@ -99,7 +99,7 @@ export async function handleRegistrarControllerEvent( // 4. Prepare referral info let encodedReferrer: EncodedReferrer | null; - let decodedReferrer: Address | null; + let decodedReferrer: NormalizedAddress | null; if (isRegistrarActionReferralAvailable(referral)) { encodedReferrer = referral.encodedReferrer; diff --git a/examples/enskit-react-example/src/DomainView.tsx b/examples/enskit-react-example/src/DomainView.tsx index 79df47e07..1f307a710 100644 --- a/examples/enskit-react-example/src/DomainView.tsx +++ b/examples/enskit-react-example/src/DomainView.tsx @@ -55,7 +55,7 @@ function RenderDomain({ name }: { name: InterpretedName }) { if (fetching) return

Loading...

; if (error) return

Error: {error.message}

; - if (!data?.domain) return

A Domain with InterpretedName '{name}' was not found.

; + if (!data?.domain) return

A Domain with name '{name}' was not found.

; const domain = readFragment(DomainFragment, data.domain); const parentName = getParentInterpretedName(name); diff --git a/packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts b/packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts index f9e2772ca..e81b659a5 100644 --- a/packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts +++ b/packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts @@ -1,4 +1,3 @@ -import { toNormalizedAddress } from "enssdk"; import z from "zod/v4"; import { diff --git a/packages/ensdb-sdk/src/ensindexer-abstract/registrars.schema.ts b/packages/ensdb-sdk/src/ensindexer-abstract/registrars.schema.ts index 3bb7000cc..4fd51f294 100644 --- a/packages/ensdb-sdk/src/ensindexer-abstract/registrars.schema.ts +++ b/packages/ensdb-sdk/src/ensindexer-abstract/registrars.schema.ts @@ -2,6 +2,7 @@ * Schema Definitions for tracking of ENS registrars. */ +import type { NormalizedAddress } from "enssdk"; import { index, onchainEnum, onchainTable, relations, uniqueIndex } from "ponder"; /** @@ -353,7 +354,7 @@ export const registrarActions = onchainTable( * 3) May be the "zero address" to represent that an `encodedReferrer` is * defined but that it is interpreted as no referrer. */ - decodedReferrer: t.hex(), + decodedReferrer: t.hex().$type(), /** * Number of the block that includes the "logical registrar action". diff --git a/packages/ensnode-sdk/src/registrars/encoded-referrer.test.ts b/packages/ensnode-sdk/src/registrars/encoded-referrer.test.ts index a3fbbed20..caf3ee5dc 100644 --- a/packages/ensnode-sdk/src/registrars/encoded-referrer.test.ts +++ b/packages/ensnode-sdk/src/registrars/encoded-referrer.test.ts @@ -24,7 +24,7 @@ describe("encoded referrer", () => { const result = decodeEncodedReferrer(input); // assert - expect(result).toEqual(vitalikEthAddressChecksummed); + expect(result).toEqual(vitalikEthAddressLowercase); }); it("returns a zeroAddress value when initial bytes were not all zeroes", () => { @@ -63,17 +63,19 @@ describe("encoded referrer", () => { { addressFormat: "lowercase", address: vitalikEthAddressLowercase }, { addressFormat: "checksummed", address: vitalikEthAddressChecksummed }, ])("returns encoded referrer for a $addressFormat EVM address", ({ address }) => { + // encoding should operate as expected const expectedEncodedReferrer = pad(address.toLowerCase() as Address, { size: ENCODED_REFERRER_BYTE_LENGTH, dir: "left", - }); // all lowercase hex - const expectedDecodedReferrer = toNormalizedAddress(address); + }); - const encodedReferrer = buildEncodedReferrer(address); - const decodedReferrer = decodeEncodedReferrer(encodedReferrer); + const encodedReferrer = buildEncodedReferrer(toNormalizedAddress(address)); + expect(encodedReferrer).toEqual(expectedEncodedReferrer); + // decoding should operate as expected + const expectedDecodedReferrer = toNormalizedAddress(address); + const decodedReferrer = decodeEncodedReferrer(encodedReferrer); expect(decodedReferrer).toStrictEqual(expectedDecodedReferrer); - expect(encodedReferrer).toEqual(expectedEncodedReferrer); }); }); }); diff --git a/packages/ensnode-sdk/src/registrars/encoded-referrer.ts b/packages/ensnode-sdk/src/registrars/encoded-referrer.ts index 2a8b66dcd..aa9efe7ad 100644 --- a/packages/ensnode-sdk/src/registrars/encoded-referrer.ts +++ b/packages/ensnode-sdk/src/registrars/encoded-referrer.ts @@ -1,5 +1,11 @@ -import { type Address, type Hex, type NormalizedAddress, toNormalizedAddress } from "enssdk"; -import { getAddress, pad, size, slice, zeroAddress } from "viem"; +import { + type Address, + type Hex, + isNormalizedAddress, + type NormalizedAddress, + toNormalizedAddress, +} from "enssdk"; +import { pad, size, slice, zeroAddress } from "viem"; /** * Encoded Referrer @@ -53,6 +59,8 @@ export const ZERO_ENCODED_REFERRER: EncodedReferrer = pad("0x", { * according to the referrer encoding with left-zero-padding. */ export function buildEncodedReferrer(address: NormalizedAddress): EncodedReferrer { + if (!isNormalizedAddress(address)) throw new Error(`Address '${address}' is not normalized.`); + return pad(address, { size: ENCODED_REFERRER_BYTE_LENGTH, dir: "left" }); } diff --git a/packages/ensnode-sdk/src/registrars/zod-schemas.ts b/packages/ensnode-sdk/src/registrars/zod-schemas.ts index ea239f3c0..ff6cca19a 100644 --- a/packages/ensnode-sdk/src/registrars/zod-schemas.ts +++ b/packages/ensnode-sdk/src/registrars/zod-schemas.ts @@ -1,4 +1,3 @@ -import type { Address } from "enssdk"; import { z } from "zod/v4"; import type { ParsePayload } from "zod/v4/core"; diff --git a/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.ts b/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.ts index 005e2b00a..8647ac332 100644 --- a/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.ts +++ b/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.ts @@ -55,7 +55,7 @@ export function interpretAddressRecordValue(value: string): string | null { if (value === "0x") return null; // if it's not an EVM address, return as-is - if (!isAddress(value)) return value; + if (!isAddress(value, { strict: false })) return value; // interpret zeroAddress as deletion if (isAddressEqual(value, zeroAddress)) return null; diff --git a/packages/ensnode-sdk/src/shared/zod-schemas.ts b/packages/ensnode-sdk/src/shared/zod-schemas.ts index dce327785..0b477820e 100644 --- a/packages/ensnode-sdk/src/shared/zod-schemas.ts +++ b/packages/ensnode-sdk/src/shared/zod-schemas.ts @@ -11,7 +11,7 @@ import type { InterpretedName, Node, } from "enssdk"; -import { isNormalizedAddress, reinterpretName, toNormalizedAddress } from "enssdk"; +import { reinterpretName, toNormalizedAddress } from "enssdk"; import { isAddress, isHex, size } from "viem"; /** * All zod schemas we define must remain internal implementation details. @@ -156,7 +156,9 @@ export const makeNormalizedAddressSchema = (valueLabel: string = "EVM address") z .string() .check((ctx) => { - if (!isNormalizedAddress(ctx.value as Address)) { + // NOTE: we intentionally use isAddress here instead of isNormalizedAddress, which allows this + // schema to transform (via toNormalizedAddress) the input into a normalized address. + if (!isAddress(ctx.value, { strict: false })) { ctx.issues.push({ code: "custom", message: `${valueLabel} must be a valid EVM address`, diff --git a/packages/enssdk/src/lib/parse-reverse-name.ts b/packages/enssdk/src/lib/parse-reverse-name.ts index 79ed74cc9..86ac9287c 100644 --- a/packages/enssdk/src/lib/parse-reverse-name.ts +++ b/packages/enssdk/src/lib/parse-reverse-name.ts @@ -21,7 +21,9 @@ const REVERSE_NAME_REGEX = /^([0-9a-fA-F]+)\.([0-9a-f]{1,64}|addr|default)\.reve const parseAddressLabel = (addressLabel: Label): Address => { const maybeAddress = `0x${addressLabel}`; - if (!isAddress(maybeAddress)) throw new Error(`Invalid EVM address "${maybeAddress}"`); + if (!isAddress(maybeAddress, { strict: false })) { + throw new Error(`Invalid EVM address "${maybeAddress}"`); + } return toNormalizedAddress(maybeAddress); }; From e49154919692f86cace7543bffd4013e16ad219c Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 15:20:45 -0500 Subject: [PATCH 18/60] fix: more specific error messages in address test --- packages/enssdk/src/lib/address.test.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/enssdk/src/lib/address.test.ts b/packages/enssdk/src/lib/address.test.ts index c0d0ce2e5..9958b2253 100644 --- a/packages/enssdk/src/lib/address.test.ts +++ b/packages/enssdk/src/lib/address.test.ts @@ -45,11 +45,13 @@ describe("toNormalizedAddress", () => { }); it("should throw for a partial address", () => { - expect(() => toNormalizedAddress("0xdeaf")).toThrow(/does not/); + expect(() => toNormalizedAddress("0xdeaf")).toThrow(/does not represent an EVM Address/); }); it("should throw for a non-hex string", () => { - expect(() => toNormalizedAddress("not-an-address" as Address)).toThrow(/does not/); + expect(() => toNormalizedAddress("not-an-address" as Address)).toThrow( + /does not represent an EVM Address/, + ); }); }); From 2960281b743ff9c5a834db1a59e055a74ebcfc15 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 15:32:54 -0500 Subject: [PATCH 19/60] fix: pr notes, asLiteralName --- .../src/lib/protocol-acceleration/find-resolver.ts | 2 +- .../src/lib/resolution/resolve-calls-and-results.ts | 4 ++-- .../omnigraph-api/schema/resolver.integration.test.ts | 3 ++- .../lib/protocol-acceleration/resolver-db-helpers.ts | 3 ++- .../protocol-acceleration/handlers/Resolver.ts | 4 ++-- .../handlers/StandaloneReverseRegistrar.ts | 5 +++-- .../ensnode-sdk/src/omnigraph-api/example-queries.ts | 4 ++-- .../interpretation/interpret-record-values.test.ts | 7 ++++--- .../shared/interpretation/interpret-record-values.ts | 4 ++-- .../enssdk/src/lib/interpreted-names-and-labels.ts | 8 ++++++++ packages/enssdk/src/lib/normalization.ts | 2 +- packages/enssdk/src/lib/parse-reverse-name.ts | 11 ++++++----- packages/enssdk/src/lib/types/evm.ts | 2 +- 13 files changed, 36 insertions(+), 23 deletions(-) diff --git a/apps/ensapi/src/lib/protocol-acceleration/find-resolver.ts b/apps/ensapi/src/lib/protocol-acceleration/find-resolver.ts index e204835ca..31ada4c3f 100644 --- a/apps/ensapi/src/lib/protocol-acceleration/find-resolver.ts +++ b/apps/ensapi/src/lib/protocol-acceleration/find-resolver.ts @@ -145,7 +145,7 @@ async function findResolverWithUniversalResolver( } // UniversalResolver returns the offset in bytes within the DNS Encoded Name where the activeName begins - // Invariant: the decoded name must be an InterpretedName + // Invariant: the decoded name is a LiteralName that must conform to InterpretedName const activeName = asInterpretedName(bytesToPacket(dnsEncodedNameBytes.slice(offset))); return { diff --git a/apps/ensapi/src/lib/resolution/resolve-calls-and-results.ts b/apps/ensapi/src/lib/resolution/resolve-calls-and-results.ts index 4f6597121..34ecba37f 100644 --- a/apps/ensapi/src/lib/resolution/resolve-calls-and-results.ts +++ b/apps/ensapi/src/lib/resolution/resolve-calls-and-results.ts @@ -1,5 +1,5 @@ import { trace } from "@opentelemetry/api"; -import type { Address, Name, Node } from "enssdk"; +import { type Address, asLiteralName, type Name, type Node } from "enssdk"; import { ContractFunctionExecutionError, decodeAbiParameters, @@ -227,7 +227,7 @@ export function interpretRawCallsAndResults { type ResolverEventsResult = { diff --git a/apps/ensindexer/src/lib/protocol-acceleration/resolver-db-helpers.ts b/apps/ensindexer/src/lib/protocol-acceleration/resolver-db-helpers.ts index 40164c395..a43d4d19c 100644 --- a/apps/ensindexer/src/lib/protocol-acceleration/resolver-db-helpers.ts +++ b/apps/ensindexer/src/lib/protocol-acceleration/resolver-db-helpers.ts @@ -2,6 +2,7 @@ import { type AccountId, type Address, type CoinType, + type LiteralName, makeResolverId, makeResolverRecordsId, type Node, @@ -82,7 +83,7 @@ export async function ensureResolverRecords( export async function handleResolverNameUpdate( context: IndexingEngineContext, resolverRecordsKey: ResolverRecordsCompositeKey, - name: string, + name: LiteralName, ) { const resolverRecordsId = makeResolverRecordsId( { chainId: resolverRecordsKey.chainId, address: resolverRecordsKey.address }, diff --git a/apps/ensindexer/src/plugins/protocol-acceleration/handlers/Resolver.ts b/apps/ensindexer/src/plugins/protocol-acceleration/handlers/Resolver.ts index d9ccf4667..21bcf0439 100644 --- a/apps/ensindexer/src/plugins/protocol-acceleration/handlers/Resolver.ts +++ b/apps/ensindexer/src/plugins/protocol-acceleration/handlers/Resolver.ts @@ -1,4 +1,4 @@ -import { bigintToCoinType, type CoinType, ETH_COIN_TYPE } from "enssdk"; +import { asLiteralName, bigintToCoinType, type CoinType, ETH_COIN_TYPE } from "enssdk"; import { ResolverABI } from "@ensnode/datasources"; import { PluginName } from "@ensnode/ensnode-sdk"; @@ -64,7 +64,7 @@ export default function () { addOnchainEventListener( namespaceContract(pluginName, "Resolver:NameChanged"), async ({ context, event }) => { - const { name } = event.args; + const name = asLiteralName(event.args.name); const resolver = getThisAccountId(context, event); await ensureResolver(context, resolver); diff --git a/apps/ensindexer/src/plugins/protocol-acceleration/handlers/StandaloneReverseRegistrar.ts b/apps/ensindexer/src/plugins/protocol-acceleration/handlers/StandaloneReverseRegistrar.ts index 9ac866ad1..92ba70fd2 100644 --- a/apps/ensindexer/src/plugins/protocol-acceleration/handlers/StandaloneReverseRegistrar.ts +++ b/apps/ensindexer/src/plugins/protocol-acceleration/handlers/StandaloneReverseRegistrar.ts @@ -1,6 +1,6 @@ import config from "@/config"; -import { DEFAULT_EVM_COIN_TYPE, evmChainIdToCoinType } from "enssdk"; +import { asLiteralName, DEFAULT_EVM_COIN_TYPE, evmChainIdToCoinType } from "enssdk"; import { getENSRootChainId } from "@ensnode/datasources"; import { PluginName } from "@ensnode/ensnode-sdk"; @@ -21,7 +21,8 @@ export default function () { "StandaloneReverseRegistrar:NameForAddrChanged", ), async ({ context, event }) => { - const { addr: address, name } = event.args; + const { addr: address } = event.args; + const name = asLiteralName(event.args.name); // The DefaultReverseRegistrar on the ENS Root chain manages 'default' names under the default coinType. // On any other chain, the L2ReverseRegistrar manages names for that chain's coinType. diff --git a/packages/ensnode-sdk/src/omnigraph-api/example-queries.ts b/packages/ensnode-sdk/src/omnigraph-api/example-queries.ts index af85cc747..6f49dc01d 100644 --- a/packages/ensnode-sdk/src/omnigraph-api/example-queries.ts +++ b/packages/ensnode-sdk/src/omnigraph-api/example-queries.ts @@ -1,4 +1,4 @@ -import { toNormalizedAddress } from "enssdk"; +import { asInterpretedName, toNormalizedAddress } from "enssdk"; import { DatasourceNames, ENSNamespaceIds } from "@ensnode/datasources"; @@ -37,7 +37,7 @@ const DEVNET_USER = toNormalizedAddress("0x3C44CdDdB6a900fa2b585dd299e03d12FA429 const VITALIK_ADDRESS = toNormalizedAddress("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"); -const DEVNET_NAME_WITH_OWNED_RESOLVER = "example.eth"; +const DEVNET_NAME_WITH_OWNED_RESOLVER = asInterpretedName("example.eth"); export const GRAPHQL_API_EXAMPLE_QUERIES: Array<{ query: string; diff --git a/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.test.ts b/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.test.ts index 2ceb379ec..ddfe16ce0 100644 --- a/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.test.ts +++ b/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.test.ts @@ -1,3 +1,4 @@ +import { asLiteralName } from "enssdk"; import { describe, expect, it } from "vitest"; import { @@ -9,15 +10,15 @@ import { describe("interpretNameRecordValue", () => { it("returns null for empty string", () => { - expect(interpretNameRecordValue("")).toBeNull(); + expect(interpretNameRecordValue(asLiteralName(""))).toBeNull(); }); it("returns null for non-normalized name", () => { - expect(interpretNameRecordValue("NotNormalized.eth")).toBeNull(); + expect(interpretNameRecordValue(asLiteralName("NotNormalized.eth"))).toBeNull(); }); it("returns value for normalized name", () => { - expect(interpretNameRecordValue("vitalik.eth")).toBe("vitalik.eth"); + expect(interpretNameRecordValue(asLiteralName("vitalik.eth"))).toBe("vitalik.eth"); }); }); diff --git a/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.ts b/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.ts index 8647ac332..1185153d1 100644 --- a/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.ts +++ b/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.ts @@ -1,4 +1,4 @@ -import type { InterpretedName } from "enssdk"; +import type { InterpretedName, LiteralName } from "enssdk"; import { isInterpretedName, toNormalizedAddress } from "enssdk"; import { isAddress, isAddressEqual, zeroAddress } from "viem"; @@ -14,7 +14,7 @@ import { hasNullByte } from "../null-bytes"; * @param value - The name record value string to interpret. * @returns The interpreted name string, or null if deleted. */ -export function interpretNameRecordValue(value: string): InterpretedName | null { +export function interpretNameRecordValue(value: LiteralName): InterpretedName | null { // empty string is technically an InterpretedName, representing the ens root node, but in the // context of a name record value, empty string is emitted when the user un-sets the record (this // is because the abi of this event is only capable of expressing string values, so empty string diff --git a/packages/enssdk/src/lib/interpreted-names-and-labels.ts b/packages/enssdk/src/lib/interpreted-names-and-labels.ts index 7fa6a0d16..7be2c3fcd 100644 --- a/packages/enssdk/src/lib/interpreted-names-and-labels.ts +++ b/packages/enssdk/src/lib/interpreted-names-and-labels.ts @@ -225,6 +225,14 @@ export function parsePartialInterpretedName(partialInterpretedName: Name): { return { concrete, partial }; } +/** + * Casts a string to a {@link LiteralName}. + * A LiteralName is a name as it literally appears onchain. + */ +export function asLiteralName(name: Name): LiteralName { + return name as LiteralName; +} + /** * Casts a string to a {@link LiteralLabel}. * A LiteralLabel is a label as it literally appears onchain. diff --git a/packages/enssdk/src/lib/normalization.ts b/packages/enssdk/src/lib/normalization.ts index 93245d7b1..542f3e23f 100644 --- a/packages/enssdk/src/lib/normalization.ts +++ b/packages/enssdk/src/lib/normalization.ts @@ -19,7 +19,7 @@ export const normalizeName = (name: Name): InterpretedName => */ export const normalizeLabel = (label: Label): InterpretedLabel => { // empty string cannot be a normalized label - if (label === "") throw new Error("Empty string cannot be normalized."); + if (label === "") throw new Error("Empty label cannot be normalized."); // normalized labels do not contain periods if (label.includes(".")) { diff --git a/packages/enssdk/src/lib/parse-reverse-name.ts b/packages/enssdk/src/lib/parse-reverse-name.ts index 86ac9287c..58cc3ea96 100644 --- a/packages/enssdk/src/lib/parse-reverse-name.ts +++ b/packages/enssdk/src/lib/parse-reverse-name.ts @@ -2,7 +2,8 @@ import { hexToBigInt, isAddress } from "viem"; import { toNormalizedAddress } from "./address"; import { bigintToCoinType, DEFAULT_EVM_COIN_TYPE, ETH_COIN_TYPE } from "./coin-type"; -import type { Address, CoinType, Label, Name } from "./types"; +import { asLiteralLabel } from "./interpreted-names-and-labels"; +import type { Address, CoinType, LiteralLabel, Name } from "./types"; /** * Matches an ENSIP-19 Reverse Name @@ -18,7 +19,7 @@ const REVERSE_NAME_REGEX = /^([0-9a-fA-F]+)\.([0-9a-f]{1,64}|addr|default)\.reve * @throws if address is invalid * @see https://docs.ens.domains/ensip/19#reverse-resolution */ -const parseAddressLabel = (addressLabel: Label): Address => { +const parseAddressLabel = (addressLabel: LiteralLabel): Address => { const maybeAddress = `0x${addressLabel}`; if (!isAddress(maybeAddress, { strict: false })) { @@ -33,7 +34,7 @@ const parseAddressLabel = (addressLabel: Label): Address => { * * @throws if coinType is invalid */ -const parseCoinTypeLabel = (coinTypeLabel: Label): CoinType => { +const parseCoinTypeLabel = (coinTypeLabel: LiteralLabel): CoinType => { if (coinTypeLabel === "default") return DEFAULT_EVM_COIN_TYPE; if (coinTypeLabel === "addr") return ETH_COIN_TYPE; @@ -53,8 +54,8 @@ export function parseReverseName(name: Name): { address: Address; coinType: Coin if (!coinTypeLabel) return null; return { - address: parseAddressLabel(addressLabel), - coinType: parseCoinTypeLabel(coinTypeLabel), + address: parseAddressLabel(asLiteralLabel(addressLabel)), + coinType: parseCoinTypeLabel(asLiteralLabel(coinTypeLabel)), }; } catch { // either of the parse methods threw, unable to parse reverse name diff --git a/packages/enssdk/src/lib/types/evm.ts b/packages/enssdk/src/lib/types/evm.ts index 5f72ba49d..d266764ff 100644 --- a/packages/enssdk/src/lib/types/evm.ts +++ b/packages/enssdk/src/lib/types/evm.ts @@ -1,7 +1,7 @@ import type { Address as ViemAddress, Hex as ViemHex } from "viem"; /** - * Represents an Hex string, in the format `0x{string}`. + * Represents a Hex string, in the format `0x{string}`. */ export type Hex = ViemHex; From 101cc78b6080fbece51e26b253bc32ecc758d804 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 15:37:58 -0500 Subject: [PATCH 20/60] fix: streamline name-tokens-api --- apps/ensapi/src/handlers/api/explore/name-tokens-api.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/ensapi/src/handlers/api/explore/name-tokens-api.ts b/apps/ensapi/src/handlers/api/explore/name-tokens-api.ts index 4dbcf9658..7e5a73377 100644 --- a/apps/ensapi/src/handlers/api/explore/name-tokens-api.ts +++ b/apps/ensapi/src/handlers/api/explore/name-tokens-api.ts @@ -2,7 +2,6 @@ import config from "@/config"; import { asInterpretedName, - ENS_ROOT_NAME, getParentInterpretedName, type Node, namehashInterpretedName, @@ -70,9 +69,10 @@ app.openapi(getNameTokensRoute, async (c) => { if (request.name !== undefined) { const name = asInterpretedName(request.name); + const parentName = getParentInterpretedName(name); - // return 404 when the requested name was the ENS Root - if (name === ENS_ROOT_NAME) { + // return 404 when the requested name was the ENS Root (which does not have a parent) + if (parentName === null) { return c.json( serializeNameTokensResponse( makeNameTokensNotIndexedResponse( @@ -83,8 +83,6 @@ app.openapi(getNameTokensRoute, async (c) => { ); } - // biome-ignore lint/style/noNonNullAssertion: getParentInterpretedName only throws if name === ENS_ROOT_NAME but we handle that case above - const parentName = getParentInterpretedName(name)!; const parentNode = namehashInterpretedName(parentName); const subregistry = indexedSubregistries.find((s) => s.node === parentNode); From 1bf85358f5a7513f0a39e248f6ee0e80f361f774 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 15:41:37 -0500 Subject: [PATCH 21/60] refactor: move EnsureInterpretedName to enskit/react --- examples/enskit-react-example/src/DomainView.tsx | 9 ++------- packages/enskit/package.json | 5 +++++ .../components/ensure-interpreted-name.tsx | 0 .../src/react/{omnigraph => }/components/index.tsx | 0 packages/enskit/src/react/index.ts | 1 + packages/enskit/src/react/omnigraph/index.ts | 1 - packages/enskit/tsup.config.ts | 1 + packages/enssdk/src/lib/address.ts | 4 ++-- 8 files changed, 11 insertions(+), 10 deletions(-) rename packages/enskit/src/react/{omnigraph => }/components/ensure-interpreted-name.tsx (100%) rename packages/enskit/src/react/{omnigraph => }/components/index.tsx (100%) create mode 100644 packages/enskit/src/react/index.ts diff --git a/examples/enskit-react-example/src/DomainView.tsx b/examples/enskit-react-example/src/DomainView.tsx index 1f307a710..23bc5a7bf 100644 --- a/examples/enskit-react-example/src/DomainView.tsx +++ b/examples/enskit-react-example/src/DomainView.tsx @@ -1,10 +1,5 @@ -import { - EnsureInterpretedName, - type FragmentOf, - graphql, - readFragment, - useOmnigraphQuery, -} from "enskit/react/omnigraph"; +import { EnsureInterpretedName } from "enskit/react"; +import { type FragmentOf, graphql, readFragment, useOmnigraphQuery } from "enskit/react/omnigraph"; import { getParentInterpretedName, type InterpretedName } from "enssdk"; import { Link, Navigate, useParams } from "react-router"; diff --git a/packages/enskit/package.json b/packages/enskit/package.json index eadc9e789..cab4321ed 100644 --- a/packages/enskit/package.json +++ b/packages/enskit/package.json @@ -20,11 +20,16 @@ "dist" ], "exports": { + "./react": "./src/react/index.ts", "./react/omnigraph": "./src/react/omnigraph/index.ts" }, "publishConfig": { "access": "public", "exports": { + "./react": { + "types": "./dist/react/index.d.ts", + "default": "./dist/react/index.js" + }, "./react/omnigraph": { "types": "./dist/react/omnigraph/index.d.ts", "default": "./dist/react/omnigraph/index.js" diff --git a/packages/enskit/src/react/omnigraph/components/ensure-interpreted-name.tsx b/packages/enskit/src/react/components/ensure-interpreted-name.tsx similarity index 100% rename from packages/enskit/src/react/omnigraph/components/ensure-interpreted-name.tsx rename to packages/enskit/src/react/components/ensure-interpreted-name.tsx diff --git a/packages/enskit/src/react/omnigraph/components/index.tsx b/packages/enskit/src/react/components/index.tsx similarity index 100% rename from packages/enskit/src/react/omnigraph/components/index.tsx rename to packages/enskit/src/react/components/index.tsx diff --git a/packages/enskit/src/react/index.ts b/packages/enskit/src/react/index.ts new file mode 100644 index 000000000..40b494c5f --- /dev/null +++ b/packages/enskit/src/react/index.ts @@ -0,0 +1 @@ +export * from "./components"; diff --git a/packages/enskit/src/react/omnigraph/index.ts b/packages/enskit/src/react/omnigraph/index.ts index c1af1b7ee..a7094eaeb 100644 --- a/packages/enskit/src/react/omnigraph/index.ts +++ b/packages/enskit/src/react/omnigraph/index.ts @@ -2,7 +2,6 @@ export type { FragmentOf, ResultOf, VariablesOf } from "enssdk/omnigraph"; export { readFragment } from "enssdk/omnigraph"; -export * from "./components"; export * from "./graphql"; export * from "./hooks"; export * from "./provider"; diff --git a/packages/enskit/tsup.config.ts b/packages/enskit/tsup.config.ts index 68a31c889..3826734c0 100644 --- a/packages/enskit/tsup.config.ts +++ b/packages/enskit/tsup.config.ts @@ -2,6 +2,7 @@ import { defineConfig } from "tsup"; export default defineConfig({ entry: { + "react/index": "src/react/index.ts", "react/omnigraph/index": "src/react/omnigraph/index.ts", }, platform: "browser", diff --git a/packages/enssdk/src/lib/address.ts b/packages/enssdk/src/lib/address.ts index 7e0a7fc13..e3374f7c2 100644 --- a/packages/enssdk/src/lib/address.ts +++ b/packages/enssdk/src/lib/address.ts @@ -6,8 +6,8 @@ import type { Address, NormalizedAddress } from "./types"; * Determines whether an {@link Address} is a {@link NormalizedAddress}. */ export function isNormalizedAddress(address: Address): address is NormalizedAddress { - const isNormalized = address === address.toLowerCase(); - return isNormalized && isAddress(address, { strict: false }); + const isLowerCase = address === address.toLowerCase(); + return isLowerCase && isAddress(address, { strict: false }); } /** From f97481ee6d2819a3462d089a9b51e5136e72afe5 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 16:49:09 -0500 Subject: [PATCH 22/60] feat: expact literalNameToInterpretedName logic --- .../enskit-react-example/src/DomainView.tsx | 29 ++- .../components/ensure-interpreted-name.tsx | 45 ++++- .../lib/interpreted-names-and-labels.test.ts | 169 +++++++++++++++--- .../src/lib/interpreted-names-and-labels.ts | 150 +++++++++++++--- packages/enssdk/src/lib/normalization.ts | 21 ++- packages/enssdk/src/lib/types/ens.ts | 1 - 6 files changed, 348 insertions(+), 67 deletions(-) diff --git a/examples/enskit-react-example/src/DomainView.tsx b/examples/enskit-react-example/src/DomainView.tsx index 23bc5a7bf..11e2c9d44 100644 --- a/examples/enskit-react-example/src/DomainView.tsx +++ b/examples/enskit-react-example/src/DomainView.tsx @@ -1,6 +1,6 @@ import { EnsureInterpretedName } from "enskit/react"; import { type FragmentOf, graphql, readFragment, useOmnigraphQuery } from "enskit/react/omnigraph"; -import { getParentInterpretedName, type InterpretedName } from "enssdk"; +import { asLiteralName, getParentInterpretedName, type InterpretedName } from "enssdk"; import { Link, Navigate, useParams } from "react-router"; const DomainFragment = graphql(` @@ -87,13 +87,30 @@ export function DomainView() { // here we ensure that the provided /domain/:name parameter is an InterpretedName return ( } - // this name can't conform to InterpretedName: it is malformed or contains unnormalizable Labels + name={asLiteralName(params.name)} + // + // options for how we interpret user input + options={{ + // while not strictly necessary to specify, since we catch the empty string case above, we'll + // be explicit in this example app and tell enskit that for our purposes, we don't want our + // downstream + allowENSRootName: false, + + // allow the incoming LiteralName to contain Encoded LabelHash segments (e.g. [abcd...xyz]) + allowEncodedLabelHashes: true, + + // if a user ever navigates to a /domain/:name that contains unnormalizable labels, we want + // to represent that label as an encoded labelhash and redirect the user to that canonical page + coerceUnnormalizableLabelsToEncodedLabelHashes: true, + }} + // + // this isn't an InterpretedName, but it was coerced to an InterpretedName: redirect the user to the canonical url + coerced={(name) => } + // + // this name can't conform to InterpretedName nor can it be coerced: it is malformed: show an error malformed={(name) => (
-

{name} is malformed

+

{name} could not be understood

Back to 'eth' Domain.
)} diff --git a/packages/enskit/src/react/components/ensure-interpreted-name.tsx b/packages/enskit/src/react/components/ensure-interpreted-name.tsx index 16081a37b..94255cc1e 100644 --- a/packages/enskit/src/react/components/ensure-interpreted-name.tsx +++ b/packages/enskit/src/react/components/ensure-interpreted-name.tsx @@ -1,32 +1,59 @@ -import { type InterpretedName, isInterpretedName, type Name, nameToInterpretedName } from "enssdk"; +import { + type InterpretedName, + isInterpretedName, + type LiteralName, + literalNameToInterpretedName, +} from "enssdk"; import type { ReactNode } from "react"; type MalformedNameRenderer = (name: string) => ReactNode; type InterpretedNameRenderer = (name: InterpretedName) => ReactNode; /** - * Renders a Name by ensuring it is an InterpretedName. If the name is already - * interpreted, renders via `children`. If not, attempts to interpret it and - * renders via `interpreted` (enabling e.g. a redirect). If interpretation - * fails (malformed or unnormalizable), renders via `malformed`. + * Renders a {@link LiteralName} by ensuring it is an {@link InterpretedName}. This is useful for + * ensuring that downstream components get the guarantees of an {@link InterpretedName}, while + * + * + * @param name - The user-provided {@link LiteralName} to render. + * @param children - Render prop called with the {@link InterpretedName} when `name` is already interpreted. + * @param coerced - Render prop called with the coerced {@link InterpretedName} when `name` was not already + * interpreted but could be successfully coerced under `options`. Typically used to redirect the user to the + * canonical URL. + * @param malformed - Render prop called with the original literal string when `name` cannot be coerced into an + * {@link InterpretedName} under `options`. + * @param options - Forwarded to {@link literalNameToInterpretedName}. Controls how the interpretation handles edge + * cases. When `options.allowENSRootName` is `true`, an empty `name` is accepted and rendered via `children`; when + * `false` (default), an empty `name` falls through to `malformed`. When `options.allowEncodedLabelHashes` is + * `true`, a Label already formatted as an EncodedLabelHash is preserved verbatim; when `false` (default), such a + * Label is treated like any other input and passed through normalization, which will fail and fall through to the + * unnormalizable-Label handling. When `options.coerceUnnormalizedLabelsToNormalizedLabels` is `true` (default), an + * unnormalized Label is passed through ENSIP-15 normalization (e.g. `"Vitalik"` → `"vitalik"`); when `false`, any + * unnormalized Label causes `malformed` to be invoked — no normalization is attempted and + * `coerceUnnormalizableLabelsToEncodedLabelHashes` is not consulted. When + * `options.coerceUnnormalizableLabelsToEncodedLabelHashes` is `true`, a Label that cannot be normalized is replaced + * with the EncodedLabelHash of its literal bytes and `coerced` is invoked; when `false` (default), encountering + * such a Label causes `malformed` to be invoked. Only consulted when + * `coerceUnnormalizedLabelsToNormalizedLabels` is `true`. */ export function EnsureInterpretedName({ name, children, - interpreted, + coerced, malformed, + options, }: { - name: Name; + name: LiteralName; children: InterpretedNameRenderer; - interpreted: InterpretedNameRenderer; + coerced: InterpretedNameRenderer; malformed: MalformedNameRenderer; + options?: Parameters[1]; }) { if (isInterpretedName(name)) return children(name); try { // this isn't an InterpretedName, let's try to redirect the user to the InterpretedName // which ensures that our app only ever operates on InterpretedNames - return interpreted(nameToInterpretedName(name)); + return coerced(literalNameToInterpretedName(name, options)); } catch { // this name can't conform to InterpretedName: it is malformed or contains unnormalizable Labels return malformed(name); diff --git a/packages/enssdk/src/lib/interpreted-names-and-labels.test.ts b/packages/enssdk/src/lib/interpreted-names-and-labels.test.ts index d29456aae..0de6d9670 100644 --- a/packages/enssdk/src/lib/interpreted-names-and-labels.test.ts +++ b/packages/enssdk/src/lib/interpreted-names-and-labels.test.ts @@ -4,11 +4,12 @@ import { ENS_ROOT_NAME } from "./constants"; import { asInterpretedLabel, asLiteralLabel, + asLiteralName, constructSubInterpretedName, interpretedLabelsToInterpretedName, literalLabelsToInterpretedName, literalLabelToInterpretedLabel, - nameToInterpretedName, + literalNameToInterpretedName, parsePartialInterpretedName, } from "./interpreted-names-and-labels"; import { encodeLabelHash, labelhashLiteralLabel } from "./labelhash"; @@ -205,32 +206,158 @@ describe("interpretation", () => { ); }); - describe("nameToInterpretedName", () => { - it("returns ENS_ROOT_NAME unchanged", () => { - expect(nameToInterpretedName(ENS_ROOT_NAME)).toBe(ENS_ROOT_NAME); - }); + describe("literalNameToInterpretedName", () => { + type Options = Parameters[1]; - it("works for tlds", () => { - expect(nameToInterpretedName("eth")).toBe("eth"); - }); + const ENCODED_TEST_NULL = encodeLabelHash(labelhashLiteralLabel(asLiteralLabel("test\0"))); + const ENCODED_BAD_BRACKET = encodeLabelHash(labelhashLiteralLabel(asLiteralLabel("bad["))); + const ENCODED_HASH_AS_LITERAL = encodeLabelHash( + labelhashLiteralLabel(asLiteralLabel(EXAMPLE_ENCODED_LABEL_HASH)), + ); + const ALL_OPTIONS = { + allowENSRootName: true, + allowEncodedLabelHashes: true, + coerceUnnormalizedLabelsToNormalizedLabels: true, + coerceUnnormalizableLabelsToEncodedLabelHashes: true, + } as const satisfies Options; - it("throws for a name with an empty label segment", () => { - expect(() => nameToInterpretedName("example..eth")).toThrow(/empty label segment/); + it.each<[string, Options, string]>([ + // defaults: fully-normalized names pass through + ["eth", undefined, "eth"], + ["vitalik.eth", undefined, "vitalik.eth"], + ["sub.vitalik.eth", undefined, "sub.vitalik.eth"], + // defaults: ENSIP-15 normalizes normalizable-but-not-normalized Labels + ["Vitalik.eth", undefined, "vitalik.eth"], + ["VITALIK.ETH", undefined, "vitalik.eth"], + ["Sub.Vitalik.Eth", undefined, "sub.vitalik.eth"], + // coerceUnnormalizable=false is irrelevant when no unnormalizable Labels are present + ["Vitalik.eth", { coerceUnnormalizableLabelsToEncodedLabelHashes: false }, "vitalik.eth"], + // coerceUnnormalized=true (explicit): normalizable-but-not-normalized Labels are normalized + ["Vitalik.eth", { coerceUnnormalizedLabelsToNormalizedLabels: true }, "vitalik.eth"], + // coerceUnnormalized=false: fully-normalized names still pass through unchanged + ["vitalik.eth", { coerceUnnormalizedLabelsToNormalizedLabels: false }, "vitalik.eth"], + ["sub.vitalik.eth", { coerceUnnormalizedLabelsToNormalizedLabels: false }, "sub.vitalik.eth"], + // coerceUnnormalized=false + allowEncodedLabelHashes=true: pre-encoded labelhashes still preserved + [ + `${EXAMPLE_ENCODED_LABEL_HASH}.eth`, + { + coerceUnnormalizedLabelsToNormalizedLabels: false, + allowEncodedLabelHashes: true, + }, + `${EXAMPLE_ENCODED_LABEL_HASH}.eth`, + ], + // allowENSRootName=true: empty input returns ENS Root Name + [ENS_ROOT_NAME, { allowENSRootName: true }, ENS_ROOT_NAME], + // allowEncodedLabelHashes=true: pre-encoded labelhashes preserved verbatim + [ + `${EXAMPLE_ENCODED_LABEL_HASH}.eth`, + { allowEncodedLabelHashes: true }, + `${EXAMPLE_ENCODED_LABEL_HASH}.eth`, + ], + [ + `sub.${EXAMPLE_ENCODED_LABEL_HASH}.eth`, + { allowEncodedLabelHashes: true }, + `sub.${EXAMPLE_ENCODED_LABEL_HASH}.eth`, + ], + // allowEncodedLabelHashes=true: still normalizes other labels in the name + [ + `Sub.${EXAMPLE_ENCODED_LABEL_HASH}.Eth`, + { allowEncodedLabelHashes: true }, + `sub.${EXAMPLE_ENCODED_LABEL_HASH}.eth`, + ], + // encodeUnnormalizable=true: unnormalizable Labels are encoded as the labelhash of their literal bytes + [ + "test\0.eth", + { coerceUnnormalizableLabelsToEncodedLabelHashes: true }, + `${ENCODED_TEST_NULL}.eth`, + ], + // encodeUnnormalizable=true: multiple unnormalizable Labels encoded independently + [ + "test\0.bad[.eth", + { coerceUnnormalizableLabelsToEncodedLabelHashes: true }, + `${ENCODED_TEST_NULL}.${ENCODED_BAD_BRACKET}.eth`, + ], + // allowEncodedLabelHashes=false + encodeUnnormalizable=true: a "[hash]" Label + // fails normalization and is encoded as the labelhash of the literal bracket + // string, NOT the original labelhash it encoded. + [ + `${EXAMPLE_ENCODED_LABEL_HASH}.eth`, + { + allowEncodedLabelHashes: false, + coerceUnnormalizableLabelsToEncodedLabelHashes: true, + }, + `${ENCODED_HASH_AS_LITERAL}.eth`, + ], + // all options enabled: ENS Root Name + [ENS_ROOT_NAME, ALL_OPTIONS, ENS_ROOT_NAME], + // all options enabled: encoded labelhash preserved, other labels normalized + [ + `Sub.${EXAMPLE_ENCODED_LABEL_HASH}.eth`, + ALL_OPTIONS, + `sub.${EXAMPLE_ENCODED_LABEL_HASH}.eth`, + ], + // all options enabled: unnormalizable Label encoded alongside preserved encoded labelhash + [ + `test\0.${EXAMPLE_ENCODED_LABEL_HASH}.eth`, + ALL_OPTIONS, + `${ENCODED_TEST_NULL}.${EXAMPLE_ENCODED_LABEL_HASH}.eth`, + ], + ])("literalNameToInterpretedName(%j, %j) → %j", (name, options, expected) => { + expect(literalNameToInterpretedName(asLiteralName(name), options)).toEqual(expected); }); - it("preserves a pre-encoded labelhash label", () => { - expect(nameToInterpretedName(`${EXAMPLE_ENCODED_LABEL_HASH}.eth`)).toEqual( + it.each<[string, Options, RegExp]>([ + // empty input rejected when allowENSRootName is false + [ENS_ROOT_NAME, undefined, /ENS Root Name/], + [ENS_ROOT_NAME, { allowENSRootName: false }, /ENS Root Name/], + // empty Label segments always rejected, regardless of options + ["example..eth", undefined, /empty Label segment/], + [".eth", undefined, /empty Label segment/], + ["eth.", undefined, /empty Label segment/], + ["example..eth", { allowENSRootName: true }, /empty Label segment/], + ["a..b", ALL_OPTIONS, /empty Label segment/], + // unnormalizable Label rejected when encodeUnnormalizable is false + ["test\0.eth", undefined, /cannot be normalized/], + [ + "test\0.eth", + { coerceUnnormalizableLabelsToEncodedLabelHashes: false }, + /cannot be normalized/, + ], + // pre-encoded labelhash rejected when allowEncodedLabelHashes is false (falls + // through to the unnormalizable handler, which also throws under defaults) + [`${EXAMPLE_ENCODED_LABEL_HASH}.eth`, undefined, /cannot be normalized/], + [ `${EXAMPLE_ENCODED_LABEL_HASH}.eth`, + { allowEncodedLabelHashes: false }, + /cannot be normalized/, + ], + // strings that merely look like encoded labelhashes (wrong length) are still + // treated as unnormalizable literals, even when allowEncodedLabelHashes=true + ["[deadbeef].eth", { allowEncodedLabelHashes: true }, /cannot be normalized/], + // coerceUnnormalized=false: a normalizable-but-not-normalized Label is rejected + // up-front without attempting normalization + [ + "Vitalik.eth", + { coerceUnnormalizedLabelsToNormalizedLabels: false }, + /coercion is disabled/, + ], + // coerceUnnormalized=false: an unnormalizable Label is rejected with the same + // "coercion is disabled" message (no normalization is attempted) + ["test\0.eth", { coerceUnnormalizedLabelsToNormalizedLabels: false }, /coercion is disabled/], + // coerceUnnormalized=false gates coerceUnnormalizable=true: even an unnormalizable + // Label that would otherwise be encoded is rejected + [ + "test\0.eth", + { + coerceUnnormalizedLabelsToNormalizedLabels: false, + coerceUnnormalizableLabelsToEncodedLabelHashes: true, + }, + /coercion is disabled/, + ], + ])("literalNameToInterpretedName(%j, %j) throws %s", (name, options, expectedError) => { + expect(() => literalNameToInterpretedName(asLiteralName(name), options)).toThrow( + expectedError, ); }); - - it("preserves a normalized label", () => { - expect(nameToInterpretedName("vitalik.eth")).toEqual("vitalik.eth"); - }); - - it("encodes a non-normalized label as an encoded labelhash", () => { - const expectedEncoded = encodeLabelHash(labelhashLiteralLabel(asLiteralLabel("Vitalik"))); - expect(nameToInterpretedName("Vitalik.eth")).toEqual(`${expectedEncoded}.eth`); - }); }); }); diff --git a/packages/enssdk/src/lib/interpreted-names-and-labels.ts b/packages/enssdk/src/lib/interpreted-names-and-labels.ts index 7be2c3fcd..d82fed6e8 100644 --- a/packages/enssdk/src/lib/interpreted-names-and-labels.ts +++ b/packages/enssdk/src/lib/interpreted-names-and-labels.ts @@ -7,7 +7,7 @@ import { labelhashInterpretedLabel, labelhashLiteralLabel, } from "./labelhash"; -import { isNormalizedLabel } from "./normalization"; +import { isNormalizedLabel, normalizeLabel } from "./normalization"; import type { InterpretedLabel, InterpretedName, @@ -20,32 +20,120 @@ import type { } from "./types"; /** - * Interprets a Name as an InterpretedName. - * @throws if the provided `name` cannot conform to InterpretedName. + * Interprets a user-provided {@link LiteralName} as an {@link InterpretedName}. * - * @dev encodes unnormalized labels in `name` to make it InterpretedName. - * @dev this is similar to the concept of Reinterpretation (packages/enssdk/src/lib/reinterpretation.ts) - * but is distinct in that we're interpreting a Name (i.e. from user input) rather than a previously - * interpreted InterpretedName. + * A {@link LiteralName} may be any arbitrary string. The ENS Root Name ('') ({@link ENS_ROOT_NAME}) + * is only accepted when `options.allowENSRootName` is `true`, and is returned as-is. + * + * This function walks each LiteralLabel of `name` and maps it to an {@link InterpretedLabel} + * according to the provided `options`: + * + * 0. If the LiteralLabel is an empty string (''), this function throws: an empty Label is not a valid + * {@link InterpretedLabel}. + * 1. If the LiteralLabel is already a normalized LiteralLabel, it is kept as-is. + * 2. Otherwise, if the LiteralLabel looks like an {@link EncodedLabelHash} (e.g. `[abcd…]`) and + * `options.allowEncodedLabelHashes` is `true`, it is kept as-is. + * 3. Otherwise, the LiteralLabel is unnormalized. If `options.coerceUnnormalizedLabelsToNormalizedLabels` is `false`, + * this function throws. Otherwise (default), the LiteralLabel is passed through ENSIP-15 normalization + * ({@link normalizeLabel}). If normalization succeeds, the normalized form is used (e.g. `"Vitalik"` → + * `"vitalik"`). + * 4. Otherwise, the LiteralLabel is unnormalizable. If `options.coerceUnnormalizableLabelsToEncodedLabelHashes` + * is `true`, the Label is replaced with the EncodedLabelHash of its literal bytes. Otherwise, this + * function throws. + * + * Note that step 3 gates step 4: if `options.coerceUnnormalizedLabelsToNormalizedLabels` is `false`, the + * function throws immediately for any unnormalized Label, regardless of whether the Label would have been + * normalizable and regardless of `options.coerceUnnormalizableLabelsToEncodedLabelHashes`. + * + * @param name - The user-provided {@link LiteralName} to interpret. + * @param options - Controls how the interpretation handles edge cases. + * @param options.allowENSRootName - When `true`, an empty `name` is accepted and returned as the ENS Root Name. + * When `false` (default), an empty `name` throws. + * @param options.allowEncodedLabelHashes - When `true`, a Label that is already formatted as an + * {@link EncodedLabelHash} is preserved verbatim. When `false` (default), such a Label is treated like any other + * input and passed through normalization, which will fail and fall through to the unnormalizable-Label handling. + * @param options.coerceUnnormalizedLabelsToNormalizedLabels - When `true` (default), a Label that is not already + * normalized is passed through ENSIP-15 normalization (e.g. `"Vitalik"` → `"vitalik"`). When `false`, any + * unnormalized Label causes this function to throw — no normalization is attempted and + * `coerceUnnormalizableLabelsToEncodedLabelHashes` is not consulted. + * @param options.coerceUnnormalizableLabelsToEncodedLabelHashes - When `true`, a Label that cannot be normalized is + * replaced with the EncodedLabelHash of its literal bytes. When `false` (default), encountering such a Label causes + * this function to throw. Only consulted when `coerceUnnormalizedLabelsToNormalizedLabels` is `true`. + * + * @throws if `name` cannot be coerced into an {@link InterpretedName} under the provided `options`. + * + * @dev casts to {@link InterpretedLabel} to avoid an additional unnecessary `asInterpretedLabel` pass. */ -export function nameToInterpretedName(name: Name): InterpretedName { - if (name === ENS_ROOT_NAME) return ENS_ROOT_NAME; +export function literalNameToInterpretedName( + name: LiteralName, + { + allowENSRootName = false, + allowEncodedLabelHashes = false, + coerceUnnormalizedLabelsToNormalizedLabels = true, + coerceUnnormalizableLabelsToEncodedLabelHashes = false, + }: { + allowENSRootName?: boolean; + allowEncodedLabelHashes?: boolean; + coerceUnnormalizedLabelsToNormalizedLabels?: boolean; + coerceUnnormalizableLabelsToEncodedLabelHashes?: boolean; + } = { + allowENSRootName: false, + allowEncodedLabelHashes: false, + coerceUnnormalizedLabelsToNormalizedLabels: true, + coerceUnnormalizableLabelsToEncodedLabelHashes: false, + }, +): InterpretedName { + if (name === "") { + if (allowENSRootName) return ENS_ROOT_NAME; + + throw new Error( + `The ENS Root Name ('') cannot conform to InterpretedName when allowENSRootName is false.`, + ); + } return interpretedLabelsToInterpretedName( - name - .split(".") - .map((label) => { - if (label === "") { - throw new Error( - `Name '${name}' cannot conform to InterpretedName because it contains an empty label segment, which is not a valid label.`, - ); + literalNameToLiteralLabels(name).map((label) => { + // Sanity Check: No empty Labels + if (label === "") { + throw new Error( + `Name '${name}' cannot conform to InterpretedName because it contains an empty Label segment, which is not a normalized Label.`, + ); + } + + // if it's already normalized, good to go + if (isNormalizedLabel(label)) { + return label as Label as InterpretedLabel; + } + + // special case: if it's an EncodedLabelHash, and the consumer allows, good to go + if (allowEncodedLabelHashes && isEncodedLabelHash(label)) { + return label as Label as InterpretedLabel; + } + + // if the consumer does not want to allow coercion of unnormalized labels, then there's nothing to do + if (!coerceUnnormalizedLabelsToNormalizedLabels) { + throw new Error( + `Name '${name}' cannot conform to InterpretedName because Label '${label}' is unnormalized and coercion is disabled.`, + ); + } + + try { + // attempt to normalize it and pass the normalized Label along + return normalizeLabel(label); + } catch { + // but the label is unnormalizable, so: + + // if the consumer wants to interpret unnormalizable Labels as an EncodedLabelHash, do so + if (coerceUnnormalizableLabelsToEncodedLabelHashes) { + return encodeLabelHash(labelhashLiteralLabel(label)) as InterpretedLabel; } - if (isEncodedLabelHash(label)) return label; - if (isNormalizedLabel(label)) return label; - return encodeLabelHash(labelhashLiteralLabel(asLiteralLabel(label))); - }) - .map(asInterpretedLabel), + // otherwise, cannot conform + throw new Error( + `Name '${name}' cannot conform to InterpretedName because Label '${label}' is unnormalized and cannot be normalized.`, + ); + } + }), ); } @@ -107,6 +195,13 @@ export function literalLabelsToLiteralName(labels: LiteralLabel[]): LiteralName return labels.join(".") as LiteralName; } +/** + * Converts an LiteralName into a list of LiteralLabels. + */ +export function literalNameToLiteralLabels(name: LiteralName): LiteralLabel[] { + return name.split(".") as LiteralLabel[]; +} + /** * Converts an Interpreted Name into a list of Interpreted Labels. */ @@ -227,7 +322,10 @@ export function parsePartialInterpretedName(partialInterpretedName: Name): { /** * Casts a string to a {@link LiteralName}. - * A LiteralName is a name as it literally appears onchain. + * + * A LiteralName is a name that should be interpreted as a string literal. It may or may not be + * normalized or normalizable. It may also include labels formatted as an encoded labelhash, but that + * does not mean it should be interpreted as perhaps containing encoded labelhashes. */ export function asLiteralName(name: Name): LiteralName { return name as LiteralName; @@ -235,7 +333,10 @@ export function asLiteralName(name: Name): LiteralName { /** * Casts a string to a {@link LiteralLabel}. - * A LiteralLabel is a label as it literally appears onchain. + * + * A LiteralLabel is a label that should be interpreted as a string literal. It may or may not be + * normalized or normalizable. It may also be formatted as an encoded labelhash, but that does not + * mean it should be interpreted as an encoded labelhash. */ export function asLiteralLabel(label: Label): LiteralLabel { return label as LiteralLabel; @@ -255,7 +356,8 @@ export function asInterpretedLabel(label: Label): InterpretedLabel { /** * Validates and casts a string to an {@link InterpretedName}. - * An InterpretedName is composed entirely of InterpretedLabels joined by dots. + * An InterpretedName is either the ENS Root Name ('') or a name made up of InterpretedLabels (which + * are either normalized Labels or EncodedLabelHashes). * * @throws if the input cannot be interpreted into an InterpretedName */ diff --git a/packages/enssdk/src/lib/normalization.ts b/packages/enssdk/src/lib/normalization.ts index 542f3e23f..2b0be0f61 100644 --- a/packages/enssdk/src/lib/normalization.ts +++ b/packages/enssdk/src/lib/normalization.ts @@ -8,8 +8,13 @@ import type { InterpretedLabel, InterpretedName, Label, Name } from "./types"; * @throws if the Name is not normalizable * @see https://docs.ens.domains/ensip/15 */ -export const normalizeName = (name: Name): InterpretedName => - ens_normalize(name) as InterpretedName; +export const normalizeName = (name: Name): InterpretedName => { + try { + return ens_normalize(name) as InterpretedName; + } catch { + throw new Error(`Name '${name}' cannot be normalized.`); + } +}; /** * Normalizes a Label according to ENS normalization rules (ENSIP-15), returning an InterpretedLabel. @@ -19,16 +24,20 @@ export const normalizeName = (name: Name): InterpretedName => */ export const normalizeLabel = (label: Label): InterpretedLabel => { // empty string cannot be a normalized label - if (label === "") throw new Error("Empty label cannot be normalized."); + if (label === "") throw new Error("Label is empty ('') and cannot be normalized."); // normalized labels do not contain periods if (label.includes(".")) { throw new Error(`Label '${label}' includes '.' and cannot be normalized.`); } - // NOTE: the ens_normalize function accepts _names_ not labels, and so we must include our own - // invariants above to ensure that the `label` input here can be safely normalized - return ens_normalize(label) as InterpretedLabel; + try { + // NOTE: the ens_normalize function accepts _names_ not labels, and so we must include our own + // invariants above to ensure that the `label` input here can be safely normalized + return ens_normalize(label) as InterpretedLabel; + } catch { + throw new Error(`Label '${label}' cannot be normalized.`); + } }; /** diff --git a/packages/enssdk/src/lib/types/ens.ts b/packages/enssdk/src/lib/types/ens.ts index 4d15420a7..d5007e59e 100644 --- a/packages/enssdk/src/lib/types/ens.ts +++ b/packages/enssdk/src/lib/types/ens.ts @@ -92,7 +92,6 @@ export type EncodedLabelHash = `[${string}]`; * - containing other unnormalized characters such as null bytes or other characters * not suitable for display. * - * * @see https://ensnode.io/docs/reference/terminology#literal-label * @dev nominally typed to enforce usage & enhance codebase clarity */ From ae3859d49c461f65a54245509f6cfe03fe801421 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 17:04:09 -0500 Subject: [PATCH 23/60] fix: correctly validate encodedlabelhashes in interpretation --- .../src/lib/interpreted-names-and-labels.ts | 56 +++++-------------- packages/enssdk/src/lib/labelhash.ts | 38 +++++++++++++ 2 files changed, 52 insertions(+), 42 deletions(-) diff --git a/packages/enssdk/src/lib/interpreted-names-and-labels.ts b/packages/enssdk/src/lib/interpreted-names-and-labels.ts index d82fed6e8..f7e257b57 100644 --- a/packages/enssdk/src/lib/interpreted-names-and-labels.ts +++ b/packages/enssdk/src/lib/interpreted-names-and-labels.ts @@ -1,7 +1,6 @@ -import { isHex } from "viem"; - import { ENS_ROOT_NAME } from "./constants"; import { + decodeEncodedLabelHash, encodeLabelHash, isEncodedLabelHash, labelhashInterpretedLabel, @@ -72,16 +71,11 @@ export function literalNameToInterpretedName( coerceUnnormalizedLabelsToNormalizedLabels = true, coerceUnnormalizableLabelsToEncodedLabelHashes = false, }: { - allowENSRootName?: boolean; - allowEncodedLabelHashes?: boolean; - coerceUnnormalizedLabelsToNormalizedLabels?: boolean; - coerceUnnormalizableLabelsToEncodedLabelHashes?: boolean; - } = { - allowENSRootName: false, - allowEncodedLabelHashes: false, - coerceUnnormalizedLabelsToNormalizedLabels: true, - coerceUnnormalizableLabelsToEncodedLabelHashes: false, - }, + allowENSRootName?: boolean | undefined; + allowEncodedLabelHashes?: boolean | undefined; + coerceUnnormalizedLabelsToNormalizedLabels?: boolean | undefined; + coerceUnnormalizableLabelsToEncodedLabelHashes?: boolean | undefined; + } = {}, ): InterpretedName { if (name === "") { if (allowENSRootName) return ENS_ROOT_NAME; @@ -209,25 +203,8 @@ export function interpretedNameToInterpretedLabels(name: InterpretedName): Inter return name.split(".") as InterpretedLabel[]; } -// https://github.com/wevm/viem/blob/main/src/utils/ens/encodedLabelToLabelhash.ts -export function encodedLabelToLabelhash(label: string): LabelHash | null { - if (label.length !== 66) return null; - if (label.indexOf("[") !== 0) return null; - if (label.indexOf("]") !== 65) return null; - const hash = `0x${label.slice(1, 65)}`; - if (!isHex(hash)) return null; - return hash; -} - export function isInterpetedLabel(label: Label): label is InterpretedLabel { - // if it looks like an encoded labelhash, it must be one - if (label.startsWith("[")) { - const labelHash = encodedLabelToLabelhash(label); - return labelHash != null; - } - - // otherwise label must be normalized - return isNormalizedLabel(label); + return isEncodedLabelHash(label) || isNormalizedLabel(label); } /** @@ -238,7 +215,7 @@ export function isInterpetedLabel(label: Label): label is InterpretedLabel { * @returns */ export function isInterpretedName(name: Name): name is InterpretedName { - if (name === "") return true; + if (name === ENS_ROOT_NAME) return true; return name.split(".").every(isInterpetedLabel); } @@ -248,18 +225,13 @@ export function isInterpretedName(name: Name): name is InterpretedName { export function interpretedLabelsToLabelHashPath(labels: InterpretedLabel[]): LabelHashPath { return labels .map((label) => { - if (!isInterpetedLabel(label)) { - throw new Error( - `Invariant(interpretedLabelsToLabelHashPath): Expected InterpretedLabel, received '${label}'.`, - ); + try { + // attempt to decode label as an encoded labelhash + return decodeEncodedLabelHash(label); + } catch { + // but if that failed, this must be a normalized label, so labelhash it + return labelhashInterpretedLabel(label); } - - // if it looks like an encoded labelhash, return it - const maybeLabelHash = encodedLabelToLabelhash(label); - if (maybeLabelHash !== null) return maybeLabelHash; - - // otherwise, labelhash it - return labelhashInterpretedLabel(label); }) .toReversed(); } diff --git a/packages/enssdk/src/lib/labelhash.ts b/packages/enssdk/src/lib/labelhash.ts index 1875f9ead..2c830a84c 100644 --- a/packages/enssdk/src/lib/labelhash.ts +++ b/packages/enssdk/src/lib/labelhash.ts @@ -51,6 +51,44 @@ export function isLabelHash(maybeLabelHash: string): maybeLabelHash is LabelHash export const encodeLabelHash = (labelHash: LabelHash): EncodedLabelHash => `[${labelHash.slice(2)}]`; +/** + * Decodes an Encoded LabelHash as a LabelHash. + * + * @throws if a valid LabelHash cannot be decoded + * + * @see https://ensnode.io/docs/reference/terminology#encoded-labelhash + * @see https://github.com/wevm/viem/blob/main/src/utils/ens/encodedLabelToLabelhash.ts + * + * @param maybeEncodedLabelHash The encoded label hash in format `[hash_without_0x_prefix]` + * @returns A 32-byte lowercase hash string starting with '0x' + */ +export const decodeEncodedLabelHash = (maybeEncodedLabelHash: string): LabelHash => { + if (maybeEncodedLabelHash.length !== 66) { + throw new Error( + `EncodedLabelHash '${maybeEncodedLabelHash}' is malformed: must have length 66.`, + ); + } + + if (maybeEncodedLabelHash.indexOf("[") !== 0) { + throw new Error( + `EncodedLabelHash '${maybeEncodedLabelHash}' is malformed: must begin with '['.`, + ); + } + + if (maybeEncodedLabelHash.indexOf("]") !== 65) { + throw new Error(`EncodedLabelHash '${maybeEncodedLabelHash}' is malformed: must end with ']'.`); + } + + const hash = `0x${maybeEncodedLabelHash.slice(1, 65)}`; + if (!isLabelHash(hash)) { + throw new Error( + `EncodedLabelHash '${maybeEncodedLabelHash}' is malformed: must contain a valid LabelHash.`, + ); + } + + return hash; +}; + /** * Checks if the value is an {@link EncodedLabelHash}. */ From 75d17924ed61c241238b0603f96cfbddceda95a0 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 17:05:41 -0500 Subject: [PATCH 24/60] fix: remove ambiguous readFragment re-export in enskit/react/omnigraph ./graphql already re-exports readFragment/FragmentOf/ResultOf/VariablesOf from gql.tada, making the explicit enssdk/omnigraph re-exports redundant and causing ambiguous re-export errors. Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/enskit/src/react/omnigraph/index.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/enskit/src/react/omnigraph/index.ts b/packages/enskit/src/react/omnigraph/index.ts index a7094eaeb..ef4984c1a 100644 --- a/packages/enskit/src/react/omnigraph/index.ts +++ b/packages/enskit/src/react/omnigraph/index.ts @@ -1,7 +1,3 @@ -// export the gql.tada subset of enssdk/omnigraph so consumers only need the one dependency -export type { FragmentOf, ResultOf, VariablesOf } from "enssdk/omnigraph"; -export { readFragment } from "enssdk/omnigraph"; - export * from "./graphql"; export * from "./hooks"; export * from "./provider"; From 21ee782e767a2a3127849d3ce40d3b1e975ae75e Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 18:22:43 -0500 Subject: [PATCH 25/60] fix: typos --- .../src/plugins/subgraph/plugins/subgraph/handlers/Registry.ts | 2 +- packages/datasources/src/invariants.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ensindexer/src/plugins/subgraph/plugins/subgraph/handlers/Registry.ts b/apps/ensindexer/src/plugins/subgraph/plugins/subgraph/handlers/Registry.ts index 3e31136f1..5fae5affb 100644 --- a/apps/ensindexer/src/plugins/subgraph/plugins/subgraph/handlers/Registry.ts +++ b/apps/ensindexer/src/plugins/subgraph/plugins/subgraph/handlers/Registry.ts @@ -83,7 +83,7 @@ export default function () { // NOTE: this logic derived from the subgraph introduces a minor bug for queries with a blockheight // below 9380380, when the new Registry was deployed, as it implicitly ignores Transfer events // of the ENS_ROOT_NODE. as a result, the root node's owner is always zeroAddress until the new - // Registry events are picked up. for backwards compatibility this beahvior is re-implemented + // Registry events are picked up. for backwards compatibility this behavior is re-implemented // here. const shouldIgnoreEvent = await shouldIgnoreRegistryOldEvents(context, event.args.node); diff --git a/packages/datasources/src/invariants.test.ts b/packages/datasources/src/invariants.test.ts index 5c9627164..e8524e262 100644 --- a/packages/datasources/src/invariants.test.ts +++ b/packages/datasources/src/invariants.test.ts @@ -23,7 +23,7 @@ describe("datasource invariants", () => { expect( // TODO: could use enssdk#isNormalizedAddress here contractConfig.address === contractConfig.address.toLowerCase(), - `The Address '${namespace}' > '${datasourceName}' > '${contractName}' > '${contractConfig.address}' is not a enssdk#NormalizedAddress (i.e. is not fully lowercase).`, + `The Address '${namespace}' > '${datasourceName}' > '${contractName}' > '${contractConfig.address}' is not an enssdk#NormalizedAddress (i.e. is not fully lowercase).`, ).toBe(true); } } From 76c9ac556a7eec7a2bc2687147c5194466dff654 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 18:23:26 -0500 Subject: [PATCH 26/60] fix: use normalized address in namewrapper.ts --- .../src/plugins/subgraph/shared-handlers/NameWrapper.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/ensindexer/src/plugins/subgraph/shared-handlers/NameWrapper.ts b/apps/ensindexer/src/plugins/subgraph/shared-handlers/NameWrapper.ts index e600df696..0711938f0 100644 --- a/apps/ensindexer/src/plugins/subgraph/shared-handlers/NameWrapper.ts +++ b/apps/ensindexer/src/plugins/subgraph/shared-handlers/NameWrapper.ts @@ -16,7 +16,6 @@ import config from "@/config"; */ import { checkPccBurned as isPccFuseUnset } from "@ensdomains/ensjs/utils"; import { - type Address, type DNSEncodedLiteralName, type DNSEncodedName, decodeDNSEncodedLiteralName, @@ -123,8 +122,8 @@ export const makeNameWrapperHandlers = () => { context: IndexingEngineContext, event: EventWithArgs, eventId: string, - tokenId: bigint, - to: Address, + tokenId: TokenId, + to: NormalizedAddress, ) { await upsertAccount(context, to); From de4bc5b49c565f069bc230cbc45f7027e7b03d53 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 18:30:57 -0500 Subject: [PATCH 27/60] fix: copilot notes --- ...ith-universal-resolver.integration.test.ts | 7 ++- apps/ensapi/src/omnigraph-api/builder.test.ts | 5 +- .../schema/permissions.integration.test.ts | 59 ++++++------------- packages/enssdk/src/lib/types/evm.ts | 2 +- 4 files changed, 25 insertions(+), 48 deletions(-) diff --git a/apps/ensapi/src/lib/resolution/resolve-with-universal-resolver.integration.test.ts b/apps/ensapi/src/lib/resolution/resolve-with-universal-resolver.integration.test.ts index d8c59d69d..3f8db4f81 100644 --- a/apps/ensapi/src/lib/resolution/resolve-with-universal-resolver.integration.test.ts +++ b/apps/ensapi/src/lib/resolution/resolve-with-universal-resolver.integration.test.ts @@ -35,7 +35,6 @@ const NAME_WITH_ENCODED_LABELHASHES = interpretedLabelsToInterpretedName([ const EXPECTED_DESCRIPTION = "example.eth"; -const CALLS = makeResolveCalls(namehashInterpretedName(NAME), { texts: ["description"] }); const publicClient = getPublicClient(ensTestEnvChain.id); describe("executeResolveCallsWithUniversalResolver", () => { @@ -43,7 +42,7 @@ describe("executeResolveCallsWithUniversalResolver", () => { await expect( executeResolveCallsWithUniversalResolver({ name: NAME, - calls: CALLS, + calls: makeResolveCalls(namehashInterpretedName(NAME), { texts: ["description"] }), publicClient, }), ).resolves.toMatchObject([{ result: EXPECTED_DESCRIPTION }]); @@ -64,7 +63,9 @@ describe("executeResolveCallsWithUniversalResolver", () => { await expect( executeResolveCallsWithUniversalResolver({ name: NAME_WITH_ENCODED_LABELHASHES, - calls: CALLS, + calls: makeResolveCalls(namehashInterpretedName(NAME_WITH_ENCODED_LABELHASHES), { + texts: ["description"], + }), publicClient, }), ).resolves.toMatchObject([{ result: null }]); diff --git a/apps/ensapi/src/omnigraph-api/builder.test.ts b/apps/ensapi/src/omnigraph-api/builder.test.ts index 1677aa71e..fe5f9cdc5 100644 --- a/apps/ensapi/src/omnigraph-api/builder.test.ts +++ b/apps/ensapi/src/omnigraph-api/builder.test.ts @@ -1,5 +1,5 @@ import type { OmnigraphScalars } from "enssdk/omnigraph"; -import { assertType, describe, it } from "vitest"; +import { describe, expectTypeOf, it } from "vitest"; import type { BuilderScalars } from "./builder"; @@ -8,7 +8,6 @@ type OmnigraphScalarNames = Record; describe("BuilderScalars", () => { it("defines the same scalar names as OmnigraphScalars from enssdk", () => { - assertType({} as OmnigraphScalarNames); - assertType({} as BuilderScalarNames); + expectTypeOf().toEqualTypeOf(); }); }); diff --git a/apps/ensapi/src/omnigraph-api/schema/permissions.integration.test.ts b/apps/ensapi/src/omnigraph-api/schema/permissions.integration.test.ts index 631daa86a..69e2df7c1 100644 --- a/apps/ensapi/src/omnigraph-api/schema/permissions.integration.test.ts +++ b/apps/ensapi/src/omnigraph-api/schema/permissions.integration.test.ts @@ -1,5 +1,5 @@ import type { - ChainId, + AccountId, NormalizedAddress, PermissionsId, PermissionsResourceId, @@ -40,30 +40,28 @@ const EAC_ROLES_CHANGED_SELECTOR = toEventSelector( )!, ); +// the type of the PermissionUser returned by the omnigraph, to DRY up the types below +type PermissionUser = { + id: PermissionsUserId; + resource: string; + user: { address: NormalizedAddress }; + roles: string; +}; + describe("Permissions", () => { type PermissionsResult = { permissions: { id: PermissionsId; - contract: { chainId: ChainId; address: NormalizedAddress }; + contract: AccountId; root: { id: PermissionsResourceId; resource: string; - users: GraphQLConnection<{ - id: PermissionsUserId; - resource: string; - user: { address: NormalizedAddress }; - roles: string; - }>; + users: GraphQLConnection; }; resources: GraphQLConnection<{ id: PermissionsResourceId; resource: string; - users: GraphQLConnection<{ - id: PermissionsUserId; - resource: string; - user: { address: NormalizedAddress }; - roles: string; - }>; + users: GraphQLConnection; }>; }; }; @@ -137,7 +135,7 @@ describe("Registry.permissions", () => { registry: { permissions: { id: PermissionsId; - contract: { chainId: ChainId; address: NormalizedAddress }; + contract: AccountId; }; }; }>(RegistryPermissions, { contract: V2_ETH_REGISTRY }); @@ -150,12 +148,7 @@ describe("Registry.permissions", () => { describe("Domain.permissions", () => { type DomainPermissionsResult = { domain: { - permissions: GraphQLConnection<{ - id: PermissionsUserId; - resource: string; - user: { address: NormalizedAddress }; - roles: string; - }>; + permissions: GraphQLConnection; }; }; @@ -169,12 +162,7 @@ describe("Domain.permissions", () => { } `; - let allUsers: { - id: PermissionsUserId; - resource: string; - user: { address: NormalizedAddress }; - roles: string; - }[]; + let allUsers: PermissionUser[]; beforeAll(async () => { const result = await request(DomainPermissions, { @@ -263,12 +251,7 @@ describe("Account.permissions and Account.registryPermissions", () => { it("resolves permissions for an account with known roles", async () => { const result = await request<{ account: { - permissions: GraphQLConnection<{ - id: PermissionsUserId; - resource: string; - user: { address: NormalizedAddress }; - roles: string; - }>; + permissions: GraphQLConnection; }; }>(AccountPermissions, { address: targetAddress }); @@ -283,13 +266,7 @@ describe("Account.permissions and Account.registryPermissions", () => { it("resolves registry-scoped permissions for an account", async () => { const result = await request<{ account: { - registryPermissions: GraphQLConnection<{ - id: PermissionsUserId; - registry: { id: RegistryId }; - resource: string; - user: { address: NormalizedAddress }; - roles: string; - }>; + registryPermissions: GraphQLConnection; }; }>(AccountRegistryPermissions, { address: targetAddress }); @@ -318,7 +295,7 @@ describe("Resolver.permissions", () => { resolver: { permissions: { id: PermissionsId; - contract: { chainId: ChainId; address: NormalizedAddress }; + contract: AccountId; }; }; }; diff --git a/packages/enssdk/src/lib/types/evm.ts b/packages/enssdk/src/lib/types/evm.ts index d266764ff..7a0df657a 100644 --- a/packages/enssdk/src/lib/types/evm.ts +++ b/packages/enssdk/src/lib/types/evm.ts @@ -75,7 +75,7 @@ export type DefaultableChainId = 0 | ChainId; */ export interface AccountId { chainId: ChainId; - address: Address; + address: NormalizedAddress; } /** From b45f191e61c423bcc9a2bcc0c63584b03ef56bfb Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 18:34:31 -0500 Subject: [PATCH 28/60] fix: ensure referrer logic is using NormalizedAddress all the way down --- .../src/v1/award-models/rev-share-limit/leaderboard.ts | 9 ++++----- .../src/v1/award-models/rev-share-limit/metrics.ts | 4 ++-- .../v1/award-models/rev-share-limit/referral-event.ts | 4 ++-- packages/ens-referrals/src/v1/edition-metrics.ts | 4 ++-- packages/ens-referrals/src/v1/referrer-metrics.ts | 9 ++++----- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.ts b/packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.ts index d01798cb4..48e59c9bc 100644 --- a/packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.ts +++ b/packages/ens-referrals/src/v1/award-models/rev-share-limit/leaderboard.ts @@ -1,5 +1,4 @@ -import type { Address, Duration, UnixTimestamp } from "enssdk"; -import { toNormalizedAddress } from "enssdk"; +import type { Duration, NormalizedAddress, UnixTimestamp } from "enssdk"; import { priceEth, priceUsdc, scalePrice } from "@ensnode/ensnode-sdk"; @@ -54,7 +53,7 @@ export interface ReferrerLeaderboardRevShareLimit { * @invariant Each value in this map is guaranteed to have a non-zero * `totalReferrals` and `totalIncrementalDuration`. */ - referrers: Map; + referrers: Map; /** * The {@link UnixTimestamp} of when the data used to build the {@link ReferrerLeaderboardRevShareLimit} was accurate as of. @@ -97,11 +96,11 @@ export const buildReferrerLeaderboardRevShareLimit = ( const sortedEvents = sortReferralEvents(events); // 2. Process events sequentially to run the race. - const referrerStates = new Map(); + const referrerStates = new Map(); let awardPoolRemaining = rules.awardPool.amount; for (const event of sortedEvents) { - const referrer = toNormalizedAddress(event.referrer); + const referrer = event.referrer; let state = referrerStates.get(referrer); if (!state) { diff --git a/packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts b/packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts index 2960d802f..aec4aea07 100644 --- a/packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts +++ b/packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts @@ -1,4 +1,4 @@ -import type { Address } from "enssdk"; +import type { NormalizedAddress } from "enssdk"; import { type PriceUsdc, priceEth, priceUsdc } from "@ensnode/ensnode-sdk"; import { makePriceEthSchema, makePriceUsdcSchema } from "@ensnode/ensnode-sdk/internal"; @@ -338,7 +338,7 @@ export const validateUnrankedReferrerMetricsRevShareLimit = ( * Build an unranked zero-metrics rev-share-limit referrer record for an address not on the leaderboard. */ export const buildUnrankedReferrerMetricsRevShareLimit = ( - referrer: Address, + referrer: NormalizedAddress, rules: ReferralProgramRulesRevShareLimit, ): UnrankedReferrerMetricsRevShareLimit => { const metrics = buildReferrerMetrics(referrer, 0, 0, priceEth(0n)); diff --git a/packages/ens-referrals/src/v1/award-models/rev-share-limit/referral-event.ts b/packages/ens-referrals/src/v1/award-models/rev-share-limit/referral-event.ts index e32b5e42b..da88a142d 100644 --- a/packages/ens-referrals/src/v1/award-models/rev-share-limit/referral-event.ts +++ b/packages/ens-referrals/src/v1/award-models/rev-share-limit/referral-event.ts @@ -1,4 +1,4 @@ -import type { Address, Duration, UnixTimestamp } from "enssdk"; +import type { Duration, NormalizedAddress, UnixTimestamp } from "enssdk"; import type { PriceEth } from "@ensnode/ensnode-sdk"; @@ -12,7 +12,7 @@ export interface ReferralEvent { /** * The fully lowercase Ethereum address of the referrer. */ - referrer: Address; + referrer: NormalizedAddress; /** * Unix seconds block timestamp. diff --git a/packages/ens-referrals/src/v1/edition-metrics.ts b/packages/ens-referrals/src/v1/edition-metrics.ts index 6efff1189..e02b761e0 100644 --- a/packages/ens-referrals/src/v1/edition-metrics.ts +++ b/packages/ens-referrals/src/v1/edition-metrics.ts @@ -1,4 +1,4 @@ -import type { Address } from "enssdk"; +import type { NormalizedAddress } from "enssdk"; import type { ReferrerEditionMetricsPieSplit, @@ -44,7 +44,7 @@ export type ReferrerEditionMetrics = * @returns The appropriate {@link ReferrerEditionMetrics} */ export const getReferrerEditionMetrics = ( - referrer: Address, + referrer: NormalizedAddress, leaderboard: ReferrerLeaderboard, ): ReferrerEditionMetrics => { switch (leaderboard.awardModel) { diff --git a/packages/ens-referrals/src/v1/referrer-metrics.ts b/packages/ens-referrals/src/v1/referrer-metrics.ts index 1087a6583..3d12b74b0 100644 --- a/packages/ens-referrals/src/v1/referrer-metrics.ts +++ b/packages/ens-referrals/src/v1/referrer-metrics.ts @@ -1,5 +1,4 @@ -import type { Address, Duration } from "enssdk"; -import { toNormalizedAddress } from "enssdk"; +import type { Duration, NormalizedAddress } from "enssdk"; import type { PriceEth } from "@ensnode/ensnode-sdk"; import { makePriceEthSchema } from "@ensnode/ensnode-sdk/internal"; @@ -19,7 +18,7 @@ export interface ReferrerMetrics { * * @invariant Guaranteed to be a valid EVM address in lowercase format */ - referrer: Address; + referrer: NormalizedAddress; /** * The total number of referrals made by the referrer within the {@link ReferralProgramRules}. @@ -47,13 +46,13 @@ export interface ReferrerMetrics { } export const buildReferrerMetrics = ( - referrer: Address, + referrer: NormalizedAddress, totalReferrals: number, totalIncrementalDuration: Duration, totalRevenueContribution: PriceEth, ): ReferrerMetrics => { const result = { - referrer: toNormalizedAddress(referrer), + referrer, totalReferrals, totalIncrementalDuration, totalRevenueContribution, From be147ecc3a5c8360cad6079eaff7a821cdbbef31 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 18:36:02 -0500 Subject: [PATCH 29/60] fix: correctly passthrough for by id lookups --- .../src/react/omnigraph/_lib/by-id-lookup-resolvers.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/enskit/src/react/omnigraph/_lib/by-id-lookup-resolvers.ts b/packages/enskit/src/react/omnigraph/_lib/by-id-lookup-resolvers.ts index 5a1d9686b..8a46901dc 100644 --- a/packages/enskit/src/react/omnigraph/_lib/by-id-lookup-resolvers.ts +++ b/packages/enskit/src/react/omnigraph/_lib/by-id-lookup-resolvers.ts @@ -38,7 +38,7 @@ export const byIdLookupResolvers: Record> = { if (by.id) return { __typename: "Account", id: by.id }; if (by.address) return { __typename: "Account", id: by.address }; - throw new Error("never"); + return passthrough(args, cache, info); }, registry(parent, args, cache, info) { const by = args.by as { id?: RegistryId; contract?: AccountId }; @@ -46,7 +46,7 @@ export const byIdLookupResolvers: Record> = { if (by.id) return { __typename: "Registry", id: by.id }; if (by.contract) return { __typename: "Registry", id: makeRegistryId(by.contract) }; - throw new Error("never"); + return passthrough(args, cache, info); }, resolver(parent, args, cache, info) { const by = args.by as { id?: ResolverId; contract?: AccountId }; @@ -54,7 +54,7 @@ export const byIdLookupResolvers: Record> = { if (by.id) return { __typename: "Resolver", id: by.id }; if (by.contract) return { __typename: "Resolver", id: makeResolverId(by.contract) }; - throw new Error("never"); + return passthrough(args, cache, info); }, permissions(parent, args, cache, info) { const by = args.by as { id?: PermissionsId; contract?: AccountId }; @@ -62,7 +62,7 @@ export const byIdLookupResolvers: Record> = { if (by.id) return { __typename: "Permissions", id: by.id }; if (by.contract) return { __typename: "Permissions", id: makePermissionsId(by.contract) }; - throw new Error("never"); + return passthrough(args, cache, info); }, }, }; From 5ced5ca068566d198e1e29fc320ebbd19cf69562 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 18:38:26 -0500 Subject: [PATCH 30/60] fix: find-domains use NormalizedAddress --- .../lib/find-domains/layers/base-domain-set.ts | 6 +++--- .../lib/find-domains/layers/filter-by-owner.ts | 4 ++-- apps/ensapi/src/omnigraph-api/schema/scalars.ts | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/ensapi/src/omnigraph-api/lib/find-domains/layers/base-domain-set.ts b/apps/ensapi/src/omnigraph-api/lib/find-domains/layers/base-domain-set.ts index ec3e2fdeb..b70ca8953 100644 --- a/apps/ensapi/src/omnigraph-api/lib/find-domains/layers/base-domain-set.ts +++ b/apps/ensapi/src/omnigraph-api/lib/find-domains/layers/base-domain-set.ts @@ -1,6 +1,6 @@ import { and, eq, sql } from "drizzle-orm"; import { alias, unionAll } from "drizzle-orm/pg-core"; -import type { Address, DomainId } from "enssdk"; +import type { DomainId, NormalizedAddress } from "enssdk"; import { ensDb, ensIndexerSchema } from "@/lib/ensdb/singleton"; @@ -30,7 +30,7 @@ export function domainsBase() { ensDb .select({ domainId: sql`${ensIndexerSchema.v1Domain.id}`.as("domainId"), - ownerId: sql
`${ensIndexerSchema.v1Domain.ownerId}`.as("ownerId"), + ownerId: sql`${ensIndexerSchema.v1Domain.ownerId}`.as("ownerId"), registryId: sql`NULL::text`.as("registryId"), parentId: sql`${ensIndexerSchema.v1Domain.parentId}`.as("parentId"), labelHash: sql`${ensIndexerSchema.v1Domain.labelHash}`.as("labelHash"), @@ -46,7 +46,7 @@ export function domainsBase() { ensDb .select({ domainId: sql`${ensIndexerSchema.v2Domain.id}`.as("domainId"), - ownerId: sql
`${ensIndexerSchema.v2Domain.ownerId}`.as("ownerId"), + ownerId: sql`${ensIndexerSchema.v2Domain.ownerId}`.as("ownerId"), registryId: sql`${ensIndexerSchema.v2Domain.registryId}`.as("registryId"), parentId: sql`${v2ParentDomain.id}`.as("parentId"), labelHash: sql`${ensIndexerSchema.v2Domain.labelHash}`.as("labelHash"), diff --git a/apps/ensapi/src/omnigraph-api/lib/find-domains/layers/filter-by-owner.ts b/apps/ensapi/src/omnigraph-api/lib/find-domains/layers/filter-by-owner.ts index 5c040ddfe..34476dfd2 100644 --- a/apps/ensapi/src/omnigraph-api/lib/find-domains/layers/filter-by-owner.ts +++ b/apps/ensapi/src/omnigraph-api/lib/find-domains/layers/filter-by-owner.ts @@ -1,5 +1,5 @@ import { eq } from "drizzle-orm"; -import type { Address } from "enssdk"; +import type { NormalizedAddress } from "enssdk"; import { ensDb } from "@/lib/ensdb/singleton"; @@ -8,7 +8,7 @@ import { type BaseDomainSet, selectBase } from "./base-domain-set"; /** * Filter a base domain set by owner address. */ -export function filterByOwner(base: BaseDomainSet, owner: Address) { +export function filterByOwner(base: BaseDomainSet, owner: NormalizedAddress) { return ensDb // .select(selectBase(base)) .from(base) diff --git a/apps/ensapi/src/omnigraph-api/schema/scalars.ts b/apps/ensapi/src/omnigraph-api/schema/scalars.ts index 9fd1efb60..27eb5e9bf 100644 --- a/apps/ensapi/src/omnigraph-api/schema/scalars.ts +++ b/apps/ensapi/src/omnigraph-api/schema/scalars.ts @@ -1,5 +1,4 @@ import { - type Address, asInterpretedLabel, asInterpretedName, type ChainId, @@ -10,6 +9,7 @@ import { isInterpretedName, type Name, type Node, + type NormalizedAddress, type PermissionsId, type PermissionsResourceId, type PermissionsUserId, @@ -38,13 +38,13 @@ builder.scalarType("BigInt", { builder.scalarType("Address", { description: "Address represents an EVM Address in all lowercase.", - serialize: (value: Address) => value.toString(), + serialize: (value: NormalizedAddress) => value, parseValue: (value) => makeNormalizedAddressSchema("Address").parse(value), }); builder.scalarType("Hex", { description: "Hex represents viem#Hex.", - serialize: (value: Hex) => value.toString(), + serialize: (value: Hex) => value, parseValue: (value) => z.coerce .string() From 3b694d3b8d51dbdb69b9b6c996da1b34a79e6766 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 18:42:33 -0500 Subject: [PATCH 31/60] fix: guard against partial data in cache-exchange accoutnid string --- packages/enskit/src/react/omnigraph/_lib/cache-exchange.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/enskit/src/react/omnigraph/_lib/cache-exchange.ts b/packages/enskit/src/react/omnigraph/_lib/cache-exchange.ts index 31d563d4a..d2b0fd5a4 100644 --- a/packages/enskit/src/react/omnigraph/_lib/cache-exchange.ts +++ b/packages/enskit/src/react/omnigraph/_lib/cache-exchange.ts @@ -24,7 +24,12 @@ export const omnigraphCacheExchange = cacheExchange({ // special handling here in the cacheExchange.keys definitions, it will issue a warning. // AccountIds are keyable by stringifying them - AccountId: (data) => stringifyAccountId(data as unknown as AccountId), + AccountId: (data) => { + if (!data.address) return null; + if (!data.chainId) return null; + + return stringifyAccountId(data as unknown as AccountId); + }, // These entities are Embedded Data and don't have a relevant key Label: EMBEDDED_DATA, From 559756d27cae4afd3d75cf2746ee06e6b85dba80 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 18:50:39 -0500 Subject: [PATCH 32/60] fix: support bigint[] in omnigraph --- .../_lib/local-bigint-resolvers.test.ts | 40 +++++++++++++++++++ .../omnigraph/_lib/local-bigint-resolvers.ts | 33 ++++++++++++--- 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.test.ts b/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.test.ts index e3d5d80d6..2fa8f4373 100644 --- a/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.test.ts +++ b/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.test.ts @@ -2,6 +2,7 @@ import { describe, expect, expectTypeOf, it, vi } from "vitest"; import { createOmnigraphUrqlClient } from "../client"; import { graphql } from "../graphql"; +import { localBigIntResolvers } from "./local-bigint-resolvers"; const mockFetch = vi.fn(); const client = createOmnigraphUrqlClient({ url: "http://whatever", fetch: mockFetch }); @@ -51,4 +52,43 @@ describe("localBigIntResolvers", () => { expect(data!.domain!.registration!.start).toEqual(BIGINT_VALUE); expectTypeOf(data!.domain!.registration!.start).toEqualTypeOf(); }); + + it("element-wise deserializes list-wrapped BigInt scalars", () => { + // synthetic introspection with a [BigInt!]! field, since no current schema field is list-wrapped BigInt + const schema = { + __schema: { + types: [ + { + kind: "OBJECT", + name: "Thing", + fields: [ + { + name: "values", + type: { + kind: "NON_NULL", + ofType: { + kind: "LIST", + ofType: { + kind: "NON_NULL", + ofType: { kind: "SCALAR", name: "BigInt" }, + }, + }, + }, + }, + ], + }, + ], + }, + }; + + const resolvers = localBigIntResolvers(schema); + const resolver = resolvers.Thing!.values!; + const result = resolver( + { values: ["1", "2", "3"] }, + {}, + {} as never, + { fieldName: "values" } as never, + ); + expect(result).toEqual([1n, 2n, 3n]); + }); }); diff --git a/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.ts b/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.ts index f66f2a49e..f20e96a6a 100644 --- a/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.ts +++ b/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.ts @@ -1,6 +1,10 @@ import type { Resolver, ScalarObject } from "@urql/exchange-graphcache"; -import { type IntrospectionSchema, unwrapType } from "./introspection-helpers"; +import { + type IntrospectionSchema, + type IntrospectionTypeRef, + unwrapType, +} from "./introspection-helpers"; // graphcache's ResolverResult type doesn't include bigint, but the value is stored // in the normalized cache and returned to the consumer as-is, so bigint works at runtime @@ -11,6 +15,24 @@ const toBigInt: Resolver = (parent, args, cache, info) => { return BigInt(value as string) as unknown as ScalarObject; }; +const toBigIntList: Resolver = (parent, args, cache, info) => { + const value = parent[info.fieldName]; + if (value == null) return value; + + // now we know value is a (string | null)[], so map to a (bigint | null)[] + return (value as readonly (string | null)[]).map((v) => (v == null ? v : BigInt(v))); +}; + +function isBigIntType(type: IntrospectionTypeRef) { + return unwrapType(type).name === "BigInt"; +} + +// NOTE: the recursion is to handle not-null-wrapped lists +function isListType(type: IntrospectionTypeRef): boolean { + if (type.kind === "LIST") return true; + return type.ofType ? isListType(type.ofType) : false; +} + /** * Derives local resolvers that parse BigInt scalar fields from cached strings into native bigint. */ @@ -23,11 +45,10 @@ export function localBigIntResolvers( if (type.kind !== "OBJECT" || type.name.startsWith("__")) continue; for (const field of type.fields ?? []) { - const leaf = unwrapType(field.type); - if (leaf.name === "BigInt") { - resolvers[type.name] ??= {}; - resolvers[type.name][field.name] = toBigInt; - } + if (!isBigIntType(field.type)) continue; + + resolvers[type.name] ??= {}; + resolvers[type.name][field.name] = isListType(field.type) ? toBigIntList : toBigInt; } } From 1fbbd3391d04083c5cc2f7a8adfa9d575c3be7d0 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 18:52:59 -0500 Subject: [PATCH 33/60] fix: comments --- packages/enskit/src/react/omnigraph/_lib/README.md | 2 ++ .../enskit/src/react/omnigraph/_lib/local-bigint-resolvers.ts | 4 +++- packages/enssdk/src/_lib/README.md | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/enskit/src/react/omnigraph/_lib/README.md b/packages/enskit/src/react/omnigraph/_lib/README.md index 42a3c5f88..f361ba38f 100644 --- a/packages/enskit/src/react/omnigraph/_lib/README.md +++ b/packages/enskit/src/react/omnigraph/_lib/README.md @@ -1 +1,3 @@ +# enskit/react/omnigraph/_lib + enskit/react/omnigraph libs or helpers not meant for export to consumers diff --git a/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.ts b/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.ts index f20e96a6a..c409882db 100644 --- a/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.ts +++ b/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.ts @@ -8,7 +8,9 @@ import { // graphcache's ResolverResult type doesn't include bigint, but the value is stored // in the normalized cache and returned to the consumer as-is, so bigint works at runtime -// the load-bearing piece of +// the load-bearing piece of type inference is in packages/enskit/src/react/omnigraph/graphql.ts where +// the GraphQL BigInt Scalar is mapped to the `bigint` primitive, which is only supported by these +// runtime local resolvers. const toBigInt: Resolver = (parent, args, cache, info) => { const value = parent[info.fieldName]; if (value == null) return value; diff --git a/packages/enssdk/src/_lib/README.md b/packages/enssdk/src/_lib/README.md index 973b4ffc5..9cd58957e 100644 --- a/packages/enssdk/src/_lib/README.md +++ b/packages/enssdk/src/_lib/README.md @@ -1 +1,3 @@ +# enssdk/_lib + enssdk-internal libs or helpers not meant for export to consumers From 365fae438c4f3e6352aa7d1420458624496a0f8c Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 19:00:00 -0500 Subject: [PATCH 34/60] fix: relax toNormalizedAddress input type and clean up callsites --- AGENTS.md | 4 +-- .../src/lib/trace-transaction-helpers.ts | 30 ++++++++----------- .../ensnode-sdk/src/shared/zod-schemas.ts | 3 +- packages/enssdk/src/lib/address.test.ts | 2 +- packages/enssdk/src/lib/address.ts | 8 ++--- packages/enssdk/src/lib/parse-reverse-name.ts | 19 +++++------- 6 files changed, 29 insertions(+), 37 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 3cf464727..e0b2cfc90 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -78,6 +78,6 @@ Fail fast and loudly on invalid inputs. - Add a changeset when your PR includes a logical change that should bump versions or be communicated in release notes: https://ensnode.io/docs/contributing/prs#changesets - Before declaring work complete, run validation in the affected packages: - 1. `pnpm -F typecheck` + 1. `pnpm -F typecheck` 2. `pnpm lint` - 3. `pnpm -F test` + 3. `pnpm test --project [--project ]` diff --git a/apps/ensindexer/src/lib/trace-transaction-helpers.ts b/apps/ensindexer/src/lib/trace-transaction-helpers.ts index 956e93693..71dc5bc41 100644 --- a/apps/ensindexer/src/lib/trace-transaction-helpers.ts +++ b/apps/ensindexer/src/lib/trace-transaction-helpers.ts @@ -1,5 +1,5 @@ -import { type Address, type Hex, toNormalizedAddress } from "enssdk"; -import { type Hash, isAddress } from "viem"; +import { type Hex, type NormalizedAddress, toNormalizedAddress } from "enssdk"; +import { type Address, type Hash, isAddress } from "viem"; /** * Options for the `callTracer` tracer. This tracer is used to enlist @@ -39,10 +39,10 @@ interface Trace { type: "CALL" | "STATICCALL" | "DELEGATECALL" | "CREATE" | "CREATE2"; // Caller address - from: Address; + from: NormalizedAddress; // Recipient address - to: Address; + to: NormalizedAddress; // Amount of gas provided for the call gas: Hex; @@ -69,9 +69,9 @@ interface Trace { * @param trace The transaction trace to extract addresses from * @returns An array of unique addresses found in the trace. */ -export function getAddressesFromTrace(trace: Trace): Set
{ +export function getAddressesFromTrace(trace: Trace): Set { const text = JSON.stringify(trace); - const uniqueAddresses = new Set
(); + const uniqueAddresses = new Set(); // Helper function to search for plain addresses (0x followed by 40 hex characters) const searchForPlainAddresses = (text: string) => { @@ -84,10 +84,10 @@ export function getAddressesFromTrace(trace: Trace): Set
{ // if matches are found, normalize them and return unique addresses if (matches) { for (const maybeAddress of matches) { - if (isAddress(maybeAddress, { strict: false })) { + try { // Add the normalized address to the set uniqueAddresses.add(toNormalizedAddress(maybeAddress)); - } else { + } catch { // Ignore invalid addresses } } @@ -107,17 +107,13 @@ export function getAddressesFromTrace(trace: Trace): Set
{ // match[1] contains the extracted address part (without the 24 zeroes) const maybePartialAddress = match[1]; - if (!maybePartialAddress) { - // If no address part is found, skip this match - continue; - } - - const maybeAddress = `0x${maybePartialAddress}`; + // If no address part is found, skip this match + if (!maybePartialAddress) continue; - if (isAddress(maybeAddress, { strict: false })) { + try { // Add the normalized address to the set - uniqueAddresses.add(toNormalizedAddress(maybeAddress)); - } else { + uniqueAddresses.add(toNormalizedAddress(`0x${maybePartialAddress}`)); + } catch { // Ignore invalid addresses } } diff --git a/packages/ensnode-sdk/src/shared/zod-schemas.ts b/packages/ensnode-sdk/src/shared/zod-schemas.ts index 0b477820e..92746e961 100644 --- a/packages/ensnode-sdk/src/shared/zod-schemas.ts +++ b/packages/ensnode-sdk/src/shared/zod-schemas.ts @@ -3,7 +3,6 @@ import { AccountId as CaipAccountId } from "caip"; import type { AccountId, AccountIdString, - Address, ChainId, DefaultableChainId, Duration, @@ -166,7 +165,7 @@ export const makeNormalizedAddressSchema = (valueLabel: string = "EVM address") }); } }) - .transform((val) => toNormalizedAddress(val as Address)); + .transform((val) => toNormalizedAddress(val)); /** * Parses an ISO 8601 string representations of {@link Datetime} diff --git a/packages/enssdk/src/lib/address.test.ts b/packages/enssdk/src/lib/address.test.ts index 9958b2253..a89691fef 100644 --- a/packages/enssdk/src/lib/address.test.ts +++ b/packages/enssdk/src/lib/address.test.ts @@ -49,7 +49,7 @@ describe("toNormalizedAddress", () => { }); it("should throw for a non-hex string", () => { - expect(() => toNormalizedAddress("not-an-address" as Address)).toThrow( + expect(() => toNormalizedAddress("not-an-address")).toThrow( /does not represent an EVM Address/, ); }); diff --git a/packages/enssdk/src/lib/address.ts b/packages/enssdk/src/lib/address.ts index e3374f7c2..3829da11e 100644 --- a/packages/enssdk/src/lib/address.ts +++ b/packages/enssdk/src/lib/address.ts @@ -15,12 +15,12 @@ export function isNormalizedAddress(address: Address): address is NormalizedAddr * * @throws if `address` does not represent an EVM Address */ -export function toNormalizedAddress(address: Address): NormalizedAddress { - if (!isAddress(address, { strict: false })) { - throw new Error(`'${address}' does not represent an EVM Address.`); +export function toNormalizedAddress(maybeAddress: string): NormalizedAddress { + if (!isAddress(maybeAddress, { strict: false })) { + throw new Error(`'${maybeAddress}' does not represent an EVM Address.`); } - return address.toLowerCase() as NormalizedAddress; + return maybeAddress.toLowerCase() as NormalizedAddress; } /** diff --git a/packages/enssdk/src/lib/parse-reverse-name.ts b/packages/enssdk/src/lib/parse-reverse-name.ts index 58cc3ea96..67a71c388 100644 --- a/packages/enssdk/src/lib/parse-reverse-name.ts +++ b/packages/enssdk/src/lib/parse-reverse-name.ts @@ -1,9 +1,9 @@ -import { hexToBigInt, isAddress } from "viem"; +import { hexToBigInt } from "viem"; import { toNormalizedAddress } from "./address"; import { bigintToCoinType, DEFAULT_EVM_COIN_TYPE, ETH_COIN_TYPE } from "./coin-type"; import { asLiteralLabel } from "./interpreted-names-and-labels"; -import type { Address, CoinType, LiteralLabel, Name } from "./types"; +import type { CoinType, LiteralLabel, Name, NormalizedAddress } from "./types"; /** * Matches an ENSIP-19 Reverse Name @@ -19,14 +19,8 @@ const REVERSE_NAME_REGEX = /^([0-9a-fA-F]+)\.([0-9a-f]{1,64}|addr|default)\.reve * @throws if address is invalid * @see https://docs.ens.domains/ensip/19#reverse-resolution */ -const parseAddressLabel = (addressLabel: LiteralLabel): Address => { - const maybeAddress = `0x${addressLabel}`; - - if (!isAddress(maybeAddress, { strict: false })) { - throw new Error(`Invalid EVM address "${maybeAddress}"`); - } - - return toNormalizedAddress(maybeAddress); +const parseAddressLabel = (addressLabel: LiteralLabel): NormalizedAddress => { + return toNormalizedAddress(`0x${addressLabel}`); }; /** @@ -44,7 +38,10 @@ const parseCoinTypeLabel = (coinTypeLabel: LiteralLabel): CoinType => { /** * Parse the address and coinType out of an ENSIP-19 reverse name. */ -export function parseReverseName(name: Name): { address: Address; coinType: CoinType } | null { +export function parseReverseName(name: Name): { + address: NormalizedAddress; + coinType: CoinType; +} | null { const match = name.match(REVERSE_NAME_REGEX); if (!match) return null; From 2637ec40e78e8be05f727f8f21d5b42289973c80 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 19:03:44 -0500 Subject: [PATCH 35/60] docs(changeset): Introduce the enskit/react submodule export for React components and (in the future) hooks. --- .changeset/humble-mice-listen.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/humble-mice-listen.md diff --git a/.changeset/humble-mice-listen.md b/.changeset/humble-mice-listen.md new file mode 100644 index 000000000..468e96461 --- /dev/null +++ b/.changeset/humble-mice-listen.md @@ -0,0 +1,5 @@ +--- +"enskit": minor +--- + +Introduce the enskit/react submodule export for React components and (in the future) hooks. From ea8aa6e223229ca7407e698ed334eea40db01af1 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 19:16:00 -0500 Subject: [PATCH 36/60] fix: handle root name --- packages/enssdk/src/lib/interpreted-names-and-labels.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/enssdk/src/lib/interpreted-names-and-labels.ts b/packages/enssdk/src/lib/interpreted-names-and-labels.ts index f7e257b57..556fdef46 100644 --- a/packages/enssdk/src/lib/interpreted-names-and-labels.ts +++ b/packages/enssdk/src/lib/interpreted-names-and-labels.ts @@ -193,6 +193,7 @@ export function literalLabelsToLiteralName(labels: LiteralLabel[]): LiteralName * Converts an LiteralName into a list of LiteralLabels. */ export function literalNameToLiteralLabels(name: LiteralName): LiteralLabel[] { + if (name === "") return []; return name.split(".") as LiteralLabel[]; } From 47c85924d1f21f947ec351beace68f88c7d420d8 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 19:17:34 -0500 Subject: [PATCH 37/60] fix: keep cause for normalization errors --- packages/enssdk/src/lib/normalization.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/enssdk/src/lib/normalization.ts b/packages/enssdk/src/lib/normalization.ts index 2b0be0f61..84093b6e5 100644 --- a/packages/enssdk/src/lib/normalization.ts +++ b/packages/enssdk/src/lib/normalization.ts @@ -11,8 +11,8 @@ import type { InterpretedLabel, InterpretedName, Label, Name } from "./types"; export const normalizeName = (name: Name): InterpretedName => { try { return ens_normalize(name) as InterpretedName; - } catch { - throw new Error(`Name '${name}' cannot be normalized.`); + } catch (cause) { + throw new Error(`Name '${name}' cannot be normalized.`, { cause }); } }; @@ -35,8 +35,8 @@ export const normalizeLabel = (label: Label): InterpretedLabel => { // NOTE: the ens_normalize function accepts _names_ not labels, and so we must include our own // invariants above to ensure that the `label` input here can be safely normalized return ens_normalize(label) as InterpretedLabel; - } catch { - throw new Error(`Label '${label}' cannot be normalized.`); + } catch (cause) { + throw new Error(`Label '${label}' cannot be normalized.`, { cause }); } }; From bb5e3ad53fc140f9aeb597f9fac81db6191c454f Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 19:17:47 -0500 Subject: [PATCH 38/60] fix: further NormalizedAddress in ens-referrals --- .../referrer-leaderboard/database-v1.ts | 6 +++--- .../ensanalytics/referrer-leaderboard/database.ts | 4 ++-- .../get-primary-name-from-index.ts | 4 ++-- .../maybe-heal-label-by-addr-reverse-subname.ts | 4 ++-- .../src/lib/trace-transaction-helpers.ts | 6 +++--- packages/ens-referrals/src/rank.ts | 8 +++----- packages/ens-referrals/src/referrer-detail.ts | 4 ++-- packages/ens-referrals/src/referrer-metrics.ts | 13 +++++++------ .../src/v1/award-models/pie-split/metrics.ts | 4 ++-- .../src/v1/award-models/rev-share-limit/rules.ts | 14 ++++---------- .../src/v1/award-models/shared/rank.ts | 8 +++----- packages/enssdk/src/lib/ids.ts | 8 ++++++-- packages/enssdk/src/lib/reverse-name.ts | 10 ++++------ 13 files changed, 43 insertions(+), 50 deletions(-) diff --git a/apps/ensapi/src/lib/ensanalytics/referrer-leaderboard/database-v1.ts b/apps/ensapi/src/lib/ensanalytics/referrer-leaderboard/database-v1.ts index b78e803c5..863d14322 100644 --- a/apps/ensapi/src/lib/ensanalytics/referrer-leaderboard/database-v1.ts +++ b/apps/ensapi/src/lib/ensanalytics/referrer-leaderboard/database-v1.ts @@ -5,7 +5,7 @@ import { type ReferrerMetrics, } from "@namehash/ens-referrals/v1"; import { and, asc, count, desc, eq, gte, isNotNull, lte, ne, sql, sum } from "drizzle-orm"; -import { type Address, stringifyAccountId } from "enssdk"; +import { type NormalizedAddress, stringifyAccountId } from "enssdk"; import { zeroAddress } from "viem"; import { deserializeDuration, priceEth } from "@ensnode/ensnode-sdk"; @@ -77,7 +77,7 @@ export const getReferrerMetrics = async ( // 2. `totalIncrementalDuration` is guaranteed to be non-null as it is the sum of non-null bigint values // 3. `totalRevenueContribution` is guaranteed to be non-null due to COALESCE with 0 interface NonNullRecord { - referrer: Address; + referrer: NormalizedAddress; totalReferrals: number; totalIncrementalDuration: string; totalRevenueContribution: string; @@ -144,7 +144,7 @@ export const getReferralEvents = async (rules: ReferralProgramRules): Promise { const _coinType = BigInt(coinType); diff --git a/apps/ensindexer/src/lib/maybe-heal-label-by-addr-reverse-subname.ts b/apps/ensindexer/src/lib/maybe-heal-label-by-addr-reverse-subname.ts index 898538396..0fd70f1f3 100644 --- a/apps/ensindexer/src/lib/maybe-heal-label-by-addr-reverse-subname.ts +++ b/apps/ensindexer/src/lib/maybe-heal-label-by-addr-reverse-subname.ts @@ -1,9 +1,9 @@ import { - type Address, addrReverseLabel, type LabelHash, type LiteralLabel, labelhashLiteralLabel, + type NormalizedAddress, } from "enssdk"; /** @@ -13,7 +13,7 @@ import { */ export const maybeHealLabelByAddrReverseSubname = ( labelHash: LabelHash, - address: Address, + address: NormalizedAddress, ): LiteralLabel | null => { // construct an addr.reverse subname label from the provided address const maybeLabel = addrReverseLabel(address); diff --git a/apps/ensindexer/src/lib/trace-transaction-helpers.ts b/apps/ensindexer/src/lib/trace-transaction-helpers.ts index 71dc5bc41..58877ede0 100644 --- a/apps/ensindexer/src/lib/trace-transaction-helpers.ts +++ b/apps/ensindexer/src/lib/trace-transaction-helpers.ts @@ -1,5 +1,5 @@ import { type Hex, type NormalizedAddress, toNormalizedAddress } from "enssdk"; -import { type Address, type Hash, isAddress } from "viem"; +import type { Address, Hash } from "viem"; /** * Options for the `callTracer` tracer. This tracer is used to enlist @@ -39,10 +39,10 @@ interface Trace { type: "CALL" | "STATICCALL" | "DELEGATECALL" | "CREATE" | "CREATE2"; // Caller address - from: NormalizedAddress; + from: Address; // Recipient address - to: NormalizedAddress; + to: Address; // Amount of gas provided for the call gas: Hex; diff --git a/packages/ens-referrals/src/rank.ts b/packages/ens-referrals/src/rank.ts index 1a416f308..559064d6f 100644 --- a/packages/ens-referrals/src/rank.ts +++ b/packages/ens-referrals/src/rank.ts @@ -1,4 +1,4 @@ -import type { Address, Duration } from "enssdk"; +import type { Duration, NormalizedAddress } from "enssdk"; import { isPositiveInteger } from "./number"; import type { ReferralProgramRules } from "./rules"; @@ -85,11 +85,9 @@ export interface ReferrerMetricsForComparison { totalIncrementalDuration: Duration; /** - * The fully lowercase Ethereum address of the referrer. - * - * @invariant Guaranteed to be a valid EVM address in lowercase format. + * The Ethereum address of the referrer. */ - referrer: Address; + referrer: NormalizedAddress; } export const compareReferrerMetrics = ( diff --git a/packages/ens-referrals/src/referrer-detail.ts b/packages/ens-referrals/src/referrer-detail.ts index 9bd52b8f3..c725b7549 100644 --- a/packages/ens-referrals/src/referrer-detail.ts +++ b/packages/ens-referrals/src/referrer-detail.ts @@ -1,4 +1,4 @@ -import type { Address, UnixTimestamp } from "enssdk"; +import type { NormalizedAddress, UnixTimestamp } from "enssdk"; import type { AggregatedReferrerMetrics } from "./aggregations"; import type { ReferrerLeaderboard } from "./leaderboard"; @@ -128,7 +128,7 @@ export type ReferrerDetail = ReferrerDetailRanked | ReferrerDetailUnranked; * @returns The appropriate {@link ReferrerDetail} (ranked or unranked) */ export const getReferrerDetail = ( - referrer: Address, + referrer: NormalizedAddress, leaderboard: ReferrerLeaderboard, ): ReferrerDetail => { const awardedReferrerMetrics = leaderboard.referrers.get(referrer); diff --git a/packages/ens-referrals/src/referrer-metrics.ts b/packages/ens-referrals/src/referrer-metrics.ts index 30cd07dc0..6c7804f1f 100644 --- a/packages/ens-referrals/src/referrer-metrics.ts +++ b/packages/ens-referrals/src/referrer-metrics.ts @@ -1,5 +1,4 @@ -import type { Address, Duration } from "enssdk"; -import { toNormalizedAddress } from "enssdk"; +import type { Duration, NormalizedAddress } from "enssdk"; import { validateAddress } from "./address"; import type { AggregatedReferrerMetrics } from "./aggregations"; @@ -28,7 +27,7 @@ export interface ReferrerMetrics { * * @invariant Guaranteed to be a valid EVM address in lowercase format */ - referrer: Address; + referrer: NormalizedAddress; /** * The total number of referrals made by the referrer within the {@link ReferralProgramRules}. @@ -56,13 +55,13 @@ export interface ReferrerMetrics { } export const buildReferrerMetrics = ( - referrer: Address, + referrer: NormalizedAddress, totalReferrals: number, totalIncrementalDuration: Duration, totalRevenueContribution: RevenueContribution, ): ReferrerMetrics => { const result = { - referrer: toNormalizedAddress(referrer), + referrer, totalReferrals, totalIncrementalDuration, totalRevenueContribution, @@ -372,7 +371,9 @@ export const validateUnrankedReferrerMetrics = (metrics: UnrankedReferrerMetrics * @param referrer - The referrer address * @returns An {@link UnrankedReferrerMetrics} with zero values for all metrics and null rank */ -export const buildUnrankedReferrerMetrics = (referrer: Address): UnrankedReferrerMetrics => { +export const buildUnrankedReferrerMetrics = ( + referrer: NormalizedAddress, +): UnrankedReferrerMetrics => { const baseMetrics = buildReferrerMetrics(referrer, 0, 0, 0n); const scoredMetrics = buildScoredReferrerMetrics(baseMetrics); diff --git a/packages/ens-referrals/src/v1/award-models/pie-split/metrics.ts b/packages/ens-referrals/src/v1/award-models/pie-split/metrics.ts index 2d859288f..37ff2b619 100644 --- a/packages/ens-referrals/src/v1/award-models/pie-split/metrics.ts +++ b/packages/ens-referrals/src/v1/award-models/pie-split/metrics.ts @@ -1,4 +1,4 @@ -import type { Address } from "enssdk"; +import type { NormalizedAddress } from "enssdk"; import { type PriceUsdc, priceEth, priceUsdc, scalePrice } from "@ensnode/ensnode-sdk"; import { makePriceEthSchema, makePriceUsdcSchema } from "@ensnode/ensnode-sdk/internal"; @@ -316,7 +316,7 @@ export const validateUnrankedReferrerMetricsPieSplit = ( * @returns An {@link UnrankedReferrerMetricsPieSplit} with zero values for all metrics and null rank */ export const buildUnrankedReferrerMetricsPieSplit = ( - referrer: Address, + referrer: NormalizedAddress, ): UnrankedReferrerMetricsPieSplit => { const metrics = buildReferrerMetrics(referrer, 0, 0, priceEth(0n)); const scoredMetrics = buildScoredReferrerMetricsPieSplit(metrics); diff --git a/packages/ens-referrals/src/v1/award-models/rev-share-limit/rules.ts b/packages/ens-referrals/src/v1/award-models/rev-share-limit/rules.ts index 56e90d189..ab46369b2 100644 --- a/packages/ens-referrals/src/v1/award-models/rev-share-limit/rules.ts +++ b/packages/ens-referrals/src/v1/award-models/rev-share-limit/rules.ts @@ -1,5 +1,4 @@ -import type { AccountId, Address, UnixTimestamp } from "enssdk"; -import { toNormalizedAddress } from "enssdk"; +import type { AccountId, NormalizedAddress, UnixTimestamp } from "enssdk"; import type { PriceUsdc } from "@ensnode/ensnode-sdk"; import { makePriceUsdcSchema } from "@ensnode/ensnode-sdk/internal"; @@ -17,10 +16,8 @@ import { export interface ReferralProgramEditionDisqualification { /** * The address of the disqualified referrer. - * - * @invariant Guaranteed to be a valid EVM address in lowercase format. */ - referrer: Address; + referrer: NormalizedAddress; /** * A human-readable explanation of why the referrer was disqualified. @@ -159,14 +156,11 @@ export const buildReferralProgramRulesRevShareLimit = ( * @param rules - The rev-share-limit rules of the referral program. */ export function isReferrerQualifiedRevShareLimit( - referrer: Address, + referrer: NormalizedAddress, totalBaseRevenueContribution: PriceUsdc, rules: ReferralProgramRulesRevShareLimit, ): boolean { - const normalizedReferrer = toNormalizedAddress(referrer); - const isAdminDisqualified = rules.disqualifications.some( - (d) => d.referrer === normalizedReferrer, - ); + const isAdminDisqualified = rules.disqualifications.some((d) => d.referrer === referrer); return ( totalBaseRevenueContribution.amount >= rules.minBaseRevenueContribution.amount && !isAdminDisqualified diff --git a/packages/ens-referrals/src/v1/award-models/shared/rank.ts b/packages/ens-referrals/src/v1/award-models/shared/rank.ts index 9ac0a75aa..a7f30004a 100644 --- a/packages/ens-referrals/src/v1/award-models/shared/rank.ts +++ b/packages/ens-referrals/src/v1/award-models/shared/rank.ts @@ -1,4 +1,4 @@ -import type { Address, Duration } from "enssdk"; +import type { Duration, NormalizedAddress } from "enssdk"; import { isPositiveInteger } from "../../number"; import type { ReferrerMetrics } from "../../referrer-metrics"; @@ -25,11 +25,9 @@ export interface ReferrerMetricsForComparison { totalIncrementalDuration: Duration; /** - * The fully lowercase Ethereum address of the referrer. - * - * @invariant Guaranteed to be a valid EVM address in lowercase format. + * The Ethereum address of the referrer. */ - referrer: Address; + referrer: NormalizedAddress; } export const compareReferrerMetrics = ( diff --git a/packages/enssdk/src/lib/ids.ts b/packages/enssdk/src/lib/ids.ts index 5450fcf49..d84094a65 100644 --- a/packages/enssdk/src/lib/ids.ts +++ b/packages/enssdk/src/lib/ids.ts @@ -10,6 +10,7 @@ import type { ENSv2DomainId, LabelHash, Node, + NormalizedAddress, PermissionsId, PermissionsResourceId, PermissionsUserId, @@ -50,8 +51,11 @@ export const makePermissionsId = (contract: AccountId) => export const makePermissionsResourceId = (contract: AccountId, resource: EACResource) => `${makePermissionsId(contract)}/${resource}` as PermissionsResourceId; -export const makePermissionsUserId = (contract: AccountId, resource: EACResource, user: Address) => - `${makePermissionsResourceId(contract, resource)}/${user}` as PermissionsUserId; +export const makePermissionsUserId = ( + contract: AccountId, + resource: EACResource, + user: NormalizedAddress, +) => `${makePermissionsResourceId(contract, resource)}/${user}` as PermissionsUserId; export const makeResolverRecordsId = (resolver: AccountId, node: Node) => `${makeResolverId(resolver)}/${node}` as ResolverRecordsId; diff --git a/packages/enssdk/src/lib/reverse-name.ts b/packages/enssdk/src/lib/reverse-name.ts index 4f849f609..660580090 100644 --- a/packages/enssdk/src/lib/reverse-name.ts +++ b/packages/enssdk/src/lib/reverse-name.ts @@ -1,16 +1,14 @@ -import type { Address } from "viem"; - import { DEFAULT_EVM_COIN_TYPE, ETH_COIN_TYPE } from "./coin-type"; import { asLiteralLabel } from "./interpreted-names-and-labels"; -import type { CoinType, Label, LiteralLabel, Name } from "./types"; +import type { CoinType, Label, LiteralLabel, Name, NormalizedAddress } from "./types"; /** * Gets the Label used for the reverse names of subnames as per ENSIP-11 & ENSIP-19. * * @see https://docs.ens.domains/ensip/19/#reverse-resolution */ -export const addrReverseLabel = (address: Address): LiteralLabel => - asLiteralLabel(address.slice(2)); // address is guaranteed to be fully lowercase +export const addrReverseLabel = (address: NormalizedAddress): LiteralLabel => + asLiteralLabel(address.slice(2)); /** * Converts `coinType` to prefix-free hex string. @@ -36,7 +34,7 @@ export const coinTypeReverseLabel = (coinType: CoinType): Label => coinType.toSt * reverseName("0x1234", BigInt(0x5678)) // "1234.5678.reverse" * ``` */ -export function reverseName(address: Address, coinType: CoinType): Name { +export function reverseName(address: NormalizedAddress, coinType: CoinType): Name { const label = addrReverseLabel(address); const middle = (() => { From b3b10d67d8d742c1c84570c8618ab4219d9551c1 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 19:20:48 -0500 Subject: [PATCH 39/60] fix: DRY up encoded labelhash parsing --- packages/enssdk/src/lib/labelhash.ts | 45 +++++++++++++--------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/packages/enssdk/src/lib/labelhash.ts b/packages/enssdk/src/lib/labelhash.ts index 2c830a84c..5cc74ed1a 100644 --- a/packages/enssdk/src/lib/labelhash.ts +++ b/packages/enssdk/src/lib/labelhash.ts @@ -51,6 +51,21 @@ export function isLabelHash(maybeLabelHash: string): maybeLabelHash is LabelHash export const encodeLabelHash = (labelHash: LabelHash): EncodedLabelHash => `[${labelHash.slice(2)}]`; +/** + * Parses an Encoded LabelHash (`[hash_without_0x_prefix]`) as a {@link LabelHash}, + * returning `null` if the input does not match the expected format. + */ +function parseEncodedLabelHash(value: string): LabelHash | null { + if (value.length !== 66) return null; + if (value[0] !== "[") return null; + if (value[65] !== "]") return null; + + const hash = `0x${value.slice(1, 65)}`; + if (!isLabelHash(hash)) return null; + + return hash; +} + /** * Decodes an Encoded LabelHash as a LabelHash. * @@ -63,38 +78,18 @@ export const encodeLabelHash = (labelHash: LabelHash): EncodedLabelHash => * @returns A 32-byte lowercase hash string starting with '0x' */ export const decodeEncodedLabelHash = (maybeEncodedLabelHash: string): LabelHash => { - if (maybeEncodedLabelHash.length !== 66) { - throw new Error( - `EncodedLabelHash '${maybeEncodedLabelHash}' is malformed: must have length 66.`, - ); - } - - if (maybeEncodedLabelHash.indexOf("[") !== 0) { - throw new Error( - `EncodedLabelHash '${maybeEncodedLabelHash}' is malformed: must begin with '['.`, - ); - } - - if (maybeEncodedLabelHash.indexOf("]") !== 65) { - throw new Error(`EncodedLabelHash '${maybeEncodedLabelHash}' is malformed: must end with ']'.`); - } - - const hash = `0x${maybeEncodedLabelHash.slice(1, 65)}`; - if (!isLabelHash(hash)) { + const parsed = parseEncodedLabelHash(maybeEncodedLabelHash); + if (parsed === null) { throw new Error( - `EncodedLabelHash '${maybeEncodedLabelHash}' is malformed: must contain a valid LabelHash.`, + `EncodedLabelHash '${maybeEncodedLabelHash}' is malformed: expected format '[<64-char lowercase hex>]'.`, ); } - - return hash; + return parsed; }; /** * Checks if the value is an {@link EncodedLabelHash}. */ export function isEncodedLabelHash(value: string): value is EncodedLabelHash { - const expectedFormatting = value.startsWith("[") && value.endsWith("]"); - const includesLabelHash = isLabelHash(`0x${value.slice(1, -1)}`); - - return expectedFormatting && includesLabelHash; + return parseEncodedLabelHash(value) !== null; } From 0b9cb683bc8c904d04645f87f1cff828a480cc5f Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 19:22:00 -0500 Subject: [PATCH 40/60] fix: don't catch the react children throwing --- .../src/react/components/ensure-interpreted-name.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/enskit/src/react/components/ensure-interpreted-name.tsx b/packages/enskit/src/react/components/ensure-interpreted-name.tsx index 94255cc1e..83c702300 100644 --- a/packages/enskit/src/react/components/ensure-interpreted-name.tsx +++ b/packages/enskit/src/react/components/ensure-interpreted-name.tsx @@ -50,12 +50,15 @@ export function EnsureInterpretedName({ }) { if (isInterpretedName(name)) return children(name); + // this isn't an InterpretedName, let's try to redirect the user to the InterpretedName + // which ensures that our app only ever operates on InterpretedNames + let interpreted: InterpretedName; try { - // this isn't an InterpretedName, let's try to redirect the user to the InterpretedName - // which ensures that our app only ever operates on InterpretedNames - return coerced(literalNameToInterpretedName(name, options)); + interpreted = literalNameToInterpretedName(name, options); } catch { // this name can't conform to InterpretedName: it is malformed or contains unnormalizable Labels return malformed(name); } + + return coerced(interpreted); } From cf73bcdbea3ae2ed1c965530d2fed0ac47bb2bf6 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 20:11:48 -0500 Subject: [PATCH 41/60] docs and typos --- apps/ensapi/src/lib/resolution/forward-resolution.ts | 2 +- .../src/react/components/ensure-interpreted-name.tsx | 3 +-- packages/enssdk/src/lib/names.ts | 7 +++++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/ensapi/src/lib/resolution/forward-resolution.ts b/apps/ensapi/src/lib/resolution/forward-resolution.ts index cb88dbae9..56af7de90 100644 --- a/apps/ensapi/src/lib/resolution/forward-resolution.ts +++ b/apps/ensapi/src/lib/resolution/forward-resolution.ts @@ -145,7 +145,7 @@ async function _resolveForward( // must be fully normalized (and therefore not contain encoded labelhash segments) // (this will be improved in a future pr) if (!isNormalizedName(name)) { - throw new Error(`'${name} must be normalized to be resolvable.'`); + throw new Error(`'${name}' must be normalized to be resolvable.`); } const node: Node = namehashInterpretedName(name); diff --git a/packages/enskit/src/react/components/ensure-interpreted-name.tsx b/packages/enskit/src/react/components/ensure-interpreted-name.tsx index 83c702300..36d723d9a 100644 --- a/packages/enskit/src/react/components/ensure-interpreted-name.tsx +++ b/packages/enskit/src/react/components/ensure-interpreted-name.tsx @@ -11,8 +11,7 @@ type InterpretedNameRenderer = (name: InterpretedName) => ReactNode; /** * Renders a {@link LiteralName} by ensuring it is an {@link InterpretedName}. This is useful for - * ensuring that downstream components get the guarantees of an {@link InterpretedName}, while - * + * ensuring that downstream components get the guarantees of an {@link InterpretedName}. * * @param name - The user-provided {@link LiteralName} to render. * @param children - Render prop called with the {@link InterpretedName} when `name` is already interpreted. diff --git a/packages/enssdk/src/lib/names.ts b/packages/enssdk/src/lib/names.ts index 40d4eacf5..c77d83bd6 100644 --- a/packages/enssdk/src/lib/names.ts +++ b/packages/enssdk/src/lib/names.ts @@ -16,10 +16,13 @@ import type { InterpretedName, Label, Name } from "./types"; * getNameHierarchy("sub.example.eth") -> ["sub.example.eth", "example.eth", "eth"] * ``` */ -export const getNameHierarchy = (name: InterpretedName): InterpretedName[] => - interpretedNameToInterpretedLabels(name).map((_, i, labels) => +export const getNameHierarchy = (name: InterpretedName): InterpretedName[] => { + if (name === ENS_ROOT_NAME) return []; + + return interpretedNameToInterpretedLabels(name).map((_, i, labels) => interpretedLabelsToInterpretedName(labels.slice(i)), ); +}; /** * Derives the parent's {@link InterpretedName} of the provided `name`, or null if there is none. From b44c2e8bb9aa816089d9d0543e618fb22429d6ee Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 20:12:10 -0500 Subject: [PATCH 42/60] fix: referrer size check --- .../award-models/rev-share-limit/api/zod-schemas.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts b/packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts index e81b659a5..d627231f2 100644 --- a/packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts +++ b/packages/ens-referrals/src/v1/award-models/rev-share-limit/api/zod-schemas.ts @@ -53,9 +53,15 @@ export const makeReferralProgramRulesRevShareLimitSchema = ( makeReferralProgramEditionDisqualificationSchema(`${valueLabel}.disqualifications[item]`), ) // NOTE: addresses are already normalized, so string equivalence here is accurate - .refine((addresses) => new Set(addresses).size === addresses.length, { - message: `${valueLabel}.disqualifications must not contain duplicate referrer addresses`, - }) + .refine( + (items) => { + const referrers = items.map((d) => d.referrer); + return new Set(referrers).size === referrers.length; + }, + { + message: `${valueLabel}.disqualifications must not contain duplicate referrer addresses`, + }, + ) .default([]), }); From dfcd4f92b506828d32645950f3daf26308f0507d Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 21:37:16 -0500 Subject: [PATCH 43/60] fix: streamline ensure-interpreted-name --- .../components/ensure-interpreted-name.tsx | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/packages/enskit/src/react/components/ensure-interpreted-name.tsx b/packages/enskit/src/react/components/ensure-interpreted-name.tsx index 36d723d9a..4b9e77e9e 100644 --- a/packages/enskit/src/react/components/ensure-interpreted-name.tsx +++ b/packages/enskit/src/react/components/ensure-interpreted-name.tsx @@ -1,9 +1,4 @@ -import { - type InterpretedName, - isInterpretedName, - type LiteralName, - literalNameToInterpretedName, -} from "enssdk"; +import { type InterpretedName, type LiteralName, literalNameToInterpretedName } from "enssdk"; import type { ReactNode } from "react"; type MalformedNameRenderer = (name: string) => ReactNode; @@ -47,10 +42,7 @@ export function EnsureInterpretedName({ malformed: MalformedNameRenderer; options?: Parameters[1]; }) { - if (isInterpretedName(name)) return children(name); - - // this isn't an InterpretedName, let's try to redirect the user to the InterpretedName - // which ensures that our app only ever operates on InterpretedNames + // attempt to convert the LiteralName to an InterpretedName let interpreted: InterpretedName; try { interpreted = literalNameToInterpretedName(name, options); @@ -59,5 +51,9 @@ export function EnsureInterpretedName({ return malformed(name); } - return coerced(interpreted); + // from here, the name is either already interpreted or was coerced; check with string equality + if ((name as string) !== (interpreted as string)) return coerced(interpreted); + + // the name was already interpreted, render the happy path + return children(interpreted); } From ffb27bb88ff3c9d749743959b848357160bb0759 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 21:47:58 -0500 Subject: [PATCH 44/60] fix: names test --- packages/enssdk/src/lib/names.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/enssdk/src/lib/names.test.ts b/packages/enssdk/src/lib/names.test.ts index de7655a96..0598b56eb 100644 --- a/packages/enssdk/src/lib/names.test.ts +++ b/packages/enssdk/src/lib/names.test.ts @@ -21,7 +21,7 @@ describe("names", () => { it("should handle empty string (root node)", () => { const name = asInterpretedName(""); - const expected = [""]; + const expected = []; expect(getNameHierarchy(name)).toEqual(expected); }); From 50a4fa0389a2234cba818fb3072c92e4f36b42d4 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 21:52:03 -0500 Subject: [PATCH 45/60] fix: decodeEncodedReferrer return type --- .../ensnode-sdk/src/registrars/encoded-referrer.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/ensnode-sdk/src/registrars/encoded-referrer.ts b/packages/ensnode-sdk/src/registrars/encoded-referrer.ts index aa9efe7ad..0943833f3 100644 --- a/packages/ensnode-sdk/src/registrars/encoded-referrer.ts +++ b/packages/ensnode-sdk/src/registrars/encoded-referrer.ts @@ -1,10 +1,4 @@ -import { - type Address, - type Hex, - isNormalizedAddress, - type NormalizedAddress, - toNormalizedAddress, -} from "enssdk"; +import { type Hex, isNormalizedAddress, type NormalizedAddress, toNormalizedAddress } from "enssdk"; import { pad, size, slice, zeroAddress } from "viem"; /** @@ -74,7 +68,7 @@ export function buildEncodedReferrer(address: NormalizedAddress): EncodedReferre * {@link ENCODED_REFERRER_BYTE_LENGTH} bytes. * @throws when decodedReferrer is not a valid EVM address. */ -export function decodeEncodedReferrer(encodedReferrer: EncodedReferrer): Address { +export function decodeEncodedReferrer(encodedReferrer: EncodedReferrer): NormalizedAddress { // Invariant: encoded referrer must be of expected size if (size(encodedReferrer) !== ENCODED_REFERRER_BYTE_LENGTH) { throw new Error( From 2b5239dd855a2ed7fb816b51658e3906d65ed33b Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 21:54:04 -0500 Subject: [PATCH 46/60] fix: remove unnecessary introspection.ts --- apps/ensapi/package.json | 1 - .../omnigraph-api/lib/write-graphql-schema.ts | 20 +- .../src/omnigraph/generated/introspection.ts | 5768 ++++++++++++++++- packages/enssdk/src/omnigraph/graphql.ts | 7 +- .../enssdk/src/omnigraph/introspection.ts | 2 - packages/enssdk/tsconfig.json | 2 +- 6 files changed, 5777 insertions(+), 23 deletions(-) delete mode 100644 packages/enssdk/src/omnigraph/introspection.ts diff --git a/apps/ensapi/package.json b/apps/ensapi/package.json index 154e6024a..60f54ace8 100644 --- a/apps/ensapi/package.json +++ b/apps/ensapi/package.json @@ -67,7 +67,6 @@ "@ensnode/shared-configs": "workspace:*", "@types/node": "catalog:", "@types/prismjs": "^1.26.6", - "@urql/introspection": "^1.2.1", "chalk": "^5.6.2", "graphql-request": "^7.4.0", "pino-pretty": "^13.1.2", diff --git a/apps/ensapi/src/omnigraph-api/lib/write-graphql-schema.ts b/apps/ensapi/src/omnigraph-api/lib/write-graphql-schema.ts index a1f1e4f0d..25cbf9594 100644 --- a/apps/ensapi/src/omnigraph-api/lib/write-graphql-schema.ts +++ b/apps/ensapi/src/omnigraph-api/lib/write-graphql-schema.ts @@ -2,8 +2,7 @@ import { writeFile } from "node:fs/promises"; import { resolve } from "node:path"; import { fileURLToPath } from "node:url"; -import { minifyIntrospectionQuery } from "@urql/introspection"; -import { introspectionFromSchema, lexicographicSortSchema, printSchema } from "graphql"; +import { lexicographicSortSchema, printSchema } from "graphql"; import { makeLogger } from "@/lib/logger"; @@ -17,21 +16,8 @@ async function _writeGraphQLSchema() { const { schema: unsortedSchema } = await import("@/omnigraph-api/schema"); const schema = lexicographicSortSchema(unsortedSchema); const sdl = printSchema(schema); - const introspection = minifyIntrospectionQuery(introspectionFromSchema(schema), { - /** - * We include Scalar types in the introspection in order to power automatic bigint deserialization - * within the Omnigraph's urql GraphCache. - */ - includeScalars: true, - }); - - await Promise.all([ - writeFile(resolve(GENERATED_DIR, "schema.graphql"), sdl), - writeFile( - resolve(GENERATED_DIR, "introspection.ts"), - `export const introspection = ${JSON.stringify(introspection)} as const;\n`, - ), - ]); + + await writeFile(resolve(GENERATED_DIR, "schema.graphql"), sdl); } /** diff --git a/packages/enssdk/src/omnigraph/generated/introspection.ts b/packages/enssdk/src/omnigraph/generated/introspection.ts index d37c822cf..5b128d151 100644 --- a/packages/enssdk/src/omnigraph/generated/introspection.ts +++ b/packages/enssdk/src/omnigraph/generated/introspection.ts @@ -1 +1,5767 @@ -export const introspection = {"__schema":{"queryType":{"name":"Query","kind":"OBJECT"},"mutationType":null,"subscriptionType":null,"types":[{"kind":"OBJECT","name":"Account","fields":[{"name":"address","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Address","ofType":null}},"args":[]},{"name":"domains","type":{"kind":"OBJECT","name":"AccountDomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"events","type":{"kind":"OBJECT","name":"AccountEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Address","ofType":null}},"args":[]},{"name":"permissions","type":{"kind":"OBJECT","name":"AccountPermissionsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"in","type":{"kind":"SCALAR","name":"Any"}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"registryPermissions","type":{"kind":"OBJECT","name":"AccountRegistryPermissionsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"resolverPermissions","type":{"kind":"OBJECT","name":"AccountResolverPermissionsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountDomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountDomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountDomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountEventsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountEventsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountEventsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountId","fields":[{"name":"address","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Address","ofType":null}},"args":[]},{"name":"chainId","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"ChainId","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountPermissionsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountPermissionsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountPermissionsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsUser","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountRegistryPermissionsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountRegistryPermissionsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountRegistryPermissionsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"RegistryPermissionsUser","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountResolverPermissionsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountResolverPermissionsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"AccountResolverPermissionsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ResolverPermissionsUser","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"Address"},{"kind":"OBJECT","name":"BaseRegistrarRegistration","fields":[{"name":"baseCost","type":{"kind":"SCALAR","name":"BigInt","ofType":null},"args":[]},{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"BigInt","ofType":null},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"RegistrationId","ofType":null}},"args":[]},{"name":"isInGracePeriod","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"args":[]},{"name":"premium","type":{"kind":"SCALAR","name":"BigInt","ofType":null},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Hex","ofType":null},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"wrapped","type":{"kind":"OBJECT","name":"WrappedBaseRegistrarRegistration","ofType":null},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Registration"}]},{"kind":"SCALAR","name":"BigInt"},{"kind":"SCALAR","name":"Boolean"},{"kind":"SCALAR","name":"ChainId"},{"kind":"SCALAR","name":"CoinType"},{"kind":"INTERFACE","name":"Domain","fields":[{"name":"events","type":{"kind":"OBJECT","name":"DomainEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"DomainId","ofType":null}},"args":[]},{"name":"label","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Label","ofType":null}},"args":[]},{"name":"name","type":{"kind":"SCALAR","name":"InterpretedName","ofType":null},"args":[]},{"name":"owner","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"path","type":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}}},"args":[]},{"name":"registration","type":{"kind":"INTERFACE","name":"Registration","ofType":null},"args":[]},{"name":"registrations","type":{"kind":"OBJECT","name":"DomainRegistrationsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"resolver","type":{"kind":"OBJECT","name":"Resolver","ofType":null},"args":[]},{"name":"subdomains","type":{"kind":"OBJECT","name":"DomainSubdomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]}],"interfaces":[],"possibleTypes":[{"kind":"OBJECT","name":"ENSv1Domain"},{"kind":"OBJECT","name":"ENSv2Domain"}]},{"kind":"OBJECT","name":"DomainEventsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"DomainEventsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"DomainEventsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"DomainId"},{"kind":"OBJECT","name":"DomainRegistrationsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"DomainRegistrationsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"DomainRegistrationsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Registration","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"DomainSubdomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"DomainSubdomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"DomainSubdomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ENSv1Domain","fields":[{"name":"events","type":{"kind":"OBJECT","name":"DomainEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"DomainId","ofType":null}},"args":[]},{"name":"label","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Label","ofType":null}},"args":[]},{"name":"name","type":{"kind":"SCALAR","name":"InterpretedName","ofType":null},"args":[]},{"name":"owner","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"parent","type":{"kind":"OBJECT","name":"ENSv1Domain","ofType":null},"args":[]},{"name":"path","type":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}}},"args":[]},{"name":"registration","type":{"kind":"INTERFACE","name":"Registration","ofType":null},"args":[]},{"name":"registrations","type":{"kind":"OBJECT","name":"DomainRegistrationsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"resolver","type":{"kind":"OBJECT","name":"Resolver","ofType":null},"args":[]},{"name":"rootRegistryOwner","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"subdomains","type":{"kind":"OBJECT","name":"DomainSubdomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]}],"interfaces":[{"kind":"INTERFACE","name":"Domain"}]},{"kind":"OBJECT","name":"ENSv2Domain","fields":[{"name":"events","type":{"kind":"OBJECT","name":"DomainEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"DomainId","ofType":null}},"args":[]},{"name":"label","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Label","ofType":null}},"args":[]},{"name":"name","type":{"kind":"SCALAR","name":"InterpretedName","ofType":null},"args":[]},{"name":"owner","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"path","type":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}}},"args":[]},{"name":"permissions","type":{"kind":"OBJECT","name":"ENSv2DomainPermissionsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"registration","type":{"kind":"INTERFACE","name":"Registration","ofType":null},"args":[]},{"name":"registrations","type":{"kind":"OBJECT","name":"DomainRegistrationsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"registry","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Registry","ofType":null}},"args":[]},{"name":"resolver","type":{"kind":"OBJECT","name":"Resolver","ofType":null},"args":[]},{"name":"subdomains","type":{"kind":"OBJECT","name":"DomainSubdomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"subregistry","type":{"kind":"OBJECT","name":"Registry","ofType":null},"args":[]},{"name":"tokenId","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Domain"}]},{"kind":"OBJECT","name":"ENSv2DomainPermissionsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ENSv2DomainPermissionsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ENSv2DomainPermissionsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsUser","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ENSv2RegistryRegistration","fields":[{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"BigInt","ofType":null},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"RegistrationId","ofType":null}},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Hex","ofType":null},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Registration"}]},{"kind":"OBJECT","name":"ENSv2RegistryReservation","fields":[{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"BigInt","ofType":null},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"RegistrationId","ofType":null}},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Hex","ofType":null},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Registration"}]},{"kind":"OBJECT","name":"Event","fields":[{"name":"address","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Address","ofType":null}},"args":[]},{"name":"blockHash","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Hex","ofType":null}},"args":[]},{"name":"blockNumber","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"chainId","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"ChainId","ofType":null}},"args":[]},{"name":"data","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Hex","ofType":null}},"args":[]},{"name":"from","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Address","ofType":null}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"ID","ofType":null}},"args":[]},{"name":"logIndex","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]},{"name":"timestamp","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"to","type":{"kind":"SCALAR","name":"Address","ofType":null},"args":[]},{"name":"topics","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Hex","ofType":null}}}},"args":[]},{"name":"transactionHash","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Hex","ofType":null}},"args":[]},{"name":"transactionIndex","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"Float"},{"kind":"SCALAR","name":"Hex"},{"kind":"SCALAR","name":"ID"},{"kind":"SCALAR","name":"Int"},{"kind":"SCALAR","name":"InterpretedLabel"},{"kind":"SCALAR","name":"InterpretedName"},{"kind":"OBJECT","name":"Label","fields":[{"name":"hash","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Hex","ofType":null}},"args":[]},{"name":"interpreted","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"InterpretedLabel","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"NameWrapperRegistration","fields":[{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"BigInt","ofType":null},"args":[]},{"name":"fuses","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"RegistrationId","ofType":null}},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Hex","ofType":null},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Registration"}]},{"kind":"SCALAR","name":"Node"},{"kind":"OBJECT","name":"PageInfo","fields":[{"name":"endCursor","type":{"kind":"SCALAR","name":"String","ofType":null},"args":[]},{"name":"hasNextPage","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"args":[]},{"name":"hasPreviousPage","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"args":[]},{"name":"startCursor","type":{"kind":"SCALAR","name":"String","ofType":null},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"Permissions","fields":[{"name":"contract","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"events","type":{"kind":"OBJECT","name":"PermissionsEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"PermissionsId","ofType":null}},"args":[]},{"name":"resources","type":{"kind":"OBJECT","name":"PermissionsResourcesConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"root","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsResource","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsEventsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsEventsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsEventsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"PermissionsId"},{"kind":"OBJECT","name":"PermissionsResource","fields":[{"name":"contract","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"PermissionsResourceId","ofType":null}},"args":[]},{"name":"permissions","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Permissions","ofType":null}},"args":[]},{"name":"resource","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"users","type":{"kind":"OBJECT","name":"PermissionsResourceUsersConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]}],"interfaces":[]},{"kind":"SCALAR","name":"PermissionsResourceId"},{"kind":"OBJECT","name":"PermissionsResourceUsersConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsResourceUsersConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsResourceUsersConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsUser","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsResourcesConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsResourcesConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsResourcesConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PermissionsResource","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"PermissionsUser","fields":[{"name":"contract","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"PermissionsUserId","ofType":null}},"args":[]},{"name":"resource","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"roles","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"user","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Account","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"PermissionsUserId"},{"kind":"OBJECT","name":"Query","fields":[{"name":"account","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[{"name":"by","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"domain","type":{"kind":"INTERFACE","name":"Domain","ofType":null},"args":[{"name":"by","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"domains","type":{"kind":"OBJECT","name":"QueryDomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"permissions","type":{"kind":"OBJECT","name":"Permissions","ofType":null},"args":[{"name":"by","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"registrations","type":{"kind":"OBJECT","name":"QueryRegistrationsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"registry","type":{"kind":"OBJECT","name":"Registry","ofType":null},"args":[{"name":"by","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"resolver","type":{"kind":"OBJECT","name":"Resolver","ofType":null},"args":[{"name":"by","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]},{"name":"resolvers","type":{"kind":"OBJECT","name":"QueryResolversConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"root","type":{"kind":"OBJECT","name":"Registry","ofType":null},"args":[]},{"name":"v1Domains","type":{"kind":"OBJECT","name":"QueryV1DomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"v2Domains","type":{"kind":"OBJECT","name":"QueryV2DomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryDomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"QueryDomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryDomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryRegistrationsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"QueryRegistrationsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryRegistrationsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Registration","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryResolversConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"QueryResolversConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryResolversConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Resolver","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryV1DomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"QueryV1DomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryV1DomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ENSv1Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryV2DomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"QueryV2DomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"QueryV2DomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ENSv2Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"INTERFACE","name":"Registration","fields":[{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"BigInt","ofType":null},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"RegistrationId","ofType":null}},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Hex","ofType":null},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]}],"interfaces":[],"possibleTypes":[{"kind":"OBJECT","name":"BaseRegistrarRegistration"},{"kind":"OBJECT","name":"ENSv2RegistryRegistration"},{"kind":"OBJECT","name":"ENSv2RegistryReservation"},{"kind":"OBJECT","name":"NameWrapperRegistration"},{"kind":"OBJECT","name":"ThreeDNSRegistration"}]},{"kind":"SCALAR","name":"RegistrationId"},{"kind":"OBJECT","name":"RegistrationRenewalsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"RegistrationRenewalsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistrationRenewalsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Renewal","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"Registry","fields":[{"name":"contract","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"domains","type":{"kind":"OBJECT","name":"RegistryDomainsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"order","type":{"kind":"SCALAR","name":"Any"}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"RegistryId","ofType":null}},"args":[]},{"name":"parents","type":{"kind":"OBJECT","name":"RegistryParentsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"permissions","type":{"kind":"OBJECT","name":"Permissions","ofType":null},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistryDomainsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"RegistryDomainsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistryDomainsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"RegistryId"},{"kind":"OBJECT","name":"RegistryParentsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"RegistryParentsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistryParentsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ENSv2Domain","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"RegistryPermissionsUser","fields":[{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"PermissionsUserId","ofType":null}},"args":[]},{"name":"registry","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Registry","ofType":null}},"args":[]},{"name":"resource","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"roles","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"user","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Account","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"Renewal","fields":[{"name":"base","type":{"kind":"SCALAR","name":"BigInt","ofType":null},"args":[]},{"name":"duration","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"RenewalId","ofType":null}},"args":[]},{"name":"premium","type":{"kind":"SCALAR","name":"BigInt","ofType":null},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Hex","ofType":null},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"RenewalId"},{"kind":"OBJECT","name":"Resolver","fields":[{"name":"bridged","type":{"kind":"OBJECT","name":"AccountId","ofType":null},"args":[]},{"name":"contract","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"events","type":{"kind":"OBJECT","name":"ResolverEventsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"where","type":{"kind":"SCALAR","name":"Any"}}]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"ResolverId","ofType":null}},"args":[]},{"name":"permissions","type":{"kind":"OBJECT","name":"Permissions","ofType":null},"args":[]},{"name":"records","type":{"kind":"OBJECT","name":"ResolverRecordsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"records_","type":{"kind":"OBJECT","name":"ResolverRecords","ofType":null},"args":[{"name":"for","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Any"}}}]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverEventsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ResolverEventsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverEventsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"ResolverId"},{"kind":"OBJECT","name":"ResolverPermissionsUser","fields":[{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"PermissionsUserId","ofType":null}},"args":[]},{"name":"resolver","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Resolver","ofType":null}},"args":[]},{"name":"resource","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"roles","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"user","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Account","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverRecords","fields":[{"name":"coinTypes","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"CoinType","ofType":null}}}},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"ResolverRecordsId","ofType":null}},"args":[]},{"name":"keys","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}}}},"args":[]},{"name":"name","type":{"kind":"SCALAR","name":"String","ofType":null},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Node","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverRecordsConnection","fields":[{"name":"edges","type":{"kind":"NON_NULL","ofType":{"kind":"LIST","ofType":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ResolverRecordsConnectionEdge","ofType":null}}}},"args":[]},{"name":"pageInfo","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"PageInfo","ofType":null}},"args":[]},{"name":"totalCount","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"OBJECT","name":"ResolverRecordsConnectionEdge","fields":[{"name":"cursor","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"String","ofType":null}},"args":[]},{"name":"node","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"ResolverRecords","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"ResolverRecordsId"},{"kind":"SCALAR","name":"String"},{"kind":"OBJECT","name":"ThreeDNSRegistration","fields":[{"name":"domain","type":{"kind":"NON_NULL","ofType":{"kind":"INTERFACE","name":"Domain","ofType":null}},"args":[]},{"name":"event","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"Event","ofType":null}},"args":[]},{"name":"expired","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Boolean","ofType":null}},"args":[]},{"name":"expiry","type":{"kind":"SCALAR","name":"BigInt","ofType":null},"args":[]},{"name":"id","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"RegistrationId","ofType":null}},"args":[]},{"name":"referrer","type":{"kind":"SCALAR","name":"Hex","ofType":null},"args":[]},{"name":"registrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]},{"name":"registrar","type":{"kind":"NON_NULL","ofType":{"kind":"OBJECT","name":"AccountId","ofType":null}},"args":[]},{"name":"renewals","type":{"kind":"OBJECT","name":"RegistrationRenewalsConnection","ofType":null},"args":[{"name":"after","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"before","type":{"kind":"SCALAR","name":"String","ofType":null}},{"name":"first","type":{"kind":"SCALAR","name":"Int","ofType":null}},{"name":"last","type":{"kind":"SCALAR","name":"Int","ofType":null}}]},{"name":"start","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]},{"name":"unregistrant","type":{"kind":"OBJECT","name":"Account","ofType":null},"args":[]}],"interfaces":[{"kind":"INTERFACE","name":"Registration"}]},{"kind":"OBJECT","name":"WrappedBaseRegistrarRegistration","fields":[{"name":"fuses","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"Int","ofType":null}},"args":[]},{"name":"tokenId","type":{"kind":"NON_NULL","ofType":{"kind":"SCALAR","name":"BigInt","ofType":null}},"args":[]}],"interfaces":[]},{"kind":"SCALAR","name":"Any"}],"directives":[]}} as const; +/* eslint-disable */ +/* prettier-ignore */ + +/** An IntrospectionQuery representation of your schema. + * + * @remarks + * This is an introspection of your schema saved as a file by GraphQLSP. + * You may import it to create a `graphql()` tag function with `gql.tada` + * by importing it and passing it to `initGraphQLTada<>()`. + * + * @example + * ``` + * import { initGraphQLTada } from 'gql.tada'; + * import type { introspection } from './introspection'; + * + * export const graphql = initGraphQLTada<{ + * introspection: typeof introspection; + * scalars: { + * DateTime: string; + * Json: any; + * }; + * }>(); + * ``` + */ +const introspection = { + "__schema": { + "queryType": { + "name": "Query" + }, + "mutationType": null, + "subscriptionType": null, + "types": [ + { + "kind": "OBJECT", + "name": "Account", + "fields": [ + { + "name": "address", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Address" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "domains", + "type": { + "kind": "OBJECT", + "name": "AccountDomainsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "order", + "type": { + "kind": "INPUT_OBJECT", + "name": "DomainsOrderInput" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "AccountDomainsWhereInput" + } + } + ], + "isDeprecated": false + }, + { + "name": "events", + "type": { + "kind": "OBJECT", + "name": "AccountEventsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "AccountEventsWhereInput" + } + } + ], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Address" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "permissions", + "type": { + "kind": "OBJECT", + "name": "AccountPermissionsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "in", + "type": { + "kind": "INPUT_OBJECT", + "name": "AccountIdInput" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "registryPermissions", + "type": { + "kind": "OBJECT", + "name": "AccountRegistryPermissionsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "resolverPermissions", + "type": { + "kind": "OBJECT", + "name": "AccountResolverPermissionsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "INPUT_OBJECT", + "name": "AccountByInput", + "inputFields": [ + { + "name": "address", + "type": { + "kind": "SCALAR", + "name": "Address" + } + }, + { + "name": "id", + "type": { + "kind": "SCALAR", + "name": "Address" + } + } + ], + "isOneOf": true + }, + { + "kind": "OBJECT", + "name": "AccountDomainsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountDomainsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "AccountDomainsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "INPUT_OBJECT", + "name": "AccountDomainsWhereInput", + "inputFields": [ + { + "name": "canonical", + "type": { + "kind": "SCALAR", + "name": "Boolean" + }, + "defaultValue": "false" + }, + { + "name": "name", + "type": { + "kind": "SCALAR", + "name": "String" + } + } + ], + "isOneOf": false + }, + { + "kind": "OBJECT", + "name": "AccountEventsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountEventsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "AccountEventsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "INPUT_OBJECT", + "name": "AccountEventsWhereInput", + "inputFields": [ + { + "name": "selector_in", + "type": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Hex" + } + } + } + }, + { + "name": "timestamp_gte", + "type": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + { + "name": "timestamp_lte", + "type": { + "kind": "SCALAR", + "name": "BigInt" + } + } + ], + "isOneOf": false + }, + { + "kind": "OBJECT", + "name": "AccountId", + "fields": [ + { + "name": "address", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Address" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "chainId", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "ChainId" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "INPUT_OBJECT", + "name": "AccountIdInput", + "inputFields": [ + { + "name": "address", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Address" + } + } + }, + { + "name": "chainId", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "ChainId" + } + } + } + ], + "isOneOf": false + }, + { + "kind": "OBJECT", + "name": "AccountPermissionsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountPermissionsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "AccountPermissionsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PermissionsUser" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "AccountRegistryPermissionsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountRegistryPermissionsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "AccountRegistryPermissionsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "RegistryPermissionsUser" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "AccountResolverPermissionsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountResolverPermissionsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "AccountResolverPermissionsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "ResolverPermissionsUser" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "SCALAR", + "name": "Address" + }, + { + "kind": "OBJECT", + "name": "BaseRegistrarRegistration", + "fields": [ + { + "name": "baseCost", + "type": { + "kind": "SCALAR", + "name": "BigInt" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "domain", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "event", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expired", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Boolean" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expiry", + "type": { + "kind": "SCALAR", + "name": "BigInt" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "RegistrationId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "isInGracePeriod", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Boolean" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "premium", + "type": { + "kind": "SCALAR", + "name": "BigInt" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "referrer", + "type": { + "kind": "SCALAR", + "name": "Hex" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrar", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "renewals", + "type": { + "kind": "OBJECT", + "name": "RegistrationRenewalsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "start", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "unregistrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "wrapped", + "type": { + "kind": "OBJECT", + "name": "WrappedBaseRegistrarRegistration" + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Registration" + } + ] + }, + { + "kind": "SCALAR", + "name": "BigInt" + }, + { + "kind": "SCALAR", + "name": "Boolean" + }, + { + "kind": "SCALAR", + "name": "ChainId" + }, + { + "kind": "SCALAR", + "name": "CoinType" + }, + { + "kind": "INTERFACE", + "name": "Domain", + "fields": [ + { + "name": "events", + "type": { + "kind": "OBJECT", + "name": "DomainEventsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EventsWhereInput" + } + } + ], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "DomainId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "label", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Label" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "name", + "type": { + "kind": "SCALAR", + "name": "InterpretedName" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "owner", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "path", + "type": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registration", + "type": { + "kind": "INTERFACE", + "name": "Registration" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrations", + "type": { + "kind": "OBJECT", + "name": "DomainRegistrationsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "resolver", + "type": { + "kind": "OBJECT", + "name": "Resolver" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "subdomains", + "type": { + "kind": "OBJECT", + "name": "DomainSubdomainsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "order", + "type": { + "kind": "INPUT_OBJECT", + "name": "DomainsOrderInput" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "SubdomainsWhereInput" + } + } + ], + "isDeprecated": false + } + ], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "ENSv1Domain" + }, + { + "kind": "OBJECT", + "name": "ENSv2Domain" + } + ] + }, + { + "kind": "OBJECT", + "name": "DomainEventsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "DomainEventsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "DomainEventsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "SCALAR", + "name": "DomainId" + }, + { + "kind": "INPUT_OBJECT", + "name": "DomainIdInput", + "inputFields": [ + { + "name": "id", + "type": { + "kind": "SCALAR", + "name": "DomainId" + } + }, + { + "name": "name", + "type": { + "kind": "SCALAR", + "name": "InterpretedName" + } + } + ], + "isOneOf": true + }, + { + "kind": "INPUT_OBJECT", + "name": "DomainPermissionsWhereInput", + "inputFields": [ + { + "name": "user", + "type": { + "kind": "SCALAR", + "name": "Address" + } + } + ], + "isOneOf": false + }, + { + "kind": "OBJECT", + "name": "DomainRegistrationsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "DomainRegistrationsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "DomainRegistrationsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Registration" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "DomainSubdomainsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "DomainSubdomainsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "DomainSubdomainsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "ENUM", + "name": "DomainsOrderBy", + "enumValues": [ + { + "name": "NAME", + "isDeprecated": false + }, + { + "name": "REGISTRATION_EXPIRY", + "isDeprecated": false + }, + { + "name": "REGISTRATION_TIMESTAMP", + "isDeprecated": false + } + ] + }, + { + "kind": "INPUT_OBJECT", + "name": "DomainsOrderInput", + "inputFields": [ + { + "name": "by", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "ENUM", + "name": "DomainsOrderBy" + } + } + }, + { + "name": "dir", + "type": { + "kind": "ENUM", + "name": "OrderDirection" + }, + "defaultValue": "ASC" + } + ], + "isOneOf": false + }, + { + "kind": "INPUT_OBJECT", + "name": "DomainsWhereInput", + "inputFields": [ + { + "name": "canonical", + "type": { + "kind": "SCALAR", + "name": "Boolean" + }, + "defaultValue": "false" + }, + { + "name": "name", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + } + } + ], + "isOneOf": false + }, + { + "kind": "OBJECT", + "name": "ENSv1Domain", + "fields": [ + { + "name": "events", + "type": { + "kind": "OBJECT", + "name": "DomainEventsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EventsWhereInput" + } + } + ], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "DomainId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "label", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Label" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "name", + "type": { + "kind": "SCALAR", + "name": "InterpretedName" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "owner", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "parent", + "type": { + "kind": "OBJECT", + "name": "ENSv1Domain" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "path", + "type": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registration", + "type": { + "kind": "INTERFACE", + "name": "Registration" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrations", + "type": { + "kind": "OBJECT", + "name": "DomainRegistrationsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "resolver", + "type": { + "kind": "OBJECT", + "name": "Resolver" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "rootRegistryOwner", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "subdomains", + "type": { + "kind": "OBJECT", + "name": "DomainSubdomainsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "order", + "type": { + "kind": "INPUT_OBJECT", + "name": "DomainsOrderInput" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "SubdomainsWhereInput" + } + } + ], + "isDeprecated": false + } + ], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Domain" + } + ] + }, + { + "kind": "OBJECT", + "name": "ENSv2Domain", + "fields": [ + { + "name": "events", + "type": { + "kind": "OBJECT", + "name": "DomainEventsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EventsWhereInput" + } + } + ], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "DomainId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "label", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Label" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "name", + "type": { + "kind": "SCALAR", + "name": "InterpretedName" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "owner", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "path", + "type": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "permissions", + "type": { + "kind": "OBJECT", + "name": "ENSv2DomainPermissionsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "DomainPermissionsWhereInput" + } + } + ], + "isDeprecated": false + }, + { + "name": "registration", + "type": { + "kind": "INTERFACE", + "name": "Registration" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrations", + "type": { + "kind": "OBJECT", + "name": "DomainRegistrationsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "registry", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Registry" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "resolver", + "type": { + "kind": "OBJECT", + "name": "Resolver" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "subdomains", + "type": { + "kind": "OBJECT", + "name": "DomainSubdomainsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "order", + "type": { + "kind": "INPUT_OBJECT", + "name": "DomainsOrderInput" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "SubdomainsWhereInput" + } + } + ], + "isDeprecated": false + }, + { + "name": "subregistry", + "type": { + "kind": "OBJECT", + "name": "Registry" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "tokenId", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Domain" + } + ] + }, + { + "kind": "OBJECT", + "name": "ENSv2DomainPermissionsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "ENSv2DomainPermissionsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "ENSv2DomainPermissionsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PermissionsUser" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "ENSv2RegistryRegistration", + "fields": [ + { + "name": "domain", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "event", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expired", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Boolean" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expiry", + "type": { + "kind": "SCALAR", + "name": "BigInt" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "RegistrationId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "referrer", + "type": { + "kind": "SCALAR", + "name": "Hex" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrar", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "renewals", + "type": { + "kind": "OBJECT", + "name": "RegistrationRenewalsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "start", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "unregistrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Registration" + } + ] + }, + { + "kind": "OBJECT", + "name": "ENSv2RegistryReservation", + "fields": [ + { + "name": "domain", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "event", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expired", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Boolean" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expiry", + "type": { + "kind": "SCALAR", + "name": "BigInt" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "RegistrationId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "referrer", + "type": { + "kind": "SCALAR", + "name": "Hex" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrar", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "renewals", + "type": { + "kind": "OBJECT", + "name": "RegistrationRenewalsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "start", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "unregistrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Registration" + } + ] + }, + { + "kind": "OBJECT", + "name": "Event", + "fields": [ + { + "name": "address", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Address" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "blockHash", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Hex" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "blockNumber", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "chainId", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "ChainId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "data", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Hex" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "from", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Address" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "ID" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "logIndex", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "timestamp", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "to", + "type": { + "kind": "SCALAR", + "name": "Address" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "topics", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Hex" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "transactionHash", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Hex" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "transactionIndex", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "INPUT_OBJECT", + "name": "EventsWhereInput", + "inputFields": [ + { + "name": "from", + "type": { + "kind": "SCALAR", + "name": "Address" + } + }, + { + "name": "selector_in", + "type": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Hex" + } + } + } + }, + { + "name": "timestamp_gte", + "type": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + { + "name": "timestamp_lte", + "type": { + "kind": "SCALAR", + "name": "BigInt" + } + } + ], + "isOneOf": false + }, + { + "kind": "SCALAR", + "name": "Hex" + }, + { + "kind": "SCALAR", + "name": "ID" + }, + { + "kind": "SCALAR", + "name": "Int" + }, + { + "kind": "SCALAR", + "name": "InterpretedLabel" + }, + { + "kind": "SCALAR", + "name": "InterpretedName" + }, + { + "kind": "OBJECT", + "name": "Label", + "fields": [ + { + "name": "hash", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Hex" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "interpreted", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "InterpretedLabel" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "INPUT_OBJECT", + "name": "NameOrNodeInput", + "inputFields": [ + { + "name": "name", + "type": { + "kind": "SCALAR", + "name": "InterpretedName" + } + }, + { + "name": "node", + "type": { + "kind": "SCALAR", + "name": "Node" + } + } + ], + "isOneOf": true + }, + { + "kind": "OBJECT", + "name": "NameWrapperRegistration", + "fields": [ + { + "name": "domain", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "event", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expired", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Boolean" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expiry", + "type": { + "kind": "SCALAR", + "name": "BigInt" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "fuses", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "RegistrationId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "referrer", + "type": { + "kind": "SCALAR", + "name": "Hex" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrar", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "renewals", + "type": { + "kind": "OBJECT", + "name": "RegistrationRenewalsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "start", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "unregistrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Registration" + } + ] + }, + { + "kind": "SCALAR", + "name": "Node" + }, + { + "kind": "ENUM", + "name": "OrderDirection", + "enumValues": [ + { + "name": "ASC", + "isDeprecated": false + }, + { + "name": "DESC", + "isDeprecated": false + } + ] + }, + { + "kind": "OBJECT", + "name": "PageInfo", + "fields": [ + { + "name": "endCursor", + "type": { + "kind": "SCALAR", + "name": "String" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "hasNextPage", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Boolean" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "hasPreviousPage", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Boolean" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "startCursor", + "type": { + "kind": "SCALAR", + "name": "String" + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "Permissions", + "fields": [ + { + "name": "contract", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "events", + "type": { + "kind": "OBJECT", + "name": "PermissionsEventsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EventsWhereInput" + } + } + ], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "PermissionsId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "resources", + "type": { + "kind": "OBJECT", + "name": "PermissionsResourcesConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "root", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PermissionsResource" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "PermissionsEventsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PermissionsEventsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "PermissionsEventsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "SCALAR", + "name": "PermissionsId" + }, + { + "kind": "INPUT_OBJECT", + "name": "PermissionsIdInput", + "inputFields": [ + { + "name": "contract", + "type": { + "kind": "INPUT_OBJECT", + "name": "AccountIdInput" + } + }, + { + "name": "id", + "type": { + "kind": "SCALAR", + "name": "PermissionsId" + } + } + ], + "isOneOf": true + }, + { + "kind": "OBJECT", + "name": "PermissionsResource", + "fields": [ + { + "name": "contract", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "PermissionsResourceId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "permissions", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Permissions" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "resource", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "users", + "type": { + "kind": "OBJECT", + "name": "PermissionsResourceUsersConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "SCALAR", + "name": "PermissionsResourceId" + }, + { + "kind": "OBJECT", + "name": "PermissionsResourceUsersConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PermissionsResourceUsersConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "PermissionsResourceUsersConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PermissionsUser" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "PermissionsResourcesConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PermissionsResourcesConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "PermissionsResourcesConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PermissionsResource" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "PermissionsUser", + "fields": [ + { + "name": "contract", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "PermissionsUserId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "resource", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "roles", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "user", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Account" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "SCALAR", + "name": "PermissionsUserId" + }, + { + "kind": "OBJECT", + "name": "Query", + "fields": [ + { + "name": "account", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [ + { + "name": "by", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INPUT_OBJECT", + "name": "AccountByInput" + } + } + } + ], + "isDeprecated": false + }, + { + "name": "domain", + "type": { + "kind": "INTERFACE", + "name": "Domain" + }, + "args": [ + { + "name": "by", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INPUT_OBJECT", + "name": "DomainIdInput" + } + } + } + ], + "isDeprecated": false + }, + { + "name": "domains", + "type": { + "kind": "OBJECT", + "name": "QueryDomainsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "order", + "type": { + "kind": "INPUT_OBJECT", + "name": "DomainsOrderInput" + } + }, + { + "name": "where", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INPUT_OBJECT", + "name": "DomainsWhereInput" + } + } + } + ], + "isDeprecated": false + }, + { + "name": "permissions", + "type": { + "kind": "OBJECT", + "name": "Permissions" + }, + "args": [ + { + "name": "by", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INPUT_OBJECT", + "name": "PermissionsIdInput" + } + } + } + ], + "isDeprecated": false + }, + { + "name": "registrations", + "type": { + "kind": "OBJECT", + "name": "QueryRegistrationsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "registry", + "type": { + "kind": "OBJECT", + "name": "Registry" + }, + "args": [ + { + "name": "by", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INPUT_OBJECT", + "name": "RegistryIdInput" + } + } + } + ], + "isDeprecated": false + }, + { + "name": "resolver", + "type": { + "kind": "OBJECT", + "name": "Resolver" + }, + "args": [ + { + "name": "by", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INPUT_OBJECT", + "name": "ResolverIdInput" + } + } + } + ], + "isDeprecated": false + }, + { + "name": "resolvers", + "type": { + "kind": "OBJECT", + "name": "QueryResolversConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "root", + "type": { + "kind": "OBJECT", + "name": "Registry" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "v1Domains", + "type": { + "kind": "OBJECT", + "name": "QueryV1DomainsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "v2Domains", + "type": { + "kind": "OBJECT", + "name": "QueryV2DomainsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "QueryDomainsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "QueryDomainsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "QueryDomainsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "QueryRegistrationsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "QueryRegistrationsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "QueryRegistrationsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Registration" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "QueryResolversConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "QueryResolversConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "QueryResolversConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Resolver" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "QueryV1DomainsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "QueryV1DomainsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "QueryV1DomainsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "ENSv1Domain" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "QueryV2DomainsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "QueryV2DomainsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "QueryV2DomainsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "ENSv2Domain" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "INTERFACE", + "name": "Registration", + "fields": [ + { + "name": "domain", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "event", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expired", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Boolean" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expiry", + "type": { + "kind": "SCALAR", + "name": "BigInt" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "RegistrationId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "referrer", + "type": { + "kind": "SCALAR", + "name": "Hex" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrar", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "renewals", + "type": { + "kind": "OBJECT", + "name": "RegistrationRenewalsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "start", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "unregistrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [], + "possibleTypes": [ + { + "kind": "OBJECT", + "name": "BaseRegistrarRegistration" + }, + { + "kind": "OBJECT", + "name": "ENSv2RegistryRegistration" + }, + { + "kind": "OBJECT", + "name": "ENSv2RegistryReservation" + }, + { + "kind": "OBJECT", + "name": "NameWrapperRegistration" + }, + { + "kind": "OBJECT", + "name": "ThreeDNSRegistration" + } + ] + }, + { + "kind": "SCALAR", + "name": "RegistrationId" + }, + { + "kind": "OBJECT", + "name": "RegistrationRenewalsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "RegistrationRenewalsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "RegistrationRenewalsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Renewal" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "Registry", + "fields": [ + { + "name": "contract", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "domains", + "type": { + "kind": "OBJECT", + "name": "RegistryDomainsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "order", + "type": { + "kind": "INPUT_OBJECT", + "name": "DomainsOrderInput" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "RegistryDomainsWhereInput" + } + } + ], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "RegistryId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "parents", + "type": { + "kind": "OBJECT", + "name": "RegistryParentsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "permissions", + "type": { + "kind": "OBJECT", + "name": "Permissions" + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "RegistryDomainsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "RegistryDomainsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "RegistryDomainsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "INPUT_OBJECT", + "name": "RegistryDomainsWhereInput", + "inputFields": [ + { + "name": "name", + "type": { + "kind": "SCALAR", + "name": "String" + } + } + ], + "isOneOf": false + }, + { + "kind": "SCALAR", + "name": "RegistryId" + }, + { + "kind": "INPUT_OBJECT", + "name": "RegistryIdInput", + "inputFields": [ + { + "name": "contract", + "type": { + "kind": "INPUT_OBJECT", + "name": "AccountIdInput" + } + }, + { + "name": "id", + "type": { + "kind": "SCALAR", + "name": "RegistryId" + } + } + ], + "isOneOf": true + }, + { + "kind": "OBJECT", + "name": "RegistryParentsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "RegistryParentsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "RegistryParentsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "ENSv2Domain" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "RegistryPermissionsUser", + "fields": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "PermissionsUserId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registry", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Registry" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "resource", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "roles", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "user", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Account" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "Renewal", + "fields": [ + { + "name": "base", + "type": { + "kind": "SCALAR", + "name": "BigInt" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "duration", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "event", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "RenewalId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "premium", + "type": { + "kind": "SCALAR", + "name": "BigInt" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "referrer", + "type": { + "kind": "SCALAR", + "name": "Hex" + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "SCALAR", + "name": "RenewalId" + }, + { + "kind": "OBJECT", + "name": "Resolver", + "fields": [ + { + "name": "bridged", + "type": { + "kind": "OBJECT", + "name": "AccountId" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "contract", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "events", + "type": { + "kind": "OBJECT", + "name": "ResolverEventsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "where", + "type": { + "kind": "INPUT_OBJECT", + "name": "EventsWhereInput" + } + } + ], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "ResolverId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "permissions", + "type": { + "kind": "OBJECT", + "name": "Permissions" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "records", + "type": { + "kind": "OBJECT", + "name": "ResolverRecordsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "records_", + "type": { + "kind": "OBJECT", + "name": "ResolverRecords" + }, + "args": [ + { + "name": "for", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INPUT_OBJECT", + "name": "NameOrNodeInput" + } + } + } + ], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "ResolverEventsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "ResolverEventsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "ResolverEventsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "SCALAR", + "name": "ResolverId" + }, + { + "kind": "INPUT_OBJECT", + "name": "ResolverIdInput", + "inputFields": [ + { + "name": "contract", + "type": { + "kind": "INPUT_OBJECT", + "name": "AccountIdInput" + } + }, + { + "name": "id", + "type": { + "kind": "SCALAR", + "name": "ResolverId" + } + } + ], + "isOneOf": true + }, + { + "kind": "OBJECT", + "name": "ResolverPermissionsUser", + "fields": [ + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "PermissionsUserId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "resolver", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Resolver" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "resource", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "roles", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "user", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Account" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "ResolverRecords", + "fields": [ + { + "name": "coinTypes", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "CoinType" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "ResolverRecordsId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "keys", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "name", + "type": { + "kind": "SCALAR", + "name": "String" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Node" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "ResolverRecordsConnection", + "fields": [ + { + "name": "edges", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "LIST", + "ofType": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "ResolverRecordsConnectionEdge" + } + } + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "PageInfo" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "totalCount", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "OBJECT", + "name": "ResolverRecordsConnectionEdge", + "fields": [ + { + "name": "cursor", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "String" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "node", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "ResolverRecords" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + }, + { + "kind": "SCALAR", + "name": "ResolverRecordsId" + }, + { + "kind": "SCALAR", + "name": "String" + }, + { + "kind": "INPUT_OBJECT", + "name": "SubdomainsWhereInput", + "inputFields": [ + { + "name": "name", + "type": { + "kind": "SCALAR", + "name": "String" + } + } + ], + "isOneOf": false + }, + { + "kind": "OBJECT", + "name": "ThreeDNSRegistration", + "fields": [ + { + "name": "domain", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "INTERFACE", + "name": "Domain" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "event", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "Event" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expired", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Boolean" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "expiry", + "type": { + "kind": "SCALAR", + "name": "BigInt" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "id", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "RegistrationId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "referrer", + "type": { + "kind": "SCALAR", + "name": "Hex" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + }, + { + "name": "registrar", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "OBJECT", + "name": "AccountId" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "renewals", + "type": { + "kind": "OBJECT", + "name": "RegistrationRenewalsConnection" + }, + "args": [ + { + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String" + } + }, + { + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int" + } + }, + { + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int" + } + } + ], + "isDeprecated": false + }, + { + "name": "start", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "unregistrant", + "type": { + "kind": "OBJECT", + "name": "Account" + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Registration" + } + ] + }, + { + "kind": "OBJECT", + "name": "WrappedBaseRegistrarRegistration", + "fields": [ + { + "name": "fuses", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "Int" + } + }, + "args": [], + "isDeprecated": false + }, + { + "name": "tokenId", + "type": { + "kind": "NON_NULL", + "ofType": { + "kind": "SCALAR", + "name": "BigInt" + } + }, + "args": [], + "isDeprecated": false + } + ], + "interfaces": [] + } + ], + "directives": [] + } +} as const; + +export { introspection }; \ No newline at end of file diff --git a/packages/enssdk/src/omnigraph/graphql.ts b/packages/enssdk/src/omnigraph/graphql.ts index a8edd6647..f7b6e9917 100644 --- a/packages/enssdk/src/omnigraph/graphql.ts +++ b/packages/enssdk/src/omnigraph/graphql.ts @@ -18,7 +18,12 @@ import type { ResolverId, ResolverRecordsId, } from "../lib/types"; -import type { introspection } from "./generated/graphql-env"; +import type { introspection } from "./generated/introspection"; + +/** + * Export the introspection for use with clients, especially urql in enskit. + */ +export { introspection } from "./generated/introspection"; /** * Scalar type mappings for the Omnigraph schema, representing the type of the serialized response diff --git a/packages/enssdk/src/omnigraph/introspection.ts b/packages/enssdk/src/omnigraph/introspection.ts deleted file mode 100644 index 23ef3090f..000000000 --- a/packages/enssdk/src/omnigraph/introspection.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { introspection } from "./generated/graphql-env"; -// export { introspection } from "./generated/introspection"; diff --git a/packages/enssdk/tsconfig.json b/packages/enssdk/tsconfig.json index 760b1d5fb..0b6a75a8b 100644 --- a/packages/enssdk/tsconfig.json +++ b/packages/enssdk/tsconfig.json @@ -6,7 +6,7 @@ { "name": "gql.tada/ts-plugin", "schema": "./src/omnigraph/generated/schema.graphql", - "tadaOutputLocation": "./src/omnigraph/generated/graphql-env.ts" + "tadaOutputLocation": "./src/omnigraph/generated/introspection.ts" } ] }, From 458c75acfe8e7b9afabd98841f12d23c242aa2c8 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 21:55:58 -0500 Subject: [PATCH 47/60] fix: lockfile --- pnpm-lock.yaml | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 00f3f61d7..5fca774bf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -466,9 +466,6 @@ importers: '@types/prismjs': specifier: ^1.26.6 version: 1.26.6 - '@urql/introspection': - specifier: ^1.2.1 - version: 1.2.1(graphql@16.11.0) chalk: specifier: ^5.6.2 version: 5.6.2 @@ -5031,11 +5028,6 @@ packages: peerDependencies: '@urql/core': ^6.0.0 - '@urql/introspection@1.2.1': - resolution: {integrity: sha512-U9FTSISz69EEK3bHWDsqux9JqOeiLzr3eDFBQ5DmHuTLaBsd5mjPdtLRzzzmb9nW1Ygd6IR8YcuM7zeNqQ5lCQ==} - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - '@vitejs/plugin-react@4.7.0': resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==} engines: {node: ^14.18.0 || >=16.0.0} @@ -13988,10 +13980,6 @@ snapshots: transitivePeerDependencies: - graphql - '@urql/introspection@1.2.1(graphql@16.11.0)': - dependencies: - graphql: 16.11.0 - '@vitejs/plugin-react@4.7.0(vite@6.4.2(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@babel/core': 7.28.5 @@ -14025,14 +14013,6 @@ snapshots: chai: 6.2.0 tinyrainbow: 3.0.3 - '@vitest/mocker@4.0.5(vite@6.4.2(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.3))': - dependencies: - '@vitest/spy': 4.0.5 - estree-walker: 3.0.3 - magic-string: 0.30.21 - optionalDependencies: - vite: 6.4.2(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.3) - '@vitest/mocker@4.0.5(vite@6.4.2(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@vitest/spy': 4.0.5 @@ -19274,7 +19254,7 @@ snapshots: vitest@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.20.6)(yaml@2.8.3): dependencies: '@vitest/expect': 4.0.5 - '@vitest/mocker': 4.0.5(vite@6.4.2(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.3)) + '@vitest/mocker': 4.0.5(vite@6.4.2(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.3)) '@vitest/pretty-format': 4.0.5 '@vitest/runner': 4.0.5 '@vitest/snapshot': 4.0.5 From 43d4afced1dc323adb3e8f74f4d8c7124a2b1188 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 22:01:13 -0500 Subject: [PATCH 48/60] pr notes --- AGENTS.md | 4 ++-- .../resolve-with-universal-resolver.integration.test.ts | 6 +++--- .../lib/maybe-heal-label-by-addr-reverse-subname.test.ts | 5 +++-- .../src/react/omnigraph/_lib/local-bigint-resolvers.test.ts | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index e0b2cfc90..ca288fbf6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -39,8 +39,8 @@ Runnable commands for validating changes; lint and format with Biome. - Install dependencies: `pnpm install` - Run all tests: `pnpm test` - - Run tests for a single project: `pnpm test --project [:project]` (e.g. `pnpm test --project ensapi`) - - Run tests for a single file: `pnpm test [:path]` + - Run tests for a single project: `pnpm test --project ` (e.g. `pnpm test --project ensapi`) + - Run tests for a single file: `pnpm test ` - Lint and format: `pnpm lint` (fixes where applicable); CI lint: `pnpm lint:ci` - Type checking: `pnpm typecheck` (runs typecheck in all workspaces) - Always use `pnpm -F typecheck`, never call `tsc` or `tsgo` directly diff --git a/apps/ensapi/src/lib/resolution/resolve-with-universal-resolver.integration.test.ts b/apps/ensapi/src/lib/resolution/resolve-with-universal-resolver.integration.test.ts index 3f8db4f81..36f46ad58 100644 --- a/apps/ensapi/src/lib/resolution/resolve-with-universal-resolver.integration.test.ts +++ b/apps/ensapi/src/lib/resolution/resolve-with-universal-resolver.integration.test.ts @@ -1,10 +1,12 @@ import { vi } from "vitest"; +import { ENSNamespaceIds, ensTestEnvChain } from "@ensnode/datasources"; + // we're testing a function specifically, not fetching through the running ensapi instance, so // we need to mock the config when this worker process attempts to import ./resolve-with-universal-resolver vi.mock("@/config", () => ({ default: { - namespace: "ens-test-env", + namespace: ENSNamespaceIds.EnsTestEnv, rpcConfigs: new Map([[ensTestEnvChain.id, { httpRPCs: [new URL("http://localhost:8545")] }]]), }, })); @@ -20,8 +22,6 @@ import { } from "enssdk"; import { describe, expect, it } from "vitest"; -import { ensTestEnvChain } from "@ensnode/datasources"; - import { getPublicClient } from "@/lib/public-client"; import { makeResolveCalls } from "@/lib/resolution/resolve-calls-and-results"; diff --git a/apps/ensindexer/src/lib/maybe-heal-label-by-addr-reverse-subname.test.ts b/apps/ensindexer/src/lib/maybe-heal-label-by-addr-reverse-subname.test.ts index b4a317820..9fbbcdf7c 100644 --- a/apps/ensindexer/src/lib/maybe-heal-label-by-addr-reverse-subname.test.ts +++ b/apps/ensindexer/src/lib/maybe-heal-label-by-addr-reverse-subname.test.ts @@ -1,16 +1,17 @@ import { - type Address, addrReverseLabel, type InterpretedLabel, labelhashInterpretedLabel, labelhashLiteralLabel, + toNormalizedAddress, } from "enssdk"; import { describe, expect, it } from "vitest"; import { maybeHealLabelByAddrReverseSubname } from "./maybe-heal-label-by-addr-reverse-subname"; +const address = toNormalizedAddress("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"); + describe("maybeHealLabelByAddrReverseSubname", () => { - const address: Address = "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"; const reverseAddressSubname = addrReverseLabel(address); const labelHash = labelhashLiteralLabel(reverseAddressSubname); const notMatchingLabelHash = labelhashInterpretedLabel("test.eth" as InterpretedLabel); diff --git a/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.test.ts b/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.test.ts index 2fa8f4373..8abd83494 100644 --- a/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.test.ts +++ b/packages/enskit/src/react/omnigraph/_lib/local-bigint-resolvers.test.ts @@ -11,7 +11,7 @@ const BIGINT_VALUE = 1234567890n; const BIGINT_STRING = BIGINT_VALUE.toString(); describe("localBigIntResolvers", () => { - it("deserialized BigInt scalars as bigint", async () => { + it("deserializes BigInt scalars as bigint", async () => { mockFetch.mockResolvedValueOnce( new Response( JSON.stringify({ From f1ad3da10b85d6773ea404deb2e35713c02be4df Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 22:03:00 -0500 Subject: [PATCH 49/60] relax isNormalizedAddress input type --- packages/enssdk/src/lib/address.test.ts | 3 +-- packages/enssdk/src/lib/address.ts | 6 +++--- packages/enssdk/src/lib/interpreted-names-and-labels.ts | 1 + 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/enssdk/src/lib/address.test.ts b/packages/enssdk/src/lib/address.test.ts index a89691fef..e05c4d84f 100644 --- a/packages/enssdk/src/lib/address.test.ts +++ b/packages/enssdk/src/lib/address.test.ts @@ -1,7 +1,6 @@ import { describe, expect, it } from "vitest"; import { asNormalizedAddress, isNormalizedAddress, toNormalizedAddress } from "./address"; -import type { Address } from "./types"; describe("isNormalizedAddress", () => { it("should return true for a lowercase address", () => { @@ -21,7 +20,7 @@ describe("isNormalizedAddress", () => { }); it("should return false for a non-hex string", () => { - expect(isNormalizedAddress("not-an-address" as Address)).toBe(false); + expect(isNormalizedAddress("not-an-address")).toBe(false); }); }); diff --git a/packages/enssdk/src/lib/address.ts b/packages/enssdk/src/lib/address.ts index 3829da11e..99b744d6e 100644 --- a/packages/enssdk/src/lib/address.ts +++ b/packages/enssdk/src/lib/address.ts @@ -5,9 +5,9 @@ import type { Address, NormalizedAddress } from "./types"; /** * Determines whether an {@link Address} is a {@link NormalizedAddress}. */ -export function isNormalizedAddress(address: Address): address is NormalizedAddress { - const isLowerCase = address === address.toLowerCase(); - return isLowerCase && isAddress(address, { strict: false }); +export function isNormalizedAddress(maybeAddress: string): maybeAddress is NormalizedAddress { + const isLowerCase = maybeAddress === maybeAddress.toLowerCase(); + return isLowerCase && isAddress(maybeAddress, { strict: false }); } /** diff --git a/packages/enssdk/src/lib/interpreted-names-and-labels.ts b/packages/enssdk/src/lib/interpreted-names-and-labels.ts index 556fdef46..48e02a5e1 100644 --- a/packages/enssdk/src/lib/interpreted-names-and-labels.ts +++ b/packages/enssdk/src/lib/interpreted-names-and-labels.ts @@ -201,6 +201,7 @@ export function literalNameToLiteralLabels(name: LiteralName): LiteralLabel[] { * Converts an Interpreted Name into a list of Interpreted Labels. */ export function interpretedNameToInterpretedLabels(name: InterpretedName): InterpretedLabel[] { + if (name === "") return []; return name.split(".") as InterpretedLabel[]; } From 4eff61f924a467acec63ec8f4f02ec8e5e2c8514 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 22:05:33 -0500 Subject: [PATCH 50/60] fix: omnigaph barrel --- packages/enssdk/src/omnigraph/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/enssdk/src/omnigraph/index.ts b/packages/enssdk/src/omnigraph/index.ts index b718f00f8..3fdc59de4 100644 --- a/packages/enssdk/src/omnigraph/index.ts +++ b/packages/enssdk/src/omnigraph/index.ts @@ -1,3 +1,2 @@ export * from "./graphql"; -export * from "./introspection"; export * from "./module"; From 13b1349e81d3c467b941270e975e1d0ec5f1f22b Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 22:12:34 -0500 Subject: [PATCH 51/60] add basic normalized address schema test --- .../ensnode-sdk/src/shared/zod-schemas.test.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/ensnode-sdk/src/shared/zod-schemas.test.ts b/packages/ensnode-sdk/src/shared/zod-schemas.test.ts index 5d1e5adec..e46a81f36 100644 --- a/packages/ensnode-sdk/src/shared/zod-schemas.test.ts +++ b/packages/ensnode-sdk/src/shared/zod-schemas.test.ts @@ -10,6 +10,7 @@ import { makeDatetimeSchema, makeIntegerSchema, makeNonNegativeIntegerSchema, + makeNormalizedAddressSchema, makePositiveIntegerSchema, makePriceSchema, makeReinterpretedNameSchema, @@ -168,6 +169,20 @@ describe("ENSIndexer: Shared", () => { ).toMatch(/Price currency must be one of ETH, USDC, DAI/i); }); + describe("NormalizedAddress", () => { + const validAddress = "0x1234567890AbcdEF1234567890aBcdef12345678"; + + it("normalizes a valid address", () => { + expect(makeNormalizedAddressSchema().parse(validAddress)).toBe(validAddress.toLowerCase()); + }); + + it("rejects invalid input with a useful error", () => { + expect( + formatParseError(makeNormalizedAddressSchema().safeParse("not-an-address")), + ).toContain("EVM address must be a valid EVM address"); + }); + }); + describe("ReinterpretedName", () => { const nameWithNormalizedLabels = "tko.basetest.eth"; const nameWithUnnormalizedLabels = "TKO.basetest.eth"; From 98dbf3dd32686c659a94fa2126c77b708c81a469 Mon Sep 17 00:00:00 2001 From: shrugs Date: Mon, 13 Apr 2026 22:15:03 -0500 Subject: [PATCH 52/60] fix: name test again --- packages/enssdk/src/lib/names.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/enssdk/src/lib/names.test.ts b/packages/enssdk/src/lib/names.test.ts index 0598b56eb..60ad985d0 100644 --- a/packages/enssdk/src/lib/names.test.ts +++ b/packages/enssdk/src/lib/names.test.ts @@ -21,8 +21,7 @@ describe("names", () => { it("should handle empty string (root node)", () => { const name = asInterpretedName(""); - const expected = []; - expect(getNameHierarchy(name)).toEqual(expected); + expect(getNameHierarchy(name)).toEqual([]); }); it("should handle names with different TLDs", () => { From 25d62b23e776cc5e2ecdc19262aa23ad46e6c1d9 Mon Sep 17 00:00:00 2001 From: shrugs Date: Tue, 14 Apr 2026 11:06:16 -0500 Subject: [PATCH 53/60] fix: pr notes and docstrings and typins --- apps/ensapi/src/lib/resolution/forward-resolution.ts | 5 +++-- packages/ens-referrals/src/rank.ts | 2 +- packages/ens-referrals/src/referrer-metrics.ts | 4 +--- .../src/v1/award-models/rev-share-cap/referral-event.ts | 2 +- .../src/v1/award-models/rev-share-cap/rules.ts | 2 +- packages/ens-referrals/src/v1/award-models/shared/rank.ts | 2 +- packages/ens-referrals/src/v1/referrer-metrics.ts | 4 +--- packages/enssdk/src/lib/parse-reverse-name.test.ts | 7 ++++--- packages/enssdk/src/lib/parse-reverse-name.ts | 4 ++-- packages/enssdk/src/lib/reverse-name.ts | 6 +++--- 10 files changed, 18 insertions(+), 20 deletions(-) diff --git a/apps/ensapi/src/lib/resolution/forward-resolution.ts b/apps/ensapi/src/lib/resolution/forward-resolution.ts index 56af7de90..8dbf700c4 100644 --- a/apps/ensapi/src/lib/resolution/forward-resolution.ts +++ b/apps/ensapi/src/lib/resolution/forward-resolution.ts @@ -5,6 +5,7 @@ import { replaceBigInts } from "@ponder/utils"; import { type AccountId, asInterpretedName, + asLiteralName, type InterpretedName, isNormalizedName, type Node, @@ -143,7 +144,7 @@ async function _resolveForward( // TODO: technically InterpretedNames are not resolvable, since ENS contracts are not // encoded-labelhash-aware; so we add a temporary additional constraint on name that it // must be fully normalized (and therefore not contain encoded labelhash segments) - // (this will be improved in a future pr) + // (this will be improved in a future pr https://github.com/namehash/ensnode/issues/1920) if (!isNormalizedName(name)) { throw new Error(`'${name}' must be normalized to be resolvable.`); } @@ -280,7 +281,7 @@ async function _resolveForward( } // Invariant: the name in question should be an ENSIP-19 Reverse Name that we're able to parse - const parsed = parseReverseName(name); + const parsed = parseReverseName(asLiteralName(name)); if (!parsed) { throw new Error( `Invariant(ENSIP-19 Reverse Resolvers Protocol Acceleration): expected a valid ENSIP-19 Reverse Name but recieved '${name}'.`, diff --git a/packages/ens-referrals/src/rank.ts b/packages/ens-referrals/src/rank.ts index 559064d6f..eb7fa2b4b 100644 --- a/packages/ens-referrals/src/rank.ts +++ b/packages/ens-referrals/src/rank.ts @@ -85,7 +85,7 @@ export interface ReferrerMetricsForComparison { totalIncrementalDuration: Duration; /** - * The Ethereum address of the referrer. + * The Ethereum address of the referrer, as a {@link NormalizedAddress}. */ referrer: NormalizedAddress; } diff --git a/packages/ens-referrals/src/referrer-metrics.ts b/packages/ens-referrals/src/referrer-metrics.ts index 6c7804f1f..c5d2b2bd4 100644 --- a/packages/ens-referrals/src/referrer-metrics.ts +++ b/packages/ens-referrals/src/referrer-metrics.ts @@ -23,9 +23,7 @@ import { validateDuration } from "./time"; */ export interface ReferrerMetrics { /** - * The fully lowercase Ethereum address of the referrer. - * - * @invariant Guaranteed to be a valid EVM address in lowercase format + * The Ethereum address of the referrer, as a {@link NormalizedAddress}. */ referrer: NormalizedAddress; diff --git a/packages/ens-referrals/src/v1/award-models/rev-share-cap/referral-event.ts b/packages/ens-referrals/src/v1/award-models/rev-share-cap/referral-event.ts index 7a3ffe7cc..af8b7e462 100644 --- a/packages/ens-referrals/src/v1/award-models/rev-share-cap/referral-event.ts +++ b/packages/ens-referrals/src/v1/award-models/rev-share-cap/referral-event.ts @@ -10,7 +10,7 @@ import type { PriceEth } from "@ensnode/ensnode-sdk"; */ export interface ReferralEvent { /** - * The fully lowercase Ethereum address of the referrer. + * The Ethereum address of the referrer, as a {@link NormalizedAddress}. */ referrer: NormalizedAddress; diff --git a/packages/ens-referrals/src/v1/award-models/rev-share-cap/rules.ts b/packages/ens-referrals/src/v1/award-models/rev-share-cap/rules.ts index 2bb50aeb3..2781a15cc 100644 --- a/packages/ens-referrals/src/v1/award-models/rev-share-cap/rules.ts +++ b/packages/ens-referrals/src/v1/award-models/rev-share-cap/rules.ts @@ -15,7 +15,7 @@ import { */ export interface ReferralProgramEditionDisqualification { /** - * The address of the disqualified referrer. + * The Ethereum address of the disqualified referrer, as a {@link NormalizedAddress}. */ referrer: NormalizedAddress; diff --git a/packages/ens-referrals/src/v1/award-models/shared/rank.ts b/packages/ens-referrals/src/v1/award-models/shared/rank.ts index a7f30004a..d4a9f11b0 100644 --- a/packages/ens-referrals/src/v1/award-models/shared/rank.ts +++ b/packages/ens-referrals/src/v1/award-models/shared/rank.ts @@ -25,7 +25,7 @@ export interface ReferrerMetricsForComparison { totalIncrementalDuration: Duration; /** - * The Ethereum address of the referrer. + * The Ethereum address of the referrer, as a {@link NormalizedAddress}. */ referrer: NormalizedAddress; } diff --git a/packages/ens-referrals/src/v1/referrer-metrics.ts b/packages/ens-referrals/src/v1/referrer-metrics.ts index 3d12b74b0..b0b5ee198 100644 --- a/packages/ens-referrals/src/v1/referrer-metrics.ts +++ b/packages/ens-referrals/src/v1/referrer-metrics.ts @@ -14,9 +14,7 @@ import { validateDuration } from "./time"; */ export interface ReferrerMetrics { /** - * The fully lowercase Ethereum address of the referrer. - * - * @invariant Guaranteed to be a valid EVM address in lowercase format + * The Ethereum address of the referrer, as a {@link NormalizedAddress}. */ referrer: NormalizedAddress; diff --git a/packages/enssdk/src/lib/parse-reverse-name.test.ts b/packages/enssdk/src/lib/parse-reverse-name.test.ts index 093dc6b43..0f64982a4 100644 --- a/packages/enssdk/src/lib/parse-reverse-name.test.ts +++ b/packages/enssdk/src/lib/parse-reverse-name.test.ts @@ -14,6 +14,7 @@ import { import { describe, expect, it } from "vitest"; import { DEFAULT_EVM_CHAIN_ID, evmChainIdToCoinType } from "./coin-type"; +import { asLiteralName } from "./interpreted-names-and-labels"; import { parseReverseName } from "./parse-reverse-name"; import { reverseName } from "./reverse-name"; @@ -132,20 +133,20 @@ const negativeCases: string[] = [ describe("parseReverseName", () => { positiveCases.forEach(([input, expected]) => { it(`parses "${input}"`, () => { - expect(parseReverseName(input)).toEqual(expected); + expect(parseReverseName(asLiteralName(input))).toEqual(expected); }); }); negativeCases.forEach((input) => { it(`does not parse "${input}"`, () => { - expect(parseReverseName(input)).toBeNull(); + expect(parseReverseName(asLiteralName(input))).toBeNull(); }); }); it("parses constructed names", () => { CHAIN_IDS.forEach((chainId) => { const coinType = evmChainIdToCoinType(chainId); - expect(parseReverseName(reverseName(EXAMPLE_ADDRESS, coinType))).toEqual({ + expect(parseReverseName(asLiteralName(reverseName(EXAMPLE_ADDRESS, coinType)))).toEqual({ address: EXAMPLE_ADDRESS, coinType, }); diff --git a/packages/enssdk/src/lib/parse-reverse-name.ts b/packages/enssdk/src/lib/parse-reverse-name.ts index 67a71c388..fdbf9e51c 100644 --- a/packages/enssdk/src/lib/parse-reverse-name.ts +++ b/packages/enssdk/src/lib/parse-reverse-name.ts @@ -3,7 +3,7 @@ import { hexToBigInt } from "viem"; import { toNormalizedAddress } from "./address"; import { bigintToCoinType, DEFAULT_EVM_COIN_TYPE, ETH_COIN_TYPE } from "./coin-type"; import { asLiteralLabel } from "./interpreted-names-and-labels"; -import type { CoinType, LiteralLabel, Name, NormalizedAddress } from "./types"; +import type { CoinType, LiteralLabel, LiteralName, NormalizedAddress } from "./types"; /** * Matches an ENSIP-19 Reverse Name @@ -38,7 +38,7 @@ const parseCoinTypeLabel = (coinTypeLabel: LiteralLabel): CoinType => { /** * Parse the address and coinType out of an ENSIP-19 reverse name. */ -export function parseReverseName(name: Name): { +export function parseReverseName(name: LiteralName): { address: NormalizedAddress; coinType: CoinType; } | null { diff --git a/packages/enssdk/src/lib/reverse-name.ts b/packages/enssdk/src/lib/reverse-name.ts index 660580090..44109056c 100644 --- a/packages/enssdk/src/lib/reverse-name.ts +++ b/packages/enssdk/src/lib/reverse-name.ts @@ -1,6 +1,6 @@ import { DEFAULT_EVM_COIN_TYPE, ETH_COIN_TYPE } from "./coin-type"; import { asLiteralLabel } from "./interpreted-names-and-labels"; -import type { CoinType, Label, LiteralLabel, Name, NormalizedAddress } from "./types"; +import type { CoinType, InterpretedName, Label, LiteralLabel, NormalizedAddress } from "./types"; /** * Gets the Label used for the reverse names of subnames as per ENSIP-11 & ENSIP-19. @@ -34,7 +34,7 @@ export const coinTypeReverseLabel = (coinType: CoinType): Label => coinType.toSt * reverseName("0x1234", BigInt(0x5678)) // "1234.5678.reverse" * ``` */ -export function reverseName(address: NormalizedAddress, coinType: CoinType): Name { +export function reverseName(address: NormalizedAddress, coinType: CoinType): InterpretedName { const label = addrReverseLabel(address); const middle = (() => { @@ -48,5 +48,5 @@ export function reverseName(address: NormalizedAddress, coinType: CoinType): Nam } })(); - return `${label}.${middle}.reverse`; + return `${label}.${middle}.reverse` as InterpretedName; } From 54a03b9581cc9635c5a45676924f6ec972ba442f Mon Sep 17 00:00:00 2001 From: shrugs Date: Tue, 14 Apr 2026 11:11:04 -0500 Subject: [PATCH 54/60] fix: parseReverseName accepts InterpretedName, better error message in DomainView --- apps/ensapi/src/lib/resolution/forward-resolution.ts | 3 +-- examples/enskit-react-example/src/DomainView.tsx | 2 +- packages/enssdk/src/lib/parse-reverse-name.test.ts | 8 ++++---- packages/enssdk/src/lib/parse-reverse-name.ts | 7 +++++-- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/apps/ensapi/src/lib/resolution/forward-resolution.ts b/apps/ensapi/src/lib/resolution/forward-resolution.ts index 8dbf700c4..b8b86db74 100644 --- a/apps/ensapi/src/lib/resolution/forward-resolution.ts +++ b/apps/ensapi/src/lib/resolution/forward-resolution.ts @@ -5,7 +5,6 @@ import { replaceBigInts } from "@ponder/utils"; import { type AccountId, asInterpretedName, - asLiteralName, type InterpretedName, isNormalizedName, type Node, @@ -281,7 +280,7 @@ async function _resolveForward( } // Invariant: the name in question should be an ENSIP-19 Reverse Name that we're able to parse - const parsed = parseReverseName(asLiteralName(name)); + const parsed = parseReverseName(name); if (!parsed) { throw new Error( `Invariant(ENSIP-19 Reverse Resolvers Protocol Acceleration): expected a valid ENSIP-19 Reverse Name but recieved '${name}'.`, diff --git a/examples/enskit-react-example/src/DomainView.tsx b/examples/enskit-react-example/src/DomainView.tsx index 11e2c9d44..8c7d6d96f 100644 --- a/examples/enskit-react-example/src/DomainView.tsx +++ b/examples/enskit-react-example/src/DomainView.tsx @@ -110,7 +110,7 @@ export function DomainView() { // this name can't conform to InterpretedName nor can it be coerced: it is malformed: show an error malformed={(name) => (
-

{name} could not be understood

+

Invalid name: '{name}'

Back to 'eth' Domain.
)} diff --git a/packages/enssdk/src/lib/parse-reverse-name.test.ts b/packages/enssdk/src/lib/parse-reverse-name.test.ts index 0f64982a4..f109ee41f 100644 --- a/packages/enssdk/src/lib/parse-reverse-name.test.ts +++ b/packages/enssdk/src/lib/parse-reverse-name.test.ts @@ -14,7 +14,7 @@ import { import { describe, expect, it } from "vitest"; import { DEFAULT_EVM_CHAIN_ID, evmChainIdToCoinType } from "./coin-type"; -import { asLiteralName } from "./interpreted-names-and-labels"; +import { asInterpretedName } from "./interpreted-names-and-labels"; import { parseReverseName } from "./parse-reverse-name"; import { reverseName } from "./reverse-name"; @@ -133,20 +133,20 @@ const negativeCases: string[] = [ describe("parseReverseName", () => { positiveCases.forEach(([input, expected]) => { it(`parses "${input}"`, () => { - expect(parseReverseName(asLiteralName(input))).toEqual(expected); + expect(parseReverseName(asInterpretedName(input))).toEqual(expected); }); }); negativeCases.forEach((input) => { it(`does not parse "${input}"`, () => { - expect(parseReverseName(asLiteralName(input))).toBeNull(); + expect(parseReverseName(asInterpretedName(input))).toBeNull(); }); }); it("parses constructed names", () => { CHAIN_IDS.forEach((chainId) => { const coinType = evmChainIdToCoinType(chainId); - expect(parseReverseName(asLiteralName(reverseName(EXAMPLE_ADDRESS, coinType)))).toEqual({ + expect(parseReverseName(asInterpretedName(reverseName(EXAMPLE_ADDRESS, coinType)))).toEqual({ address: EXAMPLE_ADDRESS, coinType, }); diff --git a/packages/enssdk/src/lib/parse-reverse-name.ts b/packages/enssdk/src/lib/parse-reverse-name.ts index fdbf9e51c..14f2f305d 100644 --- a/packages/enssdk/src/lib/parse-reverse-name.ts +++ b/packages/enssdk/src/lib/parse-reverse-name.ts @@ -3,7 +3,7 @@ import { hexToBigInt } from "viem"; import { toNormalizedAddress } from "./address"; import { bigintToCoinType, DEFAULT_EVM_COIN_TYPE, ETH_COIN_TYPE } from "./coin-type"; import { asLiteralLabel } from "./interpreted-names-and-labels"; -import type { CoinType, LiteralLabel, LiteralName, NormalizedAddress } from "./types"; +import type { CoinType, InterpretedName, LiteralLabel, NormalizedAddress } from "./types"; /** * Matches an ENSIP-19 Reverse Name @@ -37,8 +37,11 @@ const parseCoinTypeLabel = (coinTypeLabel: LiteralLabel): CoinType => { /** * Parse the address and coinType out of an ENSIP-19 reverse name. + * + * @dev accepts InterpretedName because all Reverse Names are Interpreted Names and we use this + * function in the context of the Resolution module in which all names are InterpretedNames. */ -export function parseReverseName(name: LiteralName): { +export function parseReverseName(name: InterpretedName): { address: NormalizedAddress; coinType: CoinType; } | null { From cefad95630b9b1f849ddae37e0056ad454b97c58 Mon Sep 17 00:00:00 2001 From: shrugs Date: Tue, 14 Apr 2026 11:17:15 -0500 Subject: [PATCH 55/60] docs updates --- examples/enskit-react-example/src/DomainView.tsx | 2 +- .../ensnode-sdk/src/registrars/encoded-referrer.test.ts | 7 +++++-- packages/enssdk/src/lib/labelhash.ts | 6 +++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/examples/enskit-react-example/src/DomainView.tsx b/examples/enskit-react-example/src/DomainView.tsx index 8c7d6d96f..0cd4b7940 100644 --- a/examples/enskit-react-example/src/DomainView.tsx +++ b/examples/enskit-react-example/src/DomainView.tsx @@ -50,7 +50,7 @@ function RenderDomain({ name }: { name: InterpretedName }) { if (fetching) return

Loading...

; if (error) return

Error: {error.message}

; - if (!data?.domain) return

A Domain with name '{name}' was not found.

; + if (!data?.domain) return

No domain was found with name '{name}'.

; const domain = readFragment(DomainFragment, data.domain); const parentName = getParentInterpretedName(name); diff --git a/packages/ensnode-sdk/src/registrars/encoded-referrer.test.ts b/packages/ensnode-sdk/src/registrars/encoded-referrer.test.ts index caf3ee5dc..bcbbc5475 100644 --- a/packages/ensnode-sdk/src/registrars/encoded-referrer.test.ts +++ b/packages/ensnode-sdk/src/registrars/encoded-referrer.test.ts @@ -1,4 +1,4 @@ -import { type Address, toNormalizedAddress } from "enssdk"; +import { type Address, asNormalizedAddress, toNormalizedAddress } from "enssdk"; import { concat, getAddress, pad, zeroAddress } from "viem"; import { describe, expect, it } from "vitest"; @@ -9,7 +9,10 @@ import { ENCODED_REFERRER_BYTE_OFFSET, } from "./encoded-referrer"; -const vitalikEthAddressLowercase: Address = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; +const vitalikEthAddressLowercase = asNormalizedAddress( + "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", +); + const vitalikEthAddressChecksummed: Address = getAddress( "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", ); diff --git a/packages/enssdk/src/lib/labelhash.ts b/packages/enssdk/src/lib/labelhash.ts index 5cc74ed1a..c3cc729c7 100644 --- a/packages/enssdk/src/lib/labelhash.ts +++ b/packages/enssdk/src/lib/labelhash.ts @@ -46,13 +46,13 @@ export function isLabelHash(maybeLabelHash: string): maybeLabelHash is LabelHash * @see https://ensnode.io/docs/reference/terminology#encoded-labelhash * * @param labelHash - A 32-byte lowercase hash string starting with '0x' - * @returns The encoded label hash in format `[hash_without_0x_prefix]` + * @returns The encoded label hash in format `[labelhash_without_0x_prefix]` */ export const encodeLabelHash = (labelHash: LabelHash): EncodedLabelHash => `[${labelHash.slice(2)}]`; /** - * Parses an Encoded LabelHash (`[hash_without_0x_prefix]`) as a {@link LabelHash}, + * Parses an Encoded LabelHash (`[labelhash_without_0x_prefix]`) as a {@link LabelHash}, * returning `null` if the input does not match the expected format. */ function parseEncodedLabelHash(value: string): LabelHash | null { @@ -74,7 +74,7 @@ function parseEncodedLabelHash(value: string): LabelHash | null { * @see https://ensnode.io/docs/reference/terminology#encoded-labelhash * @see https://github.com/wevm/viem/blob/main/src/utils/ens/encodedLabelToLabelhash.ts * - * @param maybeEncodedLabelHash The encoded label hash in format `[hash_without_0x_prefix]` + * @param maybeEncodedLabelHash The encoded label hash in format `[labelhash_without_0x_prefix]` * @returns A 32-byte lowercase hash string starting with '0x' */ export const decodeEncodedLabelHash = (maybeEncodedLabelHash: string): LabelHash => { From cedd1348d677a7a8c285c134f0e8c035cbe96b2b Mon Sep 17 00:00:00 2001 From: shrugs Date: Tue, 14 Apr 2026 13:20:44 -0500 Subject: [PATCH 56/60] docstrings --- packages/enssdk/src/lib/interpreted-names-and-labels.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/enssdk/src/lib/interpreted-names-and-labels.ts b/packages/enssdk/src/lib/interpreted-names-and-labels.ts index 48e02a5e1..862147342 100644 --- a/packages/enssdk/src/lib/interpreted-names-and-labels.ts +++ b/packages/enssdk/src/lib/interpreted-names-and-labels.ts @@ -298,8 +298,8 @@ export function parsePartialInterpretedName(partialInterpretedName: Name): { * Casts a string to a {@link LiteralName}. * * A LiteralName is a name that should be interpreted as a string literal. It may or may not be - * normalized or normalizable. It may also include labels formatted as an encoded labelhash, but that - * does not mean it should be interpreted as perhaps containing encoded labelhashes. + * normalized or normalizable. It may also include labels formatted as an EncodedLabelHash, but that + * such labels must be interpreted literally and not as an EncodedLabelHash. */ export function asLiteralName(name: Name): LiteralName { return name as LiteralName; @@ -309,8 +309,8 @@ export function asLiteralName(name: Name): LiteralName { * Casts a string to a {@link LiteralLabel}. * * A LiteralLabel is a label that should be interpreted as a string literal. It may or may not be - * normalized or normalizable. It may also be formatted as an encoded labelhash, but that does not - * mean it should be interpreted as an encoded labelhash. + * normalized or normalizable. It may also be formatted as an EncodedLabelHash, but such labels must + * be interpreted literally and not as an EncodedLabelHash. */ export function asLiteralLabel(label: Label): LiteralLabel { return label as LiteralLabel; From 41bffaa3aad1ab60065d4c7227fbe44cd71390b7 Mon Sep 17 00:00:00 2001 From: shrugs Date: Tue, 14 Apr 2026 13:26:14 -0500 Subject: [PATCH 57/60] fix: parse reverse name test --- packages/enssdk/src/lib/parse-reverse-name.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/enssdk/src/lib/parse-reverse-name.test.ts b/packages/enssdk/src/lib/parse-reverse-name.test.ts index f109ee41f..2f0b62e37 100644 --- a/packages/enssdk/src/lib/parse-reverse-name.test.ts +++ b/packages/enssdk/src/lib/parse-reverse-name.test.ts @@ -17,6 +17,7 @@ import { DEFAULT_EVM_CHAIN_ID, evmChainIdToCoinType } from "./coin-type"; import { asInterpretedName } from "./interpreted-names-and-labels"; import { parseReverseName } from "./parse-reverse-name"; import { reverseName } from "./reverse-name"; +import type { InterpretedName } from "./types"; const EXAMPLE_ADDRESS = "0x51050ec063d393217b436747617ad1c2285aeeee"; const CHAIN_IDS = [ @@ -139,7 +140,8 @@ describe("parseReverseName", () => { negativeCases.forEach((input) => { it(`does not parse "${input}"`, () => { - expect(parseReverseName(asInterpretedName(input))).toBeNull(); + // NOTE: directly cast to avoid running asInterpretedName validation + expect(parseReverseName(input as InterpretedName)).toBeNull(); }); }); From 604803b6ebaab22dee379d281991a89198556ab8 Mon Sep 17 00:00:00 2001 From: shrugs Date: Tue, 14 Apr 2026 13:27:11 -0500 Subject: [PATCH 58/60] fix: typo --- .../src/shared/interpretation/interpret-record-values.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.ts b/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.ts index 1185153d1..6e62c712b 100644 --- a/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.ts +++ b/packages/ensnode-sdk/src/shared/interpretation/interpret-record-values.ts @@ -8,7 +8,7 @@ import { hasNullByte } from "../null-bytes"; * Interprets a name record value string and returns null if the value is interpreted as a deletion. * * The interpreted record value is either: - * a) null, representing a non-existant or deletion of the record, or + * a) null, representing a non-existent or deletion of the record, or * b) an {@link InterpretedName}. * * @param value - The name record value string to interpret. @@ -32,7 +32,7 @@ export function interpretNameRecordValue(value: LiteralName): InterpretedName | * Interprets an address record value string and returns null if the value is interpreted as a deletion. * * The interpreted record value is either: - * a) null, representing a non-existant or deletion of the record, or + * a) null, representing a non-existent or deletion of the record, or * i. contains null bytes * ii. empty string * iii. empty hex (0x) @@ -92,7 +92,7 @@ export function interpretTextRecordKey(key: string): string | null { * Interprets a text record value string and returns null if the value is interpreted as a deletion. * * The interpreted record value is either: - * a) null, representing a non-existant or deletion of the record, or + * a) null, representing a non-existent or deletion of the record, or * i. contains null bytes * ii. empty string * b) a text record value that From 921731cf675f9194c7d17fe247628b6b3ff0dc8d Mon Sep 17 00:00:00 2001 From: shrugs Date: Tue, 14 Apr 2026 14:04:52 -0500 Subject: [PATCH 59/60] fix: minor nits --- AGENTS.md | 2 +- apps/ensapi/src/omnigraph-api/schema/scalars.ts | 4 ++-- packages/ens-referrals/src/address.ts | 4 ++-- packages/ens-referrals/src/v1/address.ts | 4 ++-- packages/enssdk/src/lib/interpreted-names-and-labels.ts | 8 ++++---- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index ca288fbf6..674d9db83 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -77,7 +77,7 @@ Fail fast and loudly on invalid inputs. ## Workflow - Add a changeset when your PR includes a logical change that should bump versions or be communicated in release notes: https://ensnode.io/docs/contributing/prs#changesets -- Before declaring work complete, run validation in the affected packages: +- Before declaring work complete, run validation in the affected project(s): 1. `pnpm -F typecheck` 2. `pnpm lint` 3. `pnpm test --project [--project ]` diff --git a/apps/ensapi/src/omnigraph-api/schema/scalars.ts b/apps/ensapi/src/omnigraph-api/schema/scalars.ts index 27eb5e9bf..9ccbbf235 100644 --- a/apps/ensapi/src/omnigraph-api/schema/scalars.ts +++ b/apps/ensapi/src/omnigraph-api/schema/scalars.ts @@ -5,7 +5,7 @@ import { type CoinType, type DomainId, type Hex, - isInterpetedLabel, + isInterpretedLabel, isInterpretedName, type Name, type Node, @@ -119,7 +119,7 @@ builder.scalarType("InterpretedLabel", { z.coerce .string() .check((ctx) => { - if (!isInterpetedLabel(ctx.value)) { + if (!isInterpretedLabel(ctx.value)) { ctx.issues.push({ code: "custom", message: "InterpretedLabel must be an Encoded LabelHash or normalized.", diff --git a/packages/ens-referrals/src/address.ts b/packages/ens-referrals/src/address.ts index 22e865c95..2580243b7 100644 --- a/packages/ens-referrals/src/address.ts +++ b/packages/ens-referrals/src/address.ts @@ -1,7 +1,7 @@ -import type { Address } from "enssdk"; +import type { NormalizedAddress } from "enssdk"; import { isNormalizedAddress } from "enssdk"; -export const validateAddress = (address: Address): void => { +export const validateAddress = (address: NormalizedAddress): void => { if (!isNormalizedAddress(address)) { throw new Error(`Invalid address: '${address}'. Address must be a lowercase EVM Address.`); } diff --git a/packages/ens-referrals/src/v1/address.ts b/packages/ens-referrals/src/v1/address.ts index 3c182284d..22c19c20e 100644 --- a/packages/ens-referrals/src/v1/address.ts +++ b/packages/ens-referrals/src/v1/address.ts @@ -1,7 +1,7 @@ -import type { Address } from "enssdk"; +import type { NormalizedAddress } from "enssdk"; import { isNormalizedAddress } from "enssdk"; -export const validateAddress = (address: Address): void => { +export const validateAddress = (address: NormalizedAddress): void => { if (!isNormalizedAddress(address)) { throw new Error(`Invalid address: '${address}'. Address must be a NormalizedAddress.`); } diff --git a/packages/enssdk/src/lib/interpreted-names-and-labels.ts b/packages/enssdk/src/lib/interpreted-names-and-labels.ts index 862147342..1cd8d40f9 100644 --- a/packages/enssdk/src/lib/interpreted-names-and-labels.ts +++ b/packages/enssdk/src/lib/interpreted-names-and-labels.ts @@ -205,7 +205,7 @@ export function interpretedNameToInterpretedLabels(name: InterpretedName): Inter return name.split(".") as InterpretedLabel[]; } -export function isInterpetedLabel(label: Label): label is InterpretedLabel { +export function isInterpretedLabel(label: Label): label is InterpretedLabel { return isEncodedLabelHash(label) || isNormalizedLabel(label); } @@ -218,7 +218,7 @@ export function isInterpetedLabel(label: Label): label is InterpretedLabel { */ export function isInterpretedName(name: Name): name is InterpretedName { if (name === ENS_ROOT_NAME) return true; - return name.split(".").every(isInterpetedLabel); + return name.split(".").every(isInterpretedLabel); } /** @@ -285,7 +285,7 @@ export function parsePartialInterpretedName(partialInterpretedName: Name): { // biome-ignore lint/style/noNonNullAssertion: there's always at least one element after a .split const partial = concrete.pop()!; - if (!concrete.every(isInterpetedLabel)) { + if (!concrete.every(isInterpretedLabel)) { throw new Error( `Invariant(parsePartialInterpretedName): Concrete portion of Partial InterpretedName contains segments that are not InterpretedLabels.\n${JSON.stringify(concrete)}`, ); @@ -323,7 +323,7 @@ export function asLiteralLabel(label: Label): LiteralLabel { * @throws if the input is not a valid InterpretedLabel */ export function asInterpretedLabel(label: Label): InterpretedLabel { - if (isInterpetedLabel(label)) return label; + if (isInterpretedLabel(label)) return label; throw new Error(`Not a valid InterpretedLabel: '${label}'`); } From ce8af051b715e2be48ac0f67e9a92f25e3b491a0 Mon Sep 17 00:00:00 2001 From: shrugs Date: Tue, 14 Apr 2026 14:36:37 -0500 Subject: [PATCH 60/60] pr notes --- .../src/lib/interpreted-names-and-labels.ts | 2 +- .../enssdk/src/lib/parse-reverse-name.test.ts | 2 +- packages/enssdk/src/lib/reverse-name.ts | 26 ++++++++++++------- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/packages/enssdk/src/lib/interpreted-names-and-labels.ts b/packages/enssdk/src/lib/interpreted-names-and-labels.ts index 1cd8d40f9..39a1a5566 100644 --- a/packages/enssdk/src/lib/interpreted-names-and-labels.ts +++ b/packages/enssdk/src/lib/interpreted-names-and-labels.ts @@ -298,7 +298,7 @@ export function parsePartialInterpretedName(partialInterpretedName: Name): { * Casts a string to a {@link LiteralName}. * * A LiteralName is a name that should be interpreted as a string literal. It may or may not be - * normalized or normalizable. It may also include labels formatted as an EncodedLabelHash, but that + * normalized or normalizable. It may also include labels formatted as an EncodedLabelHash, but * such labels must be interpreted literally and not as an EncodedLabelHash. */ export function asLiteralName(name: Name): LiteralName { diff --git a/packages/enssdk/src/lib/parse-reverse-name.test.ts b/packages/enssdk/src/lib/parse-reverse-name.test.ts index 2f0b62e37..9e8212a7c 100644 --- a/packages/enssdk/src/lib/parse-reverse-name.test.ts +++ b/packages/enssdk/src/lib/parse-reverse-name.test.ts @@ -148,7 +148,7 @@ describe("parseReverseName", () => { it("parses constructed names", () => { CHAIN_IDS.forEach((chainId) => { const coinType = evmChainIdToCoinType(chainId); - expect(parseReverseName(asInterpretedName(reverseName(EXAMPLE_ADDRESS, coinType)))).toEqual({ + expect(parseReverseName(reverseName(EXAMPLE_ADDRESS, coinType))).toEqual({ address: EXAMPLE_ADDRESS, coinType, }); diff --git a/packages/enssdk/src/lib/reverse-name.ts b/packages/enssdk/src/lib/reverse-name.ts index 44109056c..e5fa78a93 100644 --- a/packages/enssdk/src/lib/reverse-name.ts +++ b/packages/enssdk/src/lib/reverse-name.ts @@ -1,21 +1,29 @@ import { DEFAULT_EVM_COIN_TYPE, ETH_COIN_TYPE } from "./coin-type"; -import { asLiteralLabel } from "./interpreted-names-and-labels"; -import type { CoinType, InterpretedName, Label, LiteralLabel, NormalizedAddress } from "./types"; +import { + asInterpretedLabel, + interpretedLabelsToInterpretedName, +} from "./interpreted-names-and-labels"; +import type { CoinType, InterpretedLabel, InterpretedName, NormalizedAddress } from "./types"; + +const ADDR_LABEL = asInterpretedLabel("addr"); +const DEFAULT_LABEL = asInterpretedLabel("default"); +const REVERSE_LABEL = asInterpretedLabel("reverse"); /** * Gets the Label used for the reverse names of subnames as per ENSIP-11 & ENSIP-19. * * @see https://docs.ens.domains/ensip/19/#reverse-resolution */ -export const addrReverseLabel = (address: NormalizedAddress): LiteralLabel => - asLiteralLabel(address.slice(2)); +export const addrReverseLabel = (address: NormalizedAddress): InterpretedLabel => + address.slice(2) as InterpretedLabel; /** * Converts `coinType` to prefix-free hex string. * * @see https://docs.ens.domains/ensip/19 */ -export const coinTypeReverseLabel = (coinType: CoinType): Label => coinType.toString(16); +export const coinTypeReverseLabel = (coinType: CoinType): InterpretedLabel => + coinType.toString(16) as InterpretedLabel; /** * Gets the reverse name for an address according to ENSIP-11 & ENSIP-19. @@ -37,16 +45,16 @@ export const coinTypeReverseLabel = (coinType: CoinType): Label => coinType.toSt export function reverseName(address: NormalizedAddress, coinType: CoinType): InterpretedName { const label = addrReverseLabel(address); - const middle = (() => { + const middle = ((): InterpretedLabel => { switch (coinType) { case ETH_COIN_TYPE: - return "addr"; + return ADDR_LABEL; case DEFAULT_EVM_COIN_TYPE: - return "default"; + return DEFAULT_LABEL; default: return coinTypeReverseLabel(coinType); } })(); - return `${label}.${middle}.reverse` as InterpretedName; + return interpretedLabelsToInterpretedName([label, middle, REVERSE_LABEL]); }