@ensnode/ensnode-sdk 1.5.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/ensapi/config/deserialize.ts","../src/ensapi/config/zod-schemas.ts","../src/ensindexer/config/zod-schemas.ts","../src/shared/account-id.ts","../src/shared/address.ts","../src/shared/cache/lru-cache.ts","../src/shared/cache/swr-cache.ts","../src/shared/deserialize.ts","../src/shared/zod-schemas.ts","../src/ens/index.ts","../src/ens/coin-type.ts","../src/ens/constants.ts","../src/ens/dns-encoded-name.ts","../src/ens/labelhash.ts","../src/ens/encode-labelhash.ts","../src/ens/fuses.ts","../src/ens/is-normalized.ts","../src/ens/names.ts","../src/ens/parse-reverse-name.ts","../src/ens/reverse-name.ts","../src/ens/subname-helpers.ts","../src/ens/types.ts","../src/shared/currencies.ts","../src/shared/interpretation/reinterpretation.ts","../src/shared/datetime.ts","../src/shared/cache/ttl-cache.ts","../src/shared/collections.ts","../src/shared/datasource-contract.ts","../src/shared/interpretation/interpret-address.ts","../src/shared/interpretation/interpret-record-values.ts","../src/shared/null-bytes.ts","../src/shared/interpretation/interpret-tokenid.ts","../src/shared/interpretation/interpreted-names-and-labels.ts","../src/shared/labelhash.ts","../src/shared/numbers.ts","../src/shared/root-registry.ts","../src/shared/serialize.ts","../src/shared/types.ts","../src/shared/url.ts","../src/ensindexer/config/is-subgraph-compatible.ts","../src/ensindexer/config/types.ts","../src/ensindexer/config/validations.ts","../src/shared/config/thegraph.ts","../src/ensindexer/config/deserialize.ts","../src/ensindexer/config/label-utils.ts","../src/ensindexer/config/labelset-utils.ts","../src/ensindexer/config/parsing.ts","../src/ensindexer/config/serialize.ts","../src/ensindexer/indexing-status/deserialize.ts","../src/ensindexer/indexing-status/zod-schemas.ts","../src/ensindexer/indexing-status/types.ts","../src/shared/block-ref.ts","../src/ensindexer/indexing-status/helpers.ts","../src/ensindexer/indexing-status/validations.ts","../src/ensindexer/indexing-status/projection.ts","../src/ensindexer/indexing-status/serialize.ts","../src/ensapi/config/serialize.ts","../src/api/config/deserialize.ts","../src/api/config/serialize.ts","../src/api/indexing-status/deserialize.ts","../src/api/indexing-status/zod-schemas.ts","../src/api/indexing-status/response.ts","../src/api/indexing-status/serialize.ts","../src/api/name-tokens/deserialize.ts","../src/api/name-tokens/zod-schemas.ts","../src/tokenscope/assets.ts","../src/tokenscope/zod-schemas.ts","../src/tokenscope/name-token.ts","../src/api/shared/errors/zod-schemas.ts","../src/api/name-tokens/response.ts","../src/api/name-tokens/prerequisites.ts","../src/api/name-tokens/serialize.ts","../src/api/registrar-actions/deserialize.ts","../src/api/registrar-actions/zod-schemas.ts","../../ens-referrals/src/address.ts","../../ens-referrals/src/encoding.ts","../../ens-referrals/src/leaderboard-page.ts","../../ens-referrals/src/link.ts","../../ens-referrals/src/referrer-detail.ts","../src/registrars/zod-schemas.ts","../src/registrars/registrar-action.ts","../src/api/shared/pagination/zod-schemas.ts","../src/api/shared/pagination/request.ts","../src/api/registrar-actions/response.ts","../src/api/registrar-actions/request.ts","../src/api/registrar-actions/filters.ts","../src/api/registrar-actions/prerequisites.ts","../src/registrars/basenames-subregistry.ts","../src/registrars/ethnames-subregistry.ts","../src/registrars/lineanames-subregistry.ts","../src/registrars/registration-expiration.ts","../src/api/registrar-actions/serialize.ts","../src/api/shared/errors/deserialize.ts","../src/api/shared/pagination/build-page-context.ts","../src/client-error.ts","../src/ensanalytics/deserialize.ts","../src/ensanalytics/zod-schemas.ts","../src/ensanalytics/types.ts","../src/ensanalytics/serialize.ts","../src/client.ts","../src/ensv2/ids-lib.ts","../src/identity/identity.ts","../src/identity/types.ts","../src/resolution/ensip19-chainid.ts","../src/resolution/resolver-records-selection.ts","../src/tracing/ens-protocol-tracing.ts"],"sourcesContent":["export * from \"./api\";\nexport { type ClientOptions, ENSNodeClient } from \"./client\";\nexport * from \"./client-error\";\nexport * from \"./ens\";\nexport * from \"./ensanalytics\";\nexport * from \"./ensapi\";\nexport * from \"./ensindexer\";\nexport * from \"./ensrainbow\";\nexport * from \"./ensv2\";\nexport * from \"./identity\";\nexport * from \"./registrars\";\nexport * from \"./resolution\";\nexport * from \"./shared\";\nexport * from \"./tokenscope\";\nexport * from \"./tracing\";\n","import { prettifyError, ZodError } from \"zod/v4\";\n\nimport type { SerializedENSApiPublicConfig } from \"./serialized-types\";\nimport type { ENSApiPublicConfig } from \"./types\";\nimport { makeENSApiPublicConfigSchema } from \"./zod-schemas\";\n\n/**\n * Deserialize a {@link ENSApiPublicConfig} object.\n */\nexport function deserializeENSApiPublicConfig(\n maybeConfig: SerializedENSApiPublicConfig,\n valueLabel?: string,\n): ENSApiPublicConfig {\n const schema = makeENSApiPublicConfigSchema(valueLabel);\n try {\n return schema.parse(maybeConfig);\n } catch (error) {\n if (error instanceof ZodError) {\n throw new Error(`Cannot deserialize ENSApiPublicConfig:\\n${prettifyError(error)}\\n`);\n }\n\n throw error;\n }\n}\n","import { z } from \"zod/v4\";\n\nimport { makeENSIndexerPublicConfigSchema } from \"../../ensindexer/config/zod-schemas\";\nimport {\n TheGraphCannotFallbackReasonSchema,\n TheGraphFallbackSchema,\n} from \"../../shared/config/thegraph\";\n\nexport { TheGraphCannotFallbackReasonSchema, TheGraphFallbackSchema };\n\n/**\n * Create a Zod schema for validating a serialized ENSApiPublicConfig.\n *\n * @param valueLabel - Optional label for the value being validated (used in error messages)\n */\nexport function makeENSApiPublicConfigSchema(valueLabel?: string) {\n const label = valueLabel ?? \"ENSApiPublicConfig\";\n\n return z.strictObject({\n version: z.string().min(1, `${label}.version must be a non-empty string`),\n theGraphFallback: TheGraphFallbackSchema,\n ensIndexerPublicConfig: makeENSIndexerPublicConfigSchema(`${label}.ensIndexerPublicConfig`),\n });\n}\n","/**\n * All zod schemas we define must remain internal implementation details.\n * We want the freedom to move away from zod in the future without impacting\n * any users of the ensnode-sdk package.\n *\n * The only way to share Zod schemas is to re-export them from\n * `./src/internal.ts` file.\n */\nimport { z } from \"zod/v4\";\n\nimport { uniq } from \"../../shared\";\nimport {\n makeChainIdSchema,\n makeENSNamespaceIdSchema,\n makeNonNegativeIntegerSchema,\n makePositiveIntegerSchema,\n} from \"../../shared/zod-schemas\";\nimport type { ZodCheckFnInput } from \"../../shared/zod-types\";\nimport { isSubgraphCompatible } from \"./is-subgraph-compatible\";\nimport type { ENSIndexerPublicConfig } from \"./types\";\nimport { PluginName } from \"./types\";\nimport { invariant_ensDbVersionIsSameAsEnsIndexerVersion } from \"./validations\";\n\n/**\n * Makes a schema for parsing {@link IndexedChainIds}.\n */\nexport const makeIndexedChainIdsSchema = (valueLabel: string = \"Indexed Chain IDs\") =>\n z\n .array(makeChainIdSchema(valueLabel), {\n error: `${valueLabel} must be an array.`,\n })\n .min(1, { error: `${valueLabel} list must include at least one element.` })\n .transform((v) => new Set(v));\n\n/**\n * Makes a schema for parsing a list of strings that (for future-proofing)\n * may or may not be current {@link PluginName} values.\n *\n * The list is guaranteed to include at least one string and no duplicates.\n */\nexport const makePluginsListSchema = (valueLabel: string = \"Plugins\") =>\n z\n .array(z.string(), {\n error: `${valueLabel} must be a list of strings.`,\n })\n .min(1, {\n error: `${valueLabel} must be a list of strings with at least one string value`,\n })\n .refine((arr) => arr.length === uniq(arr).length, {\n error: `${valueLabel} cannot contain duplicate values.`,\n });\n\n/**\n * Makes a schema for parsing a name for a database schema.\n *\n * The name is guaranteed to be a non-empty string.\n */\nexport const makeDatabaseSchemaNameSchema = (valueLabel: string = \"Database schema name\") =>\n z\n .string({ error: `${valueLabel} must be a string` })\n .trim()\n .nonempty({\n error: `${valueLabel} is required and must be a non-empty string.`,\n });\n\n/**\n * Makes a schema for parsing a label set ID.\n *\n * The label set ID is guaranteed to be a string between 1-50 characters\n * containing only lowercase letters (a-z) and hyphens (-).\n *\n * @param valueLabel - The label to use in error messages (e.g., \"Label set ID\", \"LABEL_SET_ID\")\n */\nexport const makeLabelSetIdSchema = (valueLabel: string) => {\n return z\n .string({ error: `${valueLabel} must be a string` })\n .min(1, { error: `${valueLabel} must be 1-50 characters long` })\n .max(50, { error: `${valueLabel} must be 1-50 characters long` })\n .regex(/^[a-z-]+$/, {\n error: `${valueLabel} can only contain lowercase letters (a-z) and hyphens (-)`,\n });\n};\n\n/**\n * Makes a schema for parsing a label set version.\n *\n * The label set version is guaranteed to be a non-negative integer.\n *\n * @param valueLabel - The label to use in error messages (e.g., \"Label set version\", \"LABEL_SET_VERSION\")\n\n */\nexport const makeLabelSetVersionSchema = (valueLabel: string) => {\n return z.coerce\n .number({ error: `${valueLabel} must be an integer.` })\n .pipe(makeNonNegativeIntegerSchema(valueLabel));\n};\n\n/**\n * Makes a schema for parsing a label set where both label set ID and label set version are required.\n *\n * @param valueLabel - The label to use in error messages (e.g., \"Label set\", \"LABEL_SET\")\n */\nexport const makeFullyPinnedLabelSetSchema = (valueLabel: string = \"Label set\") => {\n let valueLabelLabelSetId = valueLabel;\n let valueLabelLabelSetVersion = valueLabel;\n if (valueLabel === \"LABEL_SET\") {\n valueLabelLabelSetId = \"LABEL_SET_ID\";\n valueLabelLabelSetVersion = \"LABEL_SET_VERSION\";\n } else {\n valueLabelLabelSetId = `${valueLabel}.labelSetId`;\n valueLabelLabelSetVersion = `${valueLabel}.labelSetVersion`;\n }\n return z.object({\n labelSetId: makeLabelSetIdSchema(valueLabelLabelSetId),\n labelSetVersion: makeLabelSetVersionSchema(valueLabelLabelSetVersion),\n });\n};\n\nconst makeNonEmptyStringSchema = (valueLabel: string = \"Value\") =>\n z.string().nonempty({ error: `${valueLabel} must be a non-empty string.` });\n\nexport const makeENSIndexerVersionInfoSchema = (valueLabel: string = \"Value\") =>\n z\n .strictObject(\n {\n nodejs: makeNonEmptyStringSchema(),\n ponder: makeNonEmptyStringSchema(),\n ensDb: makeNonEmptyStringSchema(),\n ensIndexer: makeNonEmptyStringSchema(),\n ensNormalize: makeNonEmptyStringSchema(),\n ensRainbow: makeNonEmptyStringSchema(),\n ensRainbowSchema: makePositiveIntegerSchema(),\n },\n {\n error: `${valueLabel} must be a valid ENSIndexerVersionInfo object.`,\n },\n )\n .check(invariant_ensDbVersionIsSameAsEnsIndexerVersion);\n\n// Invariant: If config.isSubgraphCompatible, the config must pass isSubgraphCompatible(config)\nexport function invariant_isSubgraphCompatibleRequirements(\n ctx: ZodCheckFnInput<\n Pick<ENSIndexerPublicConfig, \"namespace\" | \"plugins\" | \"isSubgraphCompatible\" | \"labelSet\">\n >,\n) {\n const { value: config } = ctx;\n\n if (config.isSubgraphCompatible && !isSubgraphCompatible(config)) {\n ctx.issues.push({\n code: \"custom\",\n input: config,\n message: `'isSubgraphCompatible' requires only the '${PluginName.Subgraph}' plugin to be active and labelSet must be {labelSetId: \"subgraph\", labelSetVersion: 0}`,\n });\n }\n}\n\n/**\n * ENSIndexer Public Config Schema\n *\n * Makes a Zod schema definition for validating all important settings used\n * during runtime of the ENSIndexer instance.\n */\nexport const makeENSIndexerPublicConfigSchema = (valueLabel: string = \"ENSIndexerPublicConfig\") =>\n z\n .object({\n labelSet: makeFullyPinnedLabelSetSchema(`${valueLabel}.labelSet`),\n indexedChainIds: makeIndexedChainIdsSchema(`${valueLabel}.indexedChainIds`),\n isSubgraphCompatible: z.boolean({ error: `${valueLabel}.isSubgraphCompatible` }),\n namespace: makeENSNamespaceIdSchema(`${valueLabel}.namespace`),\n plugins: makePluginsListSchema(`${valueLabel}.plugins`),\n databaseSchemaName: makeDatabaseSchemaNameSchema(`${valueLabel}.databaseSchemaName`),\n versionInfo: makeENSIndexerVersionInfoSchema(`${valueLabel}.versionInfo`),\n })\n /**\n * Validations\n *\n * All required data validations must be performed below.\n */\n .check(invariant_isSubgraphCompatibleRequirements);\n","import { isAddressEqual } from \"viem\";\n\nimport type { AccountId } from \"./types\";\n\n/**\n * Determines where the provided AccountId values represent the same address on the same chain.\n */\nexport const accountIdEqual = (a: AccountId, b: AccountId): boolean => {\n return a.chainId === b.chainId && isAddressEqual(a.address, b.address);\n};\n","import type { Address } from \"viem\";\n\n/**\n * Converts an EVM address to its lowercase representation.\n *\n * @param address - EVM address to convert.\n * @returns The lowercase representation of the EVM address.\n */\nexport function asLowerCaseAddress(address: Address): Address {\n return address.toLowerCase() as Address;\n}\n","import type { Cache } from \"./cache\";\n\n/**\n * Cache that maps from string -> ValueType with a LRU (least recently used) eviction policy.\n *\n * `get` and `set` are O(1) operations.\n *\n * @link https://en.wikipedia.org/wiki/Cache_replacement_policies#LRU\n */\nexport class LruCache<KeyType extends string, ValueType> implements Cache<KeyType, ValueType> {\n private readonly _cache = new Map<string, ValueType>();\n private readonly _capacity: number;\n\n /**\n * Create a new LRU cache with the given capacity.\n *\n * @param capacity The maximum number of items in the cache. If set to 0, the cache is effectively disabled.\n * @throws Error if capacity is not a non-negative integer.\n */\n public constructor(capacity: number) {\n if (!Number.isInteger(capacity)) {\n throw new Error(\n `LruCache requires capacity to be an integer but a capacity of ${capacity} was requested.`,\n );\n }\n\n if (capacity < 0) {\n throw new Error(\n `LruCache requires a non-negative capacity but a capacity of ${capacity} was requested.`,\n );\n }\n\n this._capacity = capacity;\n }\n\n public set(key: string, value: ValueType) {\n this._cache.set(key, value);\n\n if (this._cache.size > this._capacity) {\n // oldestKey is guaranteed to be defined\n const oldestKey = this._cache.keys().next().value as string;\n this._cache.delete(oldestKey);\n }\n }\n\n public get(key: string) {\n const value = this._cache.get(key);\n if (value) {\n // The key is already in the cache, move it to the end (most recent)\n this._cache.delete(key);\n this._cache.set(key, value);\n }\n return value;\n }\n\n public clear() {\n this._cache.clear();\n }\n\n public get size() {\n return this._cache.size;\n }\n\n public get capacity() {\n return this._capacity;\n }\n}\n","import { secondsToMilliseconds } from \"date-fns\";\nimport { getUnixTime } from \"date-fns/getUnixTime\";\n\nimport { durationBetween } from \"../datetime\";\nimport type { Duration, UnixTimestamp } from \"../types\";\n\n/**\n * Data structure for a single cached result.\n */\ninterface CachedResult<ValueType> {\n /**\n * The cached result of the fn, either its ValueType or Error.\n */\n result: ValueType | Error;\n\n /**\n * Unix timestamp indicating when the cached `result` was generated.\n */\n updatedAt: UnixTimestamp;\n}\n\nexport interface SWRCacheOptions<ValueType> {\n /**\n * The async function generating a value of `ValueType` to wrap with SWR caching. It may throw an\n * Error type.\n */\n fn: () => Promise<ValueType>;\n\n /**\n * Time-to-live duration of a cached result in seconds. After this duration:\n * - the currently cached result is considered \"stale\" but is still retained in the cache\n * until successfully replaced.\n * - Each time the cache is read, if the cached result is \"stale\" and no background\n * revalidation attempt is already in progress, a new background revalidation\n * attempt will be made.\n */\n ttl: Duration;\n\n /**\n * Optional time-to-proactively-revalidate duration in seconds. After a cached result is\n * initialized, and this duration has passed, attempts to asynchronously revalidate\n * the cached result will be proactively made in the background on this interval.\n */\n proactiveRevalidationInterval?: Duration;\n\n /**\n * Optional proactive initialization. Defaults to `false`.\n *\n * If `true`: The SWR cache will proactively initialize itself.\n * If `false`: The SWR cache will lazily wait to initialize itself until the first read.\n */\n proactivelyInitialize?: boolean;\n}\n\n/**\n * Stale-While-Revalidate (SWR) cache for async functions.\n *\n * This caching strategy serves cached data immediately (even if stale) while\n * asynchronously revalidating the cache in the background. This provides:\n * - Sub-millisecond response times (after first fetch)\n * - Always available data (serves stale data during revalidation)\n * - Automatic background updates via configurable intervals\n *\n * @example\n * ```typescript\n * const cache = new SWRCache({\n * fn: async () => fetch('/api/data').then(r => r.json()),\n * ttl: 60, // 1 minute TTL\n * proactiveRevalidationInterval: 300 // proactively revalidate every 5 minutes\n * });\n *\n * // Returns cached data or waits for initial fetch\n * const data = await cache.read();\n *\n * if (data instanceof Error) { ... }\n * ```\n *\n * @link https://web.dev/stale-while-revalidate/\n * @link https://datatracker.ietf.org/doc/html/rfc5861\n */\nexport class SWRCache<ValueType> {\n private cache: CachedResult<ValueType> | null = null;\n private inProgressRevalidate: Promise<void> | null = null;\n private backgroundInterval: ReturnType<typeof setInterval> | null = null;\n\n constructor(private readonly options: SWRCacheOptions<ValueType>) {\n if (options.proactiveRevalidationInterval) {\n this.backgroundInterval = setInterval(\n () => this.revalidate(),\n secondsToMilliseconds(options.proactiveRevalidationInterval),\n );\n }\n\n if (options.proactivelyInitialize) this.revalidate();\n }\n\n private async revalidate() {\n // ensure that there is exactly one in progress revalidation promise\n if (!this.inProgressRevalidate) {\n this.inProgressRevalidate = this.options\n .fn()\n .then((result) => {\n // on success, always update the cache with the latest revalidation\n this.cache = {\n result,\n updatedAt: getUnixTime(new Date()),\n };\n })\n .catch((error) => {\n // on error, only update the cache if this is the first revalidation\n if (!this.cache) {\n this.cache = {\n // ensure thrown value is always an Error instance\n result: error instanceof Error ? error : new Error(String(error)),\n updatedAt: getUnixTime(new Date()),\n };\n }\n })\n .finally(() => {\n this.inProgressRevalidate = null;\n });\n }\n\n // provide it to the caller so that it may be awaited\n return this.inProgressRevalidate;\n }\n\n /**\n * Read the most recently cached result from the `SWRCache`.\n *\n * @returns a `ValueType` that was most recently successfully returned by `fn` or `Error` if `fn`\n * has never successfully returned.\n */\n public async read(): Promise<ValueType | Error> {\n // if no cache, populate the cache by awaiting revalidation\n if (!this.cache) await this.revalidate();\n\n // after any revalidation, this.cache is always set\n // NOTE: not documenting read() as throwable because this is just for typechecking\n if (!this.cache) throw new Error(\"never\");\n\n // if ttl expired, revalidate in background\n if (durationBetween(this.cache.updatedAt, getUnixTime(new Date())) > this.options.ttl) {\n this.revalidate();\n }\n\n return this.cache.result;\n }\n\n /**\n * Destroys the background revalidation interval, if exists.\n */\n public destroy(): void {\n if (this.backgroundInterval) {\n clearInterval(this.backgroundInterval);\n this.backgroundInterval = null;\n }\n }\n}\n","import { prettifyError } from \"zod/v4\";\n\nimport type { ChainIdString, UrlString } from \"./serialized-types\";\nimport type {\n AccountId,\n BlockNumber,\n BlockRef,\n Blockrange,\n ChainId,\n Datetime,\n Duration,\n} from \"./types\";\nimport {\n makeAccountIdStringSchema,\n makeBlockNumberSchema,\n makeBlockRefSchema,\n makeBlockrangeSchema,\n makeChainIdStringSchema,\n makeDatetimeSchema,\n makeDurationSchema,\n makeUnixTimestampSchema,\n makeUrlSchema,\n} from \"./zod-schemas\";\n\nexport function deserializeChainId(maybeChainId: ChainIdString, valueLabel?: string): ChainId {\n const schema = makeChainIdStringSchema(valueLabel);\n const parsed = schema.safeParse(maybeChainId);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize ChainId:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n\nexport function deserializeDatetime(maybeDatetime: string, valueLabel?: string): Datetime {\n const schema = makeDatetimeSchema(valueLabel);\n const parsed = schema.safeParse(maybeDatetime);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize Datetime:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n\nexport function deserializeUnixTimestamp(maybeTimestamp: number, valueLabel?: string) {\n const schema = makeUnixTimestampSchema(valueLabel);\n const parsed = schema.safeParse(maybeTimestamp);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize Unix Timestamp:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n\nexport function deserializeUrl(maybeUrl: UrlString, valueLabel?: string): URL {\n const schema = makeUrlSchema(valueLabel);\n const parsed = schema.safeParse(maybeUrl);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize URL:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n\nexport function deserializeBlockNumber(maybeBlockNumber: number, valueLabel?: string): BlockNumber {\n const schema = makeBlockNumberSchema(valueLabel);\n const parsed = schema.safeParse(maybeBlockNumber);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize BlockNumber:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n\nexport function deserializeBlockrange(maybeBlockrange: Partial<Blockrange>, valueLabel?: string) {\n const schema = makeBlockrangeSchema(valueLabel);\n const parsed = schema.safeParse(maybeBlockrange);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize Blockrange:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n\nexport function deserializeBlockRef(\n maybeBlockRef: Partial<BlockRef>,\n valueLabel?: string,\n): BlockRef {\n const schema = makeBlockRefSchema(valueLabel);\n const parsed = schema.safeParse(maybeBlockRef);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize BlockRef:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n\nexport function deserializeDuration(maybeDuration: unknown, valueLabel?: string): Duration {\n const schema = makeDurationSchema(valueLabel);\n const parsed = schema.safeParse(maybeDuration);\n\n if (parsed.error) {\n throw new RangeError(`Cannot deserialize Duration:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n\nexport function parseAccountId(maybeAccountId: unknown, valueLabel?: string): AccountId {\n const schema = makeAccountIdStringSchema(valueLabel);\n const parsed = schema.safeParse(maybeAccountId);\n\n if (parsed.error) {\n throw new RangeError(`Cannot deserialize AccountId:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n","import type { CoinType } from \"@ensdomains/address-encoder\";\nimport { AccountId as CaipAccountId } from \"caip\";\nimport { type Address, type Hex, isAddress, isHex, size } from \"viem\";\n/**\n * All zod schemas we define must remain internal implementation details.\n * We want the freedom to move away from zod in the future without impacting\n * any users of the ensnode-sdk package.\n *\n * The only way to share Zod schemas is to re-export them from\n * `./src/internal.ts` file.\n */\nimport { z } from \"zod/v4\";\n\nimport { ENSNamespaceIds, type InterpretedName, Node } from \"../ens\";\nimport { asLowerCaseAddress } from \"./address\";\nimport { type CurrencyId, CurrencyIds, Price, type PriceEth } from \"./currencies\";\nimport { reinterpretName } from \"./interpretation/reinterpretation\";\nimport type { AccountIdString } from \"./serialized-types\";\nimport type {\n AccountId,\n BlockRef,\n ChainId,\n Datetime,\n DefaultableChainId,\n Duration,\n UnixTimestamp,\n} from \"./types\";\n\n/**\n * Parses a string value as a boolean.\n */\nexport const makeBooleanStringSchema = (valueLabel: string = \"Value\") =>\n z\n .string()\n .pipe(\n z.enum([\"true\", \"false\"], {\n error: `${valueLabel} must be 'true' or 'false'.`,\n }),\n )\n .transform((val) => val === \"true\");\n\n/**\n * Parses a numeric value as a finite non-negative number.\n */\nexport const makeFiniteNonNegativeNumberSchema = (valueLabel: string = \"Value\") =>\n z\n .number({\n // NOTE: Zod's implementation of `number` automatically rejects NaN and Infinity values.\n // and therefore the finite check is implicit.\n error: `${valueLabel} must be a finite number.`,\n })\n .nonnegative({\n error: `${valueLabel} must be a non-negative number (>=0).`,\n });\n\n/**\n * Parses a numeric value as an integer.\n */\nexport const makeIntegerSchema = (valueLabel: string = \"Value\") =>\n z.int({\n error: `${valueLabel} must be an integer.`,\n });\n\n/**\n * Parses a numeric value as a positive integer.\n */\nexport const makePositiveIntegerSchema = (valueLabel: string = \"Value\") =>\n makeIntegerSchema(valueLabel).positive({\n error: `${valueLabel} must be a positive integer (>0).`,\n });\n\n/**\n * Parses a numeric value as a non-negative integer.\n */\nexport const makeNonNegativeIntegerSchema = (valueLabel: string = \"Value\") =>\n makeIntegerSchema(valueLabel).nonnegative({\n error: `${valueLabel} must be a non-negative integer (>=0).`,\n });\n\n/**\n * Parses a numeric value as {@link Duration}\n */\nexport const makeDurationSchema = (valueLabel: string = \"Value\") =>\n z.coerce\n .number({\n error: `${valueLabel} must be a number.`,\n })\n .pipe(makeNonNegativeIntegerSchema(valueLabel));\n\n/**\n * Parses Chain ID\n *\n * {@link ChainId}\n */\nexport const makeChainIdSchema = (valueLabel: string = \"Chain ID\") =>\n makePositiveIntegerSchema(valueLabel).transform((val) => val as ChainId);\n\n/**\n * Parses a serialized representation of {@link ChainId}.\n */\nexport const makeChainIdStringSchema = (valueLabel: string = \"Chain ID String\") =>\n z\n .string({ error: `${valueLabel} must be a string representing a chain ID.` })\n .pipe(z.coerce.number({ error: `${valueLabel} must represent a positive integer (>0).` }))\n .pipe(makeChainIdSchema(`The numeric value represented by ${valueLabel}`));\n\n/**\n * Parses Defaultable Chain ID\n *\n * {@link DefaultableChainId}\n */\nexport const makeDefaultableChainIdSchema = (valueLabel: string = \"Defaultable Chain ID\") =>\n makeNonNegativeIntegerSchema(valueLabel).transform((val) => val as DefaultableChainId);\n\n/**\n * Parses a serialized representation of {@link DefaultableChainId}.\n */\nexport const makeDefaultableChainIdStringSchema = (\n valueLabel: string = \"Defaultable Chain ID String\",\n) =>\n z\n .string({ error: `${valueLabel} must be a string representing a chain ID.` })\n .pipe(z.coerce.number({ error: `${valueLabel} must represent a non-negative integer (>=0).` }))\n .pipe(makeDefaultableChainIdSchema(`The numeric value represented by ${valueLabel}`));\n\n/**\n * Parses {@link CoinType}.\n */\nexport const makeCoinTypeSchema = (valueLabel: string = \"Coin Type\") =>\n z\n .number({ error: `${valueLabel} must be a number.` })\n .int({ error: `${valueLabel} must be an integer.` })\n .nonnegative({ error: `${valueLabel} must be a non-negative integer (>=0).` })\n .transform((val) => val as CoinType);\n\n/**\n * Parses a serialized representation of {@link CoinType}.\n */\nexport const makeCoinTypeStringSchema = (valueLabel: string = \"Coin Type String\") =>\n z\n .string({ error: `${valueLabel} must be a string representing a coin type.` })\n .pipe(z.coerce.number({ error: `${valueLabel} must represent a non-negative integer (>=0).` }))\n .pipe(makeCoinTypeSchema(`The numeric value represented by ${valueLabel}`));\n\n/**\n * Parses a serialized representation of an EVM address into a lowercase Address.\n */\nexport const makeLowercaseAddressSchema = (valueLabel: string = \"EVM address\") =>\n z\n .string()\n .check((ctx) => {\n if (!isAddress(ctx.value)) {\n ctx.issues.push({\n code: \"custom\",\n message: `${valueLabel} must be a valid EVM address`,\n input: ctx.value,\n });\n }\n })\n .transform((val) => asLowerCaseAddress(val as Address));\n\n/**\n * Parses an ISO 8601 string representations of {@link Datetime}\n */\nexport const makeDatetimeSchema = (valueLabel: string = \"Datetime string\") =>\n z.iso\n .datetime({ error: `${valueLabel} must be a string in ISO 8601 format.` })\n .transform((v) => new Date(v));\n\n/**\n * Parses value as {@link UnixTimestamp}.\n */\nexport const makeUnixTimestampSchema = (valueLabel: string = \"Timestamp\") =>\n makeIntegerSchema(valueLabel);\n\n/**\n * Parses a string representations of {@link URL}\n */\nexport const makeUrlSchema = (valueLabel: string = \"Value\") =>\n z\n .url({\n error: `${valueLabel} must be a valid URL string (e.g., http://localhost:8080 or https://example.com).`,\n abort: true,\n })\n .transform((v) => new URL(v));\n\n/**\n * Parses a serialized representation of a comma separated list.\n */\nexport const makeCommaSeparatedList = (valueLabel: string = \"Value\") =>\n z\n .string({ error: `${valueLabel} must be a comma separated list.` })\n .transform((val) => val.split(\",\").filter(Boolean))\n .refine((val) => val.length > 0, {\n error: `${valueLabel} must be a comma separated list with at least one value.`,\n });\n\n/**\n * Parses a numeric value as a block number.\n */\nexport const makeBlockNumberSchema = (valueLabel: string = \"Block number\") =>\n makeNonNegativeIntegerSchema(valueLabel);\n\n/**\n * Parses an object value as the {@link Blockrange} object.\n */\nexport const makeBlockrangeSchema = (valueLabel: string = \"Value\") =>\n z\n .strictObject(\n {\n startBlock: makeBlockNumberSchema(`${valueLabel}.startBlock`).optional(),\n endBlock: makeBlockNumberSchema(`${valueLabel}.endBlock`).optional(),\n },\n {\n error: `${valueLabel} must be a valid Blockrange object.`,\n },\n )\n .refine(\n (v) => {\n if (v.startBlock && v.endBlock) {\n return v.startBlock <= v.endBlock;\n }\n\n return true;\n },\n { error: `${valueLabel}: startBlock must be before or equal to endBlock` },\n );\n\n/**\n * Parses an object value as the {@link BlockRef} object.\n */\nexport const makeBlockRefSchema = (valueLabel: string = \"Value\") =>\n z.strictObject(\n {\n timestamp: makeUnixTimestampSchema(`${valueLabel}.timestamp`),\n number: makeBlockNumberSchema(`${valueLabel}.number`),\n },\n {\n error: `${valueLabel} must be a valid BlockRef object.`,\n },\n );\n\n/**\n * Parses a string value as ENSNamespaceId.\n */\nexport const makeENSNamespaceIdSchema = (valueLabel: string = \"ENSNamespaceId\") =>\n z.enum(ENSNamespaceIds, {\n error() {\n return `Invalid ${valueLabel}. Supported ENS namespace IDs are: ${Object.keys(ENSNamespaceIds).join(\", \")}`;\n },\n });\n\nconst makePriceAmountSchema = (valueLabel: string = \"Amount\") =>\n z.coerce\n .bigint({\n error: `${valueLabel} must represent a bigint.`,\n })\n .nonnegative({\n error: `${valueLabel} must not be negative.`,\n });\n\nexport const makePriceCurrencySchema = (\n currency: CurrencyId,\n valueLabel: string = \"Price Currency\",\n) =>\n z.strictObject({\n amount: makePriceAmountSchema(`${valueLabel} amount`),\n\n currency: z.literal(currency, {\n error: `${valueLabel} currency must be set to '${currency}'.`,\n }),\n });\n\n/**\n * Schema for {@link Price} type.\n */\nexport const makePriceSchema = (valueLabel: string = \"Price\") =>\n z.discriminatedUnion(\n \"currency\",\n [\n makePriceCurrencySchema(CurrencyIds.ETH, valueLabel),\n makePriceCurrencySchema(CurrencyIds.USDC, valueLabel),\n makePriceCurrencySchema(CurrencyIds.DAI, valueLabel),\n ],\n { error: `${valueLabel} currency must be one of ${Object.values(CurrencyIds).join(\", \")}` },\n );\n\n/**\n * Schema for {@link PriceEth} type.\n */\nexport const makePriceEthSchema = (valueLabel: string = \"Price ETH\") =>\n makePriceCurrencySchema(CurrencyIds.ETH, valueLabel).transform((v) => v as PriceEth);\n\n/**\n * Schema for {@link AccountId} type.\n */\nexport const makeAccountIdSchema = (valueLabel: string = \"AccountId\") =>\n z.strictObject({\n chainId: makeChainIdSchema(`${valueLabel} chain ID`),\n address: makeLowercaseAddressSchema(`${valueLabel} address`),\n });\n\n/**\n * Schema for {@link AccountIdString} type.\n */\nexport const makeAccountIdStringSchema = (valueLabel: string = \"Account ID String\") =>\n z.coerce\n .string()\n .transform((v) => {\n const result = new CaipAccountId(v);\n\n return {\n chainId: Number(result.chainId.reference),\n address: result.address,\n };\n })\n .pipe(makeAccountIdSchema(valueLabel));\n\n/**\n * Make a schema for {@link Hex} representation of bytes array.\n *\n * @param {number} options.bytesCount expected count of bytes to be hex-encoded\n */\nexport const makeHexStringSchema = (\n options: { bytesCount: number },\n valueLabel: string = \"String representation of bytes array\",\n) =>\n z\n .string()\n .check(function invariant_isHexEncoded(ctx) {\n if (!isHex(ctx.value)) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `${valueLabel} must be a hexadecimal value which starts with '0x'.`,\n });\n }\n })\n .transform((v) => v as Hex)\n .check(function invariant_encodesRequiredBytesCount(ctx) {\n const expectedBytesCount = options.bytesCount;\n const actualBytesCount = size(ctx.value);\n\n if (actualBytesCount !== expectedBytesCount) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `${valueLabel} must represent exactly ${expectedBytesCount} bytes. Currently represented bytes count: ${actualBytesCount}.`,\n });\n }\n });\n\n/**\n * Make schema for {@link Node}.\n */\nexport const makeNodeSchema = (valueLabel: string = \"Node\") =>\n makeHexStringSchema({ bytesCount: 32 }, valueLabel);\n\n/**\n * Make schema for Transaction Hash\n */\nexport const makeTransactionHashSchema = (valueLabel: string = \"Transaction hash\") =>\n makeHexStringSchema({ bytesCount: 32 }, valueLabel);\n\n/**\n * Make schema for {@link ReinterpretedName}.\n */\nexport const makeReinterpretedNameSchema = (valueLabel: string = \"Reinterpreted Name\") =>\n z\n .string()\n .transform((v) => v as InterpretedName)\n .check((ctx) => {\n try {\n reinterpretName(ctx.value);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Unknown error\";\n\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `${valueLabel} cannot be reinterpreted: ${errorMessage}`,\n });\n }\n })\n .transform(reinterpretName);\n","export { getENSRootChainId } from \"@ensnode/datasources\";\n\nexport * from \"./coin-type\";\nexport * from \"./constants\";\nexport * from \"./dns-encoded-name\";\nexport * from \"./encode-labelhash\";\nexport * from \"./fuses\";\nexport * from \"./is-normalized\";\nexport * from \"./labelhash\";\nexport * from \"./names\";\nexport * from \"./parse-reverse-name\";\nexport * from \"./reverse-name\";\nexport * from \"./subname-helpers\";\nexport * from \"./types\";\n","import type { CoinType, EvmCoinType } from \"@ensdomains/address-encoder\";\nimport {\n coinTypeToEvmChainId as _coinTypeToEvmChainId,\n evmChainIdToCoinType as _evmChainIdToCoinType,\n} from \"@ensdomains/address-encoder/utils\";\n\nimport type { ChainId } from \"../shared\";\n\n// re-export CoinType and EvmCoinType from @ensdomains/address-encoder\n// so consumers don't need it as a dependency\nexport type { CoinType, EvmCoinType } from \"@ensdomains/address-encoder\";\n\n/**\n * The ETH coinType.\n *\n * @see https://docs.ens.domains/ensip/9\n */\nexport const ETH_COIN_TYPE: CoinType = 60;\n\n/**\n * The 'default' chainId corresponding to the below {@link DEFAULT_EVM_COIN_TYPE} in the context of\n * ENSIP-19.\n *\n * @see https://docs.ens.domains/ensip/19\n */\nexport const DEFAULT_EVM_CHAIN_ID = 0;\n\n/**\n * ENSIP-19 EVM CoinType representing the 'default' coinType for EVM chains in ENS.\n *\n * @see https://docs.ens.domains/ensip/19/#reverse-resolution\n */\nexport const DEFAULT_EVM_COIN_TYPE = 0x8000_0000 as EvmCoinType;\n\n/**\n * Converts a CoinType to an EVM Chain Id.\n *\n * NOTE: for whatever reason @ensdomains/address-encoder#coinTypeToEvmChainId doesn't handle the\n * mainnet case so we implement that here\n *\n * @see https://docs.ens.domains/ensip/11/\n */\nexport const coinTypeToEvmChainId = (coinType: CoinType): ChainId => {\n if (coinType === ETH_COIN_TYPE) return 1;\n return _coinTypeToEvmChainId(coinType);\n};\n\n/**\n * Converts an EVM Chain Id to a CoinType.\n *\n * NOTE: for whatever reason @ensdomains/address-encoder#evmChainIdToCoinType doesn't handle the\n * mainnet case so we implement that here\n */\nexport const evmChainIdToCoinType = (chainId: ChainId): CoinType => {\n if (chainId === 1) return ETH_COIN_TYPE;\n return _evmChainIdToCoinType(chainId);\n};\n\n/**\n * Converts a bigint value representing a CoinType into a valid CoinType.\n *\n * This is useful when onchain events emit coinTypes as bigint but we want to constrain them to\n * the CoinType type.\n *\n * @throws if `value` is too large to fit in Number.MAX_SAFE_INTEGER\n */\nexport const bigintToCoinType = (value: bigint): CoinType => {\n if (value > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new Error(`'${value}' cannot represent as CoinType, it is too large.`);\n }\n\n return Number(value) as CoinType;\n};\n","import { namehash, zeroHash } from \"viem\";\n\nimport type { Node } from \"./types\";\n\nexport const ROOT_NODE: Node = namehash(\"\");\nexport const ETH_NODE: Node = namehash(\"eth\");\nexport const BASENAMES_NODE: Node = namehash(\"base.eth\");\nexport const LINEANAMES_NODE: Node = namehash(\"linea.eth\");\nexport const ADDR_REVERSE_NODE: Node = namehash(\"addr.reverse\");\n\n/**\n * NODE_ANY is a placeholder Node used in the context of DedicatedResolvers — IResolver events are\n * emitted with NODE_ANY as the `node` for which the records are issued, but the DedicatedResolver\n * returns those records regardless of the name used for record resolution.\n */\nexport const NODE_ANY: Node = zeroHash;\n\n/**\n * ROOT_RESOURCE represents the 'root' resource in an EnhancedAccessControl contract.\n */\nexport const ROOT_RESOURCE = 0n;\n","import { bytesToString, hexToBytes } from \"viem\";\n\nimport type { DNSEncodedLiteralName, DNSEncodedName, LiteralLabel } from \"./types\";\n\n/**\n * Decodes a DNS-Encoded name consisting of Literal Labels into an ordered list of Literal Labels.\n *\n * For discussion on DNS-Encoding, see the {@link DNSEncodedName} and {@link DNSEncodedLiteralName} types.\n *\n * Due to the constraints of DNS-Encoding, there is an additional guarantee that each Literal Label\n * in the resulting list is guaranteed to have a maximum byte length of 255.\n *\n * @param packet a hex string that encodes a DNSEncodedLiteralName\n * @returns A list of the LiteralLabels contained in packet\n * @throws If the packet is malformed\n * @dev This is just `decodeDNSEncodedName` with semantic input/output\n */\nexport function decodeDNSEncodedLiteralName(packet: DNSEncodedLiteralName): LiteralLabel[] {\n return decodeDNSEncodedName(packet) as LiteralLabel[];\n}\n\n/**\n * Decodes a DNS-Encoded Name into an ordered list of string segments.\n *\n * For discussion on DNS-Encoding, see the {@link DNSEncodedName} type.\n *\n * Due to the constraints of DNS-Encoding, there is an additional guarantee that each segment\n * in the resulting list is guaranteed to have a maximum byte length of 255.\n *\n * @param packet a hex string that encodes a DNSEncodedName\n * @returns A UTF-8 string array of the segments contained in packet\n * @throws If the packet is malformed\n * @dev This is the generic implementation of DNS-Encoded Name Decoding\n */\nexport function decodeDNSEncodedName(packet: DNSEncodedName): string[] {\n const segments: string[] = [];\n\n const bytes = hexToBytes(packet);\n if (bytes.length === 0) throw new Error(`Packet is empty.`);\n\n let offset = 0;\n while (offset < bytes.length) {\n // NOTE: `len` is always [0, 255] because ByteArray is array of unsigned 8-bit integers. Because\n // the length of the next label is limited to one unsigned byte, this is why labels with bytelength\n // greater than 255 cannot be DNS Encoded.\n const len = bytes[offset];\n\n // Invariant: the while conditional enforces that there's always _something_ in bytes at offset\n if (len === undefined) {\n throw new Error(`Invariant: bytes[offset] is undefined after offset < bytes.length check.`);\n }\n\n // Invariant: `len` is always [0, 255]. technically not necessary but good for clarity\n if (len < 0 || len > 255) {\n throw new Error(\n `Invariant: this should be literally impossible, but an unsigned byte was less than zero or greater than 255. The value in question is ${len}`,\n );\n }\n\n // stop condition\n if (len === 0) break;\n\n // decode to UTF-8 string\n const segment = bytesToString(bytes.subarray(offset + 1, offset + len + 1));\n\n // add to list of segments and continue decoding\n segments.push(segment);\n offset += len + 1;\n }\n\n // check for overflow\n if (offset >= bytes.length) throw new Error(`Overflow, offset >= bytes.length`);\n\n // check for junk\n if (offset !== bytes.length - 1) throw new Error(`Junk at end of name`);\n\n return segments;\n}\n","import { isHex } from \"viem\";\n\nimport type { LabelHash } from \"./types\";\n\n/**\n * Checks if the input is a {@link LabelHash}.\n *\n * @see https://ensnode.io/docs/reference/terminology#label-processing-and-classification\n */\nexport function isLabelHash(maybeLabelHash: string): maybeLabelHash is LabelHash {\n const expectedLength = maybeLabelHash.length === 66;\n const expectedEncoding = isHex(maybeLabelHash);\n const expectedCasing = maybeLabelHash === maybeLabelHash.toLowerCase();\n\n return expectedLength && expectedEncoding && expectedCasing;\n}\n","import { isLabelHash } from \"./labelhash\";\nimport type { EncodedLabelHash, LabelHash } from \"./types\";\n\n/**\n * Formats a LabelHash as an Encoded LabelHash.\n *\n * @see https://ensnode.io/docs/reference/terminology#encoded-labelhash\n *\n * @param labelHash - A 32-byte lowercase hash string starting with '0x'\n * @returns The encoded label hash in format `[hash_without_0x_prefix]`\n */\nexport const encodeLabelHash = (labelHash: LabelHash): EncodedLabelHash =>\n `[${labelHash.slice(2)}]`;\n\n/**\n * Checks if the input value is an {@link EncodedLabelHash}.\n */\nexport function isEncodedLabelHash(\n maybeEncodedLabelHash: string,\n): maybeEncodedLabelHash is EncodedLabelHash {\n const expectedFormatting =\n maybeEncodedLabelHash.startsWith(\"[\") && maybeEncodedLabelHash.endsWith(\"]\");\n const includesLabelHash = isLabelHash(`0x${maybeEncodedLabelHash.slice(1, -1)}`);\n\n return expectedFormatting && includesLabelHash;\n}\n","/**\n * The NameWrapper's PARENT_CANNOT_CONTROL fuse.\n */\nconst PARENT_CANNOT_CONTROL = 0x10000;\n\n/**\n * Determines whether `fuses` has set ('burnt') the PARENT_CANNOT_CONTROL fuse.\n */\nexport const isPccFuseSet = (fuses: number) =>\n (fuses & PARENT_CANNOT_CONTROL) === PARENT_CANNOT_CONTROL;\n","import { normalize } from \"viem/ens\";\n\nimport type { Label, Name, NormalizedName } from \"./types\";\n\n/**\n * Determines whether the Name is normalized.\n *\n * @param name - The Name to check for normalization\n * @returns True if the name is normalized according to ENS normalization rules, false otherwise\n */\nexport function isNormalizedName(name: Name): name is NormalizedName {\n try {\n return name === normalize(name);\n } catch {\n return false;\n }\n}\n\n/**\n * Determines whether the Label is normalized.\n *\n * @param label - The Label to check for normalization\n * @returns True if the label is normalized according to ENS normalization rules, false otherwise\n */\nexport function isNormalizedLabel(label: Label): boolean {\n // empty string is not a normalized label\n if (label === \"\") return false;\n\n // normalized labels do not contain periods\n if (label.includes(\".\")) return false;\n\n try {\n return label === normalize(label);\n } catch {\n return false;\n }\n}\n","import { ens_beautify } from \"@adraffy/ens-normalize\";\n\nimport { isNormalizedLabel } from \"./is-normalized\";\nimport type { Label, Name, NormalizedName } from \"./types\";\n\n/**\n * Name for the ENS Root\n */\nexport const ENS_ROOT: Name = \"\";\n\n/**\n * Constructs a name hierarchy from a given NormalizedName.\n *\n * @example\n * ```\n * getNameHierarchy(\"sub.example.eth\") -> [\"sub.example.eth\", \"example.eth\", \"eth\"]\n * ```\n *\n * @dev by restricting the input type to NormalizedName we guarantee that we can split and join\n * on '.' and receive NormalizedNames as a result\n */\nexport const getNameHierarchy = (name: NormalizedName): NormalizedName[] =>\n name.split(\".\").map((_, i, labels) => labels.slice(i).join(\".\")) as NormalizedName[];\n\n/**\n * Get FQDN of parent for a name.\n */\nexport const getParentNameFQDN = (name: Name): Name => {\n // Invariant: name is not ENS root.\n if (name === ENS_ROOT) {\n throw new Error(\"There is no parent name for ENS Root.\");\n }\n\n const labels = name.split(\".\");\n\n // For TLDs, return ENS_ROOT\n if (labels.length === 1) {\n return ENS_ROOT;\n }\n\n // Strip off the child-most label in the name to get the FQDN of the parent\n return labels.slice(1).join(\".\");\n};\n\n/**\n * Beautifies a name by converting each normalized label in the provided name to\n * its \"beautified\" form. Labels that are not normalized retain their original value.\n *\n * Invariants:\n * - The number of labels in the returned name is the same as the number of labels in the input name.\n * - The order of the labels in the returned name is the same as the order of the labels in the input name.\n * - If a label in the input is normalized, it is returned in its \"beautified\" form.\n * - If a label in the input name is not normalized, it is returned without modification.\n * - Therefore, the result of ens_normalize(beautifyName(name)) is the same as the result of ens_normalize(name).\n *\n * The \"beautified form\" of a normalized label converts special sequences of\n * emojis and other special characters to their \"beautified\" equivalents. All\n * such conversions transform X -> Y where Y is normalizable and normalizes back to X.\n * Ex: '1⃣2⃣' (normalized) to '1️⃣2️⃣' (normalizable but not normalized).\n * Ex: 'ξethereum' (normalized) to 'Ξethereum' (normalizable, but not normalized).\n * Ex: 'abc' (normalized) to 'abc' (also normalized, no conversion).\n * Ex: 'ABC' (normalizable but not normalized) to 'ABC' (no conversion).\n * Ex: 'invalid|label' (not normalizable) to 'invalid|label' (no conversion).\n * Ex: '' (unnormalized as a label) to '' (no conversion).\n *\n * @param name - The name to beautify.\n * @returns The beautified name.\n */\nexport const beautifyName = (name: Name): Name => {\n const beautifiedLabels = name.split(\".\").map((label: Label) => {\n if (isNormalizedLabel(label)) {\n return ens_beautify(label);\n } else {\n return label;\n }\n });\n return beautifiedLabels.join(\".\");\n};\n","import { type Address, hexToBigInt, isAddress } from \"viem\";\n\nimport { asLowerCaseAddress } from \"../shared\";\nimport { bigintToCoinType, type CoinType, DEFAULT_EVM_COIN_TYPE, ETH_COIN_TYPE } from \"./coin-type\";\nimport type { Label, Name } from \"./types\";\n\n/**\n * Matches an ENSIP-19 Reverse Name\n *\n * @see https://github.com/ensdomains/ens-contracts/blob/20e34971fd55f9e3b3cf4a5825d52e1504d36493/contracts/utils/ENSIP19.sol#L70\n */\nconst REVERSE_NAME_REGEX = /^([0-9a-fA-F]+)\\.([0-9a-f]{1,64}|addr|default)\\.reverse$/;\n\n/**\n * Parses an address label (hex sans prefix) into an Address.\n *\n * @param addressLabel - Lowercase hex string derived from a reverse address.\n * @throws if address is invalid\n * @see https://docs.ens.domains/ensip/19#reverse-resolution\n */\nconst parseAddressLabel = (addressLabel: Label): Address => {\n const maybeAddress = `0x${addressLabel}`;\n\n if (!isAddress(maybeAddress)) {\n throw new Error(`Invalid EVM address \"${maybeAddress}\"`);\n }\n\n return asLowerCaseAddress(maybeAddress);\n};\n\n/**\n * Parses a coinType label (hex sans prefix) into an EVMCoinType.\n *\n * @throws if coinType is invalid\n */\nconst parseCoinTypeLabel = (coinTypeLabel: Label): CoinType => {\n if (coinTypeLabel === \"default\") return DEFAULT_EVM_COIN_TYPE;\n if (coinTypeLabel === \"addr\") return ETH_COIN_TYPE;\n\n return bigintToCoinType(hexToBigInt(`0x${coinTypeLabel}`));\n};\n\n/**\n * Parse the address and coinType out of an ENSIP-19 reverse name.\n */\nexport function parseReverseName(name: Name): { address: Address; coinType: CoinType } | null {\n const match = name.match(REVERSE_NAME_REGEX);\n if (!match) return null;\n\n try {\n const [, addressLabel, coinTypeLabel] = match;\n if (!addressLabel) return null;\n if (!coinTypeLabel) return null;\n\n return {\n address: parseAddressLabel(addressLabel),\n coinType: parseCoinTypeLabel(coinTypeLabel),\n };\n } catch {\n // either of the parse methods threw, unable to parse reverse name\n return null;\n }\n}\n","import type { Address } from \"viem\";\n\nimport { type CoinType, DEFAULT_EVM_COIN_TYPE, ETH_COIN_TYPE } from \"./coin-type\";\nimport type { Label, LiteralLabel, Name } from \"./types\";\n\n/**\n * Gets the Label used for the reverse names of subnames as per ENSIP-11 & ENSIP-19.\n *\n * @see https://docs.ens.domains/ensip/19/#reverse-resolution\n */\nexport const addrReverseLabel = (address: Address): LiteralLabel =>\n address.slice(2) as LiteralLabel; // address is guaranteed to be fully lowercase\n\n/**\n * Converts `coinType` to prefix-free hex string.\n *\n * @see https://docs.ens.domains/ensip/19\n */\nexport const coinTypeReverseLabel = (coinType: CoinType): Label => coinType.toString(16);\n\n/**\n * Gets the reverse name for an address according to ENSIP-11 & ENSIP-19.\n *\n * @see https://docs.ens.domains/ensip/11#specification\n * @see https://docs.ens.domains/ensip/19#specification\n *\n * @param address - The address to get the reverse name for\n * @param coinType - The coin type to use for the reverse name\n * @returns The reverse name for the address\n *\n * @example\n * ```ts\n * reverseName(\"0x1234\", BigInt(ETH_COIN_TYPE)) // \"1234.addr.reverse\"\n * reverseName(\"0x1234\", BigInt(0x80000000)) // \"1234.default.reverse\"\n * reverseName(\"0x1234\", BigInt(0x5678)) // \"1234.5678.reverse\"\n * ```\n */\nexport function reverseName(address: Address, coinType: CoinType): Name {\n const label = addrReverseLabel(address);\n\n const middle = (() => {\n switch (coinType) {\n case ETH_COIN_TYPE:\n return \"addr\";\n case DEFAULT_EVM_COIN_TYPE:\n return \"default\";\n default:\n return coinTypeReverseLabel(coinType);\n }\n })();\n\n return `${label}.${middle}.reverse`;\n}\n","import { concat, type Hex, keccak256, toHex } from \"viem\";\n\nimport type { LabelHash, Node } from \"./types\";\n\n/**\n * Implements one step of the namehash algorithm, combining `labelHash` with `node` to produce\n * the `node` of a given subdomain. Note that the order of the arguments is 'reversed' (as compared to\n * the actual concatenation) in order to improve readability (i.e. read as [labelHash].[node]).\n */\nexport const makeSubdomainNode = (labelHash: LabelHash, node: Node): Node =>\n keccak256(concat([node, labelHash]));\n\n/**\n * Encodes a uint256 bigint as hex string sized to 32 bytes.\n * Uses include, in the context of ENS, decoding the uint256-encoded tokenId of NFT-issuing contracts\n * into Node or LabelHash, which is a common behavior in the ENS ecosystem.\n * (see NameWrapper, ETHRegistrarController)\n */\nexport const uint256ToHex32 = (num: bigint): Hex => toHex(num, { size: 32 });\n","import type { Hex } from \"viem\";\n\nimport type { DomainId } from \"../ensv2\";\n\nexport type { ENSNamespaceId } from \"@ensnode/datasources\";\n// re-export ENSNamespaceIds and ENSNamespaceId from @ensnode/datasources\n// so consumers don't need it as a dependency\nexport { ENSNamespaceIds } from \"@ensnode/datasources\";\n\n/**\n * A hash value that uniquely identifies a single ENS name.\n * Result of `namehash` function as specified in ENSIP-1.\n *\n * @example\n * ```\n * namehash(\"vitalik.eth\") === \"0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835\"\n * ```\n * @see https://docs.ens.domains/ensip/1#namehash-algorithm\n * @see https://ensnode.io/docs/reference/terminology#name-node-namehash\n */\nexport type Node = Hex;\n\n/**\n * An ENS Name that may or may not be normalized.\n *\n * @example vitalik.eth\n * @see https://ensnode.io/docs/reference/terminology#name-node-namehash\n * @see https://docs.ens.domains/ensip/15\n */\nexport type Name = string;\n\n/**\n * A Normalized Name is an ENS Name that is guaranteed to be normalized.\n *\n * @example vitalik.eth\n * @see https://ensnode.io/docs/reference/terminology#name-node-namehash\n * @see https://docs.ens.domains/ensip/15\n * @dev nominally typed to enforce usage & enhance codebase clarity\n */\nexport type NormalizedName = Name & { __brand: \"NormalizedName\" };\n\n/**\n * A LabelHash is the result of the labelhash function (which is just keccak256) on a Label.\n *\n * @example\n * ```\n * labelhash('vitalik') === '0xaf2caa1c2ca1d027f1ac823b529d0a67cd144264b2789fa2ea4d63a67c7103cc'\n * ```\n *\n * @see https://docs.ens.domains/terminology#labelhash\n * @see https://ensnode.io/docs/reference/terminology#labels-labelhashes-labelhash-function\n * @see https://ensnode.io/ensrainbow/concepts/glossary#labelhash\n */\nexport type LabelHash = Hex;\n\n/**\n * A LabelHashPath is an ordered list of LabelHashes that uniquely identify an ENS Name.\n * It is ordered in namegraph TRAVERSAL order (i.e. the opposite order of an ENS Name's labels).\n *\n * ex: example.eth's LabelHashPath is\n * [\n * '0x4f5b812789fc606be1b3b16908db13fc7a9adf7ca72641f84d75b47069d3d7f0', // 'eth'\n * '0x6fd43e7cffc31bb581d7421c8698e29aa2bd8e7186a394b85299908b4eb9b175', // 'example'\n * ]\n */\nexport type LabelHashPath = LabelHash[];\n\n/**\n * CanonicalPath is an ordered list of DomainIds describing the canonical path to a Domain.\n * It is ordered in namegraph TRAVERSAL order (i.e. the opposite order of an ENS Name's labels).\n */\nexport type CanonicalPath = DomainId[];\n\n/**\n * A Label is a single part of an ENS Name.\n *\n * @example vitalik\n *\n * @see https://docs.ens.domains/terminology#label\n * @see https://ensnode.io/docs/reference/terminology#labels-labelhashes-labelhash-function\n */\nexport type Label = string;\n\n/**\n * An EncodedLabelHash is a specially formatted (unnormalized) Label formatted\n * as a non-0x prefixed 32-byte hex string enclosed in square brackets.\n *\n * Care should be taken to distinguish Label values formatted as an\n * EncodedLabelHash as either a LiteralLabel or an InterpretedLabel:\n * - If a LiteralLabel is formatted as an EncodedLabelHash it does NOT\n * symbolically represent the encoding of a LabelHash literal.\n * - If an InterpretedLabel is formatted as an EncodedLabelHash it should be\n * interpreted as encoding a LabelHash literal.\n *\n * An InterpretedLabel may be formatted as an EncodedLabelHash if the related\n * LiteralLabel is:\n * - not a normalized label\n * - is an unknown value that could not be healed.\n * - is too long for DNS-Encoding in contexts where DNS-Encoding was required.\n *\n * @example [af2caa1c2ca1d027f1ac823b529d0a67cd144264b2789fa2ea4d63a67c7103cc]\n *\n * @see https://ensnode.io/docs/reference/terminology#encoded-labelhash\n */\nexport type EncodedLabelHash = `[${string}]`;\n\n/**\n * A Literal Label is a Label as it literally appears onchain, without any interpretation\n * or normalization processing. It may be an unnormalized label for reasons including:\n * - being an empty label,\n * - containing '.' characters,\n * - being formatted as an EncodedLabelHash (which are not normalizable). Note that\n * when LiteralLabel are formatted as an EncodedLabelHash they do NOT symbolically\n * represent the encoding of a LabelHash literal, or\n * - containing other unnormalized characters such as null bytes or other characters\n * not suitable for display.\n *\n *\n * @see https://ensnode.io/docs/reference/terminology#literal-label\n * @dev nominally typed to enforce usage & enhance codebase clarity\n */\nexport type LiteralLabel = Label & { __brand: \"LiteralLabel\" };\n\n/**\n * An Interpreted Label is a Label that is either:\n * a) a Normalized Label, or\n * b) an Unnormalizable Label exclusively for the reason that it is formatted\n * as an Encoded LabelHash that should be interpreted as encoding a\n * LabelHash literal, where the encoded LabelHash literal is the `labelhash`\n * of the related LiteralLabel.\n *\n * @see https://ensnode.io/docs/reference/terminology#interpreted-label\n * @dev nominally typed to enforce usage & enhance codebase clarity\n */\nexport type InterpretedLabel = Label & { __brand: \"InterpretedLabel\" };\n\n/**\n * A Literal Name is a Name as it literally appears onchain, composed of 0 or more Literal Labels\n * joined by dots. It may be an unnormalized name for reasons including:\n * - containing empty labels,\n * - containing LiteralLabel values formatted as an EncodedLabelHash (which are\n * not normalizable)). Note that when LiteralLabel values are formatted as an\n * EncodedLabelHash they do NOT symbolically represent the encoding of a\n * LabelHash literal, or\n * - containing other unnormalized characters such as null bytes or other characters\n * not suitable for display.\n *\n * @see https://ensnode.io/docs/reference/terminology#literal-name\n * @dev nominally typed to enforce usage & enhance codebase clarity\n */\nexport type LiteralName = Name & { __brand: \"LiteralName\" };\n\n/**\n * An Interpreted Name is a Name that is entirely composed of 0 or more Interpreted Labels.\n *\n * That is, it is either:\n * a) a Normalized Name, or\n * b) an Unnormalizable Name exclusively for the reason that it contains 1 or\n * more labels formatted as Encoded LabelHashes that should be interpreted\n * as encoding a LabelHash literal, where the encoded LabelHash literal is\n * the `labelhash` of the related LiteralLabel.\n *\n * @see https://ensnode.io/docs/reference/terminology#interpreted-name\n * @dev nominally typed to enforce usage & enhance codebase clarity\n */\nexport type InterpretedName = Name & { __brand: \"InterpretedName\" };\n\n/**\n * A Subgraph Interpreted Label is a Literal Label that is either:\n * a) (if subgraph-indexable): a Literal Label, of unknown normalization status, guaranteed to not\n * contain any of the subgraph-unindexable UTF-8 characters (and therefore guaranteed not to be\n * an Encoded LabelHash), or\n * b) (if subgraph-unindexable): an Encoded LabelHash.\n *\n * @see https://ensnode.io/docs/reference/terminology#subgraph-interpreted-label\n * @dev nominally typed to enforce usage & enhance codebase clarity\n */\nexport type SubgraphInterpretedLabel = Label & { __brand: \"SubgraphInterpretedLabel\" };\n\n/**\n * A Subgraph Interpreted Name is a name exclusively composed of 0 or more Subgraph Interpreted Labels.\n *\n * @see https://ensnode.io/docs/reference/terminology#subgraph-interpreted-name\n * @dev nominally typed to enforce usage & enhance codebase clarity\n */\nexport type SubgraphInterpretedName = Name & { __brand: \"SubgraphInterpretedName\" };\n\n/**\n * A DNS-Encoded Name as a hex string, representing the binary DNS wire format encoding\n * of a domain name. Used in ENS contracts for efficient name storage and transmission.\n * Each label is prefixed with a length byte, and the entire sequence is null-terminated.\n *\n * @example \"0x076578616d706c650365746800\" represents \"example.eth\"\n *\n * @see https://docs.ens.domains/resolution/names/#dns-encoding\n * @see https://github.com/ensdomains/ens-contracts/blob/staging/contracts/utils/NameCoder.sol\n *\n * DNS Packet Format for Domain Names:\n * - Domain names are encoded as a sequence of 0 or more labels\n * - Each label begins with a length byte (1 byte) indicating how many bytes follow for that label\n * Note how this constrains each label in DNS encoded names to a max byte length of 255 bytes.\n * - The bytes after the length byte represent the label, as a UTF-8 byte array\n * - Labels are concatenated with no separators\n * - The sequence ends with a null byte (0x00)\n *\n * Example: \"example.eth\" is encoded as:\n * [0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0x03, 'e', 't', 'h', 0x00]\n * Where 0x07 is the length of \"example\", 0x03 is the length of \"eth\", and 0x00 marks the end\n *\n * Example: \"\" (empty string, i.e. root node) is encoded as:\n * [0x00]\n *\n * Example: \"👩🏼‍❤‍💋‍👨🏼.eth\" (multi-byte unicode character) is encoded as:\n * [0x20, 240, 159, 145, 169, 240, 159, 143, 188, 226, 128, 141, 226, 157, 164, 226,\n * 128, 141, 240, 159, 146, 139, 226, 128, 141, 240, 159, 145, 168, 240, 159, 143,\n * 188, 3, 'e', 't', 'h', 0x00]\n *\n * A DNS-Encoded Name Packet may be malformed if it does not exactly follow that specification.\n * Possible reasons a DNS-Encoded Name may be malfomed include:\n * - 'empty' packet\n * - e.g. []\n * ^-- that's empty!\n * - 'length' byte overflowing packet byte length\n * - e.g. [0x06, 'e', 't', 'h', 0x00]\n * ^-- length overflows available bytes!\n * - 'junk' at the end of the dns-encoded\n * - e.g. [0x03, 'e', 't', 'h', 0x00, 0x01]\n * ^-- junk!\n *\n * @dev This type is _structurally_ typed to aid Event Argument Typing — consumers should further\n * cast the type of the event argument to a _nominally_ typed DNSEncodedName like {@link DNSEncodedLiteralName}\n * or {@link DNSEncodedPartiallyInterpretedName} depending on the context.\n */\nexport type DNSEncodedName = Hex;\n\n/**\n * A DNSEncodedName that encodes a name containing 0 or more {@link LiteralLabel}s.\n *\n * In a DNSEncodedLiteralName, all labels are Literal Labels, including any Encoded-LabelHash-looking\n * labels. Any Encoded-LabelHash-looking Literal Label values, when interpreted, will be formatted as\n * the `labelhash` of the Literal Label value.\n *\n * The NameWrapper contract emits DNSEncodedLiteralNames:\n * @see https://github.com/ensdomains/ens-contracts/blob/staging/contracts/utils/BytesUtils_LEGACY.sol\n *\n * The ThreeDNSToken contract emits DNSEncodedLiteralNames:\n * @see https://github.com/3dns-xyz/contracts/blob/44937318ae26cc036982e8c6a496cd82ebdc2b12/src/regcontrol/libraries/BytesUtils.sol\n *\n * @dev nominally typed to enforce usage & enhance codebase clarity\n */\nexport type DNSEncodedLiteralName = DNSEncodedName & { __brand: \"DNSEncodedLiteralName\" };\n\n/**\n * A DNSEncodedName that encodes a name consisting of 0 or more labels that are either:\n * a) Literal Labels, or\n * b) Encoded LabelHashes, which are already an Interpreted Label.\n *\n * In a DNSEncodedPartiallyInterpretedName, any Encoded-LabelHash-looking decoded Labels (i.e. ones\n * that match the regex /^\\[[\\da-f]{64}\\]$/) represent an Encoded LabelHash. When decoding a\n * DNSEncodedPartiallyInterpretedName, these labels are already considered Interpreted.\n *\n * NOTE: This type is unused in ENSv1, but its usage is anticipated in ENSv2 due to Encoded\n * LabelHash support in the ENSv2 implementation of the NameCoder contract.\n *\n * @see https://github.com/ensdomains/ens-contracts/blob/staging/contracts/utils/NameCoder.sol\n *\n * @dev nominally typed to enforce usage & enhance codebase clarity\n */\nexport type DNSEncodedPartiallyInterpretedName = DNSEncodedName & {\n __brand: \"DNSEncodedPartiallyInterpretedName\";\n};\n","/**\n * Identifiers for supported currencies.\n *\n * TODO: Add support for WETH\n */\nexport const CurrencyIds = {\n ETH: \"ETH\",\n USDC: \"USDC\",\n DAI: \"DAI\",\n} as const;\n\nexport type CurrencyId = (typeof CurrencyIds)[keyof typeof CurrencyIds];\n\n/**\n * The amount of the currency in the smallest unit of the currency\n * (see {@link CurrencyInfo.decimals} for the currency).\n *\n * Guaranteed to be non-negative.\n */\nexport type CurrencyAmount = bigint;\n\n/**\n * Serialized representation of {@link CurrencyAmount}.\n */\nexport type SerializedCurrencyAmount = string;\n\nexport interface PriceEth {\n currency: typeof CurrencyIds.ETH;\n\n amount: CurrencyAmount;\n}\n\nexport interface PriceDai {\n currency: typeof CurrencyIds.DAI;\n\n amount: CurrencyAmount;\n}\n\nexport interface PriceUsdc {\n currency: typeof CurrencyIds.USDC;\n\n amount: CurrencyAmount;\n}\n\nexport type Price = PriceEth | PriceDai | PriceUsdc;\n\n/**\n * Serialized representation of {@link PriceEth}.\n */\nexport interface SerializedPriceEth extends Omit<PriceEth, \"amount\"> {\n amount: SerializedCurrencyAmount;\n}\n\n/**\n * Serialized representation of {@link PriceDai}.\n */\nexport interface SerializedPriceDai extends Omit<PriceDai, \"amount\"> {\n amount: SerializedCurrencyAmount;\n}\n\n/**\n * Serialized representation of {@link PriceUsdc}.\n */\nexport interface SerializedPriceUsdc extends Omit<PriceUsdc, \"amount\"> {\n amount: SerializedCurrencyAmount;\n}\n\n/**\n * Serialized representation of {@link Price}.\n */\nexport type SerializedPrice = SerializedPriceEth | SerializedPriceDai | SerializedPriceUsdc;\n\nexport interface CurrencyInfo {\n id: CurrencyId;\n name: string;\n decimals: number;\n}\n\nconst currencyInfo: Record<CurrencyId, CurrencyInfo> = {\n [CurrencyIds.ETH]: {\n id: CurrencyIds.ETH,\n name: \"ETH\",\n decimals: 18,\n },\n [CurrencyIds.USDC]: {\n id: CurrencyIds.USDC,\n name: \"USDC\",\n decimals: 6,\n },\n [CurrencyIds.DAI]: {\n id: CurrencyIds.DAI,\n name: \"Dai Stablecoin\",\n decimals: 18,\n },\n};\n\n/**\n * Get currency info for a provided currency.\n */\nexport function getCurrencyInfo(currencyId: CurrencyId): CurrencyInfo {\n return currencyInfo[currencyId];\n}\n\n/**\n * Create price in ETH for given amount.\n */\nexport function priceEth(amount: Price[\"amount\"]): PriceEth {\n return {\n amount,\n currency: CurrencyIds.ETH,\n };\n}\n\n/**\n * Create price in USDC for given amount.\n */\nexport function priceUsdc(amount: Price[\"amount\"]): PriceUsdc {\n return {\n amount,\n currency: CurrencyIds.USDC,\n };\n}\n\n/**\n * Create price in DAI for given amount.\n */\nexport function priceDai(amount: Price[\"amount\"]): PriceDai {\n return {\n amount,\n currency: CurrencyIds.DAI,\n };\n}\n\n/**\n * Check if two prices have the same currency.\n */\nexport function isPriceCurrencyEqual(priceA: Price, priceB: Price): boolean {\n return priceA.currency === priceB.currency;\n}\n\n/**\n * Check if two {@link Price} values have the same currency and amount.\n */\nexport function isPriceEqual(priceA: Price, priceB: Price): boolean {\n return isPriceCurrencyEqual(priceA, priceB) && priceA.amount === priceB.amount;\n}\n\n/**\n * Add prices\n *\n * @param prices at least two {@link Price} values to be added together.\n * @returns total of all prices.\n * @throws if not all prices have the same currency.\n */\nexport function addPrices<const PriceType extends Price = Price>(\n ...prices: [PriceType, PriceType, ...PriceType[]]\n): PriceType {\n const firstPrice = prices[0];\n const allPricesInSameCurrency = prices.every((price) => isPriceCurrencyEqual(firstPrice, price));\n\n if (allPricesInSameCurrency === false) {\n throw new Error(\"All prices must have the same currency to be added together.\");\n }\n\n const { currency } = firstPrice;\n\n return prices.reduce(\n (acc, price) => ({\n amount: acc.amount + price.amount,\n currency,\n }),\n {\n amount: 0n,\n currency: firstPrice.currency,\n },\n ) as PriceType;\n}\n","import { labelhash as labelToLabelHash } from \"viem\";\n\nimport {\n encodeLabelHash,\n type InterpretedLabel,\n type InterpretedName,\n isEncodedLabelHash,\n isNormalizedLabel,\n} from \"../../ens\";\n\n/**\n * Reinterpret Label\n *\n * Reinterprets {@link InterpretedLabel} values received by \"External System\"\n * into {@link InterpretedLabel} values in \"Internal System\" where:\n * 1. \"External System\" is not guaranteed to be using the same ENSNormalize\n * version as \"Internal System\", and therefore the `InterpretedLabel` passed into\n * this function (from \"External System\") is not guaranteed to 100% align\n * with the invariants of an `InterpretedLabel` in \"Internal System\".\n * 2. The `InterpretedLabel` returned by this function is guaranteed to match\n * the invariants of `InterpretedLabel` in \"Internal System\".\n *\n * @returns reinterpreted label.\n * @throws an error if the provided label is an empty label\n * (and therefore violates the invariants of an InterpretedLabel).\n */\nexport function reinterpretLabel(label: InterpretedLabel): InterpretedLabel {\n // Invariant: InterpretedLabel value must never be an empty label.\n if (label === \"\") {\n throw new Error(\n `Cannot reinterpret an empty label that violates the invariants of an InterpretedLabel.`,\n );\n }\n\n // no change required for EncodedLabelHash\n if (isEncodedLabelHash(label)) return label;\n\n // no change required for NormalizedLabel\n if (isNormalizedLabel(label)) return label;\n\n // the provided `label` is unnormalized,\n // turn into an EncodedLabelHash\n return encodeLabelHash(labelToLabelHash(label)) as InterpretedLabel;\n}\n\n/**\n * Reinterpret Name\n *\n * Reinterprets {@link InterpretedName} values received by \"External System\"\n * into {@link InterpretedName} values in \"Internal System\" where:\n * 1. \"External System\" is not guaranteed to be using the same ENSNormalize\n * version as \"Internal System\", and therefore the `InterpretedName` passed into\n * this function (from \"External System\") is not guaranteed to 100% align\n * with the invariants of an `InterpretedName` in \"Internal System\".\n * 2. The `InterpretedName` returned by this function is guaranteed to match\n * the invariants of `InterpretedName` in \"Internal System\".\n */\nexport function reinterpretName(name: InterpretedName): InterpretedName {\n if (name === \"\") return name;\n\n const interpretedLabels = name.split(\".\") as InterpretedLabel[];\n const reinterpretedLabels = interpretedLabels.map(reinterpretLabel);\n const reinterpretedName = reinterpretedLabels.join(\".\") as InterpretedName;\n\n return reinterpretedName;\n}\n","import { deserializeDuration, deserializeUnixTimestamp } from \"./deserialize\";\nimport type { Duration, UnixTimestamp } from \"./types\";\n\n/**\n * Duration between two moments in time.\n */\nexport function durationBetween(start: UnixTimestamp, end: UnixTimestamp): Duration {\n return deserializeDuration(end - start, \"Duration\");\n}\n\n/**\n * Add a duration to a timestamp.\n */\nexport function addDuration(timestamp: UnixTimestamp, duration: Duration): UnixTimestamp {\n return deserializeUnixTimestamp(timestamp + duration, \"UnixTimestamp\");\n}\n","import { getUnixTime } from \"date-fns/getUnixTime\";\n\nimport { addDuration } from \"../datetime\";\nimport type { Duration, UnixTimestamp } from \"../types\";\nimport type { Cache } from \"./cache\";\n\ninterface CacheEntry<ValueType> {\n value: ValueType;\n expiresAt: UnixTimestamp;\n}\n\n/**\n * Cache that maps from string -> ValueType with TTL (time-to-live) expiration.\n *\n * Items are automatically removed when they expire.\n */\nexport class TtlCache<KeyType extends string, ValueType> implements Cache<KeyType, ValueType> {\n private readonly _cache = new Map<string, CacheEntry<ValueType>>();\n private readonly _ttl: Duration;\n\n /**\n * Create a new TTL cache with the given TTL.\n *\n * @param ttl Time-to-live duration in seconds. Items expire after this duration.\n */\n public constructor(ttl: Duration) {\n this._ttl = ttl;\n }\n\n private _cleanup(): void {\n const now = getUnixTime(new Date());\n for (const [key, entry] of this._cache.entries()) {\n if (entry.expiresAt <= now) {\n this._cache.delete(key);\n }\n }\n }\n\n public set(key: string, value: ValueType): void {\n this._cleanup();\n\n const expiresAt = addDuration(getUnixTime(new Date()), this._ttl);\n this._cache.set(key, { value, expiresAt });\n }\n\n public get(key: string): ValueType | undefined {\n this._cleanup();\n\n const entry = this._cache.get(key);\n if (!entry) {\n return undefined;\n }\n\n if (entry.expiresAt <= getUnixTime(new Date())) {\n this._cache.delete(key);\n return undefined;\n }\n\n return entry.value;\n }\n\n public clear(): void {\n this._cache.clear();\n }\n\n public get size(): number {\n this._cleanup();\n return this._cache.size;\n }\n\n public get capacity(): number {\n return Number.MAX_SAFE_INTEGER;\n }\n\n public has(key: string): boolean {\n this._cleanup();\n\n const entry = this._cache.get(key);\n if (!entry) {\n return false;\n }\n\n if (entry.expiresAt <= getUnixTime(new Date())) {\n this._cache.delete(key);\n return false;\n }\n\n return true;\n }\n\n public delete(key: string): boolean {\n return this._cache.delete(key);\n }\n}\n","/**\n * Filter out duplicates.\n */\nexport const uniq = <T>(arr: T[]): T[] => [...new Set(arr)];\n","import {\n type Datasource,\n type DatasourceName,\n type ENSNamespaceId,\n maybeGetDatasource,\n} from \"@ensnode/datasources\";\nimport { type AccountId, accountIdEqual } from \"@ensnode/ensnode-sdk\";\n\n/**\n * Gets the AccountId for the contract in the specified namespace, datasource, and\n * contract name, or undefined if it is not defined or is not a single AccountId.\n *\n * This is useful when you want to retrieve the AccountId for a contract by its name\n * where it may or may not actually be defined for the given namespace and datasource.\n *\n * @param namespaceId - The ENSNamespace identifier (e.g. 'mainnet', 'sepolia', 'ens-test-env')\n * @param datasourceName - The name of the Datasource to search for contractName in\n * @param contractName - The name of the contract to retrieve\n * @returns The AccountId of the contract with the given namespace, datasource,\n * and contract name, or undefined if it is not found or is not a single AccountId\n */\nexport const maybeGetDatasourceContract = <\n N extends ENSNamespaceId,\n D extends DatasourceName,\n C extends string,\n>(\n namespaceId: N,\n datasourceName: D,\n contractName: C,\n): AccountId | undefined => {\n const datasource = maybeGetDatasource(namespaceId, datasourceName) as Datasource | undefined;\n if (!datasource) return undefined;\n\n const address = datasource.contracts[contractName]?.address;\n if (address === undefined || Array.isArray(address)) return undefined;\n\n return {\n chainId: datasource.chain.id,\n address,\n };\n};\n\n/**\n * Gets the AccountId for the contract in the specified namespace, datasource, and\n * contract name, or throws an error if it is not defined or is not a single AccountId.\n *\n * @param namespaceId - The ENSNamespace identifier (e.g. 'mainnet', 'sepolia', 'ens-test-env')\n * @param datasourceName - The name of the Datasource to search for contractName in\n * @param contractName - The name of the contract to retrieve\n * @returns The AccountId of the contract with the given namespace, datasource,\n * and contract name\n * @throws Error if the contract is not found or is not a single AccountId\n */\nexport const getDatasourceContract = (\n namespaceId: ENSNamespaceId,\n datasourceName: DatasourceName,\n contractName: string,\n): AccountId => {\n const contract = maybeGetDatasourceContract(namespaceId, datasourceName, contractName);\n if (!contract) {\n throw new Error(\n `Expected contract not found for ${namespaceId} ${datasourceName} ${contractName}`,\n );\n }\n return contract;\n};\n\n/**\n * Makes a comparator fn for `b` against the contract described by `namespace`, `datasourceName`, and `contractName`.\n */\nexport const makeContractMatcher =\n (namespace: ENSNamespaceId, b: AccountId) =>\n (datasourceName: DatasourceName, contractName: string) => {\n const a = maybeGetDatasourceContract(namespace, datasourceName, contractName);\n return a && accountIdEqual(a, b);\n };\n","import { type Address, isAddressEqual, zeroAddress } from \"viem\";\n\n/**\n * Interprets a viem#Address. zeroAddress is interpreted as null, otherwise Address.\n */\nexport const interpretAddress = (owner: Address) =>\n isAddressEqual(zeroAddress, owner) ? null : owner;\n","import { isAddress, isAddressEqual, zeroAddress } from \"viem\";\n\nimport { asLowerCaseAddress, isNormalizedName, type NormalizedName } from \"@ensnode/ensnode-sdk\";\n\nimport { hasNullByte } from \"../null-bytes\";\n\n/**\n * Interprets a name record value string and returns null if the value is interpreted as a deletion.\n *\n * The interpreted record value is either:\n * a) null, representing a non-existant or deletion of the record, or\n * b) a normalized, non-empty-string Name.\n *\n * @param value - The name record value string to interpret.\n * @returns The interpreted name string, or null if deleted.\n */\nexport function interpretNameRecordValue(value: string): NormalizedName | null {\n // empty string is technically a normalized name, representing the ens root node, but in the\n // context of a name record value, empty string is emitted when the user un-sets the record (this\n // is because the abi of this event is only capable of expressing string values, so empty string\n // canonically represents the non-existence or deletion of the record value)\n if (value === \"\") return null;\n\n // if not normalized, is not valid `name` record value\n if (!isNormalizedName(value)) return null;\n\n // otherwise, this is a non-empty-string normalized Name that can be used as a name() record value\n return value;\n}\n\n/**\n * Interprets an address record value string and returns null if the value is interpreted as a deletion.\n *\n * The interpreted record value is either:\n * a) null, representing a non-existant or deletion of the record, or\n * i. contains null bytes\n * ii. empty string\n * iii. empty hex (0x)\n * iv. zeroAddress\n * b) an address record value that\n * i. does not contain null bytes\n * ii. (if is an EVM address) is lowercase\n *\n * @param value - The address record value to interpret.\n * @returns The interpreted address string or null if deleted.\n */\nexport function interpretAddressRecordValue(value: string): string | null {\n // TODO(null-bytes): store null bytes correctly — for now, interpret as deletion\n if (hasNullByte(value)) return null;\n\n // interpret empty string as deletion of address record\n if (value === \"\") return null;\n\n // interpret empty bytes as deletion of address record\n if (value === \"0x\") return null;\n\n // if it's not an EVM address, return as-is\n if (!isAddress(value)) return value;\n\n // interpret zeroAddress as deletion\n if (isAddressEqual(value, zeroAddress)) return null;\n\n // otherwise convert to lowercase\n return asLowerCaseAddress(value);\n}\n\n/**\n * Interprets a text record key string and returns null if the key should be ignored.\n *\n * The interpreted text record key is either:\n * a) null, representing a text record key that should be ignored, or\n * i. contains null bytes\n * ii. empty string\n * b) a text record key that\n * i. does not contain null bytes\n *\n * @param value - The text record key to interpret.\n * @returns The interpreted text string or null if ignored.\n */\nexport function interpretTextRecordKey(key: string): string | null {\n // TODO(null-bytes): store null bytes correctly — for now, ignore\n if (hasNullByte(key)) return null;\n\n // ignore empty-string keys\n if (key === \"\") return null;\n\n // otherwise return the key as-is\n return key;\n}\n\n/**\n * Interprets a text record value string and returns null if the value is interpreted as a deletion.\n *\n * The interpreted record value is either:\n * a) null, representing a non-existant or deletion of the record, or\n * i. contains null bytes\n * ii. empty string\n * b) a text record value that\n * i. does not contain null bytes\n *\n * @param value - The text record value to interpret.\n * @returns The interpreted text string or null if deleted.\n */\nexport function interpretTextRecordValue(value: string): string | null {\n // TODO(null-bytes): store null bytes correctly — for now, interpret as deletion\n if (hasNullByte(value)) return null;\n\n // interpret empty string as deletion of a text record\n if (value === \"\") return null;\n\n // otherwise return the string as-is\n return value;\n}\n","export const hasNullByte = (value: string) => value.indexOf(\"\\u0000\") !== -1;\n\nexport const stripNullBytes = (value: string) => value.replaceAll(\"\\u0000\", \"\");\n","import { type LabelHash, type Node, uint256ToHex32 } from \"../../ens\";\n\n/**\n * Decodes a uint256-encoded-LabelHash (eg. from a tokenId) into a {@link LabelHash}.\n *\n * Remember that contracts that operate in the context of a Managed Name frequently store and operate\n * over _LabelHashes_ that represent a direct subname of a Managed Name. These contracts also frequently\n * implement ERC721 or ERC1155 to represent ownership of these Names. As such, to construct the\n * ERC721/ERC1155 tokenId, they may encode the direct subnames's LabelHash as a uint256.\n *\n * This is true for the ENSv1 BaseRegistrar, RegistrarControllers, as well as any\n * contracts forked from it (which includes Basenames' and Lineanames' implementations).\n *\n * So, in order to turn the tokenId into a LabelHash, we perform the opposite operation, decoding\n * from a uint256 into a Hex (of size 32) and cast it as our semantic {@link LabelHash} type.\n *\n * @see https://github.com/ensdomains/ens-contracts/blob/db613bc/contracts/ethregistrar/ETHRegistrarController.sol#L215\n * @see https://github.com/base/basenames/blob/1b5c1ad/src/L2/RegistrarController.sol#L488\n * @see https://github.com/Consensys/linea-ens/blob/3a4f02f/packages/linea-ens-contracts/contracts/ethregistrar/ETHRegistrarController.sol#L447\n */\nexport const interpretTokenIdAsLabelHash = (tokenId: bigint): LabelHash => uint256ToHex32(tokenId);\n\n/**\n * Decodes a uint256-encoded-Node (eg. from a tokenId) into a {@link Node}.\n *\n * Contracts in the ENSv1 ecosystem frequently implement ERC721 or ERC1155 to represent\n * ownership of a Domain. As such, to construct the ERC721/ERC1155 tokenId, they may encode the\n * domain's {@link Node} as a uint256.\n *\n * This is true for the ENSv1 NameWrapper, as well as any contracts forked from it (which includes\n * Lineanames' implementation).\n *\n * So, in order to turn the tokenId into a Node, we perform the opposite operation, decoding\n * from a uint256 into a Hex (of size 32) and cast it as our semantic {@link Node} type.\n *\n * @see https://github.com/ensdomains/ens-contracts/blob/db613bc/contracts/wrapper/ERC1155Fuse.sol#L262\n */\nexport const interpretTokenIdAsNode = (tokenId: bigint): Node => uint256ToHex32(tokenId);\n","import { isHex } from \"viem\";\nimport { labelhash } from \"viem/ens\";\n\nimport {\n encodeLabelHash,\n type InterpretedLabel,\n type InterpretedName,\n isNormalizedLabel,\n type Label,\n type LabelHash,\n type LabelHashPath,\n type LiteralLabel,\n type LiteralName,\n type Name,\n} from \"../../ens\";\nimport { labelhashLiteralLabel } from \"../labelhash\";\n\n/**\n * Interprets a Literal Label, producing an Interpreted Label.\n *\n * @see https://ensnode.io/docs/reference/terminology#literal-label\n * @see https://ensnode.io/docs/reference/terminology#interpreted-label\n *\n * @param label - The Literal Label string to interpret\n * @returns The provided label if it is a normalized label, else the EncodedLabelHash of the label\n */\nexport function literalLabelToInterpretedLabel(label: LiteralLabel): InterpretedLabel {\n // if the label is normalized, good to go\n if (isNormalizedLabel(label)) return label as Label as InterpretedLabel;\n\n // otherwise, encode the labelhash of the literal Label\n return encodeLabelHash(labelhashLiteralLabel(label)) as InterpretedLabel;\n}\n\n/**\n * Interprets an ordered list of Literal Labels, producing an Interpreted Name.\n *\n * Note that it's important that the Literal Labels are provided as an array, otherwise it's\n * impossible to differentiate between 'a.label.eth' being ['a.label', 'eth'] or ['a', 'label', 'eth'].\n *\n * Note that the input is an ordered list of _Literal_ Labels: in this context, any literal label\n * that is formatted as an Encoded LabelHash will NOT be interpreted as such. Instead it will be\n * interpreted into an Encoded LabelHash that encodes the literal labelhash of the Literal Label.\n *\n * @param labels An ordered list of 0 or more Literal Labels\n * @returns An InterpretedName\n */\nexport function literalLabelsToInterpretedName(labels: LiteralLabel[]): InterpretedName {\n return labels.map(literalLabelToInterpretedLabel).join(\".\") as InterpretedName;\n}\n\n/**\n * Joins the list of Interpreted Labels with '.' to form an Interpreted Name.\n *\n * @param labels An ordered list of 0 or more Interpreted Labels\n * @returns An InterpretedName\n */\nexport function interpretedLabelsToInterpretedName(labels: InterpretedLabel[]): InterpretedName {\n return labels.join(\".\") as InterpretedName;\n}\n\n/**\n * Joins the list of Literal Labels with '.' to form a Literal Name.\n *\n * Note: LiteralLabel values may contain '.' characters, which will be preserved\n * in the resulting LiteralName. Therefore, the number of labels in the returned\n * LiteralName may be greater than the number of LiteralLabels in the input array.\n *\n * @param labels An ordered list of 0 or more Literal Labels\n * @returns An LiteralName\n */\nexport function literalLabelsToLiteralName(labels: LiteralLabel[]): LiteralName {\n return labels.join(\".\") as LiteralName;\n}\n\n/**\n * Converts an Interpreted Name into a list of Interpreted Labels.\n */\nexport function interpretedNameToInterpretedLabels(name: InterpretedName): InterpretedLabel[] {\n return name.split(\".\") as InterpretedLabel[];\n}\n\n// https://github.com/wevm/viem/blob/main/src/utils/ens/encodedLabelToLabelhash.ts\nexport function encodedLabelToLabelhash(label: string): LabelHash | null {\n if (label.length !== 66) return null;\n if (label.indexOf(\"[\") !== 0) return null;\n if (label.indexOf(\"]\") !== 65) return null;\n const hash = `0x${label.slice(1, 65)}`;\n if (!isHex(hash)) return null;\n return hash;\n}\n\nexport function isInterpetedLabel(label: Label): label is InterpretedLabel {\n // if it looks like an encoded labelhash, it must be one\n if (label.startsWith(\"[\")) {\n const labelHash = encodedLabelToLabelhash(label);\n if (labelHash === null) return false;\n }\n\n // otherwise label must be normalized\n return isNormalizedLabel(label);\n}\n\nexport function isInterpretedName(name: Name): name is InterpretedName {\n return name.split(\".\").every(isInterpetedLabel);\n}\n\n/**\n * Converts an InterpretedName into a LabelHashPath.\n */\nexport function interpretedNameToLabelHashPath(name: InterpretedName): LabelHashPath {\n return interpretedNameToInterpretedLabels(name)\n .map((label) => {\n if (!isInterpetedLabel(label)) {\n throw new Error(\n `Invariant(interpretedNameToLabelHashPath): Expected InterpretedLabel, received '${label}'.`,\n );\n }\n\n // if it looks like an encoded labelhash, return it\n const maybeLabelHash = encodedLabelToLabelhash(label);\n if (maybeLabelHash !== null) return maybeLabelHash;\n\n // otherwise, labelhash it\n return labelhash(label);\n })\n .toReversed();\n}\n","import { keccak256, stringToBytes } from \"viem\";\n\nimport type { LabelHash, LiteralLabel } from \"../ens\";\n\n/**\n * Implements the ENS `labelhash` function for Literal Labels.\n * @see https://docs.ens.domains/ensip/1\n *\n * @param label the Literal Label to hash\n * @returns the hash of the provided label\n * @dev This function is viem/ens#labelhash but without the special-case handling of Encoded LabelHashes.\n */\nexport const labelhashLiteralLabel = (label: LiteralLabel): LabelHash =>\n keccak256(stringToBytes(label));\n","/**\n * Converts a bigint value into a number value.\n *\n * @throws when value is outside the range of `Number.MIN_SAFE_INTEGER` and\n * `Number.MAX_SAFE_INTEGER`.\n */\nexport function bigIntToNumber(n: bigint): number {\n if (n < Number.MIN_SAFE_INTEGER) {\n throw new Error(\n `The bigint '${n.toString()}' value is too low to be to converted into a number.'`,\n );\n }\n\n if (n > Number.MAX_SAFE_INTEGER) {\n throw new Error(\n `The bigint '${n.toString()}' value is too high to be to converted into a number.'`,\n );\n }\n\n return Number(n);\n}\n","import { DatasourceNames, type ENSNamespaceId } from \"@ensnode/datasources\";\nimport {\n type AccountId,\n accountIdEqual,\n getDatasourceContract,\n makeRegistryId,\n} from \"@ensnode/ensnode-sdk\";\n\n//////////////\n// ENSv1\n//////////////\n\n/**\n * Gets the AccountId representing the ENSv1 Registry in the selected `namespace`.\n */\nexport const getENSv1Registry = (namespace: ENSNamespaceId) =>\n getDatasourceContract(namespace, DatasourceNames.ENSRoot, \"ENSv1Registry\");\n\n/**\n * Determines whether `contract` is the ENSv1 Registry in `namespace`.\n */\nexport const isENSv1Registry = (namespace: ENSNamespaceId, contract: AccountId) =>\n accountIdEqual(getENSv1Registry(namespace), contract);\n\n//////////////\n// ENSv2\n//////////////\n\n/**\n * Gets the AccountId representing the ENSv2 Root Registry in the selected `namespace`.\n */\nexport const getENSv2RootRegistry = (namespace: ENSNamespaceId) =>\n getDatasourceContract(namespace, DatasourceNames.ENSRoot, \"RootRegistry\");\n\n/**\n * Gets the RegistryId representing the ENSv2 Root Registry in the selected `namespace`.\n */\nexport const getENSv2RootRegistryId = (namespace: ENSNamespaceId) =>\n makeRegistryId(getENSv2RootRegistry(namespace));\n\n/**\n * Determines whether `contract` is the ENSv2 Root Registry in `namespace`.\n */\nexport const isENSv2RootRegistry = (namespace: ENSNamespaceId, contract: AccountId) =>\n accountIdEqual(getENSv2RootRegistry(namespace), contract);\n","import { AccountId as CaipAccountId, AssetId as CaipAssetId } from \"caip\";\n\nimport { uint256ToHex32 } from \"../ens\";\nimport type { Price, PriceEth, SerializedPrice, SerializedPriceEth } from \"./currencies\";\nimport type {\n AccountIdString,\n AssetIdString,\n ChainIdString,\n DatetimeISO8601,\n UrlString,\n} from \"./serialized-types\";\nimport type { AccountId, AssetId, ChainId, Datetime } from \"./types\";\n\n/**\n * Serializes a {@link ChainId} value into its string representation.\n */\nexport function serializeChainId(chainId: ChainId): ChainIdString {\n return chainId.toString();\n}\n\n/**\n * Serializes a {@link Datetime} value into its string representation.\n */\nexport function serializeDatetime(datetime: Datetime): DatetimeISO8601 {\n return datetime.toISOString();\n}\n\n/**\n * Serializes a {@link URL} value into its string representation.\n */\nexport function serializeUrl(url: URL): UrlString {\n return url.toString();\n}\n\n/**\n * Serializes a {@link Price} object.\n */\nexport function serializePrice(price: Price): SerializedPrice {\n return {\n currency: price.currency,\n amount: price.amount.toString(),\n };\n}\n\n/**\n * Serializes a {@link PriceEth} object.\n */\nexport function serializePriceEth(price: PriceEth): SerializedPriceEth {\n return serializePrice(price) as SerializedPriceEth;\n}\n\n/**\n * Format {@link AccountId} object as a string.\n *\n * Formatted as a fully lowercase CAIP-10 AccountId.\n *\n * @see https://chainagnostic.org/CAIPs/caip-10\n */\nexport function formatAccountId(accountId: AccountId): AccountIdString {\n return CaipAccountId.format({\n chainId: { namespace: \"eip155\", reference: accountId.chainId.toString() },\n address: accountId.address,\n }).toLowerCase();\n}\n\n/**\n * Format {@link AssetId} object as a string.\n *\n * Formatted as a fully lowercase CAIP-19 AssetId.\n *\n * @see https://chainagnostic.org/CAIPs/caip-19\n */\nexport function formatAssetId({\n assetNamespace,\n contract: { chainId, address },\n tokenId,\n}: AssetId): AssetIdString {\n return CaipAssetId.format({\n chainId: { namespace: \"eip155\", reference: chainId.toString() },\n assetName: { namespace: assetNamespace, reference: address },\n tokenId: uint256ToHex32(tokenId),\n }).toLowerCase();\n}\n","import type { Address } from \"viem\";\n\nimport type { DEFAULT_EVM_CHAIN_ID } from \"../ens\";\n\n/**\n * Chain ID\n *\n * Represents a unique identifier for a chain.\n * Guaranteed to be a positive integer.\n *\n * Chain id standards are organized by the Ethereum Community @ https://github.com/ethereum-lists/chains\n **/\nexport type ChainId = number;\n\n/**\n * Defaultable Chain ID\n *\n * Represents a unique identifier for a chain, or\n * the default chain as defined by ENSIP-19.\n *\n * @see https://docs.ens.domains/ensip/19/#annex-supported-chains\n *\n * Guaranteed to be a non-negative integer.\n **/\nexport type DefaultableChainId = typeof DEFAULT_EVM_CHAIN_ID | ChainId;\n\n/**\n * Represents an account (contract or EOA) at `address` on chain `chainId`.\n *\n * @see https://chainagnostic.org/CAIPs/caip-10\n */\nexport interface AccountId {\n chainId: ChainId;\n address: Address;\n}\n\n/**\n * An enum representing the possible CAIP-19 Asset Namespace values.\n *\n * @see https://chainagnostic.org/CAIPs/caip-19\n */\nexport const AssetNamespaces = {\n ERC721: \"erc721\",\n ERC1155: \"erc1155\",\n} as const;\n\nexport type AssetNamespace = (typeof AssetNamespaces)[keyof typeof AssetNamespaces];\n\n/**\n * A uint256 value that identifies a specific NFT within a NFT contract.\n */\nexport type TokenId = bigint;\n\n/**\n * Represents an Asset in `assetNamespace` by `tokenId` in `contract`.\n *\n * @see https://chainagnostic.org/CAIPs/caip-19\n */\nexport interface AssetId {\n assetNamespace: AssetNamespace;\n contract: AccountId;\n tokenId: TokenId;\n}\n\n/**\n * Block Number\n *\n * Guaranteed to be a non-negative integer.\n */\nexport type BlockNumber = number;\n\n/**\n * Datetime value\n */\nexport type Datetime = Date;\n\n/**\n * Unix timestamp value\n *\n * Represents the number of seconds that have elapsed\n * since January 1, 1970 (midnight UTC/GMT).\n *\n * Guaranteed to be an integer. May be zero or negative to represent a time at or\n * before Jan 1, 1970.\n */\nexport type UnixTimestamp = number;\n\n/**\n * Represents a URL that is used for RPC endpoints.\n */\nexport type RpcUrl = URL;\n\n/**\n * BlockRef\n *\n * Describes a block.\n *\n * We use parameter types to maintain fields layout and documentation across\n * the domain model and its serialized counterpart.\n */\nexport interface BlockRef {\n /** Block number (height) */\n number: BlockNumber;\n\n /** Block timestamp */\n timestamp: UnixTimestamp;\n}\n\n/**\n * Block range\n *\n * Represents a range of blocks\n */\nexport interface Blockrange<BlockType = BlockNumber> {\n /** Start block number */\n startBlock?: BlockType;\n\n /** End block number */\n endBlock?: BlockType;\n}\n\n/**\n * Duration\n *\n * Representing a duration in seconds.\n *\n * Guaranteed to be a non-negative integer.\n */\nexport type Duration = number;\n\n/**\n * A utility type that makes all properties of a type optional recursively,\n * including nested objects and arrays.\n *\n * @example\n * ```typescript\n * type Config = {\n * a: string;\n * b: {\n * x: number;\n * y: { z: boolean };\n * };\n * c: { id: string }[];\n * }\n *\n * type PartialConfig = DeepPartial<Config>;\n * // Results in:\n * // {\n * // a?: string;\n * // b?: {\n * // x?: number;\n * // y?: { z?: boolean };\n * // };\n * // c?: { id?: string }[];\n * // }\n *\n * // Usage:\n * const update: PartialConfig = { b: { y: { z: true } } };\n * ```\n */\nexport type DeepPartial<T> = {\n [P in keyof T]?: T[P] extends (infer U)[]\n ? DeepPartial<U>[]\n : T[P] extends object\n ? DeepPartial<T[P]>\n : T[P];\n};\n\n/**\n * Marks keys in K as required (not undefined) and not null.\n */\nexport type RequiredAndNotNull<T, K extends keyof T> = T & {\n [P in K]-?: NonNullable<T[P]>;\n};\n","export function isHttpProtocol(url: URL): boolean {\n return [\"http:\", \"https:\"].includes(url.protocol);\n}\n\nexport function isWebSocketProtocol(url: URL): boolean {\n return [\"ws:\", \"wss:\"].includes(url.protocol);\n}\n","import { ENSNamespaceIds } from \"@ensnode/datasources\";\n\nimport { type ENSIndexerPublicConfig, PluginName } from \"./types\";\n\n/**\n * Determines if the provided `config` results in indexing behavior compatible with the legacy ENS\n * Subgraph.\n *\n * @see https://ensnode.io/docs/reference/subgraph-compatibility/\n */\nexport function isSubgraphCompatible(\n config: Pick<ENSIndexerPublicConfig, \"namespace\" | \"plugins\" | \"labelSet\">,\n): boolean {\n // 1. only the subgraph plugin is active\n const onlySubgraphPluginActivated =\n config.plugins.length === 1 && config.plugins[0] === PluginName.Subgraph;\n\n // 2. label set id must be \"subgraph\" and version must be 0\n const isSubgraphLabelSet =\n config.labelSet.labelSetId === \"subgraph\" && config.labelSet.labelSetVersion === 0;\n\n const isEnsTestEnvLabelSet =\n config.labelSet.labelSetId === \"ens-test-env\" && config.labelSet.labelSetVersion === 0;\n\n // config should be considered subgraph-compatible if in ens-test-env namespace with ens-test-env labelset\n const labelSetIsSubgraphCompatible =\n isSubgraphLabelSet || (config.namespace === ENSNamespaceIds.EnsTestEnv && isEnsTestEnvLabelSet);\n\n return onlySubgraphPluginActivated && labelSetIsSubgraphCompatible;\n}\n","import type { ENSNamespaceId } from \"@ensnode/datasources\";\n\nimport type { EnsRainbowClientLabelSet } from \"../../ensrainbow\";\nimport type { ChainId } from \"../../shared\";\n\n/**\n * A PluginName is a unique id for a 'plugin': we use the notion of\n * 'plugins' to describe bundles of indexing logic.\n */\nexport enum PluginName {\n Subgraph = \"subgraph\",\n Basenames = \"basenames\",\n Lineanames = \"lineanames\",\n ThreeDNS = \"threedns\",\n ProtocolAcceleration = \"protocol-acceleration\",\n Registrars = \"registrars\",\n TokenScope = \"tokenscope\",\n ENSv2 = \"ensv2\",\n}\n\n/**\n * Version info about ENSIndexer and its dependencies.\n */\nexport interface ENSIndexerVersionInfo {\n /**\n * Node.js runtime version\n *\n * @see https://nodejs.org/en/about/previous-releases\n **/\n nodejs: string;\n\n /**\n * Ponder framework version\n *\n * @see https://www.npmjs.com/package/ponder\n **/\n ponder: string;\n\n /**\n * ENSDb service version\n *\n * Guaranteed to be the same as {@link ENSIndexerVersionInfo.ensIndexer}.\n * */\n ensDb: string;\n\n /**\n * ENSIndexer service version\n *\n * @see https://ghcr.io/namehash/ensnode/ensindexer\n **/\n ensIndexer: string;\n\n /**\n * ENSRainbow service version\n *\n * @see https://ghcr.io/namehash/ensnode/ensindexer\n **/\n ensRainbow: string;\n\n /**\n * ENSRainbow schema version\n **/\n ensRainbowSchema: number;\n\n /**\n * ENS Normalize package version\n *\n * Available on NPM as: `@adraffy/ens-normalize`\n *\n * @see https://www.npmjs.com/package/@adraffy/ens-normalize\n **/\n ensNormalize: string;\n}\n\n/**\n * Complete public configuration object for ENSIndexer.\n *\n * We use parameter types to maintain fields layout and documentation across\n * the domain model and its serialized counterpart.\n */\nexport interface ENSIndexerPublicConfig {\n /**\n * The ENS namespace that ENSNode operates in the context of.\n *\n * See {@link ENSNamespaceIds} for available namespace identifiers.\n */\n namespace: ENSNamespaceId;\n\n /**\n * The \"fully pinned\" label set reference that ENSIndexer will request ENSRainbow use for deterministic label healing across time. This label set reference is \"fully pinned\" as it requires both the labelSetId and labelSetVersion fields to be defined.\n */\n labelSet: Required<EnsRainbowClientLabelSet>;\n\n /**\n * A Postgres database schema name. This instance of ENSIndexer will write\n * indexed data to the tables in this schema.\n *\n * Invariants:\n * - Must be a non-empty string that is a valid Postgres database schema\n * identifier.\n */\n databaseSchemaName: string;\n\n /**\n * A set of strings referring to the names of plugins that are active.\n *\n * For future-proofing, this is a list of strings that may or may\n * not be currently valid {@link PluginName} values.\n *\n * Invariants:\n * - A set of strings with at least one value.\n */\n plugins: string[];\n\n /**\n * Indexed Chain IDs\n *\n * Includes the {@link ChainId} for each chain being indexed.\n */\n indexedChainIds: Set<ChainId>;\n\n /**\n * A feature flag to enable/disable ENSIndexer's Subgraph Compatible Indexing Behavior.\n *\n * If {@link isSubgraphCompatible} is true, indexing behavior will match that of the legacy ENS\n * Subgraph.\n *\n * ENSIndexer will store and return Literal Labels and Literal Names without further interpretation.\n * @see https://ensnode.io/docs/reference/terminology#literal-label\n * @see https://ensnode.io/docs/reference/terminology#literal-name\n *\n * If {@link isSubgraphCompatible} is true, the following invariants are true for the ENSIndexerConfig:\n * 1. only the 'subgraph' plugin is enabled, and\n * 2. the labelSet must be { labelSetId: 'subgraph', labelSetVersion: 0 }\n *\n * If {@link isSubgraphCompatible} is false, ENSIndexer will additionally:\n *\n * 1. ENSIndexer will heal all subnames of addr.reverse on the ENS Root Chain.\n *\n * 2. ENSIndexer will track both the keys and the values of Resolver records.\n *\n * WARNING: Special care must be taken when interacting with indexed resolver record values. It\n * is unsafe to naively assume that indexed resolver record values are equivalent to the\n * resolver record values that would be returned through dynamic lookups via the ENS protocol.\n * For example, if a resolver implements CCIP-Read, the resolver records may not be\n * discoverable through onchain indexing.\n *\n * 3. Literal Labels and Literal Names encountered by ENSIndexer will be Interpreted.\n * @see https://ensnode.io/docs/reference/terminology#interpreted-label\n * @see https://ensnode.io/docs/reference/terminology#interpreted-name\n *\n * That is,\n * a) all Labels stored and returned by ENSIndexer will be Interpreted Labels, which are either:\n * i. normalized, or\n * ii. represented as an Encoded LabelHash of the Literal Label value found onchain, and\n * b) all Names stored and returned by ENSIndexer will be Interpreted Names, which are exclusively\n * composed of Interpreted Labels.\n */\n isSubgraphCompatible: boolean;\n\n /**\n * Version info about ENSIndexer.\n */\n versionInfo: ENSIndexerVersionInfo;\n}\n","import type { ZodCheckFnInput } from \"../../shared/zod-types\";\nimport type { ENSIndexerVersionInfo } from \"./types\";\n\n/**\n * Invariant: ensDb version is same as ensIndexer version\n */\nexport function invariant_ensDbVersionIsSameAsEnsIndexerVersion(\n ctx: ZodCheckFnInput<ENSIndexerVersionInfo>,\n) {\n const versionInfo = ctx.value;\n\n if (versionInfo.ensDb !== versionInfo.ensIndexer) {\n ctx.issues.push({\n code: \"custom\",\n input: versionInfo,\n message: \"`ensDb` version must be same as `ensIndexer` version\",\n });\n }\n}\n","import { z } from \"zod/v4\";\n\n/**\n * Reasons why TheGraph fallback cannot be used.\n */\nexport const TheGraphCannotFallbackReasonSchema = z.enum({\n NotSubgraphCompatible: \"not-subgraph-compatible\",\n NoApiKey: \"no-api-key\",\n NoSubgraphUrl: \"no-subgraph-url\",\n});\n\nexport type TheGraphCannotFallbackReason = z.infer<typeof TheGraphCannotFallbackReasonSchema>;\n\n/**\n * Configuration for TheGraph fallback behavior.\n * Indicates whether fallback to TheGraph is possible and the reason if not.\n */\nexport const TheGraphFallbackSchema = z.discriminatedUnion(\"canFallback\", [\n z.strictObject({\n canFallback: z.literal(true),\n url: z.string(),\n }),\n z.strictObject({\n canFallback: z.literal(false),\n reason: TheGraphCannotFallbackReasonSchema,\n }),\n]);\n\nexport type TheGraphFallback = z.infer<typeof TheGraphFallbackSchema>;\n","import { prettifyError } from \"zod/v4\";\n\nimport type { SerializedENSIndexerPublicConfig } from \"./serialized-types\";\nimport type { ENSIndexerPublicConfig } from \"./types\";\nimport { makeENSIndexerPublicConfigSchema } from \"./zod-schemas\";\n\n/**\n * Serialize a {@link ENSIndexerPublicConfig} object.\n */\nexport function deserializeENSIndexerPublicConfig(\n maybeConfig: SerializedENSIndexerPublicConfig,\n valueLabel?: string,\n): ENSIndexerPublicConfig {\n const schema = makeENSIndexerPublicConfigSchema(valueLabel);\n const parsed = schema.safeParse(maybeConfig);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize ENSIndexerPublicConfig:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n","import { type ByteArray, hexToBytes } from \"viem\";\n\nimport type { LabelHash } from \"../../ens\";\n\n/**\n * Converts a Labelhash to bytes, with validation\n * @param labelHash The Labelhash to convert\n * @returns A ByteArray containing the bytes\n * @throws Error if `labelHash` is not a valid 32-byte hex string\n */\nexport function labelHashToBytes(labelHash: LabelHash): ByteArray {\n try {\n if (labelHash.length !== 66) {\n throw new Error(`Invalid labelHash length ${labelHash.length} characters (expected 66)`);\n }\n if (labelHash !== labelHash.toLowerCase()) {\n throw new Error(\"Labelhash must be in lowercase\");\n }\n if (!labelHash.startsWith(\"0x\")) {\n throw new Error(\"Labelhash must be 0x-prefixed\");\n }\n const bytes = hexToBytes(labelHash);\n if (bytes.length !== 32) {\n // should be redundant but keeping it for the principle of defensive programming\n throw new Error(`Invalid labelHash length ${bytes.length} bytes (expected 32)`);\n }\n return bytes;\n } catch (e) {\n if (e instanceof Error) {\n throw e;\n }\n throw new Error(\"Invalid hex format\");\n }\n}\n","import type {\n EnsRainbowClientLabelSet,\n EnsRainbowServerLabelSet,\n LabelSetId,\n LabelSetVersion,\n} from \"../../ensrainbow\";\nimport { makeLabelSetIdSchema, makeLabelSetVersionSchema } from \"./zod-schemas\";\n\n/**\n * Builds a valid LabelSetId from a string.\n * @param maybeLabelSetId - The string to validate and convert to a LabelSetId.\n * @returns A valid LabelSetId.\n * @throws If the input string is not a valid LabelSetId.\n */\nexport function buildLabelSetId(maybeLabelSetId: string): LabelSetId {\n return makeLabelSetIdSchema(\"LabelSetId\").parse(maybeLabelSetId);\n}\n\n/**\n * Builds a valid LabelSetVersion from a number or string.\n * @param maybeLabelSetVersion - The number or string to validate and convert to a LabelSetVersion.\n * @returns A valid LabelSetVersion.\n * @throws If the input is not a valid LabelSetVersion.\n */\nexport function buildLabelSetVersion(maybeLabelSetVersion: number | string): LabelSetVersion {\n return makeLabelSetVersionSchema(\"LabelSetVersion\").parse(maybeLabelSetVersion);\n}\n\n/**\n * Builds an EnsRainbowClientLabelSet.\n * @param labelSetId - The label set ID.\n * @param labelSetVersion - The label set version.\n * @returns A valid EnsRainbowClientLabelSet object.\n * @throws If `labelSetVersion` is defined without `labelSetId`.\n */\nexport function buildEnsRainbowClientLabelSet(\n labelSetId?: LabelSetId,\n labelSetVersion?: LabelSetVersion,\n): EnsRainbowClientLabelSet {\n if (labelSetVersion !== undefined && labelSetId === undefined) {\n throw new Error(\"When a labelSetVersion is defined, labelSetId must also be defined.\");\n }\n\n return { labelSetId, labelSetVersion };\n}\n\n/**\n * Validates that the server's label set is compatible with the client's requested label set.\n * @param serverSet - The label set provided by the server.\n * @param clientSet - The label set requested by the client.\n * @throws If the server set is not compatible with the client set.\n */\nexport function validateSupportedLabelSetAndVersion(\n serverSet: EnsRainbowServerLabelSet,\n clientSet: EnsRainbowClientLabelSet,\n): void {\n if (clientSet.labelSetId === undefined) {\n // Client did not specify a label set, so any server set is acceptable.\n return;\n }\n\n if (serverSet.labelSetId !== clientSet.labelSetId) {\n throw new Error(\n `Server label set ID \"${serverSet.labelSetId}\" does not match client's requested label set ID \"${clientSet.labelSetId}\".`,\n );\n }\n\n if (\n clientSet.labelSetVersion !== undefined &&\n serverSet.highestLabelSetVersion < clientSet.labelSetVersion\n ) {\n throw new Error(\n `Server highest label set version ${serverSet.highestLabelSetVersion} is less than client's requested version ${clientSet.labelSetVersion} for label set ID \"${clientSet.labelSetId}\".`,\n );\n }\n}\n","/**\n * Parses a string into a non-negative integer.\n * @param input The string to parse\n * @returns The parsed non-negative integer\n * @throws Error if the input is not a valid non-negative integer\n */\nexport function parseNonNegativeInteger(maybeNumber: string): number {\n const trimmed = maybeNumber.trim();\n\n // Check for empty strings\n if (!trimmed) {\n throw new Error(\"Input cannot be empty\");\n }\n\n // Check for -0\n if (trimmed === \"-0\") {\n throw new Error(\"Negative zero is not a valid non-negative integer\");\n }\n\n const num = Number(maybeNumber);\n\n // Check if it's not a number\n if (Number.isNaN(num)) {\n throw new Error(`\"${maybeNumber}\" is not a valid number`);\n }\n\n // Check if it's not finite\n if (!Number.isFinite(num)) {\n throw new Error(`\"${maybeNumber}\" is not a finite number`);\n }\n\n // Check if it's not an integer\n if (!Number.isInteger(num)) {\n throw new Error(`\"${maybeNumber}\" is not an integer`);\n }\n\n // Check if it's negative\n if (num < 0) {\n throw new Error(`\"${maybeNumber}\" is not a non-negative integer`);\n }\n\n return num;\n}\n","import type { ChainId } from \"../../shared\";\nimport type {\n SerializedENSIndexerPublicConfig,\n SerializedIndexedChainIds,\n} from \"./serialized-types\";\nimport type { ENSIndexerPublicConfig } from \"./types\";\n\n/**\n * Serializes a {@link ChainConfig} object.\n */\nexport function serializeIndexedChainIds(indexedChainIds: Set<ChainId>): SerializedIndexedChainIds {\n return Array.from(indexedChainIds);\n}\n/**\n * Serialize a {@link ENSIndexerPublicConfig} object.\n */\nexport function serializeENSIndexerPublicConfig(\n config: ENSIndexerPublicConfig,\n): SerializedENSIndexerPublicConfig {\n const {\n labelSet,\n indexedChainIds,\n databaseSchemaName,\n isSubgraphCompatible,\n namespace,\n plugins,\n versionInfo,\n } = config;\n\n return {\n labelSet,\n indexedChainIds: serializeIndexedChainIds(indexedChainIds),\n databaseSchemaName,\n isSubgraphCompatible,\n namespace,\n plugins,\n versionInfo,\n } satisfies SerializedENSIndexerPublicConfig;\n}\n","import { prettifyError } from \"zod/v4\";\n\nimport type {\n SerializedChainIndexingStatusSnapshot,\n SerializedCrossChainIndexingStatusSnapshot,\n SerializedOmnichainIndexingStatusSnapshot,\n SerializedRealtimeIndexingStatusProjection,\n} from \"./serialized-types\";\nimport type {\n ChainIndexingStatusSnapshot,\n CrossChainIndexingStatusSnapshot,\n OmnichainIndexingStatusSnapshot,\n RealtimeIndexingStatusProjection,\n} from \"./types\";\nimport {\n makeChainIndexingStatusSnapshotSchema,\n makeCrossChainIndexingStatusSnapshotSchema,\n makeOmnichainIndexingStatusSnapshotSchema,\n makeRealtimeIndexingStatusProjectionSchema,\n} from \"./zod-schemas\";\n\n/**\n * Deserialize into a {@link ChainIndexingSnapshot} object.\n */\nexport function deserializeChainIndexingStatusSnapshot(\n maybeSnapshot: SerializedChainIndexingStatusSnapshot,\n valueLabel?: string,\n): ChainIndexingStatusSnapshot {\n const schema = makeChainIndexingStatusSnapshotSchema(valueLabel);\n const parsed = schema.safeParse(maybeSnapshot);\n\n if (parsed.error) {\n throw new Error(\n `Cannot deserialize into ChainIndexingStatusSnapshot:\\n${prettifyError(parsed.error)}\\n`,\n );\n }\n\n return parsed.data;\n}\n\n/**\n * Deserialize an {@link OmnichainIndexingStatusSnapshot} object.\n */\nexport function deserializeOmnichainIndexingStatusSnapshot(\n maybeSnapshot: SerializedOmnichainIndexingStatusSnapshot,\n valueLabel?: string,\n): OmnichainIndexingStatusSnapshot {\n const schema = makeOmnichainIndexingStatusSnapshotSchema(valueLabel);\n const parsed = schema.safeParse(maybeSnapshot);\n\n if (parsed.error) {\n throw new Error(\n `Cannot deserialize into OmnichainIndexingStatusSnapshot:\\n${prettifyError(parsed.error)}\\n`,\n );\n }\n\n return parsed.data;\n}\n\n/**\n * Deserialize an {@link CrossChainIndexingStatusSnapshot} object.\n */\nexport function deserializeCrossChainIndexingStatusSnapshot(\n maybeSnapshot: SerializedCrossChainIndexingStatusSnapshot,\n valueLabel?: string,\n): CrossChainIndexingStatusSnapshot {\n const schema = makeCrossChainIndexingStatusSnapshotSchema(valueLabel);\n const parsed = schema.safeParse(maybeSnapshot);\n\n if (parsed.error) {\n throw new Error(\n `Cannot deserialize into CrossChainIndexingStatusSnapshot:\\n${prettifyError(parsed.error)}\\n`,\n );\n }\n\n return parsed.data;\n}\n\n/**\n * Deserialize into a {@link RealtimeIndexingStatusProjection} object.\n */\nexport function deserializeRealtimeIndexingStatusProjection(\n maybeProjection: SerializedRealtimeIndexingStatusProjection,\n valueLabel?: string,\n): RealtimeIndexingStatusProjection {\n const schema = makeRealtimeIndexingStatusProjectionSchema(valueLabel);\n const parsed = schema.safeParse(maybeProjection);\n\n if (parsed.error) {\n throw new Error(\n `Cannot deserialize into RealtimeIndexingStatusProjection:\\n${prettifyError(parsed.error)}\\n`,\n );\n }\n\n return parsed.data;\n}\n","/**\n * All zod schemas we define must remain internal implementation details.\n * We want the freedom to move away from zod in the future without impacting\n * any users of the ensnode-sdk package.\n *\n * The only way to share Zod schemas is to re-export them from\n * `./src/internal.ts` file.\n */\nimport { z } from \"zod/v4\";\n\nimport { type ChainId, deserializeChainId } from \"../../shared\";\nimport {\n makeBlockRefSchema,\n makeChainIdStringSchema,\n makeDurationSchema,\n makeUnixTimestampSchema,\n} from \"../../shared/zod-schemas\";\nimport {\n ChainIndexingConfig,\n ChainIndexingConfigTypeIds,\n ChainIndexingStatusIds,\n type ChainIndexingStatusSnapshot,\n ChainIndexingStatusSnapshotBackfill,\n type ChainIndexingStatusSnapshotCompleted,\n ChainIndexingStatusSnapshotFollowing,\n type ChainIndexingStatusSnapshotForOmnichainIndexingStatusSnapshotBackfill,\n type ChainIndexingStatusSnapshotQueued,\n CrossChainIndexingStatusSnapshot,\n CrossChainIndexingStatusSnapshotOmnichain,\n CrossChainIndexingStrategyIds,\n OmnichainIndexingStatusIds,\n OmnichainIndexingStatusSnapshotBackfill,\n OmnichainIndexingStatusSnapshotCompleted,\n OmnichainIndexingStatusSnapshotFollowing,\n OmnichainIndexingStatusSnapshotUnstarted,\n RealtimeIndexingStatusProjection,\n} from \"./types\";\nimport {\n invariant_chainSnapshotBackfillBlocks,\n invariant_chainSnapshotCompletedBlocks,\n invariant_chainSnapshotFollowingBlocks,\n invariant_chainSnapshotQueuedBlocks,\n invariant_omnichainIndexingCursorIsEqualToHighestLatestIndexedBlockAcrossIndexedChain,\n invariant_omnichainIndexingCursorLowerThanEarliestStartBlockAcrossQueuedChains,\n invariant_omnichainIndexingCursorLowerThanOrEqualToLatestBackfillEndBlockAcrossBackfillChains,\n invariant_omnichainSnapshotStatusIsConsistentWithChainSnapshot,\n invariant_omnichainSnapshotUnstartedHasValidChains,\n invariant_omnichainStatusSnapshotBackfillHasValidChains,\n invariant_omnichainStatusSnapshotCompletedHasValidChains,\n invariant_realtimeIndexingStatusProjectionProjectedAtIsAfterOrEqualToSnapshotTime,\n invariant_realtimeIndexingStatusProjectionWorstCaseDistanceIsCorrect,\n invariant_slowestChainEqualsToOmnichainSnapshotTime,\n invariant_snapshotTimeIsTheHighestKnownBlockTimestamp,\n} from \"./validations\";\n\n/**\n * Makes Zod schema for {@link ChainIndexingConfig} type.\n */\nconst makeChainIndexingConfigSchema = (valueLabel: string = \"Value\") =>\n z.discriminatedUnion(\"configType\", [\n z.strictObject({\n configType: z.literal(ChainIndexingConfigTypeIds.Indefinite),\n startBlock: makeBlockRefSchema(valueLabel),\n }),\n z.strictObject({\n configType: z.literal(ChainIndexingConfigTypeIds.Definite),\n startBlock: makeBlockRefSchema(valueLabel),\n endBlock: makeBlockRefSchema(valueLabel),\n }),\n ]);\n\n/**\n * Makes Zod schema for {@link ChainIndexingStatusSnapshotQueued} type.\n */\nexport const makeChainIndexingStatusSnapshotQueuedSchema = (valueLabel: string = \"Value\") =>\n z\n .strictObject({\n chainStatus: z.literal(ChainIndexingStatusIds.Queued),\n config: makeChainIndexingConfigSchema(valueLabel),\n })\n .check(invariant_chainSnapshotQueuedBlocks);\n\n/**\n * Makes Zod schema for {@link ChainIndexingStatusSnapshotBackfill} type.\n */\nexport const makeChainIndexingStatusSnapshotBackfillSchema = (valueLabel: string = \"Value\") =>\n z\n .strictObject({\n chainStatus: z.literal(ChainIndexingStatusIds.Backfill),\n config: makeChainIndexingConfigSchema(valueLabel),\n latestIndexedBlock: makeBlockRefSchema(valueLabel),\n backfillEndBlock: makeBlockRefSchema(valueLabel),\n })\n .check(invariant_chainSnapshotBackfillBlocks);\n\n/**\n * Makes Zod schema for {@link ChainIndexingStatusSnapshotCompleted} type.\n */\nexport const makeChainIndexingStatusSnapshotCompletedSchema = (valueLabel: string = \"Value\") =>\n z\n .strictObject({\n chainStatus: z.literal(ChainIndexingStatusIds.Completed),\n config: z.strictObject({\n configType: z.literal(ChainIndexingConfigTypeIds.Definite),\n startBlock: makeBlockRefSchema(valueLabel),\n endBlock: makeBlockRefSchema(valueLabel),\n }),\n latestIndexedBlock: makeBlockRefSchema(valueLabel),\n })\n .check(invariant_chainSnapshotCompletedBlocks);\n\n/**\n * Makes Zod schema for {@link ChainIndexingStatusSnapshotFollowing} type.\n */\nexport const makeChainIndexingStatusSnapshotFollowingSchema = (valueLabel: string = \"Value\") =>\n z\n .strictObject({\n chainStatus: z.literal(ChainIndexingStatusIds.Following),\n config: z.strictObject({\n configType: z.literal(ChainIndexingConfigTypeIds.Indefinite),\n startBlock: makeBlockRefSchema(valueLabel),\n }),\n latestIndexedBlock: makeBlockRefSchema(valueLabel),\n latestKnownBlock: makeBlockRefSchema(valueLabel),\n })\n .check(invariant_chainSnapshotFollowingBlocks);\n\n/**\n * Makes Zod schema for {@link ChainIndexingStatusSnapshot}\n */\nexport const makeChainIndexingStatusSnapshotSchema = (valueLabel: string = \"Value\") =>\n z.discriminatedUnion(\"chainStatus\", [\n makeChainIndexingStatusSnapshotQueuedSchema(valueLabel),\n makeChainIndexingStatusSnapshotBackfillSchema(valueLabel),\n makeChainIndexingStatusSnapshotCompletedSchema(valueLabel),\n makeChainIndexingStatusSnapshotFollowingSchema(valueLabel),\n ]);\n\n/**\n * Makes Zod schema for {@link ChainIndexingStatusSnapshot} per chain.\n */\nexport const makeChainIndexingStatusesSchema = (valueLabel: string = \"Value\") =>\n z\n .record(makeChainIdStringSchema(), makeChainIndexingStatusSnapshotSchema(valueLabel), {\n error:\n \"Chains indexing statuses must be an object mapping valid chain IDs to their indexing status snapshots.\",\n })\n .transform((serializedChainsIndexingStatus) => {\n const chainsIndexingStatus = new Map<ChainId, ChainIndexingStatusSnapshot>();\n\n for (const [chainIdString, chainStatus] of Object.entries(serializedChainsIndexingStatus)) {\n chainsIndexingStatus.set(deserializeChainId(chainIdString), chainStatus);\n }\n\n return chainsIndexingStatus;\n });\n\n/**\n * Makes Zod schema for {@link OmnichainIndexingStatusSnapshotUnstarted}\n */\nconst makeOmnichainIndexingStatusSnapshotUnstartedSchema = (valueLabel?: string) =>\n z.strictObject({\n omnichainStatus: z.literal(OmnichainIndexingStatusIds.Unstarted),\n chains: makeChainIndexingStatusesSchema(valueLabel)\n .check(invariant_omnichainSnapshotUnstartedHasValidChains)\n .transform((chains) => chains as Map<ChainId, ChainIndexingStatusSnapshotQueued>),\n omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel),\n });\n\n/**\n * Makes Zod schema for {@link OmnichainIndexingStatusSnapshotBackfill}\n */\nconst makeOmnichainIndexingStatusSnapshotBackfillSchema = (valueLabel?: string) =>\n z.strictObject({\n omnichainStatus: z.literal(OmnichainIndexingStatusIds.Backfill),\n chains: makeChainIndexingStatusesSchema(valueLabel)\n .check(invariant_omnichainStatusSnapshotBackfillHasValidChains)\n .transform(\n (chains) =>\n chains as Map<\n ChainId,\n ChainIndexingStatusSnapshotForOmnichainIndexingStatusSnapshotBackfill\n >,\n ),\n omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel),\n });\n\n/**\n * Makes Zod schema for {@link OmnichainIndexingStatusSnapshotCompleted}\n */\nconst makeOmnichainIndexingStatusSnapshotCompletedSchema = (valueLabel?: string) =>\n z.strictObject({\n omnichainStatus: z.literal(OmnichainIndexingStatusIds.Completed),\n chains: makeChainIndexingStatusesSchema(valueLabel)\n .check(invariant_omnichainStatusSnapshotCompletedHasValidChains)\n .transform((chains) => chains as Map<ChainId, ChainIndexingStatusSnapshotCompleted>),\n omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel),\n });\n\n/**\n * Makes Zod schema for {@link OmnichainIndexingStatusSnapshotFollowing}\n */\nconst makeOmnichainIndexingStatusSnapshotFollowingSchema = (valueLabel?: string) =>\n z.strictObject({\n omnichainStatus: z.literal(OmnichainIndexingStatusIds.Following),\n chains: makeChainIndexingStatusesSchema(valueLabel),\n omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel),\n });\n\n/**\n * Omnichain Indexing Snapshot Schema\n *\n * Makes a Zod schema definition for validating indexing snapshot\n * across all chains indexed by ENSIndexer instance.\n */\nexport const makeOmnichainIndexingStatusSnapshotSchema = (\n valueLabel: string = \"Omnichain Indexing Snapshot\",\n) =>\n z\n .discriminatedUnion(\"omnichainStatus\", [\n makeOmnichainIndexingStatusSnapshotUnstartedSchema(valueLabel),\n makeOmnichainIndexingStatusSnapshotBackfillSchema(valueLabel),\n makeOmnichainIndexingStatusSnapshotCompletedSchema(valueLabel),\n makeOmnichainIndexingStatusSnapshotFollowingSchema(valueLabel),\n ])\n .check(invariant_omnichainSnapshotStatusIsConsistentWithChainSnapshot)\n .check(invariant_omnichainIndexingCursorLowerThanEarliestStartBlockAcrossQueuedChains)\n .check(\n invariant_omnichainIndexingCursorLowerThanOrEqualToLatestBackfillEndBlockAcrossBackfillChains,\n )\n .check(invariant_omnichainIndexingCursorIsEqualToHighestLatestIndexedBlockAcrossIndexedChain);\n\n/**\n * Makes Zod schema for {@link CrossChainIndexingStatusSnapshotOmnichain}\n */\nconst makeCrossChainIndexingStatusSnapshotOmnichainSchema = (\n valueLabel: string = \"Cross-chain Indexing Status Snapshot Omnichain\",\n) =>\n z\n .strictObject({\n strategy: z.literal(CrossChainIndexingStrategyIds.Omnichain),\n slowestChainIndexingCursor: makeUnixTimestampSchema(valueLabel),\n snapshotTime: makeUnixTimestampSchema(valueLabel),\n omnichainSnapshot: makeOmnichainIndexingStatusSnapshotSchema(valueLabel),\n })\n .check(invariant_slowestChainEqualsToOmnichainSnapshotTime)\n .check(invariant_snapshotTimeIsTheHighestKnownBlockTimestamp);\n\n/**\n * Makes Zod schema for {@link CrossChainIndexingStatusSnapshot}\n */\nexport const makeCrossChainIndexingStatusSnapshotSchema = (\n valueLabel: string = \"Cross-chain Indexing Status Snapshot\",\n) =>\n z.discriminatedUnion(\"strategy\", [\n makeCrossChainIndexingStatusSnapshotOmnichainSchema(valueLabel),\n ]);\n\n/**\n * Makes Zod schema for {@link RealtimeIndexingStatusProjection}\n */\nexport const makeRealtimeIndexingStatusProjectionSchema = (\n valueLabel: string = \"Realtime Indexing Status Projection\",\n) =>\n z\n .strictObject({\n projectedAt: makeUnixTimestampSchema(valueLabel),\n worstCaseDistance: makeDurationSchema(valueLabel),\n snapshot: makeCrossChainIndexingStatusSnapshotSchema(valueLabel),\n })\n .check(invariant_realtimeIndexingStatusProjectionProjectedAtIsAfterOrEqualToSnapshotTime)\n .check(invariant_realtimeIndexingStatusProjectionWorstCaseDistanceIsCorrect);\n","import type { BlockRef, ChainId, Duration, UnixTimestamp } from \"../../shared\";\n\n/**\n * The type of indexing configuration for a chain.\n */\nexport const ChainIndexingConfigTypeIds = {\n /**\n * Represents that indexing of the chain should be performed for an indefinite range.\n */\n Indefinite: \"indefinite\",\n\n /**\n * Represents that indexing of the chain should be performed for a definite range.\n */\n Definite: \"definite\",\n} as const;\n\n/**\n * The derived string union of possible {@link ChainIndexingConfigTypeIds}.\n */\nexport type ChainIndexingConfigTypeId =\n (typeof ChainIndexingConfigTypeIds)[keyof typeof ChainIndexingConfigTypeIds];\n\n/**\n * Chain indexing config for a chain whose indexing config `configType` is\n * {@link ChainIndexingConfigTypeIds.Indefinite}.\n *\n * Invariants:\n * - `configType` is always `ChainIndexingConfigTypeIds.Indefinite`.\n */\nexport interface ChainIndexingConfigIndefinite {\n /**\n * The type of chain indexing config.\n */\n configType: typeof ChainIndexingConfigTypeIds.Indefinite;\n\n /**\n * A {@link BlockRef} to the block where indexing of the chain should start.\n */\n startBlock: BlockRef;\n}\n\n/**\n * Chain indexing config for a chain whose indexing config `configType` is\n * {@link ChainIndexingConfigTypeIds.Definite}.\n *\n * Invariants:\n * - `configType` is always `ChainIndexingConfigTypeIds.Definite`.\n * - `startBlock` is always before or the same as `endBlock`.\n */\nexport interface ChainIndexingConfigDefinite {\n /**\n * The type of chain indexing config.\n */\n configType: typeof ChainIndexingConfigTypeIds.Definite;\n\n /**\n * A {@link BlockRef} to the block where indexing of the chain should start.\n */\n startBlock: BlockRef;\n\n /**\n * A {@link BlockRef} to the block where indexing of the chain should end.\n */\n endBlock: BlockRef;\n}\n\n/**\n * Indexing configuration for a chain.\n *\n * Use the `configType` field to determine the specific type interpretation\n * at runtime.\n */\nexport type ChainIndexingConfig = ChainIndexingConfigIndefinite | ChainIndexingConfigDefinite;\n\n/**\n * The status of indexing a chain at the time an indexing status snapshot\n * is captured.\n */\nexport const ChainIndexingStatusIds = {\n /**\n * Represents that indexing of the chain is not ready to begin yet because:\n * - ENSIndexer is in its initialization phase and the data to build a\n * \"true\" {@link ChainIndexingSnapshot} for the chain is still being loaded; or\n * - ENSIndexer is using an omnichain indexing strategy and the\n * `omnichainIndexingCursor` is <= `config.startBlock.timestamp` for the chain's\n * {@link ChainIndexingSnapshot}.\n */\n Queued: \"chain-queued\",\n\n /**\n * Represents that indexing of the chain is in progress and under a special\n * \"backfill\" phase that optimizes for accelerated indexing until reaching the\n * \"fixed target\" `backfillEndBlock`.\n */\n Backfill: \"chain-backfill\",\n\n /**\n * Represents that the \"backfill\" phase of indexing the chain is completed\n * and that the chain is configured to be indexed for an indefinite range.\n * Therefore, indexing of the chain remains indefinitely in progress where\n * ENSIndexer will continuously work to discover and index new blocks as they\n * are added to the chain across time.\n */\n Following: \"chain-following\",\n\n /**\n * Represents that indexing of the chain is completed as the chain is configured\n * to be indexed for a definite range and the indexing of all blocks through\n * that definite range is completed.\n */\n Completed: \"chain-completed\",\n} as const;\n\n/**\n * The derived string union of possible {@link ChainIndexingStatusIds}.\n */\nexport type ChainIndexingStatusId =\n (typeof ChainIndexingStatusIds)[keyof typeof ChainIndexingStatusIds];\n\n/**\n * Chain indexing status snapshot for a chain whose `chainStatus` is\n * {@link ChainIndexingStatusIds.Queued}.\n *\n * Invariants:\n * - `chainStatus` is always {@link ChainIndexingStatusIds.Queued}.\n */\nexport interface ChainIndexingStatusSnapshotQueued {\n /**\n * The status of indexing the chain at the time the indexing status snapshot\n * was captured.\n */\n chainStatus: typeof ChainIndexingStatusIds.Queued;\n\n /**\n * The indexing configuration of the chain.\n */\n config: ChainIndexingConfig;\n}\n\n/**\n * Chain indexing status snapshot for a chain whose `chainStatus` is\n * {@link ChainIndexingStatusIds.Backfill}.\n *\n * During a backfill, special performance optimizations are applied to\n * index all blocks between `config.startBlock` and `backfillEndBlock`\n * as fast as possible.\n *\n * Note how `backfillEndBlock` is a \"fixed target\" that does not change during\n * the lifetime of an ENSIndexer process instance:\n * - If the `config` is {@link ChainIndexingConfigDefinite}:\n * `backfillEndBlock` is always the same as `config.endBlock`.\n * - If the `config` is {@link ChainIndexingConfigIndefinite}:\n * `backfillEndBlock` is a {@link BlockRef} to what was the latest block on the\n * chain when the ENSIndexer process was performing its initialization. Note how\n * this means that if the backfill process takes X hours to complete, because the\n * `backfillEndBlock` is a \"fixed target\", when `chainStatus` transitions to\n * {@link ChainIndexingStatusIds.Following} the chain will be X hours behind\n * \"realtime\" indexing.\n *\n * When `latestIndexedBlock` reaches `backfillEndBlock` the backfill is complete.\n * The moment backfill is complete the `chainStatus` may not immediately transition.\n * Instead, internal processing is completed for a period of time while\n * `chainStatus` remains {@link ChainIndexingStatusIds.Backfill}. After this internal\n * processing is completed `chainStatus` will transition:\n * - to {@link ChainIndexingStatusIds.Following} if the `config` is\n * {@link ChainIndexingConfigIndefinite}.\n * - to {@link ChainIndexingStatusIds.Completed} if the `config` is\n * {@link ChainIndexingConfigDefinite}.\n *\n * Invariants:\n * - `chainStatus` is always {@link ChainIndexingStatusIds.Backfill}.\n * - `config.startBlock` is always before or the same as `latestIndexedBlock`\n * - `config.endBlock` is always the same as `backfillEndBlock` if and only if\n * the config is {@link ChainIndexingConfigDefinite}.\n * - `latestIndexedBlock` is always before or the same as `backfillEndBlock`\n */\nexport interface ChainIndexingStatusSnapshotBackfill {\n /**\n * The status of indexing the chain at the time the indexing status snapshot\n * was captured.\n */\n chainStatus: typeof ChainIndexingStatusIds.Backfill;\n\n /**\n * The indexing configuration of the chain.\n */\n config: ChainIndexingConfig;\n\n /**\n * A {@link BlockRef} to the block that was most recently indexed as of the time the\n * indexing status snapshot was captured.\n */\n latestIndexedBlock: BlockRef;\n\n /**\n * A {@link BlockRef} to the block where the backfill will end.\n */\n backfillEndBlock: BlockRef;\n}\n\n/**\n * Chain indexing status snapshot for a chain whose `chainStatus` is\n * {@link ChainIndexingStatusIds.Following}.\n *\n * Invariants:\n * - `chainStatus` is always {@link ChainIndexingStatusIds.Following}.\n * - `config` is always {@link ChainIndexingConfigIndefinite}\n * - `config.startBlock` is always before or the same as `latestIndexedBlock`\n * - `latestIndexedBlock` is always before or the same as `latestKnownBlock`\n */\nexport interface ChainIndexingStatusSnapshotFollowing {\n /**\n * The status of indexing the chain at the time the indexing status snapshot\n * was captured.\n */\n chainStatus: typeof ChainIndexingStatusIds.Following;\n\n /**\n * The indexing configuration of the chain.\n */\n config: ChainIndexingConfigIndefinite;\n\n /**\n * A {@link BlockRef} to the block that was most recently indexed as of the time the\n * indexing status snapshot was captured.\n */\n latestIndexedBlock: BlockRef;\n\n /**\n * A {@link BlockRef} to the \"highest\" block that has been discovered by RPCs\n * and stored in the RPC cache as of the time the indexing status snapshot was\n * captured.\n */\n latestKnownBlock: BlockRef;\n}\n\n/**\n * Chain indexing status snapshot for a chain whose `chainStatus` is\n * {@link ChainIndexingStatusIds.Completed}.\n *\n * After the backfill of a chain is completed, if the chain was configured\n * to be indexed for a definite range, the chain indexing status will transition to\n * {@link ChainIndexingStatusIds.Completed}.\n *\n * Invariants:\n * - `chainStatus` is always {@link ChainIndexingStatusIds.Completed}.\n * - `config` is always {@link ChainIndexingConfigDefinite}\n * - `config.startBlock` is always before or the same as `latestIndexedBlock`\n * - `latestIndexedBlock` is always the same as `config.endBlock`.\n */\nexport interface ChainIndexingStatusSnapshotCompleted {\n /**\n * The status of indexing the chain at the time the indexing status snapshot\n * was captured.\n */\n chainStatus: typeof ChainIndexingStatusIds.Completed;\n\n /**\n * The indexing configuration of the chain.\n */\n config: ChainIndexingConfigDefinite;\n\n /**\n * A {@link BlockRef} to the block that was most recently indexed as of the time the\n * indexing status snapshot was captured.\n */\n latestIndexedBlock: BlockRef;\n}\n\n/**\n * Indexing status snapshot for a single chain.\n *\n * Use the `chainStatus` field to determine the specific type interpretation\n * at runtime.\n */\nexport type ChainIndexingStatusSnapshot =\n | ChainIndexingStatusSnapshotQueued\n | ChainIndexingStatusSnapshotBackfill\n | ChainIndexingStatusSnapshotFollowing\n | ChainIndexingStatusSnapshotCompleted;\n\n/**\n * The status of omnichain indexing at the time an omnichain indexing status\n * snapshot is captured.\n */\nexport const OmnichainIndexingStatusIds = {\n /**\n * Represents that omnichain indexing is not ready to begin yet because\n * ENSIndexer is in its initialization phase and the data to build a \"true\"\n * {@link OmnichainIndexingStatusSnapshot} is still being loaded.\n */\n Unstarted: \"omnichain-unstarted\",\n\n /**\n * Represents that omnichain indexing is in an overall \"backfill\" status because\n * - At least one indexed chain has a `chainStatus` of\n * {@link ChainIndexingStatusIds.Backfill}; and\n * - No indexed chain has a `chainStatus` of {@link ChainIndexingStatusIds.Following}.\n */\n Backfill: \"omnichain-backfill\",\n\n /**\n * Represents that omnichain indexing is in an overall \"following\" status because\n * at least one indexed chain has a `chainStatus` of\n * {@link ChainIndexingStatusIds.Following}.\n */\n Following: \"omnichain-following\",\n\n /**\n * Represents that omnichain indexing has completed because all indexed chains have\n * a `chainStatus` of {@link ChainIndexingStatusIds.Completed}.\n */\n Completed: \"omnichain-completed\",\n} as const;\n\n/**\n * The derived string union of possible {@link OmnichainIndexingStatusIds}.\n */\nexport type OmnichainIndexingStatusId =\n (typeof OmnichainIndexingStatusIds)[keyof typeof OmnichainIndexingStatusIds];\n\n/**\n * Omnichain indexing status snapshot when the overall `omnichainStatus` is\n * {@link OmnichainIndexingStatusIds.Unstarted}.\n *\n * Invariants:\n * - `omnichainStatus` is always {@link OmnichainIndexingStatusIds.Unstarted}.\n * - `chains` is always a map to {@link ChainIndexingStatusSnapshotQueued} values exclusively.\n * - `omnichainIndexingCursor` is always < the `config.startBlock.timestamp` for all\n * chains with `chainStatus` of {@link ChainIndexingStatusIds.Queued}.\n */\nexport interface OmnichainIndexingStatusSnapshotUnstarted {\n /**\n * The status of omnichain indexing.\n */\n omnichainStatus: typeof OmnichainIndexingStatusIds.Unstarted;\n\n /**\n * The indexing status snapshot for each indexed chain.\n */\n chains: Map<ChainId, ChainIndexingStatusSnapshotQueued>;\n\n /**\n * The timestamp of omnichain indexing progress across all indexed chains.\n */\n omnichainIndexingCursor: UnixTimestamp;\n}\n\n/**\n * The range of {@link ChainIndexingSnapshot} types allowed when the\n * overall omnichain indexing status is {@link OmnichainIndexingStatusIds.Backfill}.\n *\n * Note that this is all of the {@link ChainIndexingSnapshot} types with the exception\n * of {@link ChainIndexingStatusSnapshotFollowing}.\n */\nexport type ChainIndexingStatusSnapshotForOmnichainIndexingStatusSnapshotBackfill =\n | ChainIndexingStatusSnapshotQueued\n | ChainIndexingStatusSnapshotBackfill\n | ChainIndexingStatusSnapshotCompleted;\n\n/**\n * Omnichain indexing status snapshot when the `omnichainStatus` is\n * {@link OmnichainIndexingStatusIds.Backfill}.\n *\n * Invariants:\n * - `omnichainStatus` is always {@link OmnichainIndexingStatusIds.Backfill}.\n * - `chains` is guaranteed to contain at least one chain with a `chainStatus` of\n * {@link ChainIndexingStatusIds.Backfill}.\n * - `chains` is guaranteed to not to contain any chain with a `chainStatus` of\n * {@link ChainIndexingStatusIds.Following}\n * - `omnichainIndexingCursor` is always < the `config.startBlock.timestamp` for all\n * chains with `chainStatus` of {@link ChainIndexingStatusIds.Queued}.\n * - `omnichainIndexingCursor` is always <= the `backfillEndBlock.timestamp` for all\n * chains with `chainStatus` of {@link ChainIndexingStatusIds.Backfill}.\n * - `omnichainIndexingCursor` is always >= the `latestIndexedBlock.timestamp` for all\n * chains with `chainStatus` of {@link ChainIndexingStatusIds.Completed}.\n * - `omnichainIndexingCursor` is always equal to the timestamp of the highest\n * `latestIndexedBlock` across all chains that have started indexing\n * (`chainStatus` is not {@link ChainIndexingStatusIds.Queued}).\n */\nexport interface OmnichainIndexingStatusSnapshotBackfill {\n /**\n * The status of omnichain indexing.\n */\n omnichainStatus: typeof OmnichainIndexingStatusIds.Backfill;\n\n /**\n * The indexing status snapshot for each indexed chain.\n */\n chains: Map<ChainId, ChainIndexingStatusSnapshotForOmnichainIndexingStatusSnapshotBackfill>;\n\n /**\n * The timestamp of omnichain indexing progress across all indexed chains.\n */\n omnichainIndexingCursor: UnixTimestamp;\n}\n\n/**\n * Omnichain indexing status snapshot when the overall `omnichainStatus` is\n * {@link OmnichainIndexingStatusIds.Following}.\n *\n * Invariants:\n * - `omnichainStatus` is always {@link OmnichainIndexingStatusIds.Following}.\n * - `chains` is guaranteed to contain at least one chain with a `status` of\n * {@link ChainIndexingStatusIds.Following}.\n * - `omnichainIndexingCursor` is always < the `config.startBlock.timestamp` for all\n * chains with `chainStatus` of {@link ChainIndexingStatusIds.Queued}.\n * - `omnichainIndexingCursor` is always <= the `backfillEndBlock.timestamp` for all\n * chains with `chainStatus` of {@link ChainIndexingStatusIds.Backfill}.\n * - `omnichainIndexingCursor` is always >= the `latestIndexedBlock.timestamp` for all\n * chains with `chainStatus` of {@link ChainIndexingStatusIds.Completed}.\n * - `omnichainIndexingCursor` is always equal to the timestamp of the highest\n * `latestIndexedBlock` across all chains that have started indexing\n * (`chainStatus` is not {@link ChainIndexingStatusIds.Queued}).\n */\nexport interface OmnichainIndexingStatusSnapshotFollowing {\n /**\n * The status of omnichain indexing.\n */\n omnichainStatus: typeof OmnichainIndexingStatusIds.Following;\n\n /**\n * The indexing status snapshot for each indexed chain.\n */\n chains: Map<ChainId, ChainIndexingStatusSnapshot>;\n\n /**\n * The timestamp of omnichain indexing progress across all indexed chains.\n */\n omnichainIndexingCursor: UnixTimestamp;\n}\n\n/**\n * Omnichain indexing status snapshot when the overall `omnichainStatus` is\n * {@link OmnichainIndexingStatusIds.Completed}.\n *\n * Invariants:\n * - `omnichainStatus` is always {@link OmnichainIndexingStatusIds.Completed}.\n * - `chains` is always a map to {@link ChainIndexingStatusSnapshotCompleted} values exclusively.\n * - `omnichainIndexingCursor` is always equal to the highest\n * `latestIndexedBlock.timestamp` for all chains.\n */\nexport interface OmnichainIndexingStatusSnapshotCompleted {\n /**\n * The status of omnichain indexing.\n */\n omnichainStatus: typeof OmnichainIndexingStatusIds.Completed;\n\n /**\n * The indexing status snapshot for each indexed chain.\n */\n chains: Map<ChainId, ChainIndexingStatusSnapshotCompleted>;\n\n /**\n * The timestamp of omnichain indexing progress across all indexed chains.\n */\n omnichainIndexingCursor: UnixTimestamp;\n}\n\n/**\n * Omnichain indexing status snapshot for one or more chains.\n *\n * Use the `omnichainStatus` field to determine the specific type interpretation\n * at runtime.\n */\nexport type OmnichainIndexingStatusSnapshot =\n | OmnichainIndexingStatusSnapshotUnstarted\n | OmnichainIndexingStatusSnapshotBackfill\n | OmnichainIndexingStatusSnapshotCompleted\n | OmnichainIndexingStatusSnapshotFollowing;\n\n/**\n * The strategy used for indexing one or more chains.\n *\n * @see https://ponder.sh/docs/api-reference/ponder/config#parameters\n */\nexport const CrossChainIndexingStrategyIds = {\n /**\n * Represents that the indexing of events across all indexed chains will\n * proceed in a deterministic \"omnichain\" ordering by block timestamp, chain ID,\n * and block number.\n *\n * This strategy is \"deterministic\" in that the order of processing cross-chain indexed\n * events and each resulting indexed data state transition recorded in ENSDb is always\n * the same for each ENSIndexer instance operating with an equivalent\n * `ENSIndexerConfig` and ENSIndexer version. However it also has the drawbacks of:\n * - increased indexing latency that must wait for the slowest indexed chain to\n * add new blocks or to discover new blocks through the configured RPCs.\n * - if any indexed chain gets \"stuck\" due to chain or RPC failures, all indexed chains\n * will be affected.\n */\n Omnichain: \"omnichain\",\n} as const;\n\n/**\n * The derived string union of possible {@link CrossChainIndexingStrategyIds}.\n */\nexport type CrossChainIndexingStrategyId =\n (typeof CrossChainIndexingStrategyIds)[keyof typeof CrossChainIndexingStrategyIds];\n\n/**\n * Cross-chain indexing status snapshot when the `strategy` is\n * {@link CrossChainIndexingStrategyId.Omnichain}.\n *\n * Invariants:\n * - `strategy` is always {@link CrossChainIndexingStrategyId.Omnichain}.\n * - `slowestChainIndexingCursor` is always equal to\n * `omnichainSnapshot.omnichainIndexingCursor`.\n * - `snapshotTime` is always >= the \"highest known block timestamp\", defined as the max of:\n * - the `slowestChainIndexingCursor`.\n * - the `config.startBlock.timestamp` for all indexed chains.\n * - the `config.endBlock.timestamp` for all indexed chains with a `config.configType` of\n * {@link ChainIndexingConfigTypeIds.Definite}.\n * - the `backfillEndBlock.timestamp` for all chains with `chainStatus` of\n * {@link ChainIndexingStatusIds.Backfill}.\n * - the `latestKnownBlock.timestamp` for all chains with `chainStatus` of\n * {@link ChainIndexingStatusIds.Following}.\n */\nexport interface CrossChainIndexingStatusSnapshotOmnichain {\n /**\n * The strategy used for indexing one or more chains.\n */\n strategy: typeof CrossChainIndexingStrategyIds.Omnichain;\n\n /**\n * The timestamp of the \"slowest\" latest indexed block timestamp\n * across all indexed chains.\n */\n slowestChainIndexingCursor: UnixTimestamp;\n\n /**\n * The timestamp when the cross-chain indexing status snapshot was generated.\n *\n * Due to possible clock skew between different systems this value must be set\n * to the max of each of the following values to ensure all invariants are followed:\n * - the current system time of the system generating this cross-chain indexing\n * status snapshot.\n * - the \"highest known block timestamp\" (see invariants above for full definition).\n */\n snapshotTime: UnixTimestamp;\n\n /**\n * The omnichain indexing status snapshot for one or more chains.\n */\n omnichainSnapshot: OmnichainIndexingStatusSnapshot;\n}\n\n/**\n * Cross-chain indexing status snapshot for one or more chains.\n *\n * Use the `strategy` field to determine the specific type interpretation\n * at runtime.\n *\n * Currently, only omnichain indexing is supported. This type could theoretically\n * be extended to support other cross-chain indexing strategies in the future,\n * such as Ponder's \"multichain\" indexing strategy that indexes each chain\n * independently without deterministic ordering.\n */\nexport type CrossChainIndexingStatusSnapshot = CrossChainIndexingStatusSnapshotOmnichain;\n\n/**\n * A \"realtime\" indexing status projection based on worst-case assumptions\n * from the `snapshot`.\n *\n * Invariants:\n * - `projectedAt` is always >= `snapshot.snapshotTime`.\n * - `worstCaseDistance` is always equal to\n * `projectedAt - snapshot.slowestChainIndexingCursor`.\n */\nexport type RealtimeIndexingStatusProjection = {\n /**\n * The timestamp representing \"now\" as of the time this projection was generated.\n */\n projectedAt: UnixTimestamp;\n\n /**\n * The distance between `projectedAt` and `snapshot.slowestChainIndexingCursor`.\n *\n * This is \"worst-case\" because it assumes all of the following:\n * - the `snapshot` (which may have `snapshot.snapshotTime < projectedAt`) is still the\n * latest snapshot and no indexing progress has been made since `snapshotTime`.\n * - each indexed chain has added a new block as of `projectedAt`.\n */\n worstCaseDistance: Duration;\n\n /**\n * The {@link CrossChainIndexingStatusSnapshot} that this projection is based on.\n */\n snapshot: CrossChainIndexingStatusSnapshot;\n};\n","import type { BlockRef } from \"./types\";\n\n/**\n * Compare two {@link BlockRef} object to check\n * if blockA is before blockB.\n */\nexport function isBefore(blockA: BlockRef, blockB: BlockRef) {\n return blockA.number < blockB.number && blockA.timestamp < blockB.timestamp;\n}\n\n/**\n * Compare two {@link BlockRef} object to check\n * if blockA is equal to blockB.\n */\nexport function isEqualTo(blockA: BlockRef, blockB: BlockRef) {\n return blockA.number === blockB.number && blockA.timestamp === blockB.timestamp;\n}\n\n/**\n * Compare two {@link BlockRef} object to check\n * if blockA is before or equal to blockB.\n */\nexport function isBeforeOrEqualTo(blockA: BlockRef, blockB: BlockRef) {\n return isBefore(blockA, blockB) || isEqualTo(blockA, blockB);\n}\n","import type { BlockRef, ChainId, UnixTimestamp } from \"../../shared\";\nimport {\n type ChainIndexingConfig,\n type ChainIndexingConfigDefinite,\n type ChainIndexingConfigIndefinite,\n ChainIndexingConfigTypeIds,\n ChainIndexingStatusIds,\n type ChainIndexingStatusSnapshot,\n type ChainIndexingStatusSnapshotCompleted,\n type ChainIndexingStatusSnapshotForOmnichainIndexingStatusSnapshotBackfill,\n type ChainIndexingStatusSnapshotQueued,\n type CrossChainIndexingStatusSnapshot,\n type OmnichainIndexingStatusId,\n OmnichainIndexingStatusIds,\n} from \"./types\";\n\n/**\n * Get {@link OmnichainIndexingStatusId} based on indexed chains' statuses.\n *\n * This function decides what is the `OmnichainIndexingStatusId` is,\n * based on provided chain indexing statuses.\n *\n * @throws an error if unable to determine overall indexing status\n */\nexport function getOmnichainIndexingStatus(\n chains: ChainIndexingStatusSnapshot[],\n): OmnichainIndexingStatusId {\n if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing(chains)) {\n return OmnichainIndexingStatusIds.Following;\n }\n\n if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill(chains)) {\n return OmnichainIndexingStatusIds.Backfill;\n }\n\n if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted(chains)) {\n return OmnichainIndexingStatusIds.Unstarted;\n }\n\n if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted(chains)) {\n return OmnichainIndexingStatusIds.Completed;\n }\n\n // if none of the chain statuses matched, throw an error\n throw new Error(`Unable to determine omnichain indexing status for provided chains.`);\n}\n\n/**\n * Get the timestamp of the lowest `config.startBlock` across all chains\n * in the provided array of {@link ChainIndexingStatusSnapshot}.\n *\n * Such timestamp is useful when presenting the \"lowest\" block\n * to be indexed across all chains.\n */\nexport function getTimestampForLowestOmnichainStartBlock(\n chains: ChainIndexingStatusSnapshot[],\n): UnixTimestamp {\n const earliestKnownBlockTimestamps: UnixTimestamp[] = chains.map(\n (chain) => chain.config.startBlock.timestamp,\n );\n\n return Math.min(...earliestKnownBlockTimestamps);\n}\n\n/**\n * Get the timestamp of the \"highest known block\" across all chains\n * in the provided array of {@link ChainIndexingStatusSnapshot}.\n *\n * Such timestamp is useful when presenting the \"highest known block\"\n * to be indexed across all chains.\n *\n * The \"highest known block\" for a chain depends on its status:\n * - `config.endBlock` for a \"queued\" chain,\n * - `backfillEndBlock` for a \"backfill\" chain,\n * - `latestIndexedBlock` for a \"completed\" chain,\n * - `latestKnownBlock` for a \"following\" chain.\n */\nexport function getTimestampForHighestOmnichainKnownBlock(\n chains: ChainIndexingStatusSnapshot[],\n): UnixTimestamp {\n const latestKnownBlockTimestamps: UnixTimestamp[] = [];\n\n for (const chain of chains) {\n switch (chain.chainStatus) {\n case ChainIndexingStatusIds.Queued:\n if (\n chain.config.configType === ChainIndexingConfigTypeIds.Definite &&\n chain.config.endBlock\n ) {\n latestKnownBlockTimestamps.push(chain.config.endBlock.timestamp);\n }\n break;\n\n case ChainIndexingStatusIds.Backfill:\n latestKnownBlockTimestamps.push(chain.backfillEndBlock.timestamp);\n\n break;\n\n case ChainIndexingStatusIds.Completed:\n latestKnownBlockTimestamps.push(chain.latestIndexedBlock.timestamp);\n break;\n\n case ChainIndexingStatusIds.Following:\n latestKnownBlockTimestamps.push(chain.latestKnownBlock.timestamp);\n break;\n }\n }\n\n return Math.max(...latestKnownBlockTimestamps);\n}\n\n/**\n * Get Omnichain Indexing Cursor\n *\n * The cursor tracks the \"highest\" latest indexed block timestamp across\n * all indexed chains. If all chains are queued, the cursor tracks the moment\n * just before the earliest start block timestamp across those chains.\n *\n * @throws an error if no chains are provided\n */\nexport function getOmnichainIndexingCursor(chains: ChainIndexingStatusSnapshot[]): UnixTimestamp {\n if (chains.length === 0) {\n throw new Error(`Unable to determine omnichain indexing cursor when no chains were provided.`);\n }\n\n // for omnichain indexing status snapshot 'unstarted', the cursor tracks\n // the moment just before the indexing would start from.\n if (getOmnichainIndexingStatus(chains) === OmnichainIndexingStatusIds.Unstarted) {\n const earliestStartBlockTimestamps = chains.map((chain) => chain.config.startBlock.timestamp);\n\n return Math.min(...earliestStartBlockTimestamps) - 1;\n }\n\n // otherwise, the cursor tracks the \"highest\" latest indexed block timestamp\n // across all indexed chains\n const latestIndexedBlockTimestamps = chains\n .filter((chain) => chain.chainStatus !== ChainIndexingStatusIds.Queued)\n .map((chain) => chain.latestIndexedBlock.timestamp);\n\n // Invariant: there's at least one element in `latestIndexedBlockTimestamps` array\n // This is theoretically impossible based on the 2 checks above,\n // but the invariant is explicitly added here as a formality.\n if (latestIndexedBlockTimestamps.length < 1) {\n throw new Error(\"latestIndexedBlockTimestamps array must include at least one element\");\n }\n\n return Math.max(...latestIndexedBlockTimestamps);\n}\n\n/**\n * Create {@link ChainIndexingConfig} for given block refs.\n *\n * @param startBlock required block ref\n * @param endBlock optional block ref\n */\nexport function createIndexingConfig(\n startBlock: BlockRef,\n endBlock: BlockRef | null,\n): ChainIndexingConfig {\n if (endBlock) {\n return {\n configType: ChainIndexingConfigTypeIds.Definite,\n startBlock,\n endBlock,\n } satisfies ChainIndexingConfigDefinite;\n }\n\n return {\n configType: ChainIndexingConfigTypeIds.Indefinite,\n startBlock,\n } satisfies ChainIndexingConfigIndefinite;\n}\n\n/**\n * Check if Chain Indexing Status Snapshots fit the 'unstarted' overall status\n * snapshot requirements:\n * - All chains are guaranteed to have a status of \"queued\".\n *\n * Note: This function narrows the {@link ChainIndexingStatusSnapshot} type to\n * {@link ChainIndexingStatusSnapshotQueued}.\n */\nexport function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted(\n chains: ChainIndexingStatusSnapshot[],\n): chains is ChainIndexingStatusSnapshotQueued[] {\n return chains.every((chain) => chain.chainStatus === ChainIndexingStatusIds.Queued);\n}\n\n/**\n * Check if Chain Indexing Status Snapshots fit the 'backfill' overall status\n * snapshot requirements:\n * - At least one chain is guaranteed to be in the \"backfill\" status.\n * - Each chain is guaranteed to have a status of either \"queued\",\n * \"backfill\" or \"completed\".\n *\n * Note: This function narrows the {@link ChainIndexingStatusSnapshot} type to\n * {@link ChainIndexingStatusSnapshotForOmnichainIndexingStatusSnapshotBackfill}.\n */\nexport function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill(\n chains: ChainIndexingStatusSnapshot[],\n): chains is ChainIndexingStatusSnapshotForOmnichainIndexingStatusSnapshotBackfill[] {\n const atLeastOneChainInTargetStatus = chains.some(\n (chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill,\n );\n const otherChainsHaveValidStatuses = chains.every(\n (chain) =>\n chain.chainStatus === ChainIndexingStatusIds.Queued ||\n chain.chainStatus === ChainIndexingStatusIds.Backfill ||\n chain.chainStatus === ChainIndexingStatusIds.Completed,\n );\n\n return atLeastOneChainInTargetStatus && otherChainsHaveValidStatuses;\n}\n\n/**\n * Checks if Chain Indexing Status Snapshots fit the 'completed' overall status\n * snapshot requirements:\n * - All chains are guaranteed to have a status of \"completed\".\n *\n * Note: This function narrows the {@link ChainIndexingStatusSnapshot} type to\n * {@link ChainIndexingStatusSnapshotCompleted}.\n */\nexport function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted(\n chains: ChainIndexingStatusSnapshot[],\n): chains is ChainIndexingStatusSnapshotCompleted[] {\n const allChainsHaveValidStatuses = chains.every(\n (chain) => chain.chainStatus === ChainIndexingStatusIds.Completed,\n );\n\n return allChainsHaveValidStatuses;\n}\n\n/**\n * Checks Chain Indexing Status Snapshots fit the 'following' overall status\n * snapshot requirements:\n * - At least one chain is guaranteed to be in the \"following\" status.\n * - Any other chain can have any status.\n */\nexport function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing(\n chains: ChainIndexingStatusSnapshot[],\n): chains is ChainIndexingStatusSnapshot[] {\n const allChainsHaveValidStatuses = chains.some(\n (chain) => chain.chainStatus === ChainIndexingStatusIds.Following,\n );\n\n return allChainsHaveValidStatuses;\n}\n\n/**\n * Sort a list of [{@link ChainId}, {@link ChainIndexingStatusSnapshot}] tuples\n * by the omnichain start block timestamp in ascending order.\n */\nexport function sortChainStatusesByStartBlockAsc<\n ChainStatusType extends ChainIndexingStatusSnapshot,\n>(chains: [ChainId, ChainStatusType][]): [ChainId, ChainStatusType][] {\n // Sort the chain statuses by the omnichain first block to index timestamp\n chains.sort(\n ([, chainA], [, chainB]) =>\n chainA.config.startBlock.timestamp - chainB.config.startBlock.timestamp,\n );\n\n return chains;\n}\n\n/**\n * Gets the latest indexed {@link BlockRef} for the given {@link ChainId}.\n *\n * @returns the latest indexed {@link BlockRef} for the given {@link ChainId}, or null if the chain\n * isn't being indexed at all or is queued and therefore hasn't started indexing yet.\n */\nexport function getLatestIndexedBlockRef(\n indexingStatus: CrossChainIndexingStatusSnapshot,\n chainId: ChainId,\n): BlockRef | null {\n const chainIndexingStatus = indexingStatus.omnichainSnapshot.chains.get(chainId);\n\n if (chainIndexingStatus === undefined) {\n // chain isn't being indexed at all\n return null;\n }\n\n if (chainIndexingStatus.chainStatus === ChainIndexingStatusIds.Queued) {\n // chain is queued, so no data for the chain has been indexed yet\n return null;\n }\n\n return chainIndexingStatus.latestIndexedBlock;\n}\n","import type { ParsePayload } from \"zod/v4/core\";\n\nimport type { ChainId } from \"../../shared\";\nimport * as blockRef from \"../../shared/block-ref\";\nimport {\n checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill,\n checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted,\n checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing,\n checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted,\n getOmnichainIndexingStatus,\n} from \"./helpers\";\nimport {\n ChainIndexingConfigTypeIds,\n ChainIndexingStatusIds,\n type ChainIndexingStatusSnapshot,\n type ChainIndexingStatusSnapshotBackfill,\n type ChainIndexingStatusSnapshotCompleted,\n type ChainIndexingStatusSnapshotFollowing,\n type ChainIndexingStatusSnapshotQueued,\n type CrossChainIndexingStatusSnapshotOmnichain,\n type OmnichainIndexingStatusSnapshot,\n type OmnichainIndexingStatusSnapshotFollowing,\n type RealtimeIndexingStatusProjection,\n} from \"./types\";\n\n/**\n * Invariants for {@link ChainIndexingSnapshot}.\n */\n\n/**\n * Invariants for chain snapshot in 'queued' status:\n * - `config.endBlock` (if set) is after `config.startBlock`.\n */\nexport function invariant_chainSnapshotQueuedBlocks(\n ctx: ParsePayload<ChainIndexingStatusSnapshotQueued>,\n) {\n const { config } = ctx.value;\n\n // The `config.endBlock` does not exists for `indefinite` config type\n if (config.configType === ChainIndexingConfigTypeIds.Indefinite) {\n // invariant holds\n return;\n }\n\n if (config.endBlock && blockRef.isBeforeOrEqualTo(config.startBlock, config.endBlock) === false) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: \"`config.startBlock` must be before or same as `config.endBlock`.\",\n });\n }\n}\n\n/**\n * Invariants for chain snapshot in 'backfill' status:\n * - `config.startBlock` is before or same as `latestIndexedBlock`.\n * - `latestIndexedBlock` is before or same as `backfillEndBlock`.\n * - `backfillEndBlock` is the same as `config.endBlock` (if set).\n */\nexport function invariant_chainSnapshotBackfillBlocks(\n ctx: ParsePayload<ChainIndexingStatusSnapshotBackfill>,\n) {\n const { config, latestIndexedBlock, backfillEndBlock } = ctx.value;\n\n if (blockRef.isBeforeOrEqualTo(config.startBlock, latestIndexedBlock) === false) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: \"`config.startBlock` must be before or same as `latestIndexedBlock`.\",\n });\n }\n\n if (blockRef.isBeforeOrEqualTo(latestIndexedBlock, backfillEndBlock) === false) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: \"`latestIndexedBlock` must be before or same as `backfillEndBlock`.\",\n });\n }\n\n // The `config.endBlock` does not exists for `indefinite` config type\n if (config.configType === ChainIndexingConfigTypeIds.Indefinite) {\n // invariant holds\n return;\n }\n\n if (config.endBlock && blockRef.isEqualTo(backfillEndBlock, config.endBlock) === false) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: \"`backfillEndBlock` must be the same as `config.endBlock`.\",\n });\n }\n}\n\n/**\n * Invariants for chain snapshot in 'completed' status:\n * - `config.startBlock` is before or same as `latestIndexedBlock`.\n * - `latestIndexedBlock` is before or same as `config.endBlock`.\n */\nexport function invariant_chainSnapshotCompletedBlocks(\n ctx: ParsePayload<ChainIndexingStatusSnapshotCompleted>,\n) {\n const { config, latestIndexedBlock } = ctx.value;\n\n if (blockRef.isBeforeOrEqualTo(config.startBlock, latestIndexedBlock) === false) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: \"`config.startBlock` must be before or same as `latestIndexedBlock`.\",\n });\n }\n\n if (blockRef.isBeforeOrEqualTo(latestIndexedBlock, config.endBlock) === false) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: \"`latestIndexedBlock` must be before or same as `config.endBlock`.\",\n });\n }\n}\n\n/**\n * Invariants for chain snapshot in 'following' status:\n * - `config.startBlock` is before or same as `latestIndexedBlock`.\n * - `latestIndexedBlock` is before or same as `latestKnownBlock`.\n */\nexport function invariant_chainSnapshotFollowingBlocks(\n ctx: ParsePayload<ChainIndexingStatusSnapshotFollowing>,\n) {\n const { config, latestIndexedBlock, latestKnownBlock } = ctx.value;\n\n if (blockRef.isBeforeOrEqualTo(config.startBlock, latestIndexedBlock) === false) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: \"`config.startBlock` must be before or same as `latestIndexedBlock`.\",\n });\n }\n\n if (blockRef.isBeforeOrEqualTo(latestIndexedBlock, latestKnownBlock) === false) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: \"`latestIndexedBlock` must be before or same as `latestKnownBlock`.\",\n });\n }\n}\n\n/**\n * Invariants for {@link OmnichainIndexingSnapshot}.\n */\n\n/**\n * Invariant: For omnichain snapshot,\n * `omnichainStatus` is set based on the snapshots of individual chains.\n */\nexport function invariant_omnichainSnapshotStatusIsConsistentWithChainSnapshot(\n ctx: ParsePayload<OmnichainIndexingStatusSnapshot>,\n) {\n const snapshot = ctx.value;\n const chains = Array.from(snapshot.chains.values());\n const expectedOmnichainStatus = getOmnichainIndexingStatus(chains);\n const actualOmnichainStatus = snapshot.omnichainStatus;\n\n if (expectedOmnichainStatus !== actualOmnichainStatus) {\n ctx.issues.push({\n code: \"custom\",\n input: snapshot,\n message: `'${actualOmnichainStatus}' is an invalid omnichainStatus. Expected '${expectedOmnichainStatus}' based on the statuses of individual chains.`,\n });\n }\n}\n\n/**\n * Invariant: For omnichain status snapshot,\n * `omnichainIndexingCursor` is lower than the earliest start block\n * across all queued chains.\n *\n * Note: if there are no queued chains, the invariant holds.\n */\nexport function invariant_omnichainIndexingCursorLowerThanEarliestStartBlockAcrossQueuedChains(\n ctx: ParsePayload<OmnichainIndexingStatusSnapshot>,\n) {\n const snapshot = ctx.value;\n const queuedChains = Array.from(snapshot.chains.values()).filter(\n (chain) => chain.chainStatus === ChainIndexingStatusIds.Queued,\n );\n\n // there are no queued chains\n if (queuedChains.length === 0) {\n // the invariant holds\n return;\n }\n\n const queuedChainStartBlocks = queuedChains.map((chain) => chain.config.startBlock.timestamp);\n const queuedChainEarliestStartBlock = Math.min(...queuedChainStartBlocks);\n\n // there are queued chains\n // the invariant holds if the omnichain indexing cursor is lower than\n // the earliest start block across all queued chains\n if (snapshot.omnichainIndexingCursor >= queuedChainEarliestStartBlock) {\n ctx.issues.push({\n code: \"custom\",\n input: snapshot,\n message:\n \"`omnichainIndexingCursor` must be lower than the earliest start block across all queued chains.\",\n });\n }\n}\n\n/**\n * Invariant: For omnichain status snapshot,\n * `omnichainIndexingCursor` is lower than or equal to\n * the highest `backfillEndBlock` across all backfill chains.\n *\n * Note: if there are no backfill chains, the invariant holds.\n */\nexport function invariant_omnichainIndexingCursorLowerThanOrEqualToLatestBackfillEndBlockAcrossBackfillChains(\n ctx: ParsePayload<OmnichainIndexingStatusSnapshot>,\n) {\n const snapshot = ctx.value;\n const backfillChains = Array.from(snapshot.chains.values()).filter(\n (chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill,\n );\n\n // there are no backfill chains\n if (backfillChains.length === 0) {\n // the invariant holds\n return;\n }\n\n const backfillEndBlocks = backfillChains.map((chain) => chain.backfillEndBlock.timestamp);\n const highestBackfillEndBlock = Math.max(...backfillEndBlocks);\n\n // there are backfill chains\n // the invariant holds if the omnichainIndexingCursor is lower than or\n // equal to the highest backfillEndBlock across all backfill chains.\n if (snapshot.omnichainIndexingCursor > highestBackfillEndBlock) {\n ctx.issues.push({\n code: \"custom\",\n input: snapshot,\n message:\n \"`omnichainIndexingCursor` must be lower than or equal to the highest `backfillEndBlock` across all backfill chains.\",\n });\n }\n}\n\n/**\n * Invariant: For omnichain status snapshot,\n * `omnichainIndexingCursor` is same as the highest latestIndexedBlock\n * across all indexed chains.\n *\n * Note: if there are no indexed chains, the invariant holds.\n */\nexport function invariant_omnichainIndexingCursorIsEqualToHighestLatestIndexedBlockAcrossIndexedChain(\n ctx: ParsePayload<OmnichainIndexingStatusSnapshot>,\n) {\n const snapshot = ctx.value;\n const indexedChains = Array.from(snapshot.chains.values()).filter(\n (chain) =>\n chain.chainStatus === ChainIndexingStatusIds.Backfill ||\n chain.chainStatus === ChainIndexingStatusIds.Completed ||\n chain.chainStatus === ChainIndexingStatusIds.Following,\n );\n\n // there are no indexed chains\n if (indexedChains.length === 0) {\n // the invariant holds\n return;\n }\n\n const indexedChainLatestIndexedBlocks = indexedChains.map(\n (chain) => chain.latestIndexedBlock.timestamp,\n );\n const indexedChainHighestLatestIndexedBlock = Math.max(...indexedChainLatestIndexedBlocks);\n\n // there are indexed chains\n // the invariant holds if the omnichain indexing cursor is same as\n // the highest latestIndexedBlock across all indexed chains\n if (snapshot.omnichainIndexingCursor !== indexedChainHighestLatestIndexedBlock) {\n ctx.issues.push({\n code: \"custom\",\n input: snapshot,\n message:\n \"`omnichainIndexingCursor` must be same as the highest `latestIndexedBlock` across all indexed chains.\",\n });\n }\n}\n\n/**\n * Invariant: For omnichain status snapshot 'unstarted',\n * all chains must have \"queued\" status.\n */\nexport function invariant_omnichainSnapshotUnstartedHasValidChains(\n ctx: ParsePayload<Map<ChainId, ChainIndexingStatusSnapshot>>,\n) {\n const chains = ctx.value;\n const hasValidChains = checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted(\n Array.from(chains.values()),\n );\n\n if (hasValidChains === false) {\n ctx.issues.push({\n code: \"custom\",\n input: chains,\n message: `For omnichain status snapshot 'unstarted', all chains must have \"queued\" status.`,\n });\n }\n}\n\n/**\n * Invariant: For omnichain status snapshot 'backfill',\n * at least one chain must be in \"backfill\" status and\n * each chain has to have a status of either \"queued\", \"backfill\"\n * or \"completed\".\n */\nexport function invariant_omnichainStatusSnapshotBackfillHasValidChains(\n ctx: ParsePayload<Map<ChainId, ChainIndexingStatusSnapshot>>,\n) {\n const chains = ctx.value;\n const hasValidChains = checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill(\n Array.from(chains.values()),\n );\n\n if (hasValidChains === false) {\n ctx.issues.push({\n code: \"custom\",\n input: chains,\n message: `For omnichain status snapshot 'backfill', at least one chain must be in \"backfill\" status and each chain has to have a status of either \"queued\", \"backfill\" or \"completed\".`,\n });\n }\n}\n\n/**\n * Invariant: For omnichain status snapshot 'completed',\n * all chains must have \"completed\" status.\n */\nexport function invariant_omnichainStatusSnapshotCompletedHasValidChains(\n ctx: ParsePayload<Map<ChainId, ChainIndexingStatusSnapshot>>,\n) {\n const chains = ctx.value;\n const hasValidChains = checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted(\n Array.from(chains.values()),\n );\n\n if (hasValidChains === false) {\n ctx.issues.push({\n code: \"custom\",\n input: chains,\n message: `For omnichain status snapshot 'completed', all chains must have \"completed\" status.`,\n });\n }\n}\n\n/**\n * Invariant: For omnichain status snapshot 'following',\n * at least one chain must be in 'following' status.\n */\nexport function invariant_omnichainStatusSnapshotFollowingHasValidChains(\n ctx: ParsePayload<OmnichainIndexingStatusSnapshotFollowing>,\n) {\n const snapshot = ctx.value;\n const hasValidChains = checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing(\n Array.from(snapshot.chains.values()),\n );\n\n if (hasValidChains === false) {\n ctx.issues.push({\n code: \"custom\",\n input: snapshot,\n message: \"For omnichainStatus 'following', at least one chain must be in 'following' status.\",\n });\n }\n}\n\n/**\n * Invariants for {@link CrossChainIndexingStatusSnapshotOmnichain}.\n */\n\n/**\n * Invariant: for cross-chain indexing status snapshot omnichain,\n * slowestChainIndexingCursor equals to omnichainSnapshot.omnichainIndexingCursor\n */\nexport function invariant_slowestChainEqualsToOmnichainSnapshotTime(\n ctx: ParsePayload<CrossChainIndexingStatusSnapshotOmnichain>,\n) {\n const { slowestChainIndexingCursor, omnichainSnapshot } = ctx.value;\n const { omnichainIndexingCursor } = omnichainSnapshot;\n\n if (slowestChainIndexingCursor !== omnichainIndexingCursor) {\n console.log(\"invariant_slowestChainEqualsToOmnichainSnapshotTime\", {\n slowestChainIndexingCursor,\n omnichainIndexingCursor,\n });\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `'slowestChainIndexingCursor' must be equal to 'omnichainSnapshot.omnichainIndexingCursor'`,\n });\n }\n}\n\n/**\n * Invariant: for cross-chain indexing status snapshot omnichain,\n * snapshotTime is greater than or equal to the \"highest known block\" timestamp.\n */\nexport function invariant_snapshotTimeIsTheHighestKnownBlockTimestamp(\n ctx: ParsePayload<CrossChainIndexingStatusSnapshotOmnichain>,\n) {\n const { snapshotTime, omnichainSnapshot } = ctx.value;\n const chains = Array.from(omnichainSnapshot.chains.values());\n\n const startBlockTimestamps = chains.map((chain) => chain.config.startBlock.timestamp);\n\n const endBlockTimestamps = chains\n .map((chain) => chain.config)\n .filter((chainConfig) => chainConfig.configType === ChainIndexingConfigTypeIds.Definite)\n .map((chainConfig) => chainConfig.endBlock.timestamp);\n\n const backfillEndBlockTimestamps = chains\n .filter((chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill)\n .map((chain) => chain.backfillEndBlock.timestamp);\n\n const latestKnownBlockTimestamps = chains\n .filter((chain) => chain.chainStatus === ChainIndexingStatusIds.Following)\n .map((chain) => chain.latestKnownBlock.timestamp);\n\n const highestKnownBlockTimestamp = Math.max(\n ...startBlockTimestamps,\n ...endBlockTimestamps,\n ...backfillEndBlockTimestamps,\n ...latestKnownBlockTimestamps,\n );\n\n if (snapshotTime < highestKnownBlockTimestamp) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `'snapshotTime' (${snapshotTime}) must be greater than or equal to the \"highest known block timestamp\" (${highestKnownBlockTimestamp})`,\n });\n }\n}\n\n/**\n * Invariants for {@link RealtimeIndexingStatusProjection}.\n */\n\n/**\n * Invariant: For realtime indexing status projection,\n * `projectedAt` is after or same as `snapshot.snapshotTime`.\n */\nexport function invariant_realtimeIndexingStatusProjectionProjectedAtIsAfterOrEqualToSnapshotTime(\n ctx: ParsePayload<RealtimeIndexingStatusProjection>,\n) {\n const projection = ctx.value;\n\n const { snapshot, projectedAt } = projection;\n\n if (snapshot.snapshotTime > projectedAt) {\n ctx.issues.push({\n code: \"custom\",\n input: projection,\n message: \"`projectedAt` must be after or same as `snapshot.snapshotTime`.\",\n });\n }\n}\n\n/**\n * Invariant: For realtime indexing status projection,\n * `worstCaseDistance` is the difference between `projectedAt`\n * and `omnichainIndexingCursor`.\n */\nexport function invariant_realtimeIndexingStatusProjectionWorstCaseDistanceIsCorrect(\n ctx: ParsePayload<RealtimeIndexingStatusProjection>,\n) {\n const projection = ctx.value;\n const { projectedAt, snapshot, worstCaseDistance } = projection;\n const { omnichainSnapshot } = snapshot;\n const expectedWorstCaseDistance = projectedAt - omnichainSnapshot.omnichainIndexingCursor;\n\n if (worstCaseDistance !== expectedWorstCaseDistance) {\n ctx.issues.push({\n code: \"custom\",\n input: projection,\n message:\n \"`worstCaseDistance` must be the exact difference between `projectedAt` and `snapshot.omnichainIndexingCursor`.\",\n });\n }\n}\n","import type { UnixTimestamp } from \"../../shared\";\nimport type { CrossChainIndexingStatusSnapshot, RealtimeIndexingStatusProjection } from \"./types\";\n\n/**\n * Create realtime indexing status projection from\n * a {@link CrossChainIndexingStatusSnapshot}.\n */\nexport function createRealtimeIndexingStatusProjection(\n snapshot: CrossChainIndexingStatusSnapshot,\n now: UnixTimestamp,\n): RealtimeIndexingStatusProjection {\n /**\n * The timestamp when the realtime indexing status was projected.\n *\n * Due to possible clock skew between different systems,\n * if the \"now\" timestamp on the system generating this indexing status\n * projection is less than the snapshot time, then this value must be set to\n * equal to the whichever is higher between the `now` and\n * the snapshot time to ensure all invariants are followed.\n */\n const projectedAt = Math.max(now, snapshot.snapshotTime);\n\n return {\n projectedAt,\n worstCaseDistance: projectedAt - snapshot.slowestChainIndexingCursor,\n snapshot,\n };\n}\n","import { type ChainId, type ChainIdString, serializeChainId } from \"../../shared\";\nimport type {\n SerializedCrossChainIndexingStatusSnapshot,\n SerializedOmnichainIndexingStatusSnapshot,\n SerializedOmnichainIndexingStatusSnapshotBackfill,\n SerializedOmnichainIndexingStatusSnapshotCompleted,\n SerializedOmnichainIndexingStatusSnapshotFollowing,\n SerializedOmnichainIndexingStatusSnapshotUnstarted,\n SerializedRealtimeIndexingStatusProjection,\n} from \"./serialized-types\";\nimport {\n type ChainIndexingStatusSnapshot,\n type CrossChainIndexingStatusSnapshot,\n OmnichainIndexingStatusIds,\n type OmnichainIndexingStatusSnapshot,\n type RealtimeIndexingStatusProjection,\n} from \"./types\";\n\nexport function serializeCrossChainIndexingStatusSnapshotOmnichain({\n strategy,\n slowestChainIndexingCursor,\n snapshotTime,\n omnichainSnapshot,\n}: CrossChainIndexingStatusSnapshot): SerializedCrossChainIndexingStatusSnapshot {\n return {\n strategy,\n slowestChainIndexingCursor,\n snapshotTime,\n omnichainSnapshot: serializeOmnichainIndexingStatusSnapshot(omnichainSnapshot),\n };\n}\n\nexport function serializeRealtimeIndexingStatusProjection(\n indexingProjection: RealtimeIndexingStatusProjection,\n): SerializedRealtimeIndexingStatusProjection {\n return {\n projectedAt: indexingProjection.projectedAt,\n worstCaseDistance: indexingProjection.worstCaseDistance,\n snapshot: serializeCrossChainIndexingStatusSnapshotOmnichain(indexingProjection.snapshot),\n } satisfies SerializedRealtimeIndexingStatusProjection;\n}\n\n/**\n * Serialize chain indexing snapshots.\n */\nexport function serializeChainIndexingSnapshots<\n ChainIndexingStatusSnapshotType extends ChainIndexingStatusSnapshot,\n>(\n chains: Map<ChainId, ChainIndexingStatusSnapshotType>,\n): Record<ChainIdString, ChainIndexingStatusSnapshotType> {\n const serializedSnapshots: Record<ChainIdString, ChainIndexingStatusSnapshotType> = {};\n\n for (const [chainId, snapshot] of chains.entries()) {\n serializedSnapshots[serializeChainId(chainId)] = snapshot;\n }\n\n return serializedSnapshots;\n}\n\n/**\n * Serialize a {@link OmnichainIndexingStatusSnapshot} object.\n */\nexport function serializeOmnichainIndexingStatusSnapshot(\n indexingStatus: OmnichainIndexingStatusSnapshot,\n): SerializedOmnichainIndexingStatusSnapshot {\n switch (indexingStatus.omnichainStatus) {\n case OmnichainIndexingStatusIds.Unstarted:\n return {\n omnichainStatus: OmnichainIndexingStatusIds.Unstarted,\n chains: serializeChainIndexingSnapshots(indexingStatus.chains),\n omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor,\n } satisfies SerializedOmnichainIndexingStatusSnapshotUnstarted;\n\n case OmnichainIndexingStatusIds.Backfill:\n return {\n omnichainStatus: OmnichainIndexingStatusIds.Backfill,\n chains: serializeChainIndexingSnapshots(indexingStatus.chains),\n omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor,\n } satisfies SerializedOmnichainIndexingStatusSnapshotBackfill;\n\n case OmnichainIndexingStatusIds.Completed: {\n return {\n omnichainStatus: OmnichainIndexingStatusIds.Completed,\n chains: serializeChainIndexingSnapshots(indexingStatus.chains),\n omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor,\n } satisfies SerializedOmnichainIndexingStatusSnapshotCompleted;\n }\n\n case OmnichainIndexingStatusIds.Following:\n return {\n omnichainStatus: OmnichainIndexingStatusIds.Following,\n chains: serializeChainIndexingSnapshots(indexingStatus.chains),\n omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor,\n } satisfies SerializedOmnichainIndexingStatusSnapshotFollowing;\n }\n}\n","import { serializeENSIndexerPublicConfig } from \"../../ensindexer\";\nimport type { SerializedENSApiPublicConfig } from \"./serialized-types\";\nimport type { ENSApiPublicConfig } from \"./types\";\n\n/**\n * Serialize a {@link ENSApiPublicConfig} object.\n */\nexport function serializeENSApiPublicConfig(\n config: ENSApiPublicConfig,\n): SerializedENSApiPublicConfig {\n const { version, theGraphFallback, ensIndexerPublicConfig } = config;\n\n return {\n version,\n theGraphFallback,\n ensIndexerPublicConfig: serializeENSIndexerPublicConfig(ensIndexerPublicConfig),\n } satisfies SerializedENSApiPublicConfig;\n}\n","import { deserializeENSApiPublicConfig } from \"../../ensapi\";\nimport type { ConfigResponse } from \"./response\";\nimport type { SerializedConfigResponse } from \"./serialized-response\";\n\n/**\n * Deserialize a {@link ConfigResponse} object.\n */\nexport function deserializeConfigResponse(\n serializedResponse: SerializedConfigResponse,\n): ConfigResponse {\n return deserializeENSApiPublicConfig(serializedResponse);\n}\n","import { serializeENSApiPublicConfig } from \"../../ensapi\";\nimport type { ConfigResponse } from \"./response\";\nimport type { SerializedConfigResponse } from \"./serialized-response\";\n\nexport function serializeConfigResponse(response: ConfigResponse): SerializedConfigResponse {\n return serializeENSApiPublicConfig(response);\n}\n","import { prettifyError } from \"zod/v4\";\n\nimport type { IndexingStatusResponse } from \"./response\";\nimport type { SerializedIndexingStatusResponse } from \"./serialized-response\";\nimport { makeIndexingStatusResponseSchema } from \"./zod-schemas\";\n\n/**\n * Deserialize a {@link IndexingStatusResponse} object.\n */\nexport function deserializeIndexingStatusResponse(\n maybeResponse: SerializedIndexingStatusResponse,\n): IndexingStatusResponse {\n const parsed = makeIndexingStatusResponseSchema().safeParse(maybeResponse);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize IndexingStatusResponse:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n","import z from \"zod/v4\";\n\nimport { makeRealtimeIndexingStatusProjectionSchema } from \"../../ensindexer/indexing-status/zod-schemas\";\nimport {\n type IndexingStatusResponse,\n IndexingStatusResponseCodes,\n type IndexingStatusResponseError,\n type IndexingStatusResponseOk,\n} from \"./response\";\n\n/**\n * Schema for {@link IndexingStatusResponseOk}\n **/\nexport const makeIndexingStatusResponseOkSchema = (\n valueLabel: string = \"Indexing Status Response OK\",\n) =>\n z.strictObject({\n responseCode: z.literal(IndexingStatusResponseCodes.Ok),\n realtimeProjection: makeRealtimeIndexingStatusProjectionSchema(valueLabel),\n });\n\n/**\n * Schema for {@link IndexingStatusResponseError}\n **/\nexport const makeIndexingStatusResponseErrorSchema = (\n _valueLabel: string = \"Indexing Status Response Error\",\n) =>\n z.strictObject({\n responseCode: z.literal(IndexingStatusResponseCodes.Error),\n });\n\n/**\n * Schema for {@link IndexingStatusResponse}\n **/\nexport const makeIndexingStatusResponseSchema = (valueLabel: string = \"Indexing Status Response\") =>\n z.discriminatedUnion(\"responseCode\", [\n makeIndexingStatusResponseOkSchema(valueLabel),\n makeIndexingStatusResponseErrorSchema(valueLabel),\n ]);\n","import type { RealtimeIndexingStatusProjection } from \"../../ensindexer\";\n\n/**\n * A status code for indexing status responses.\n */\nexport const IndexingStatusResponseCodes = {\n /**\n * Represents that the indexing status is available.\n */\n Ok: \"ok\",\n\n /**\n * Represents that the indexing status is unavailable.\n */\n Error: \"error\",\n} as const;\n\n/**\n * The derived string union of possible {@link IndexingStatusResponseCodes}.\n */\nexport type IndexingStatusResponseCode =\n (typeof IndexingStatusResponseCodes)[keyof typeof IndexingStatusResponseCodes];\n\n/**\n * An indexing status response when the indexing status is available.\n */\nexport type IndexingStatusResponseOk = {\n responseCode: typeof IndexingStatusResponseCodes.Ok;\n realtimeProjection: RealtimeIndexingStatusProjection;\n};\n\n/**\n * An indexing status response when the indexing status is unavailable.\n */\nexport type IndexingStatusResponseError = {\n responseCode: typeof IndexingStatusResponseCodes.Error;\n};\n\n/**\n * Indexing status response.\n *\n * Use the `responseCode` field to determine the specific type interpretation\n * at runtime.\n */\nexport type IndexingStatusResponse = IndexingStatusResponseOk | IndexingStatusResponseError;\n","import { serializeRealtimeIndexingStatusProjection } from \"../../ensindexer\";\nimport { type IndexingStatusResponse, IndexingStatusResponseCodes } from \"./response\";\nimport type {\n SerializedIndexingStatusResponse,\n SerializedIndexingStatusResponseOk,\n} from \"./serialized-response\";\n\nexport function serializeIndexingStatusResponse(\n response: IndexingStatusResponse,\n): SerializedIndexingStatusResponse {\n switch (response.responseCode) {\n case IndexingStatusResponseCodes.Ok:\n return {\n responseCode: response.responseCode,\n realtimeProjection: serializeRealtimeIndexingStatusProjection(response.realtimeProjection),\n } satisfies SerializedIndexingStatusResponseOk;\n\n case IndexingStatusResponseCodes.Error:\n return response;\n }\n}\n","import { prettifyError } from \"zod/v4\";\n\nimport type { NameTokensResponse, SerializedNameTokensResponse } from \"../name-tokens\";\nimport { makeNameTokensResponseSchema } from \"./zod-schemas\";\n\n/**\n * Deserialize a {@link NameTokensResponse} object.\n */\nexport function deserializedNameTokensResponse(\n maybeResponse: SerializedNameTokensResponse,\n): NameTokensResponse {\n const parsed = makeNameTokensResponseSchema(\"Name Tokens Response\", false).safeParse(\n maybeResponse,\n );\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize NameTokensResponse:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n","import { namehash } from \"viem\";\nimport z from \"zod/v4\";\n\nimport {\n makeNodeSchema,\n makeReinterpretedNameSchema,\n makeUnixTimestampSchema,\n} from \"../../shared/zod-schemas\";\nimport { NameTokenOwnershipTypes } from \"../../tokenscope\";\nimport { makeNameTokenSchema } from \"../../tokenscope/zod-schemas\";\nimport { ErrorResponseSchema } from \"../shared/errors/zod-schemas\";\nimport {\n NameTokensResponse,\n NameTokensResponseCodes,\n NameTokensResponseError,\n NameTokensResponseErrorCodes,\n NameTokensResponseErrorEnsIndexerConfigUnsupported,\n NameTokensResponseErrorIndexingStatusUnsupported,\n NameTokensResponseErrorNameTokensNotIndexed,\n NameTokensResponseOk,\n type RegisteredNameTokens,\n} from \"./response\";\n\n/**\n * Schema for {@link RegisteredNameTokens}.\n */\nexport const makeRegisteredNameTokenSchema = <const SerializableType extends boolean>(\n valueLabel: string = \"Registered Name Token\",\n serializable?: SerializableType,\n) =>\n z\n .object({\n domainId: makeNodeSchema(`${valueLabel}.domainId`),\n name: makeReinterpretedNameSchema(valueLabel),\n tokens: z.array(makeNameTokenSchema(`${valueLabel}.tokens`, serializable)).nonempty(),\n expiresAt: makeUnixTimestampSchema(`${valueLabel}.expiresAt`),\n accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`),\n })\n .check(function invariant_nameIsAssociatedWithDomainId(ctx) {\n const { name, domainId } = ctx.value;\n\n if (namehash(name) !== domainId) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `'name' must be associated with 'domainId': ${domainId}`,\n });\n }\n })\n .check(\n function invariant_nameTokensOwnershipTypeNameWrapperRequiresOwnershipTypeFullyOnchainOrUnknown(\n ctx,\n ) {\n const { tokens } = ctx.value;\n const containsOwnershipNameWrapper = tokens.some(\n (t) => t.ownership.ownershipType === NameTokenOwnershipTypes.NameWrapper,\n );\n const containsOwnershipFullyOnchainOrUnknown = tokens.some(\n (t) =>\n t.ownership.ownershipType === NameTokenOwnershipTypes.FullyOnchain ||\n t.ownership.ownershipType === NameTokenOwnershipTypes.Unknown,\n );\n if (containsOwnershipNameWrapper && !containsOwnershipFullyOnchainOrUnknown) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `'tokens' must contain name token with ownership type 'fully-onchain' or 'unknown' when name token with ownership type 'namewrapper' in listed`,\n });\n }\n },\n )\n .check(function invariant_nameTokensContainAtMostOneWithOwnershipTypeEffective(ctx) {\n const { tokens } = ctx.value;\n const tokensCountWithOwnershipFullyOnchain = tokens.filter(\n (t) => t.ownership.ownershipType === NameTokenOwnershipTypes.FullyOnchain,\n ).length;\n if (tokensCountWithOwnershipFullyOnchain > 1) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `'tokens' must contain at most one name token with ownership type 'fully-onchain', current count: ${tokensCountWithOwnershipFullyOnchain}`,\n });\n }\n });\n\n/**\n * Schema for {@link NameTokensResponseOk}\n */\nexport const makeNameTokensResponseOkSchema = <const SerializableType extends boolean>(\n valueLabel: string = \"Name Tokens Response OK\",\n serializable?: SerializableType,\n) =>\n z.strictObject({\n responseCode: z.literal(NameTokensResponseCodes.Ok),\n registeredNameTokens: makeRegisteredNameTokenSchema(`${valueLabel}.nameTokens`, serializable),\n });\n\n/**\n * Schema for {@link NameTokensResponseErrorNameTokensNotIndexed}\n */\nexport const makeNameTokensResponseErrorNameTokensNotIndexedSchema = (\n _valueLabel: string = \"Name Tokens Response Error Name Not Indexed\",\n) =>\n z.strictObject({\n responseCode: z.literal(NameTokensResponseCodes.Error),\n errorCode: z.literal(NameTokensResponseErrorCodes.NameTokensNotIndexed),\n error: ErrorResponseSchema,\n });\n\n/**\n * Schema for {@link NameTokensResponseErrorEnsIndexerConfigUnsupported}\n */\nexport const makeNameTokensResponseErrorEnsIndexerConfigUnsupported = (\n _valueLabel: string = \"Name Tokens Response Error ENSIndexer Config Unsupported\",\n) =>\n z.strictObject({\n responseCode: z.literal(NameTokensResponseCodes.Error),\n errorCode: z.literal(NameTokensResponseErrorCodes.EnsIndexerConfigUnsupported),\n error: ErrorResponseSchema,\n });\n/**\n * Schema for {@link NameTokensResponseErrorIndexingStatusUnsupported}\n */\nexport const makeNameTokensResponseErrorNameIndexingStatusUnsupported = (\n _valueLabel: string = \"Name Tokens Response Error Indexing Status Unsupported\",\n) =>\n z.strictObject({\n responseCode: z.literal(NameTokensResponseCodes.Error),\n errorCode: z.literal(NameTokensResponseErrorCodes.IndexingStatusUnsupported),\n error: ErrorResponseSchema,\n });\n/**\n * Schema for {@link NameTokensResponseError}\n */\nexport const makeNameTokensResponseErrorSchema = (\n valueLabel: string = \"Name Tokens Response Error\",\n) =>\n z.discriminatedUnion(\"errorCode\", [\n makeNameTokensResponseErrorNameTokensNotIndexedSchema(valueLabel),\n makeNameTokensResponseErrorEnsIndexerConfigUnsupported(valueLabel),\n makeNameTokensResponseErrorNameIndexingStatusUnsupported(valueLabel),\n ]);\n\n/**\n * Schema for {@link NameTokensResponse}\n */\nexport const makeNameTokensResponseSchema = <const SerializableType extends boolean = false>(\n valueLabel: string = \"Name Tokens Response\",\n serializable?: SerializableType,\n) => {\n return z.discriminatedUnion(\"responseCode\", [\n makeNameTokensResponseOkSchema(valueLabel, serializable ?? false),\n makeNameTokensResponseErrorSchema(valueLabel),\n ]);\n};\n","import { type Address, type Hex, isAddressEqual, zeroAddress } from \"viem\";\nimport { prettifyError } from \"zod/v4\";\n\nimport { type Node, uint256ToHex32 } from \"../ens\";\nimport {\n type AccountId,\n type AssetId,\n type AssetNamespace,\n type ChainId,\n formatAssetId,\n type TokenId,\n} from \"../shared\";\nimport type { AssetIdString } from \"../shared/serialized-types\";\nimport { makeAssetIdSchema, makeAssetIdStringSchema } from \"./zod-schemas\";\n\n/**\n * Serialized representation of {@link TokenId}.\n */\nexport type SerializedTokenId = string;\n\n/**\n * Serialized representation of {@link AssetId}.\n */\nexport interface SerializedAssetId extends Omit<AssetId, \"tokenId\"> {\n tokenId: SerializedTokenId;\n}\n\n/**\n * Serializes {@link AssetId} object to a structured form.\n */\nexport function serializeAssetId(assetId: AssetId): SerializedAssetId {\n return {\n assetNamespace: assetId.assetNamespace,\n contract: assetId.contract,\n tokenId: uint256ToHex32(assetId.tokenId),\n };\n}\n\n/**\n * Deserialize a {@link AssetId} object.\n */\nexport function deserializeAssetId(maybeAssetId: unknown, valueLabel?: string): AssetId {\n const schema = makeAssetIdSchema(valueLabel);\n const parsed = schema.safeParse(maybeAssetId);\n\n if (parsed.error) {\n throw new RangeError(`Cannot deserialize AssetId:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n\n/**\n * Parse a stringified representation of {@link AssetId} object.\n */\nexport function parseAssetId(maybeAssetId: AssetIdString, valueLabel?: string): AssetId {\n const schema = makeAssetIdStringSchema(valueLabel);\n const parsed = schema.safeParse(maybeAssetId);\n\n if (parsed.error) {\n throw new RangeError(`Cannot parse AssetId:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n\n/**\n * Builds an AssetId for the NFT represented by the given contract,\n * tokenId, and assetNamespace.\n *\n * @param contract - The contract that manages the NFT\n * @param tokenId - The tokenId of the NFT\n * @param assetNamespace - The assetNamespace of the NFT\n * @returns The AssetId for the NFT represented by the given contract,\n * tokenId, and assetNamespace\n */\nexport const buildAssetId = (\n contract: AccountId,\n tokenId: TokenId,\n assetNamespace: AssetNamespace,\n): AssetId => {\n return {\n assetNamespace,\n contract,\n tokenId,\n };\n};\n\n/**\n * A globally unique reference to an NFT tokenizing the ownership of a domain.\n */\nexport interface DomainAssetId extends AssetId {\n /**\n * The namehash (node) of the domain who's ownership is tokenized by\n * this `AssetId`.\n */\n domainId: Node;\n}\n\n/**\n * Serialized representation of {@link DomainAssetId}.\n */\nexport interface SerializedDomainAssetId extends SerializedAssetId {\n domainId: Node;\n}\n\nexport function serializeDomainAssetId(domainAsset: DomainAssetId): SerializedDomainAssetId {\n return {\n ...serializeAssetId(domainAsset),\n domainId: domainAsset.domainId,\n };\n}\n\n/**\n * An enum representing the mint status of a DomainAssetId.\n *\n * After we index a NFT we never delete it from our index. Instead, when an\n * indexed NFT is burned onchain we retain its record and update its mint\n * status as `burned`. If a NFT is minted again after it is burned its mint\n * status is updated to `minted`.\n */\nexport const NFTMintStatuses = {\n Minted: \"minted\",\n Burned: \"burned\",\n} as const;\n\nexport type NFTMintStatus = (typeof NFTMintStatuses)[keyof typeof NFTMintStatuses];\n\n/**\n * Metadata about a NFT transfer event.\n *\n * This metadata can be used for building more helpful messages when processing\n * NFT transfer events.\n */\nexport interface NFTTransferEventMetadata {\n chainId: ChainId;\n blockNumber: bigint;\n transactionHash: Hex;\n eventHandlerName: string;\n nft: DomainAssetId;\n}\n\nexport const formatNFTTransferEventMetadata = (metadata: NFTTransferEventMetadata): string => {\n const assetIdString = formatAssetId(metadata.nft);\n\n return [\n `Event: ${metadata.eventHandlerName}`,\n `Chain ID: ${metadata.chainId}`,\n `Block Number: ${metadata.blockNumber}`,\n `Transaction Hash: ${metadata.transactionHash}`,\n `NFT: ${assetIdString}`,\n ]\n .map((line) => ` - ${line}`)\n .join(\"\\n\");\n};\n\n/**\n * An enum representing the type of transfer that has occurred to a DomainAssetId.\n */\nexport const NFTTransferTypes = {\n /**\n * Initial transfer from zeroAddress to a non-zeroAddress\n * Can happen at most once to a NFT AssetId\n *\n * Invariants:\n * - NFT is not indexed and therefore has no previous mint status or owner\n * - new NFT mint status is `minted`\n * - new NFT owner is a non-zeroAddress\n */\n Mint: \"mint\",\n\n /**\n * Subsequent transfer from zeroAddress to a non-zeroAddress\n * Can happen any number of times to a NFT AssetId as it passes in a cycle from\n * mint -> burn -> remint -> burn -> remint -> ...\n *\n * Invariants:\n * - NFT is indexed\n * - previous NFT mint status was `burned`\n * - previous NFT owner is the zeroAddress\n * - new NFT mint status is `minted`\n * - new NFT owner is a non-zeroAddress\n */\n Remint: \"remint\",\n\n /**\n * Special transfer type for improperly implemented NFT contracts that allow a NFT\n * that is currently minted to be reminted before an intermediate burn.\n *\n * Transfer from zeroAddress to non-zeroAddress for an indexed NFT where the\n * previously indexed nft had status `minted` with a non-zeroAddress owner.\n *\n * Invariants:\n * - NFT is indexed\n * - previous NFT mint status was `minted`\n * - previous NFT owner was a non-zeroAddress\n * - new NFT mint status is `minted`\n * - new NFT owner is a non-zeroAddress\n */\n MintedRemint: \"minted-remint\",\n\n /**\n * Transfer from a non-zeroAddress to zeroAddress\n *\n * Invariants:\n * - NFT is indexed\n * - previous NFT mint status was `minted`\n * - previous NFT owner is a non-zeroAddress\n * - new NFT mint status is `burned`\n * - new NFT owner is the zeroAddress\n */\n Burn: \"burn\",\n\n /**\n * Transfer from a non-zeroAddress to a distinct non-zeroAddress\n *\n * Invariants:\n * - NFT is indexed\n * - previous and new NFT mint status is `minted`\n * - previous and new NFT owner are distinct non-zeroAddress\n */\n Transfer: \"transfer\",\n\n /**\n * Transfer from a non-zeroAddress to the same non-zeroAddress\n *\n * Invariants:\n * - NFT is indexed\n * - previous and new NFT mint status is `minted`\n * - previous and new NFT owner are equivalent non-zeroAddress\n */\n SelfTransfer: \"self-transfer\",\n\n /**\n * Transfer from zeroAddress to zeroAddress for an indexed NFT\n *\n * Invariants:\n * - NFT is indexed\n * - previous and new NFT mint status is `burned`\n * - previous and new NFT owner are zeroAddress\n */\n RemintBurn: \"remint-burn\",\n\n /**\n * Special transfer type for improperly implemented NFT contracts that allow a NFT\n * that is currently minted to be reminted again before an intermediate burn.\n *\n * Transfer from zeroAddress to zeroAddress for an indexed NFT where the\n * previously indexed nft had status `minted` with a non-zeroAddress owner.\n *\n * Invariants:\n * - NFT is indexed\n * - previous NFT mint status was `minted`\n * - previous NFT owner was a non-zeroAddress\n * - new NFT mint status is `burned`\n * - new NFT owner is the zeroAddress\n */\n MintedRemintBurn: \"minted-remint-burn\",\n\n /**\n * Transfer from zeroAddress to zeroAddress for an unindexed NFT\n *\n * Invariants:\n * - NFT is not indexed and therefore has no previous mint status or owner\n * - NFT should remain unindexed and without any mint status or owner\n */\n MintBurn: \"mint-burn\",\n} as const;\n\nexport type NFTTransferType = (typeof NFTTransferTypes)[keyof typeof NFTTransferTypes];\n\nexport const getNFTTransferType = (\n from: Address,\n to: Address,\n allowMintedRemint: boolean,\n metadata: NFTTransferEventMetadata,\n currentlyIndexedOwner?: Address,\n): NFTTransferType => {\n const isIndexed = currentlyIndexedOwner !== undefined;\n const isIndexedAsMinted = isIndexed && !isAddressEqual(currentlyIndexedOwner, zeroAddress);\n\n // a transfer from the zeroAddress to a non-zeroAddress represents minting\n const isMint = isAddressEqual(from, zeroAddress);\n\n // a transfer from a non-zeroAddress to the zeroAddress represents burning\n const isBurn = isAddressEqual(to, zeroAddress);\n\n // it's possible to transfer to and from the same address\n const isSelfTransfer = isAddressEqual(from, to);\n\n if (isIndexed && !isAddressEqual(currentlyIndexedOwner, from)) {\n if (isMint && allowMintedRemint) {\n // special case to allow minted remint from improperly implemented NFT contracts\n } else {\n throw new Error(\n `Error: Sending from ${from} conflicts with currently indexed owner ${currentlyIndexedOwner}.\\n${formatNFTTransferEventMetadata(metadata)}`,\n );\n }\n }\n\n if (isSelfTransfer) {\n if (isMint) {\n // a self-transfer to and from the zeroAddress represents either mint-burn, remint-burn,\n // or minted-remint-burn\n if (!isIndexed) {\n // mint-burn with !isIndexed && !isIndexedAsMinted\n return NFTTransferTypes.MintBurn;\n } else if (!isIndexedAsMinted) {\n // remint-burn with isIndexed && !isIndexedAsMinted\n return NFTTransferTypes.RemintBurn;\n } else if (allowMintedRemint) {\n // minted-remint-burn with isIndexed && isIndexedAsMinted && allowMintedRemint\n //\n // this is a non-standard special case for improperly implemented NFT contracts\n // that allow a NFT that is currently minted to be reminted again before an\n // intermediate burn.\n //\n // this is a self-transfer from zeroAddress to zeroAddress for an indexed NFT\n // where the previously indexed nft had status `minted` with a non-zeroAddress owner.\n return NFTTransferTypes.MintedRemintBurn;\n } else {\n // remint-burn with isIndexed && isIndexedAsMinted && !allowMintedRemint\n // invalid state transition to be minted and then remint again\n throw new Error(\n `Error: Invalid state transition from minted -> remint-burn\\n${formatNFTTransferEventMetadata(metadata)}`,\n );\n }\n } else {\n // a self-transfer to and from the same non-zero address\n if (!isIndexed) {\n // self-transfer with !isIndexed && !isIndexedAsMinted\n // this branch is unreachable because:\n // - from !== zeroAddress; and\n // - !isIndexedAsMinted requires that from === zeroAddress\n // throw an error to validate above assertions\n throw new Error(\n `Error: Invalid state transition from unindexed -> self-transfer\\n${formatNFTTransferEventMetadata(metadata)}`,\n );\n } else if (!isIndexedAsMinted) {\n // self-transfer with isIndexed && !isIndexedAsMinted\n throw new Error(\n `Error: invalid state transition from burned -> self-transfer\\n${formatNFTTransferEventMetadata(metadata)}`,\n );\n } else {\n // self-transfer with isIndexed && isIndexedAsMinted\n return NFTTransferTypes.SelfTransfer;\n }\n }\n } else if (isMint) {\n if (!isIndexed) {\n // mint with !isIndexed && !isIndexedAsMinted\n return NFTTransferTypes.Mint;\n } else if (!isIndexedAsMinted) {\n // mint with isIndexed && !isIndexedAsMinted\n return NFTTransferTypes.Remint;\n } else if (allowMintedRemint) {\n // mint with isIndexed && isIndexedAsMinted && allowMintedRemint\n //\n // this is a non-standard special case for improperly implemented NFT contracts\n // that allow a NFT that is currently minted to be reminted again before an\n // intermediate burn.\n //\n // this is a transfer from zeroAddress to non-zeroAddress for an indexed NFT\n // where the previously indexed nft had status `minted` with a non-zeroAddress owner.\n return NFTTransferTypes.MintedRemint;\n } else {\n // mint with isIndexed && isIndexedAsMinted && !allowMintedRemint\n throw new Error(\n `Error: Invalid state transition from minted -> mint\\n${formatNFTTransferEventMetadata(metadata)}`,\n );\n }\n } else if (isBurn) {\n if (!isIndexed) {\n // burn with !isIndexed && !isIndexedAsMinted\n throw new Error(\n `Error: Invalid state transition from unindexed -> burn\\n${formatNFTTransferEventMetadata(metadata)}`,\n );\n } else if (!isIndexedAsMinted) {\n // burn with isIndexed && !isIndexedAsMinted\n throw new Error(\n `Error: Invalid state transition from burned -> burn\\n${formatNFTTransferEventMetadata(metadata)}`,\n );\n } else {\n // burn with isIndexed && isIndexedAsMinted\n return NFTTransferTypes.Burn;\n }\n } else {\n // a transfer from a non-zeroAddress to a non-zeroAddress represents a transfer\n if (!isIndexed) {\n // transfer with !isIndexed && !isIndexedAsMinted\n throw new Error(\n `Error: Invalid state transition from unindexed -> transfer\\n${formatNFTTransferEventMetadata(metadata)}`,\n );\n } else if (!isIndexedAsMinted) {\n // transfer with isIndexed && !isIndexedAsMinted\n throw new Error(\n `Error: Invalid state transition from burned -> transfer\\n${formatNFTTransferEventMetadata(metadata)}`,\n );\n } else {\n // transfer with isIndexed && isIndexedAsMinted\n return NFTTransferTypes.Transfer;\n }\n }\n};\n","import { AssetId as CaipAssetId } from \"caip\";\nimport { zeroAddress } from \"viem\";\nimport z from \"zod/v4\";\nimport type { ParsePayload } from \"zod/v4/core\";\n\nimport { type AssetId, AssetNamespaces } from \"../shared/types\";\nimport { makeAccountIdSchema, makeNodeSchema } from \"../shared/zod-schemas\";\nimport { type DomainAssetId, NFTMintStatuses, type SerializedAssetId } from \"./assets\";\nimport {\n type NameToken,\n type NameTokenOwnershipBurned,\n type NameTokenOwnershipFullyOnchain,\n type NameTokenOwnershipNameWrapper,\n NameTokenOwnershipTypes,\n type NameTokenOwnershipUnknown,\n} from \"./name-token\";\n\nconst tokenIdSchemaSerializable = z.string();\nconst tokenIdSchemaNative = z.preprocess(\n (v) => (typeof v === \"string\" ? BigInt(v) : v),\n z.bigint().positive(),\n);\n\nexport function makeTokenIdSchema<const SerializableType extends boolean>(\n _valueLabel: string,\n serializable: SerializableType,\n): SerializableType extends true ? typeof tokenIdSchemaSerializable : typeof tokenIdSchemaNative;\nexport function makeTokenIdSchema(\n _valueLabel: string = \"Token ID Schema\",\n serializable: true | false = false,\n): typeof tokenIdSchemaSerializable | typeof tokenIdSchemaNative {\n if (serializable) {\n return tokenIdSchemaSerializable;\n } else {\n return tokenIdSchemaNative;\n }\n}\n\n/**\n * Make schema for {@link AssetId}.\n *\n */\nexport const makeAssetIdSchema = <const SerializableType extends boolean = false>(\n valueLabel: string = \"Asset ID Schema\",\n serializable?: SerializableType,\n) => {\n return z.object({\n assetNamespace: z.enum(AssetNamespaces),\n contract: makeAccountIdSchema(valueLabel),\n tokenId: makeTokenIdSchema(valueLabel, serializable ?? false),\n });\n};\n\n/**\n * Make schema for {@link AssetIdString}.\n */\nexport const makeAssetIdStringSchema = (valueLabel: string = \"Asset ID String Schema\") =>\n z.preprocess((v) => {\n if (typeof v === \"string\") {\n const result = new CaipAssetId(v);\n return {\n assetNamespace: result.assetName.namespace,\n contract: {\n chainId: Number(result.chainId.reference),\n address: result.assetName.reference,\n },\n tokenId: result.tokenId,\n } as SerializedAssetId;\n }\n\n return v;\n }, makeAssetIdSchema(valueLabel));\n\n/**\n * Make schema for {@link DomainAssetId}.\n */\nexport const makeDomainAssetSchema = (valueLabel: string = \"Domain Asset Schema\") =>\n makeAssetIdSchema(valueLabel).extend({\n domainId: makeNodeSchema(`${valueLabel}.domainId`),\n });\n\nfunction invariant_nameTokenOwnershipHasNonZeroAddressOwner(\n ctx: ParsePayload<\n NameTokenOwnershipNameWrapper | NameTokenOwnershipFullyOnchain | NameTokenOwnershipUnknown\n >,\n) {\n const ownership = ctx.value;\n if (ctx.value.owner.address === zeroAddress) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `Name Token Ownership with '${ownership.ownershipType}' must have 'address' other than the zero address.`,\n });\n }\n}\n\nexport const makeNameTokenOwnershipNameWrapperSchema = (\n valueLabel: string = \"Name Token Ownership NameWrapper\",\n) =>\n z\n .object({\n ownershipType: z.literal(NameTokenOwnershipTypes.NameWrapper),\n owner: makeAccountIdSchema(`${valueLabel}.owner`),\n })\n .check(invariant_nameTokenOwnershipHasNonZeroAddressOwner);\n\nexport const makeNameTokenOwnershipFullyOnchainSchema = (\n valueLabel: string = \"Name Token Ownership Fully Onchain\",\n) =>\n z\n .object({\n ownershipType: z.literal(NameTokenOwnershipTypes.FullyOnchain),\n owner: makeAccountIdSchema(`${valueLabel}.owner`),\n })\n .check(invariant_nameTokenOwnershipHasNonZeroAddressOwner);\n\nexport const makeNameTokenOwnershipBurnedSchema = (\n valueLabel: string = \"Name Token Ownership Burned\",\n) =>\n z\n .object({\n ownershipType: z.literal(NameTokenOwnershipTypes.Burned),\n owner: makeAccountIdSchema(`${valueLabel}.owner`),\n })\n .check(invariant_nameTokenOwnershipHasZeroAddressOwner);\n\nexport const makeNameTokenOwnershipUnknownSchema = (\n valueLabel: string = \"Name Token Ownership Unknown\",\n) =>\n z\n .object({\n ownershipType: z.literal(NameTokenOwnershipTypes.Unknown),\n owner: makeAccountIdSchema(`${valueLabel}.owner`),\n })\n .check(invariant_nameTokenOwnershipHasNonZeroAddressOwner);\n\nfunction invariant_nameTokenOwnershipHasZeroAddressOwner(\n ctx: ParsePayload<NameTokenOwnershipBurned>,\n) {\n const ownership = ctx.value;\n if (ctx.value.owner.address !== zeroAddress) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `Name Token Ownership with '${ownership.ownershipType}' must have 'address' set to the zero address.`,\n });\n }\n}\n\nexport const makeNameTokenOwnershipSchema = (valueLabel: string = \"Name Token Ownership\") =>\n z.discriminatedUnion(\"ownershipType\", [\n makeNameTokenOwnershipNameWrapperSchema(valueLabel),\n makeNameTokenOwnershipFullyOnchainSchema(valueLabel),\n makeNameTokenOwnershipBurnedSchema(valueLabel),\n makeNameTokenOwnershipUnknownSchema(valueLabel),\n ]);\n\n/**\n * Make schema for {@link NameToken}.\n */\nexport const makeNameTokenSchema = <const SerializableType extends boolean>(\n valueLabel: string = \"Name Token Schema\",\n serializable?: SerializableType,\n) =>\n z.object({\n token: makeAssetIdSchema(`${valueLabel}.token`, serializable),\n\n ownership: makeNameTokenOwnershipSchema(`${valueLabel}.ownership`),\n\n mintStatus: z.enum(NFTMintStatuses),\n });\n","import { isAddressEqual, zeroAddress } from \"viem\";\n\nimport { DatasourceNames, type ENSNamespaceId } from \"@ensnode/datasources\";\n\nimport { getParentNameFQDN, type InterpretedName } from \"../ens\";\nimport { type AccountId, accountIdEqual } from \"../shared\";\nimport { getDatasourceContract, maybeGetDatasourceContract } from \"../shared/datasource-contract\";\nimport type { AssetId } from \"../shared/types\";\nimport { type NFTMintStatus, type SerializedAssetId, serializeAssetId } from \"./assets\";\n\n/**\n * An enum representing the possible Name Token Ownership types.\n */\nexport const NameTokenOwnershipTypes = {\n /**\n * Name Token is owned by NameWrapper account.\n */\n NameWrapper: \"namewrapper\",\n\n /**\n * Name Token is owned fully onchain.\n *\n * This ownership type can only apply to direct subnames of `.eth`\n */\n FullyOnchain: \"fully-onchain\",\n\n /**\n * Name Token ownership has been transferred to the null address.\n */\n Burned: \"burned\",\n\n /**\n * Name Token ownership is unknown.\n */\n Unknown: \"unknown\",\n} as const;\n\nexport type NameTokenOwnershipType =\n (typeof NameTokenOwnershipTypes)[keyof typeof NameTokenOwnershipTypes];\n\nexport interface NameTokenOwnershipNameWrapper {\n ownershipType: typeof NameTokenOwnershipTypes.NameWrapper;\n\n /**\n * Owner\n *\n * Guarantees:\n * - `owner.address` is not the zero address.\n * - `owner.chainId` is same as the chainId of the associated NFT,\n * even if that NFT has been burned.\n */\n owner: AccountId;\n}\n\nexport interface NameTokenOwnershipFullyOnchain {\n ownershipType: typeof NameTokenOwnershipTypes.FullyOnchain;\n\n /**\n * Owner\n *\n * Guarantees:\n * - `owner.address` is not the zero address.\n * - `owner.chainId` is same as the chainId of the associated NFT,\n * even if that NFT has been burned.\n */\n owner: AccountId;\n}\n\nexport interface NameTokenOwnershipBurned {\n ownershipType: typeof NameTokenOwnershipTypes.Burned;\n\n /**\n * Owner\n *\n * Guarantees:\n * - `owner.address` is the zero address.\n * - `owner.chainId` is same as the chainId of the associated NFT,\n * even if that NFT has been burned.\n */\n owner: AccountId;\n}\n\nexport interface NameTokenOwnershipUnknown {\n ownershipType: typeof NameTokenOwnershipTypes.Unknown;\n\n /**\n * Owner\n *\n * Guarantees:\n * - `owner.address` is the zero address.\n * - `owner.chainId` is same as the chainId of the associated NFT,\n * even if that NFT has been burned.\n */\n owner: AccountId;\n}\n\nexport type NameTokenOwnership =\n | NameTokenOwnershipNameWrapper\n | NameTokenOwnershipFullyOnchain\n | NameTokenOwnershipBurned\n | NameTokenOwnershipUnknown;\n\nexport interface NameToken {\n /**\n * Token\n *\n * References the NFT that currently or previously tokenized ownership of\n * `name`.\n */\n token: AssetId;\n\n /**\n * Owner\n *\n * Identifies the ownership state of the token.\n *\n * Guarantees:\n * - The `ownership.owner.chainId` of this address is the same as is referenced\n * in `domainAsset.contract.chainId`.\n */\n ownership: NameTokenOwnership;\n\n /**\n * The mint status of the token.\n *\n * After ENSNode indexes the token for a name, even if that token is burned,\n * ENSNode will never forget how the token once represented the name.\n * When the token for a name is burned, ENSNode remembers this token but\n * updates its `mintStatus` to `burned`. If this token becomes minted again\n * after it was burned, its `mintStatus` is updated to `minted` again.\n *\n * NOTE: Tokens managed by the .eth BaseRegistrar for\n * direct subnames of .eth can only be burned when undergoing\n * a state transition of `minted` -> `burned` -> `minted` all within\n * the same registrar action for the case that a direct subname of .eth\n * has expired and has been fully released and is now being registered again.\n * Since all of those mint status state transitions are processed within\n * a single block, once the token managed by the .eth BaseRegistrar for\n * a direct subname of .eth has been minted, our state model will forever\n * represent it as `minted`.\n *\n * Guarantees:\n * - The `mintStatus` will be burned if and only\n * if `ownership.ownershipType` is `NameTokenOwnershipTypes.Burned`.\n */\n mintStatus: NFTMintStatus;\n}\n\n/**\n * Serialized representation of {@link NameToken}.\n */\nexport interface SerializedNameToken extends Omit<NameToken, \"token\"> {\n token: SerializedAssetId;\n}\n\nexport function serializeNameToken(nameToken: NameToken): SerializedNameToken {\n return {\n token: serializeAssetId(nameToken.token),\n ownership: nameToken.ownership,\n mintStatus: nameToken.mintStatus,\n };\n}\n\n/**\n * Get all NameWrapper accounts within provided ENS Namespace.\n *\n * Guaranteed to return at least one account for ENSRoot Datasource.\n */\nexport function getNameWrapperAccounts(namespaceId: ENSNamespaceId): [AccountId, ...AccountId[]] {\n const ethnamesNameWrapperAccount = getDatasourceContract(\n namespaceId,\n DatasourceNames.ENSRoot,\n \"NameWrapper\",\n );\n\n const lineanamesNameWrapperAccount = maybeGetDatasourceContract(\n namespaceId,\n DatasourceNames.Lineanames,\n \"NameWrapper\",\n );\n\n const nameWrapperAccounts: [AccountId, ...AccountId[]] = [\n // NameWrapper for direct subnames of .eth is defined for all ENS namespaces\n ethnamesNameWrapperAccount,\n ];\n\n if (lineanamesNameWrapperAccount) {\n // NameWrapper for Lineanames is only defined for some ENS namespaces\n nameWrapperAccounts.push(lineanamesNameWrapperAccount);\n }\n\n return nameWrapperAccounts;\n}\n\n/**\n * Get name token ownership for provided owner account within selected ENS Namespace.\n */\nexport function getNameTokenOwnership(\n namespaceId: ENSNamespaceId,\n name: InterpretedName,\n owner: AccountId,\n): NameTokenOwnership {\n const nameWrapperAccounts = getNameWrapperAccounts(namespaceId);\n const hasNameWrapperOwnership = nameWrapperAccounts.some((nameWrapperAccount) =>\n accountIdEqual(owner, nameWrapperAccount),\n );\n\n if (hasNameWrapperOwnership) {\n return {\n ownershipType: NameTokenOwnershipTypes.NameWrapper,\n owner,\n } satisfies NameTokenOwnershipNameWrapper;\n }\n\n if (isAddressEqual(owner.address, zeroAddress)) {\n return {\n ownershipType: NameTokenOwnershipTypes.Burned,\n owner,\n } satisfies NameTokenOwnershipBurned;\n }\n\n const parentName = getParentNameFQDN(name);\n\n // set ownershipType as 'fully-onchain' if `name` is a direct subname of .eth\n if (parentName === \"eth\") {\n return {\n ownershipType: NameTokenOwnershipTypes.FullyOnchain,\n owner,\n } satisfies NameTokenOwnershipFullyOnchain;\n }\n\n return {\n ownershipType: NameTokenOwnershipTypes.Unknown,\n owner,\n } satisfies NameTokenOwnershipUnknown;\n}\n","import z from \"zod/v4\";\n\nimport type { ErrorResponse } from \"./response\";\n\n/**\n * Schema for {@link ErrorResponse}.\n */\nexport const ErrorResponseSchema = z.object({\n message: z.string(),\n details: z.optional(z.unknown()),\n});\n","import type { UnixTimestamp } from \"@namehash/ens-referrals\";\n\nimport type { InterpretedName, Node } from \"../../ens\";\nimport type { NameToken, NameTokenOwnershipTypes } from \"../../tokenscope\";\nimport type { ErrorResponse } from \"../shared/errors\";\n\n/**\n * A status code for Name Tokens API responses.\n */\nexport const NameTokensResponseCodes = {\n /**\n * Represents a response when Name Tokens API can respond with requested data.\n */\n Ok: \"ok\",\n\n /**\n * Represents a response when Name Tokens API could not respond with requested data.\n */\n Error: \"error\",\n} as const;\n\n/**\n * The derived string union of possible {@link NameTokensResponseCodes}.\n */\nexport type NameTokensResponseCode =\n (typeof NameTokensResponseCodes)[keyof typeof NameTokensResponseCodes];\n\n/**\n * Error codes for Name Tokens API responses with 'error' response code.\n */\nexport const NameTokensResponseErrorCodes = {\n /**\n * Name tokens not indexed\n *\n * Represents an error when tokens for the requested name are not indexed by\n * the ENSNode instance's configuration.\n */\n NameTokensNotIndexed: \"name-tokens-not-indexed\",\n\n /**\n * Unsupported ENSIndexer Config\n *\n * Represents a prerequisites error when connected ENSIndexer config lacks\n * params required to enable Name Tokens API.\n */\n EnsIndexerConfigUnsupported: \"unsupported-ensindexer-config\",\n\n /**\n * Unsupported Indexing Status\n *\n * Represents a prerequisites error when Indexing Status has not yet reached\n * status required to enable Name Tokens API.\n */\n IndexingStatusUnsupported: \"unsupported-indexing-status\",\n} as const;\n\n/**\n * The derived string union of possible {@link NameTokensResponseErrorCodes}.\n */\nexport type NameTokensResponseErrorCode =\n (typeof NameTokensResponseErrorCodes)[keyof typeof NameTokensResponseErrorCodes];\n\n/**\n * Name Tokens for a name who's tokens are configured to\n * be indexed by the ENSNode instance's configuration.\n */\nexport interface RegisteredNameTokens {\n /**\n * Domain ID\n */\n domainId: Node;\n\n /**\n * Name\n *\n * FQDN of the name associated with `domainId`.\n *\n * Guarantees:\n * - `namehash(name)` is always `domainId`.\n */\n name: InterpretedName;\n\n /**\n * Name Tokens associated with the `domainId`.\n *\n * It contains every tokenized representation of `name` that\n * has ever been indexed for the given name as of `accurateAsOf`,\n * even if the given token has been burned or expired.\n *\n * Guarantees:\n * - Always includes at least one name token.\n * - When it includes more than one name token, it means that:\n * 1) More than 1 distinct tokenized representation of the ownership of\n * the `name` has been indexed as of `accurateAsOf`.\n * 2) All possible permutations of mint statuses of these tokens are\n * possible:\n * a) Multiple could be actively minted.\n * b) Multiple could be burned.\n * c) Some could be burned, others could be minted.\n * - Order of name tokens follows the order of onchain events that were\n * indexed when a token was minted, or burned.\n * - Each name token has a distinct `token` value which references\n * the NFT that currently or previously tokenized ownership of `name`.\n * - Each name token has ownership type (`ownership.ownershipType`) assigned:\n * - If there's a name token with ownership type\n * {@link NameTokenOwnershipTypes.NameWrapper}, it means that there must be also\n * another name token with ownership type either\n * {@link NameTokenOwnershipTypes.FullyOnchain}, or\n * {@link NameTokenOwnershipTypes.Unknown}.\n * - There can be at most one name token with ownership type\n * {@link NameTokenOwnershipTypes.FullyOnchain}.\n * - There can be any number of name tokens with ownership type\n * {@link NameTokenOwnershipTypes.Burned}.\n *\n * NOTE: It can be useful to get tokenized representations of the name that\n * are now burned: This can be helpful for looking up historical activity for\n * the name, including past buy orders, sell orders, and sales.\n *\n * How will the direct subnames of .eth that are wrapped by the NameWrapper\n * be represented?\n * 1) A direct subname of .eth that has been registered but\n * has never been wrapped by the NameWrapper, and:\n * a) Is still actively minted (independent of its expiry state).\n * b) Has been burned by sending it to the null address.\n * 2) A direct subname of .eth that has been registered and\n * has been wrapped by the NameWrapper, and:\n * a) Is still actively wrapped by the NameWrapper (independent of its\n * expiry state).\n * b) Is no longer wrapped by the NameWrapper, but is still actively\n * minted by the BaseRegistrar (independent of its expiry state).\n * c) Is no longer wrapped by the NameWrapper, and is also no longer\n * minted by the BaseRegistrar (both tokens now burned by sending to\n * the null address).\n */\n tokens: NameToken[];\n\n /**\n * Expiry date for the Registration Lifecycle\n *\n * The latest Registration Lifecycle for a node referenced in `domainId`.\n */\n expiresAt: UnixTimestamp;\n\n /**\n * The {@link UnixTimestamp} of when the data used to build the {@link NameTokensResponseOk.nameTokens} was accurate as of.\n */\n accurateAsOf: UnixTimestamp;\n}\n\n/**\n * A response when Name Tokens API can respond with requested data.\n */\nexport type NameTokensResponseOk = {\n responseCode: typeof NameTokensResponseCodes.Ok;\n\n /**\n * Name Tokens for the requested name.\n */\n registeredNameTokens: RegisteredNameTokens;\n};\n\n/**\n * Represents an error response when requested name was not indexed by ENSNode.\n */\nexport interface NameTokensResponseErrorNameTokensNotIndexed {\n responseCode: typeof NameTokensResponseCodes.Error;\n errorCode: typeof NameTokensResponseErrorCodes.NameTokensNotIndexed;\n error: ErrorResponse;\n}\n\n/**\n * Represents an error response when connected ENSIndexer config lacks\n * params required to enable Name Tokens API.\n */\nexport interface NameTokensResponseErrorEnsIndexerConfigUnsupported {\n responseCode: typeof NameTokensResponseCodes.Error;\n errorCode: typeof NameTokensResponseErrorCodes.EnsIndexerConfigUnsupported;\n error: ErrorResponse;\n}\n\n/**\n * Represents an error response when Indexing Status has not yet reached\n * status required to enable Name Tokens API.\n */\nexport interface NameTokensResponseErrorIndexingStatusUnsupported {\n responseCode: typeof NameTokensResponseCodes.Error;\n errorCode: typeof NameTokensResponseErrorCodes.IndexingStatusUnsupported;\n error: ErrorResponse;\n}\n\nexport type NameTokensResponseError =\n | NameTokensResponseErrorNameTokensNotIndexed\n | NameTokensResponseErrorEnsIndexerConfigUnsupported\n | NameTokensResponseErrorIndexingStatusUnsupported;\n\n/**\n * Name Tokens response.\n *\n * Use the `responseCode` field to determine the specific type interpretation\n * at runtime.\n */\nexport type NameTokensResponse = NameTokensResponseOk | NameTokensResponseError;\n","import {\n type ENSIndexerPublicConfig,\n type OmnichainIndexingStatusId,\n OmnichainIndexingStatusIds,\n PluginName,\n} from \"../../ensindexer\";\n\nexport const nameTokensPrerequisites = Object.freeze({\n /**\n * Required plugins to enable Name Tokens API routes.\n *\n * 1. `registrars` plugin is required so that data in the `registrationLifecycles`\n * table is populated.\n * 2. `tokenscope` plugin is required so that data in the `nameTokens`\n * table is populated.\n */\n requiredPlugins: [PluginName.Registrars, PluginName.TokenScope] as const,\n\n /**\n * Check if provided ENSApiPublicConfig supports the Name Tokens API.\n */\n hasEnsIndexerConfigSupport(config: ENSIndexerPublicConfig): boolean {\n return nameTokensPrerequisites.requiredPlugins.every((plugin) =>\n config.plugins.includes(plugin),\n );\n },\n /**\n * Required Indexing Status IDs\n *\n * Database indexes are created by the time the omnichain indexing status\n * is either `completed` or `following`.\n */\n supportedIndexingStatusIds: [\n OmnichainIndexingStatusIds.Completed,\n OmnichainIndexingStatusIds.Following,\n ],\n\n /**\n * Check if provided indexing status supports the Name Tokens API.\n */\n hasIndexingStatusSupport(omnichainIndexingStatusId: OmnichainIndexingStatusId): boolean {\n return nameTokensPrerequisites.supportedIndexingStatusIds.some(\n (supportedIndexingStatusId) => supportedIndexingStatusId === omnichainIndexingStatusId,\n );\n },\n});\n","import { serializeNameToken } from \"../../tokenscope\";\nimport {\n type NameTokensResponse,\n NameTokensResponseCodes,\n type RegisteredNameTokens,\n} from \"./response\";\nimport type {\n SerializedNameTokensResponse,\n SerializedNameTokensResponseOk,\n SerializedRegisteredNameTokens,\n} from \"./serialized-response\";\n\nexport function serializeRegisteredNameTokens({\n domainId,\n name,\n tokens,\n expiresAt,\n accurateAsOf,\n}: RegisteredNameTokens): SerializedRegisteredNameTokens {\n return {\n domainId,\n name,\n tokens: tokens.map(serializeNameToken),\n expiresAt,\n accurateAsOf,\n };\n}\n\nexport function serializeNameTokensResponse(\n response: NameTokensResponse,\n): SerializedNameTokensResponse {\n switch (response.responseCode) {\n case NameTokensResponseCodes.Ok:\n return {\n responseCode: response.responseCode,\n registeredNameTokens: serializeRegisteredNameTokens(response.registeredNameTokens),\n } satisfies SerializedNameTokensResponseOk;\n\n case NameTokensResponseCodes.Error:\n return response;\n }\n}\n","import { prettifyError } from \"zod/v4\";\n\nimport type { RegistrarActionsResponse } from \"./response\";\nimport type { SerializedRegistrarActionsResponse } from \"./serialized-response\";\nimport { makeRegistrarActionsResponseSchema } from \"./zod-schemas\";\n\n/**\n * Deserialize a {@link RegistrarActionsResponse} object.\n */\nexport function deserializeRegistrarActionsResponse(\n maybeResponse: SerializedRegistrarActionsResponse,\n): RegistrarActionsResponse {\n const parsed = makeRegistrarActionsResponseSchema().safeParse(maybeResponse);\n\n if (parsed.error) {\n throw new Error(\n `Cannot deserialize RegistrarActionsResponse:\\n${prettifyError(parsed.error)}\\n`,\n );\n }\n\n return parsed.data;\n}\n","import { namehash } from \"viem/ens\";\nimport z from \"zod/v4\";\nimport type { ParsePayload } from \"zod/v4/core\";\n\nimport { makeRegistrarActionSchema } from \"../../registrars/zod-schemas\";\nimport { makeReinterpretedNameSchema, makeUnixTimestampSchema } from \"../../shared/zod-schemas\";\nimport { ErrorResponseSchema } from \"../shared/errors/zod-schemas\";\nimport { makeResponsePageContextSchema } from \"../shared/pagination/zod-schemas\";\nimport { type NamedRegistrarAction, RegistrarActionsResponseCodes } from \"./response\";\n\nfunction invariant_registrationLifecycleNodeMatchesName(ctx: ParsePayload<NamedRegistrarAction>) {\n const { name, action } = ctx.value;\n const expectedNode = action.registrationLifecycle.node;\n const actualNode = namehash(name);\n\n if (actualNode !== expectedNode) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `The 'action.registrationLifecycle.node' must match namehash of 'name'`,\n });\n }\n}\n\n/**\n * Schema for {@link NamedRegistrarAction}.\n */\nexport const makeNamedRegistrarActionSchema = (valueLabel: string = \"Named Registrar Action\") =>\n z\n .object({\n action: makeRegistrarActionSchema(valueLabel),\n name: makeReinterpretedNameSchema(valueLabel),\n })\n .check(invariant_registrationLifecycleNodeMatchesName);\n\n/**\n * Schema for {@link RegistrarActionsResponseOk}\n */\nexport const makeRegistrarActionsResponseOkSchema = (\n valueLabel: string = \"Registrar Actions Response OK\",\n) =>\n z.object({\n responseCode: z.literal(RegistrarActionsResponseCodes.Ok),\n registrarActions: z.array(makeNamedRegistrarActionSchema(valueLabel)),\n pageContext: makeResponsePageContextSchema(`${valueLabel}.pageContext`),\n accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`).optional(),\n });\n\n/**\n * Schema for {@link RegistrarActionsResponseError}\n */\nexport const makeRegistrarActionsResponseErrorSchema = (\n _valueLabel: string = \"Registrar Actions Response Error\",\n) =>\n z.strictObject({\n responseCode: z.literal(RegistrarActionsResponseCodes.Error),\n error: ErrorResponseSchema,\n });\n\n/**\n * Schema for {@link RegistrarActionsResponse}\n */\nexport const makeRegistrarActionsResponseSchema = (\n valueLabel: string = \"Registrar Actions Response\",\n) =>\n z.discriminatedUnion(\"responseCode\", [\n makeRegistrarActionsResponseOkSchema(valueLabel),\n makeRegistrarActionsResponseErrorSchema(valueLabel),\n ]);\n","import { type Address, isAddress } from \"viem\";\n\nexport const validateLowercaseAddress = (address: Address): void => {\n if (!isAddress(address, { strict: false })) {\n throw new Error(`Invalid address: ${address}. Address must be a valid EVM address.`);\n }\n\n if (address !== address.toLowerCase()) {\n throw new Error(`Invalid address: ${address}. Address must be in lowercase format.`);\n }\n};\n\nexport const normalizeAddress = (address: Address): Address => {\n return address.toLowerCase() as Address;\n};\n","import { type Address, getAddress, type Hex, pad, size, slice, zeroAddress } from \"viem\";\n\n/**\n * Encoded Referrer\n *\n * Represents a \"raw\" ENS referrer value.\n *\n * Guaranteed to be a hex string representation of a 32-byte value.\n * For ENS Holiday Awards a correctly encoded referrer is\n * a left-padded lowercase EVM address.\n */\nexport type EncodedReferrer = Hex;\n\n/**\n * Encoded Referrer byte offset for ENS Holiday Awards.\n *\n * The count of left-padded bytes in an {@link EncodedReferrer} value for ENS Holiday Awards.\n */\nexport const ENCODED_REFERRER_BYTE_OFFSET = 12;\n\n/**\n * Encoded Referrer byte length\n *\n * The count of bytes the {@link EncodedReferrer} value consists of.\n */\nexport const ENCODED_REFERRER_BYTE_LENGTH = 32;\n\n/**\n * Encoded Referrer Padding for ENS Holiday Awards\n *\n * The initial bytes of correctly encoded referrer value for ENS Holiday Awards.\n */\nexport const EXPECTED_ENCODED_REFERRER_PADDING: Hex = pad(\"0x\", {\n size: ENCODED_REFERRER_BYTE_OFFSET,\n dir: \"left\",\n});\n\n/**\n * Zero Encoded Referrer\n *\n * Guaranteed to be a hex string representation of a 32-byte zero value.\n */\nexport const ZERO_ENCODED_REFERRER: EncodedReferrer = pad(\"0x\", {\n size: ENCODED_REFERRER_BYTE_LENGTH,\n dir: \"left\",\n});\n\n/**\n * Build an {@link EncodedReferrer} value for the given {@link Address}\n * according to the subjective referrer encoding used for ENS Holiday Awards.\n */\nexport function buildEncodedReferrer(address: Address): EncodedReferrer {\n const lowercaseAddress = address.toLowerCase() as Address;\n\n return pad(lowercaseAddress, { size: ENCODED_REFERRER_BYTE_LENGTH, dir: \"left\" });\n}\n\n/**\n * Decode an {@link EncodedReferrer} value into a checksummed {@link Address}\n * according to the subjective referrer encoding used for ENS Holiday Awards.\n *\n * @param encodedReferrer - The \"raw\" {@link EncodedReferrer} value to decode.\n * @returns The decoded referrer checksummed address.\n * @throws when encodedReferrer value is not represented by\n * {@link ENCODED_REFERRER_BYTE_LENGTH} bytes.\n * @throws when decodedReferrer is not a valid EVM address.\n */\nexport function decodeEncodedReferrer(encodedReferrer: EncodedReferrer): Address {\n // Invariant: encoded referrer must be of expected size\n if (size(encodedReferrer) !== ENCODED_REFERRER_BYTE_LENGTH) {\n throw new Error(\n `Encoded referrer value must be represented by ${ENCODED_REFERRER_BYTE_LENGTH} bytes.`,\n );\n }\n\n const padding = slice(encodedReferrer, 0, ENCODED_REFERRER_BYTE_OFFSET);\n\n // return zero address if the padding of encoded referrer is not correct\n // for ENS Holiday Awards\n if (padding !== EXPECTED_ENCODED_REFERRER_PADDING) {\n return zeroAddress;\n }\n\n const decodedReferrer = slice(encodedReferrer, ENCODED_REFERRER_BYTE_OFFSET);\n\n try {\n // return checksummed address\n return getAddress(decodedReferrer);\n } catch {\n throw new Error(`Decoded referrer value must be a valid EVM address.`);\n }\n}\n","import type { AggregatedReferrerMetrics } from \"./aggregations\";\nimport type { ReferrerLeaderboard } from \"./leaderboard\";\nimport { isNonNegativeInteger, isPositiveInteger } from \"./number\";\nimport type { AwardedReferrerMetrics } from \"./referrer-metrics\";\nimport type { ReferralProgramRules } from \"./rules\";\nimport type { UnixTimestamp } from \"./time\";\n\n/**\n * The default number of referrers per leaderboard page.\n */\nexport const REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT = 25;\n\n/**\n * The maximum number of referrers per leaderboard page.\n */\n\nexport const REFERRERS_PER_LEADERBOARD_PAGE_MAX = 100;\n\n/**\n * Pagination params for leaderboard queries.\n */\nexport interface ReferrerLeaderboardPageParams {\n /**\n * Requested referrer leaderboard page number (1-indexed)\n * @invariant Must be a positive integer (>= 1)\n * @default 1\n */\n page?: number;\n\n /**\n * Maximum number of referrers to return per leaderboard page\n * @invariant Must be a positive integer (>= 1) and less than or equal to {@link REFERRERS_PER_LEADERBOARD_PAGE_MAX}\n * @default {@link REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT}\n */\n recordsPerPage?: number;\n}\n\nconst validateReferrerLeaderboardPageParams = (params: ReferrerLeaderboardPageParams): void => {\n if (params.page !== undefined && !isPositiveInteger(params.page)) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageParams: ${params.page}. page must be a positive integer.`,\n );\n }\n if (params.recordsPerPage !== undefined && !isPositiveInteger(params.recordsPerPage)) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageParams: ${params.recordsPerPage}. recordsPerPage must be a positive integer.`,\n );\n }\n if (\n params.recordsPerPage !== undefined &&\n params.recordsPerPage > REFERRERS_PER_LEADERBOARD_PAGE_MAX\n ) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageParams: ${params.recordsPerPage}. recordsPerPage must be less than or equal to ${REFERRERS_PER_LEADERBOARD_PAGE_MAX}.`,\n );\n }\n};\n\nexport const buildReferrerLeaderboardPageParams = (\n params: ReferrerLeaderboardPageParams,\n): Required<ReferrerLeaderboardPageParams> => {\n const result = {\n page: params.page ?? 1,\n recordsPerPage: params.recordsPerPage ?? REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT,\n } satisfies Required<ReferrerLeaderboardPageParams>;\n validateReferrerLeaderboardPageParams(result);\n return result;\n};\n\nexport interface ReferrerLeaderboardPageContext extends Required<ReferrerLeaderboardPageParams> {\n /**\n * Total number of referrers across all leaderboard pages\n * @invariant Guaranteed to be a non-negative integer (>= 0)\n */\n totalRecords: number;\n\n /**\n * Total number of pages in the leaderboard\n * @invariant Guaranteed to be a positive integer (>= 1)\n */\n totalPages: number;\n\n /**\n * Indicates if there is a next page available\n * @invariant true if and only if (`page` * `recordsPerPage` < `total`)\n */\n hasNext: boolean;\n\n /**\n * Indicates if there is a previous page available\n * @invariant true if and only if (`page` > 1)\n */\n hasPrev: boolean;\n\n /**\n * The start index of the referrers on the page (0-indexed)\n *\n * `undefined` if and only if `totalRecords` is 0.\n *\n * @invariant Guaranteed to be a non-negative integer (>= 0)\n */\n startIndex?: number;\n\n /**\n * The end index of the referrers on the page (0-indexed)\n *\n * `undefined` if and only if `totalRecords` is 0.\n *\n * @invariant Guaranteed to be a non-negative integer (>= 0)\n * @invariant If `totalRecords` is > 0:\n * - Guaranteed to be greater than or equal to `startIndex`.\n * - Guaranteed to be less than `totalRecords`.\n */\n endIndex?: number;\n}\n\nexport const validateReferrerLeaderboardPageContext = (\n context: ReferrerLeaderboardPageContext,\n): void => {\n validateReferrerLeaderboardPageParams(context);\n if (!isNonNegativeInteger(context.totalRecords)) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: total must be a non-negative integer but is ${context.totalRecords}.`,\n );\n }\n const startIndex = (context.page - 1) * context.recordsPerPage;\n const endIndex = startIndex + context.recordsPerPage;\n\n if (!context.hasNext && endIndex < context.totalRecords) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: if hasNext is false, endIndex (${endIndex}) must be greater than or equal to total (${context.totalRecords}).`,\n );\n } else if (context.hasNext && context.page * context.recordsPerPage >= context.totalRecords) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: if hasNext is true, endIndex (${endIndex}) must be less than total (${context.totalRecords}).`,\n );\n }\n if (!context.hasPrev && context.page !== 1) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: if hasPrev is false, page must be the first page (1) but is ${context.page}.`,\n );\n } else if (context.hasPrev && context.page === 1) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: if hasPrev is true, page must not be the first page (1) but is ${context.page}.`,\n );\n }\n};\n\nexport const buildReferrerLeaderboardPageContext = (\n optionalParams: ReferrerLeaderboardPageParams,\n leaderboard: ReferrerLeaderboard,\n): ReferrerLeaderboardPageContext => {\n const materializedParams = buildReferrerLeaderboardPageParams(optionalParams);\n\n const totalRecords = leaderboard.referrers.size;\n\n const totalPages = Math.max(1, Math.ceil(totalRecords / materializedParams.recordsPerPage));\n\n if (materializedParams.page > totalPages) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: page ${materializedParams.page} exceeds total pages ${totalPages}.`,\n );\n }\n\n if (totalRecords === 0) {\n return {\n ...materializedParams,\n totalRecords: 0,\n totalPages: 1,\n hasNext: false,\n hasPrev: false,\n startIndex: undefined,\n endIndex: undefined,\n } satisfies ReferrerLeaderboardPageContext;\n }\n\n const startIndex = (materializedParams.page - 1) * materializedParams.recordsPerPage;\n const maxTheoreticalIndexOnPage = startIndex + (materializedParams.recordsPerPage - 1);\n const endIndex = Math.min(maxTheoreticalIndexOnPage, totalRecords - 1);\n const hasNext = maxTheoreticalIndexOnPage < totalRecords - 1;\n const hasPrev = materializedParams.page > 1;\n\n const result = {\n ...materializedParams,\n totalRecords,\n totalPages,\n hasNext,\n hasPrev,\n startIndex,\n endIndex,\n } satisfies ReferrerLeaderboardPageContext;\n validateReferrerLeaderboardPageContext(result);\n return result;\n};\n\n/**\n * A page of referrers from the referrer leaderboard.\n */\nexport interface ReferrerLeaderboardPage {\n /**\n * The {@link ReferralProgramRules} used to generate the {@link ReferrerLeaderboard}\n * that this {@link ReferrerLeaderboardPage} comes from.\n */\n rules: ReferralProgramRules;\n\n /**\n * Ordered list of {@link AwardedReferrerMetrics} for the {@link ReferrerLeaderboardPage}\n * described by `pageContext` within the related {@link ReferrerLeaderboard}.\n *\n * @invariant Array will be empty if `pageContext.totalRecords` is 0.\n * @invariant Array entries are ordered by `rank` (descending).\n */\n referrers: AwardedReferrerMetrics[];\n\n /**\n * Aggregated metrics for all referrers on the leaderboard.\n */\n aggregatedMetrics: AggregatedReferrerMetrics;\n\n /**\n * The {@link ReferrerLeaderboardPageContext} of this {@link ReferrerLeaderboardPage} relative to the overall\n * {@link ReferrerLeaderboard}.\n */\n pageContext: ReferrerLeaderboardPageContext;\n\n /**\n * The {@link UnixTimestamp} of when the data used to build the {@link ReferrerLeaderboardPage} was accurate as of.\n */\n accurateAsOf: UnixTimestamp;\n}\n\nexport const getReferrerLeaderboardPage = (\n pageParams: ReferrerLeaderboardPageParams,\n leaderboard: ReferrerLeaderboard,\n): ReferrerLeaderboardPage => {\n const pageContext = buildReferrerLeaderboardPageContext(pageParams, leaderboard);\n\n let referrers: AwardedReferrerMetrics[];\n\n if (\n pageContext.totalRecords > 0 &&\n typeof pageContext.startIndex !== \"undefined\" &&\n typeof pageContext.endIndex !== \"undefined\"\n ) {\n // extract the referrers from the leaderboard in the range specified by `pageContext`.\n referrers = Array.from(leaderboard.referrers.values()).slice(\n pageContext.startIndex,\n pageContext.endIndex + 1, // For `slice`, this is exclusive of the element at the index 'end'. We need it to be inclusive, hence plus one.\n );\n } else {\n referrers = [];\n }\n\n return {\n rules: leaderboard.rules,\n referrers,\n aggregatedMetrics: leaderboard.aggregatedMetrics,\n pageContext,\n accurateAsOf: leaderboard.accurateAsOf,\n };\n};\n","import { type Address, getAddress } from \"viem\";\n\n/**\n * Build a URL to the official ENS manager app\n * where the given {@link Address} is set as the referrer.\n */\nexport function buildEnsReferralUrl(address: Address): URL {\n const ensAppUrl = new URL(\"https://app.ens.domains\");\n\n ensAppUrl.searchParams.set(\"referrer\", getAddress(address));\n\n return ensAppUrl;\n}\n","import type { Address } from \"viem\";\n\nimport type { AggregatedReferrerMetrics } from \"./aggregations\";\nimport type { ReferrerLeaderboard } from \"./leaderboard\";\nimport {\n type AwardedReferrerMetrics,\n buildUnrankedReferrerMetrics,\n type UnrankedReferrerMetrics,\n} from \"./referrer-metrics\";\nimport type { ReferralProgramRules } from \"./rules\";\nimport type { UnixTimestamp } from \"./time\";\n\n/**\n * The type of referrer detail data.\n */\nexport const ReferrerDetailTypeIds = {\n /**\n * Represents a referrer who is ranked on the leaderboard.\n */\n Ranked: \"ranked\",\n\n /**\n * Represents a referrer who is not ranked on the leaderboard.\n */\n Unranked: \"unranked\",\n} as const;\n\n/**\n * The derived string union of possible {@link ReferrerDetailTypeIds}.\n */\nexport type ReferrerDetailTypeId =\n (typeof ReferrerDetailTypeIds)[keyof typeof ReferrerDetailTypeIds];\n\n/**\n * Referrer detail data for a specific referrer address on the leaderboard.\n *\n * Includes the referrer's awarded metrics from the leaderboard plus timestamp.\n *\n * Invariants:\n * - `type` is always {@link ReferrerDetailTypeIds.Ranked}.\n *\n * @see {@link AwardedReferrerMetrics}\n */\nexport interface ReferrerDetailRanked {\n /**\n * The type of referrer detail data.\n */\n type: typeof ReferrerDetailTypeIds.Ranked;\n\n /**\n * The {@link ReferralProgramRules} used to calculate the {@link AwardedReferrerMetrics}.\n */\n rules: ReferralProgramRules;\n\n /**\n * The awarded referrer metrics from the leaderboard.\n *\n * Contains all calculated metrics including score, rank, qualification status,\n * and award pool share information.\n */\n referrer: AwardedReferrerMetrics;\n\n /**\n * Aggregated metrics for all referrers on the leaderboard.\n */\n aggregatedMetrics: AggregatedReferrerMetrics;\n\n /**\n * The {@link UnixTimestamp} of when the data used to build the {@link ReferrerDetailData} was accurate as of.\n */\n accurateAsOf: UnixTimestamp;\n}\n\n/**\n * Referrer detail data for a specific referrer address NOT on the leaderboard.\n *\n * Includes the referrer's unranked metrics (with null rank and isQualified: false) plus timestamp.\n *\n * Invariants:\n * - `type` is always {@link ReferrerDetailTypeIds.Unranked}.\n *\n * @see {@link UnrankedReferrerMetrics}\n */\nexport interface ReferrerDetailUnranked {\n /**\n * The type of referrer detail data.\n */\n type: typeof ReferrerDetailTypeIds.Unranked;\n\n /**\n * The {@link ReferralProgramRules} used to calculate the {@link UnrankedReferrerMetrics}.\n */\n rules: ReferralProgramRules;\n\n /**\n * The unranked referrer metrics (not on the leaderboard).\n *\n * Contains all calculated metrics with rank set to null and isQualified set to false.\n */\n referrer: UnrankedReferrerMetrics;\n\n /**\n * Aggregated metrics for all referrers on the leaderboard.\n */\n aggregatedMetrics: AggregatedReferrerMetrics;\n\n /**\n * The {@link UnixTimestamp} of when the data used to build the {@link UnrankedReferrerDetailData} was accurate as of.\n */\n accurateAsOf: UnixTimestamp;\n}\n\n/**\n * Referrer detail data for a specific referrer address.\n *\n * Use the `type` field to determine the specific type interpretation\n * at runtime.\n */\nexport type ReferrerDetail = ReferrerDetailRanked | ReferrerDetailUnranked;\n\n/**\n * Get the detail for a specific referrer from the leaderboard.\n *\n * Returns a {@link ReferrerDetailRanked} if the referrer is on the leaderboard,\n * or a {@link ReferrerDetailUnranked} if the referrer has no referrals.\n *\n * @param referrer - The referrer address to look up\n * @param leaderboard - The referrer leaderboard to query\n * @returns The appropriate {@link ReferrerDetail} (ranked or unranked)\n */\nexport const getReferrerDetail = (\n referrer: Address,\n leaderboard: ReferrerLeaderboard,\n): ReferrerDetail => {\n const awardedReferrerMetrics = leaderboard.referrers.get(referrer);\n\n // If referrer is on the leaderboard, return their ranked metrics\n if (awardedReferrerMetrics) {\n return {\n type: ReferrerDetailTypeIds.Ranked,\n rules: leaderboard.rules,\n referrer: awardedReferrerMetrics,\n aggregatedMetrics: leaderboard.aggregatedMetrics,\n accurateAsOf: leaderboard.accurateAsOf,\n };\n }\n\n // If referrer not found, return an unranked referrer record\n return {\n type: ReferrerDetailTypeIds.Unranked,\n rules: leaderboard.rules,\n referrer: buildUnrankedReferrerMetrics(referrer),\n aggregatedMetrics: leaderboard.aggregatedMetrics,\n accurateAsOf: leaderboard.accurateAsOf,\n };\n};\n","import { decodeEncodedReferrer, ENCODED_REFERRER_BYTE_LENGTH } from \"@namehash/ens-referrals\";\nimport type { Address } from \"viem\";\nimport { z } from \"zod/v4\";\nimport type { ParsePayload } from \"zod/v4/core\";\n\nimport { addPrices, isPriceEqual } from \"../shared\";\nimport {\n makeAccountIdSchema,\n makeBlockRefSchema,\n makeDurationSchema,\n makeHexStringSchema,\n makeLowercaseAddressSchema,\n makeNodeSchema,\n makePriceEthSchema,\n makeTransactionHashSchema,\n makeUnixTimestampSchema,\n} from \"../shared/zod-schemas\";\nimport {\n type RegistrarAction,\n type RegistrarActionEventId,\n RegistrarActionPricing,\n type RegistrarActionPricingAvailable,\n type RegistrarActionPricingUnknown,\n type RegistrarActionReferralAvailable,\n RegistrarActionTypes,\n} from \"./registrar-action\";\nimport type { RegistrationLifecycle } from \"./registration-lifecycle\";\nimport { Subregistry } from \"./subregistry\";\n\n/**\n * Schema for parsing objects into {@link Subregistry}.\n */\nconst makeSubregistrySchema = (valueLabel: string = \"Subregistry\") =>\n z.object({\n subregistryId: makeAccountIdSchema(`${valueLabel} Subregistry ID`),\n node: makeNodeSchema(`${valueLabel} Node`),\n });\n\n/**\n * Schema for parsing objects into {@link RegistrationLifecycle}.\n */\nexport const makeRegistrationLifecycleSchema = (valueLabel: string = \"Registration Lifecycle\") =>\n z.object({\n subregistry: makeSubregistrySchema(`${valueLabel} Subregistry`),\n node: makeNodeSchema(`${valueLabel} Node`),\n expiresAt: makeUnixTimestampSchema(`${valueLabel} Expires at`),\n });\n\n/** Invariant: total is sum of baseCost and premium */\nfunction invariant_registrarActionPricingTotalIsSumOfBaseCostAndPremium(\n ctx: ParsePayload<RegistrarActionPricingAvailable>,\n) {\n const { baseCost, premium, total } = ctx.value;\n const actualTotal = addPrices(baseCost, premium);\n\n if (!isPriceEqual(actualTotal, total)) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `'total' must be equal to the sum of 'baseCost' and 'premium'`,\n });\n }\n}\n\n/**\n * Schema for parsing objects into {@link RegistrarActionPricing}.\n */\nconst makeRegistrarActionPricingSchema = (valueLabel: string = \"Registrar Action Pricing\") =>\n z.union([\n // pricing available\n z\n .object({\n baseCost: makePriceEthSchema(`${valueLabel} Base Cost`),\n premium: makePriceEthSchema(`${valueLabel} Premium`),\n total: makePriceEthSchema(`${valueLabel} Total`),\n })\n .check(invariant_registrarActionPricingTotalIsSumOfBaseCostAndPremium)\n .transform((v) => v as RegistrarActionPricingAvailable),\n\n // pricing unknown\n z\n .object({\n baseCost: z.null(),\n premium: z.null(),\n total: z.null(),\n })\n .transform((v) => v as RegistrarActionPricingUnknown),\n ]);\n\n/** Invariant: decodedReferrer is based on encodedReferrer */\nfunction invariant_registrarActionDecodedReferrerBasedOnRawReferrer(\n ctx: ParsePayload<RegistrarActionReferralAvailable>,\n) {\n const { encodedReferrer, decodedReferrer } = ctx.value;\n\n try {\n // decodeEncodedReferrer returns checksummed address, but ENSNode work on lowercase address values\n // so we lowercase the result before using for checks\n const expectedDecodedReferrer = decodeEncodedReferrer(encodedReferrer).toLowerCase() as Address;\n\n if (decodedReferrer !== expectedDecodedReferrer) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `'decodedReferrer' must be based on 'encodedReferrer'`,\n });\n }\n } catch (error) {\n // in case decoding the encodedReferrer value could not succeed\n // pass the decoding error message\n const errorMessage = error instanceof Error ? error.message : \"Unknown error\";\n\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: errorMessage,\n });\n }\n}\n\nconst makeRegistrarActionReferralSchema = (valueLabel: string = \"Registrar Action Referral\") =>\n z.union([\n // referral available\n z\n .object({\n encodedReferrer: makeHexStringSchema(\n { bytesCount: ENCODED_REFERRER_BYTE_LENGTH },\n `${valueLabel} Encoded Referrer`,\n ),\n decodedReferrer: makeLowercaseAddressSchema(`${valueLabel} Decoded Referrer`),\n })\n .check(invariant_registrarActionDecodedReferrerBasedOnRawReferrer),\n\n // referral not applicable\n z.object({\n encodedReferrer: z.null(),\n decodedReferrer: z.null(),\n }),\n ]);\n\nfunction invariant_eventIdsInitialElementIsTheActionId(\n ctx: ParsePayload<Pick<RegistrarAction, \"id\" | \"eventIds\">>,\n) {\n const { id, eventIds } = ctx.value;\n\n if (eventIds[0] !== id) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: \"The initial element of `eventIds` must be the `id` value\",\n });\n }\n}\n\nconst EventIdSchema = z.string().nonempty();\n\nconst EventIdsSchema = z\n .array(EventIdSchema)\n .min(1)\n .transform((v) => v as [RegistrarActionEventId, ...RegistrarActionEventId[]]);\n\nexport const makeBaseRegistrarActionSchema = (valueLabel: string = \"Base Registrar Action\") =>\n z\n .object({\n id: EventIdSchema,\n incrementalDuration: makeDurationSchema(`${valueLabel} Incremental Duration`),\n registrant: makeLowercaseAddressSchema(`${valueLabel} Registrant`),\n registrationLifecycle: makeRegistrationLifecycleSchema(\n `${valueLabel} Registration Lifecycle`,\n ),\n pricing: makeRegistrarActionPricingSchema(`${valueLabel} Pricing`),\n referral: makeRegistrarActionReferralSchema(`${valueLabel} Referral`),\n block: makeBlockRefSchema(`${valueLabel} Block`),\n transactionHash: makeTransactionHashSchema(`${valueLabel} Transaction Hash`),\n eventIds: EventIdsSchema,\n })\n .check(invariant_eventIdsInitialElementIsTheActionId);\n\nexport const makeRegistrarActionRegistrationSchema = (valueLabel: string = \"Registration \") =>\n makeBaseRegistrarActionSchema(valueLabel).extend({\n type: z.literal(RegistrarActionTypes.Registration),\n });\n\nexport const makeRegistrarActionRenewalSchema = (valueLabel: string = \"Renewal\") =>\n makeBaseRegistrarActionSchema(valueLabel).extend({\n type: z.literal(RegistrarActionTypes.Renewal),\n });\n\n/**\n * Schema for {@link RegistrarAction}.\n */\nexport const makeRegistrarActionSchema = (valueLabel: string = \"Registrar Action\") =>\n z.discriminatedUnion(\"type\", [\n makeRegistrarActionRegistrationSchema(`${valueLabel} Registration`),\n makeRegistrarActionRenewalSchema(`${valueLabel} Renewal`),\n ]);\n","import type { EncodedReferrer } from \"@namehash/ens-referrals\";\n\nexport type { EncodedReferrer } from \"@namehash/ens-referrals\";\nexport { decodeEncodedReferrer, ZERO_ENCODED_REFERRER } from \"@namehash/ens-referrals\";\n\nimport type { Address, Hash } from \"viem\";\n\nimport {\n type BlockRef,\n type Duration,\n type PriceEth,\n type SerializedPriceEth,\n serializePriceEth,\n} from \"../shared\";\nimport type { RegistrationLifecycle } from \"./registration-lifecycle\";\n\n/**\n * Globally unique, deterministic ID of an indexed onchain event\n * associated with the \"logical registrar action\".\n */\nexport type RegistrarActionEventId = string;\n\n/**\n * Types of \"logical registrar action\".\n */\nexport const RegistrarActionTypes = {\n Registration: \"registration\",\n Renewal: \"renewal\",\n} as const;\n\nexport type RegistrarActionType = (typeof RegistrarActionTypes)[keyof typeof RegistrarActionTypes];\n\n/**\n * Pricing information for a \"logical registrar action\".\n */\nexport interface RegistrarActionPricingAvailable {\n /**\n * Base cost\n *\n * Base cost (before any `premium`) of Ether measured in units of Wei\n * paid to execute the \"logical registrar action\".\n *\n * May be 0.\n */\n baseCost: PriceEth;\n\n /**\n * Premium\n *\n * \"premium\" cost (in excesses of the `baseCost`) of Ether measured in\n * units of Wei paid to execute the \"logical registrar action\".\n *\n * May be 0.\n */\n premium: PriceEth;\n\n /**\n * Total\n *\n * Total cost of Ether measured in units of Wei paid to execute\n * the \"logical registrar action\".\n *\n * May be 0.\n */\n total: PriceEth;\n}\n\n/**\n * Pricing information for a \"logical registrar action\" when\n * there is no known pricing data.\n */\nexport interface RegistrarActionPricingUnknown {\n /**\n * Base cost\n *\n * Base cost (before any `premium`) of Ether measured in units of Wei\n * paid to execute the \"logical registrar action\".\n */\n baseCost: null;\n\n /**\n * Premium\n *\n * \"premium\" cost (in excesses of the `baseCost`) of Ether measured in\n * units of Wei paid to execute the \"logical registrar action\".\n */\n premium: null;\n\n /**\n * Total\n *\n * Total cost of Ether measured in units of Wei paid to execute\n * the \"logical registrar action\".\n */\n total: null;\n}\n\nexport type RegistrarActionPricing =\n | RegistrarActionPricingAvailable\n | RegistrarActionPricingUnknown;\n\nexport function isRegistrarActionPricingAvailable(\n registrarActionPricing: RegistrarActionPricing,\n): registrarActionPricing is RegistrarActionPricingAvailable {\n const { baseCost, premium, total } = registrarActionPricing;\n\n return baseCost !== null && premium !== null && total !== null;\n}\n\n/**\n * * Referral information for performing a \"logical registrar action\".\n */\nexport interface RegistrarActionReferralAvailable {\n /**\n * Encoded Referrer\n *\n * Represents the \"raw\" 32-byte \"referrer\" value emitted onchain in\n * association with the registrar action.\n */\n encodedReferrer: EncodedReferrer;\n\n /**\n * Decoded Referrer\n *\n * Decoded referrer according to the subjective interpretation of\n * `encodedReferrer` defined for ENS Holiday Awards.\n *\n * Identifies the interpreted address of the referrer.\n * The \"chainId\" of this address is the same as is referenced in\n * `subregistryId`.\n *\n * May be the \"zero address\" to represent that an `encodedReferrer` is\n * defined but that it is interpreted as no referrer.\n */\n decodedReferrer: Address;\n}\n\n/**\n * Referral information for performing a \"logical registrar action\" when\n * registrar controller does not implement referrals.\n */\nexport interface RegistrarActionReferralNotApplicable {\n /**\n * Encoded Referrer\n *\n * Represents the \"raw\" 32-byte \"referrer\" value emitted onchain in\n * association with the registrar action.\n */\n encodedReferrer: null;\n\n /**\n * Decoded Referrer\n *\n * Decoded referrer according to the subjective interpretation of\n * `encodedReferrer` defined for ENS Holiday Awards.\n *\n */\n decodedReferrer: null;\n}\n\nexport type RegistrarActionReferral =\n | RegistrarActionReferralAvailable\n | RegistrarActionReferralNotApplicable;\n\nexport function isRegistrarActionReferralAvailable(\n registrarActionReferral: RegistrarActionReferral,\n): registrarActionReferral is RegistrarActionReferralAvailable {\n const { encodedReferrer, decodedReferrer } = registrarActionReferral;\n\n return encodedReferrer !== null && decodedReferrer !== null;\n}\n\n/**\n * \"Logical registrar action\"\n *\n * Represents a state of \"logical registrar action\". May be built using data\n * from multiple events within the same \"logical\" registration / renewal action.\n */\nexport interface RegistrarAction {\n /**\n * \"Logical registrar action\" ID\n *\n * The `id` value is a deterministic and globally unique identifier for\n * the \"logical registrar action\".\n *\n * The `id` value represents the *initial* onchain event associated with\n * the \"logical registrar action\", but the full state of\n * the \"logical registrar action\" is an aggregate across each of\n * the onchain events referenced in the `eventIds` field.\n *\n * Guaranteed to be the very first element in `eventIds` array.\n */\n id: RegistrarActionEventId;\n\n /**\n * The type of the \"logical registrar action\".\n */\n type: RegistrarActionType;\n\n /**\n *\n * Incremental Duration\n *\n * If `type` is \"registration\":\n * - Represents the duration between `block.timestamp` and\n * the initial `registrationLifecycle.expiresAt` value that the associated\n * \"registration lifecycle\" will be initialized with.\n * If `type` is \"renewal\":\n * - Represents the incremental increase in duration made to\n * the `registrationLifecycle.expiresAt` value in the associated\n * \"registration lifecycle\".\n *\n * A \"registration lifecycle\" may be extended via renewal even after it\n * expires if it is still within its grace period.\n *\n * Consider the following scenario:\n *\n * The \"registration lifecycle\" of a direct subname of .eth is scheduled to\n * expire on Jan 1, midnight UTC. It is currently 30 days after this\n * expiration time. Therefore, there are currently another 60 days of grace\n * period remaining for this name. Anyone can still make a renewal to\n * extend the \"registration lifecycle\" of this name.\n *\n * Given this scenario, consider the following examples:\n *\n * 1. If a renewal is made with 10 days incremental duration,\n * the \"registration lifecycle\" for this name will remain in\n * an \"expired\" state, but it will now have another 70 days of\n * grace period remaining.\n *\n * 2. If a renewal is made with 50 days incremental duration,\n * the \"registration lifecycle\" for this name will no longer be\n * \"expired\" and will become \"active\", but the \"registration lifecycle\"\n * will now be scheduled to expire again in 20 days.\n *\n * After the \"registration lifecycle\" for a name becomes expired by more\n * than its grace period, it can no longer be renewed by anyone and is\n * considered \"released\". The name must first be registered again, starting\n * a new \"registration lifecycle\" of\n * active / expired / grace period / released.\n *\n * May be 0.\n *\n * Guaranteed to be a non-negative bigint value.\n */\n incrementalDuration: Duration;\n\n /**\n * Registrant\n *\n * Identifies the address that initiated the \"logical registrar action\" and\n * is paying the `pricing.total` cost (if applicable).\n *\n * It may not be the owner of the name:\n * 1. When a name is registered, the initial owner of the name may be\n * distinct from the registrant.\n * 2. There are no restrictions on who may renew a name.\n * Therefore the owner of the name may be distinct from the registrant.\n *\n * The \"chainId\" of this address is the same as is referenced in\n * `registrationLifecycle.subregistry.subregistryId`.\n */\n registrant: Address;\n\n /**\n * Registration Lifecycle associated with this \"logical registrar action\".\n */\n registrationLifecycle: RegistrationLifecycle;\n\n /**\n * Pricing information associated with this \"logical registrar action\".\n */\n pricing: RegistrarActionPricing;\n\n /**\n * Referral information associated with this \"logical registrar action\".\n */\n referral: RegistrarActionReferral;\n\n /**\n * Block ref\n *\n * References the block where the \"logical registrar action\" was executed.\n *\n * The \"chainId\" of this block is the same as is referenced in\n * `registrationLifecycle.subregistry.subregistryId`.\n */\n block: BlockRef;\n\n /**\n * Transaction hash\n *\n * Transaction hash of the transaction associated with\n * the \"logical registrar action\".\n *\n * The \"chainId\" of this transaction is the same as is referenced in\n * `registrationLifecycle.subregistry.subregistryId`.\n *\n * Note that a single transaction may be associated with any number of\n * \"logical registrar actions\".\n */\n transactionHash: Hash;\n\n /**\n * Event IDs\n *\n * Array of the eventIds that have contributed to the state of\n * the \"logical registrar action\" record.\n *\n * Each eventId is a deterministic and globally unique onchain event\n * identifier.\n *\n * Guarantees:\n * - Each eventId is of events that occurred within the block\n * referenced by `block.number`.\n * - At least 1 eventId.\n * - Ordered chronologically (ascending) by logIndex within `block.number`.\n * - The first element in the array is equal to the `id` of\n * the overall \"logical registrar action\" record.\n *\n * The following ideas are not generalized for ENS overall but happen to\n * be a characteristic of the scope of our current indexing logic:\n * 1. These id's always reference events emitted by\n * a related \"BaseRegistrar\" contract.\n * 2. These id's optionally reference events emitted by\n * a related \"Registrar Controller\" contract. This is because our\n * current indexing logic doesn't guarantee to index\n * all \"Registrar Controller\" contracts.\n */\n eventIds: [RegistrarActionEventId, ...RegistrarActionEventId[]];\n}\n\n/**\n * Serialized representation of {@link RegistrarActionPricingUnknown}.\n */\nexport type SerializedRegistrarActionPricingUnknown = RegistrarActionPricingUnknown;\n\n/**\n * Serialized representation of {@link RegistrarActionPricingAvailable}.\n */\nexport interface SerializedRegistrarActionPricingAvailable {\n baseCost: SerializedPriceEth;\n\n premium: SerializedPriceEth;\n\n total: SerializedPriceEth;\n}\n\n/**\n * Serialized representation of {@link RegistrarActionPricing}.\n */\nexport type SerializedRegistrarActionPricing =\n | SerializedRegistrarActionPricingAvailable\n | SerializedRegistrarActionPricingUnknown;\n\n/**\n * Serialized representation of {@link RegistrarAction}.\n */\nexport interface SerializedRegistrarAction extends Omit<RegistrarAction, \"pricing\"> {\n pricing: SerializedRegistrarActionPricing;\n}\n\nexport function serializeRegistrarActionPricing(\n pricing: RegistrarActionPricing,\n): SerializedRegistrarActionPricing {\n if (isRegistrarActionPricingAvailable(pricing)) {\n return {\n baseCost: serializePriceEth(pricing.baseCost),\n premium: serializePriceEth(pricing.premium),\n total: serializePriceEth(pricing.total),\n } satisfies SerializedRegistrarActionPricingAvailable;\n }\n\n return pricing satisfies SerializedRegistrarActionPricingUnknown;\n}\n\nexport function serializeRegistrarAction(\n registrarAction: RegistrarAction,\n): SerializedRegistrarAction {\n return {\n id: registrarAction.id,\n type: registrarAction.type,\n incrementalDuration: registrarAction.incrementalDuration,\n registrant: registrarAction.registrant,\n registrationLifecycle: registrarAction.registrationLifecycle,\n pricing: serializeRegistrarActionPricing(registrarAction.pricing),\n referral: registrarAction.referral,\n block: registrarAction.block,\n transactionHash: registrarAction.transactionHash,\n eventIds: registrarAction.eventIds,\n };\n}\n","import z from \"zod/v4\";\nimport type { ParsePayload } from \"zod/v4/core\";\n\nimport {\n makeNonNegativeIntegerSchema,\n makePositiveIntegerSchema,\n} from \"../../../shared/zod-schemas\";\nimport { RECORDS_PER_PAGE_MAX, RequestPageParams } from \"./request\";\nimport {\n ResponsePageContext,\n ResponsePageContextWithNoRecords,\n type ResponsePageContextWithRecords,\n} from \"./response\";\n\n/**\n * Schema for {@link RequestPageParams}\n */\nexport const makeRequestPageParamsSchema = (valueLabel: string = \"RequestPageParams\") =>\n z.object({\n page: makePositiveIntegerSchema(`${valueLabel}.page`),\n recordsPerPage: makePositiveIntegerSchema(`${valueLabel}.recordsPerPage`).max(\n RECORDS_PER_PAGE_MAX,\n `${valueLabel}.recordsPerPage must not exceed ${RECORDS_PER_PAGE_MAX}`,\n ),\n });\n\n/**\n * Schema for {@link ResponsePageContextWithNoRecords}\n */\nexport const makeResponsePageContextSchemaWithNoRecords = (\n valueLabel: string = \"ResponsePageContextWithNoRecords\",\n) =>\n z\n .object({\n totalRecords: z.literal(0),\n totalPages: z.literal(1),\n hasNext: z.literal(false),\n hasPrev: z.literal(false),\n startIndex: z.undefined(),\n endIndex: z.undefined(),\n })\n .extend(makeRequestPageParamsSchema(valueLabel).shape);\n\nfunction invariant_responsePageWithRecordsIsCorrect(\n ctx: ParsePayload<ResponsePageContextWithRecords>,\n) {\n const { hasNext, hasPrev, recordsPerPage, page, totalRecords, startIndex, endIndex } = ctx.value;\n\n const expectedHasNext = page * recordsPerPage < totalRecords;\n if (hasNext !== expectedHasNext) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `hasNext must be equal to '${expectedHasNext ? \"true\" : \"false\"}'`,\n });\n }\n\n const expectedHasPrev = page > 1;\n if (hasPrev !== expectedHasPrev) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `hasPrev must be equal to '${expectedHasPrev ? \"true\" : \"false\"}'`,\n });\n }\n\n if (endIndex < startIndex) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `endIndex must be greater than or equal to startIndex`,\n });\n }\n\n if (endIndex >= totalRecords) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `endIndex must be lower than totalRecords`,\n });\n }\n}\n\n/**\n * Schema for {@link ResponsePageContextWithRecords}\n */\nexport const makeResponsePageContextSchemaWithRecords = (\n valueLabel: string = \"ResponsePageContextWithRecords\",\n) =>\n z\n .object({\n totalRecords: makePositiveIntegerSchema(`${valueLabel}.totalRecords`),\n totalPages: makePositiveIntegerSchema(`${valueLabel}.totalPages`),\n hasNext: z.boolean(),\n hasPrev: z.boolean(),\n startIndex: makeNonNegativeIntegerSchema(`${valueLabel}.startIndex`),\n endIndex: makeNonNegativeIntegerSchema(`${valueLabel}.endIndex`),\n })\n .extend(makeRequestPageParamsSchema(valueLabel).shape)\n .check(invariant_responsePageWithRecordsIsCorrect);\n\n/**\n * Schema for {@link ResponsePageContext}\n */\nexport const makeResponsePageContextSchema = (valueLabel: string = \"ResponsePageContext\") =>\n z.union([\n makeResponsePageContextSchemaWithNoRecords(valueLabel),\n makeResponsePageContextSchemaWithRecords(valueLabel),\n ]);\n","export const RECORDS_PER_PAGE_DEFAULT = 10;\n\nexport const RECORDS_PER_PAGE_MAX = 100;\n\n/**\n * Request page params.\n */\nexport interface RequestPageParams {\n /**\n * Requested page number (1-indexed)\n * @invariant Must be a positive integer (>= 1)\n * @default 1\n */\n page?: number;\n\n /**\n * Maximum number of records to return per page\n * @invariant Must be a positive integer (>= 1) and less than or equal to {@link RECORDS_PER_PAGE_MAX}\n * @default {@link RECORDS_PER_PAGE_DEFAULT}\n */\n recordsPerPage?: number;\n}\n","import type { InterpretedName } from \"../../ens\";\nimport type { RegistrarAction } from \"../../registrars\";\nimport type { UnixTimestamp } from \"../../shared\";\nimport type { IndexingStatusResponseCodes } from \"../indexing-status\";\nimport type { ErrorResponse } from \"../shared/errors\";\nimport type { ResponsePageContext } from \"../shared/pagination\";\n\n/**\n * A status code for Registrar Actions API responses.\n */\nexport const RegistrarActionsResponseCodes = {\n /**\n * Represents that Registrar Actions are available.\n */\n Ok: \"ok\",\n\n /**\n * Represents that Registrar Actions are unavailable.\n */\n Error: \"error\",\n} as const;\n\n/**\n * The derived string union of possible {@link RegistrarActionsResponseCodes}.\n */\nexport type RegistrarActionsResponseCode =\n (typeof RegistrarActionsResponseCodes)[keyof typeof RegistrarActionsResponseCodes];\n\n/**\n * \"Logical registrar action\" with its associated name.\n */\nexport interface NamedRegistrarAction {\n action: RegistrarAction;\n\n /**\n * Name\n *\n * FQDN of the name associated with `action`.\n *\n * Guarantees:\n * - `namehash(name)` is always `action.registrationLifecycle.node`.\n */\n name: InterpretedName;\n}\n\n/**\n * A response when Registrar Actions are available.\n */\nexport type RegistrarActionsResponseOk = {\n responseCode: typeof RegistrarActionsResponseCodes.Ok;\n registrarActions: NamedRegistrarAction[];\n pageContext: ResponsePageContext;\n\n /**\n * The {@link UnixTimestamp} of when the data used to build the list of {@link NamedRegistrarAction} was accurate as of.\n *\n * @remarks\n * **Note:** This value represents the `slowestChainIndexingCursor` from the latest omnichain indexing status\n * snapshot captured by ENSApi. The state returned in the response is guaranteed to be accurate as of this\n * timestamp but may be from a timestamp higher than this value.\n *\n * **Temporary:** This field is currently optional to maintain backward compatibility with ENS Awards\n * using older snapshot NPM packages. This will be changed to required in a future release.\n * See: https://github.com/namehash/ensnode/issues/1497\n */\n accurateAsOf?: UnixTimestamp;\n};\n\n/**\n * A response when Registrar Actions are unavailable.\n */\nexport interface RegistrarActionsResponseError {\n responseCode: typeof IndexingStatusResponseCodes.Error;\n error: ErrorResponse;\n}\n\n/**\n * Registrar Actions response.\n *\n * Use the `responseCode` field to determine the specific type interpretation\n * at runtime.\n */\nexport type RegistrarActionsResponse = RegistrarActionsResponseOk | RegistrarActionsResponseError;\n","import type { Address } from \"viem\";\n\nimport type { Node } from \"../../ens\";\nimport type { UnixTimestamp } from \"../../shared\";\nimport type { RequestPageParams } from \"../shared/pagination\";\n\n/**\n * Records Filters: Filter Types\n */\nexport const RegistrarActionsFilterTypes = {\n BySubregistryNode: \"bySubregistryNode\",\n WithEncodedReferral: \"withEncodedReferral\",\n ByDecodedReferrer: \"byDecodedReferrer\",\n BeginTimestamp: \"beginTimestamp\",\n EndTimestamp: \"endTimestamp\",\n} as const;\n\nexport type RegistrarActionsFilterType =\n (typeof RegistrarActionsFilterTypes)[keyof typeof RegistrarActionsFilterTypes];\n\nexport type RegistrarActionsFilterBySubregistryNode = {\n filterType: typeof RegistrarActionsFilterTypes.BySubregistryNode;\n value: Node;\n};\n\nexport type RegistrarActionsFilterWithEncodedReferral = {\n filterType: typeof RegistrarActionsFilterTypes.WithEncodedReferral;\n};\n\nexport type RegistrarActionsFilterByDecodedReferrer = {\n filterType: typeof RegistrarActionsFilterTypes.ByDecodedReferrer;\n value: Address;\n};\n\nexport type RegistrarActionsFilterBeginTimestamp = {\n filterType: typeof RegistrarActionsFilterTypes.BeginTimestamp;\n value: UnixTimestamp;\n};\n\nexport type RegistrarActionsFilterEndTimestamp = {\n filterType: typeof RegistrarActionsFilterTypes.EndTimestamp;\n value: UnixTimestamp;\n};\n\nexport type RegistrarActionsFilter =\n | RegistrarActionsFilterBySubregistryNode\n | RegistrarActionsFilterWithEncodedReferral\n | RegistrarActionsFilterByDecodedReferrer\n | RegistrarActionsFilterBeginTimestamp\n | RegistrarActionsFilterEndTimestamp;\n\n/**\n * Records Orders\n */\nexport const RegistrarActionsOrders = {\n LatestRegistrarActions: \"orderBy[timestamp]=desc\",\n} as const;\n\nexport type RegistrarActionsOrder =\n (typeof RegistrarActionsOrders)[keyof typeof RegistrarActionsOrders];\n\n/**\n * Represents a request to Registrar Actions API.\n */\nexport interface RegistrarActionsRequest extends RequestPageParams {\n /**\n * Filters to be applied while generating results.\n */\n filters?: RegistrarActionsFilter[];\n\n /**\n * Order applied while generating results.\n */\n order?: RegistrarActionsOrder;\n}\n","import type { Address } from \"viem\";\n\nimport type { Node } from \"../../ens\";\nimport type { UnixTimestamp } from \"../../shared\";\nimport {\n type RegistrarActionsFilter,\n type RegistrarActionsFilterBeginTimestamp,\n type RegistrarActionsFilterByDecodedReferrer,\n type RegistrarActionsFilterEndTimestamp,\n RegistrarActionsFilterTypes,\n type RegistrarActionsFilterWithEncodedReferral,\n} from \"./request\";\n\n/**\n * Build a \"parent node\" filter object for Registrar Actions query.\n */\nfunction byParentNode(parentNode: Node): RegistrarActionsFilter;\nfunction byParentNode(parentNode: undefined): undefined;\nfunction byParentNode(parentNode: Node | undefined): RegistrarActionsFilter | undefined {\n if (typeof parentNode === \"undefined\") {\n return undefined;\n }\n\n return {\n filterType: RegistrarActionsFilterTypes.BySubregistryNode,\n value: parentNode,\n };\n}\n\n/**\n * Build a \"with referral\" filter object for Registrar Actions query.\n */\nfunction withReferral(withReferral: true): RegistrarActionsFilter;\nfunction withReferral(withReferral: false | undefined): undefined;\nfunction withReferral(withReferral: boolean | undefined): RegistrarActionsFilter | undefined {\n if (!withReferral) {\n return undefined;\n }\n\n return {\n filterType: RegistrarActionsFilterTypes.WithEncodedReferral,\n } satisfies RegistrarActionsFilterWithEncodedReferral;\n}\n\n/**\n * Build a \"decoded referrer\" filter object for Registrar Actions query.\n */\nfunction byDecodedReferrer(decodedReferrer: Address): RegistrarActionsFilter;\nfunction byDecodedReferrer(decodedReferrer: undefined): undefined;\nfunction byDecodedReferrer(\n decodedReferrer: Address | undefined,\n): RegistrarActionsFilter | undefined {\n if (typeof decodedReferrer === \"undefined\") {\n return undefined;\n }\n\n return {\n filterType: RegistrarActionsFilterTypes.ByDecodedReferrer,\n value: decodedReferrer,\n } satisfies RegistrarActionsFilterByDecodedReferrer;\n}\n\n/**\n * Build a \"begin timestamp\" filter object for Registrar Actions query.\n *\n * Filters registrar actions to only include those at or after the specified timestamp (inclusive).\n */\nfunction beginTimestamp(timestamp: UnixTimestamp): RegistrarActionsFilter;\nfunction beginTimestamp(timestamp: undefined): undefined;\nfunction beginTimestamp(timestamp: UnixTimestamp | undefined): RegistrarActionsFilter | undefined {\n if (typeof timestamp === \"undefined\") {\n return undefined;\n }\n\n return {\n filterType: RegistrarActionsFilterTypes.BeginTimestamp,\n value: timestamp,\n } satisfies RegistrarActionsFilterBeginTimestamp;\n}\n\n/**\n * Build an \"end timestamp\" filter object for Registrar Actions query.\n *\n * Filters registrar actions to only include those at or before the specified timestamp (inclusive).\n */\nfunction endTimestamp(timestamp: UnixTimestamp): RegistrarActionsFilter;\nfunction endTimestamp(timestamp: undefined): undefined;\nfunction endTimestamp(timestamp: UnixTimestamp | undefined): RegistrarActionsFilter | undefined {\n if (typeof timestamp === \"undefined\") {\n return undefined;\n }\n\n return {\n filterType: RegistrarActionsFilterTypes.EndTimestamp,\n value: timestamp,\n } satisfies RegistrarActionsFilterEndTimestamp;\n}\n\nexport const registrarActionsFilter = {\n byParentNode,\n withReferral,\n byDecodedReferrer,\n beginTimestamp,\n endTimestamp,\n};\n","import {\n type ENSIndexerPublicConfig,\n type OmnichainIndexingStatusId,\n OmnichainIndexingStatusIds,\n PluginName,\n} from \"../../ensindexer\";\n\nexport const registrarActionsPrerequisites = Object.freeze({\n /**\n * Required plugins to enable Registrar Actions API routes.\n *\n * 1. `registrars` plugin is required so that data in the `registrarActions`\n * table is populated.\n * 2. `subgraph`, `basenames`, and `lineanames` are required to get the data\n * for the name associated with each registrar action.\n * 3. In theory not all of `subgraph`, `basenames`, and `lineanames` plugins\n * might be required. Ex: At least one, but the current logic in\n * the `registrars` plugin always indexes registrar actions across\n * Ethnames (subgraph), Basenames, and Lineanames and therefore we need to\n * ensure each value in the registrar actions table has\n * an associated record in the domains table.\n */\n requiredPlugins: [\n PluginName.Subgraph,\n PluginName.Basenames,\n PluginName.Lineanames,\n PluginName.Registrars,\n ] as const,\n\n /**\n * Check if provided ENSApiPublicConfig supports the Registrar Actions API.\n */\n hasEnsIndexerConfigSupport(config: ENSIndexerPublicConfig): boolean {\n return registrarActionsPrerequisites.requiredPlugins.every((plugin) =>\n config.plugins.includes(plugin),\n );\n },\n /**\n * Required Indexing Status IDs\n *\n * Database indexes are created by the time the omnichain indexing status\n * is either `completed` or `following`.\n */\n supportedIndexingStatusIds: [\n OmnichainIndexingStatusIds.Completed,\n OmnichainIndexingStatusIds.Following,\n ],\n\n /**\n * Check if provided indexing status supports the Registrar Actions API.\n */\n hasIndexingStatusSupport(omnichainIndexingStatusId: OmnichainIndexingStatusId): boolean {\n return registrarActionsPrerequisites.supportedIndexingStatusIds.some(\n (supportedIndexingStatusId) => supportedIndexingStatusId === omnichainIndexingStatusId,\n );\n },\n});\n","import {\n DatasourceNames,\n type ENSNamespaceId,\n ENSNamespaceIds,\n maybeGetDatasource,\n} from \"@ensnode/datasources\";\n\nimport type { Name } from \"../ens\";\nimport type { AccountId } from \"../shared\";\n\n/**\n * Gets the SubregistryId (an AccountId) of the Basenames Subregistry contract (this is the\n * \"BaseRegistrar\" contract for Basenames) for the provided namespace.\n *\n * @param namespace The ENS namespace to get the Basenames Subregistry ID for\n * @returns The AccountId for the Basenames Subregistry contract for the provided namespace.\n * @throws Error if the contract is not found for the given namespace.\n */\nexport function getBasenamesSubregistryId(namespace: ENSNamespaceId): AccountId {\n const datasource = maybeGetDatasource(namespace, DatasourceNames.Basenames);\n if (!datasource) {\n throw new Error(`Datasource not found for ${namespace} ${DatasourceNames.Basenames}`);\n }\n\n const address = datasource.contracts.BaseRegistrar?.address;\n if (address === undefined || Array.isArray(address)) {\n throw new Error(`BaseRegistrar contract not found or has multiple addresses for ${namespace}`);\n }\n\n return {\n chainId: datasource.chain.id,\n address,\n };\n}\n\n/**\n * Get the managed name for the Basenames subregistry for the selected ENS namespace.\n *\n * @param namespaceId\n * @returns registrar managed name\n * @throws an error when no registrar managed name could be returned\n */\nexport function getBasenamesSubregistryManagedName(namespaceId: ENSNamespaceId): Name {\n switch (namespaceId) {\n case ENSNamespaceIds.Mainnet:\n return \"base.eth\";\n case ENSNamespaceIds.Sepolia:\n return \"basetest.eth\";\n case ENSNamespaceIds.EnsTestEnv:\n throw new Error(\n `No registrar managed name is known for the 'basenames' subregistry within the \"${namespaceId}\" namespace.`,\n );\n }\n}\n","import {\n DatasourceNames,\n type ENSNamespaceId,\n ENSNamespaceIds,\n maybeGetDatasource,\n} from \"@ensnode/datasources\";\n\nimport type { Name } from \"../ens\";\nimport type { AccountId } from \"../shared\";\n\n/**\n * Gets the SubregistryId (an AccountId) of the Ethnames Subregistry contract (this is the\n * \"BaseRegistrar\" contract for direct subnames of .eth) for the provided namespace.\n *\n * @param namespace The ENS namespace to get the Ethnames Subregistry ID for\n * @returns The AccountId for the Ethnames Subregistry contract for the provided namespace.\n * @throws Error if the contract is not found for the given namespace.\n */\nexport function getEthnamesSubregistryId(namespace: ENSNamespaceId): AccountId {\n const datasource = maybeGetDatasource(namespace, DatasourceNames.ENSRoot);\n if (!datasource) {\n throw new Error(`Datasource not found for ${namespace} ${DatasourceNames.ENSRoot}`);\n }\n\n const address = datasource.contracts.BaseRegistrar?.address;\n if (address === undefined || Array.isArray(address)) {\n throw new Error(`BaseRegistrar contract not found or has multiple addresses for ${namespace}`);\n }\n\n return {\n chainId: datasource.chain.id,\n address,\n };\n}\n\n/**\n * Get the managed name for the Ethnames subregistry for the selected ENS namespace.\n *\n * @param namespaceId\n * @returns registrar managed name\n */\nexport function getEthnamesSubregistryManagedName(namespaceId: ENSNamespaceId): Name {\n switch (namespaceId) {\n case ENSNamespaceIds.Mainnet:\n case ENSNamespaceIds.Sepolia:\n case ENSNamespaceIds.EnsTestEnv:\n return \"eth\";\n }\n}\n","import {\n DatasourceNames,\n type ENSNamespaceId,\n ENSNamespaceIds,\n maybeGetDatasource,\n} from \"@ensnode/datasources\";\n\nimport type { Name } from \"../ens\";\nimport type { AccountId } from \"../shared\";\n\n/**\n * Gets the SubregistryId (an AccountId) of the Lineanames Subregistry contract (this is the\n * \"BaseRegistrar\" contract for Lineanames) for the provided namespace.\n *\n * @param namespace The ENS namespace to get the Lineanames Subregistry ID for\n * @returns The AccountId for the Lineanames Subregistry contract for the provided namespace.\n * @throws Error if the contract is not found for the given namespace.\n */\nexport function getLineanamesSubregistryId(namespace: ENSNamespaceId): AccountId {\n const datasource = maybeGetDatasource(namespace, DatasourceNames.Lineanames);\n if (!datasource) {\n throw new Error(`Datasource not found for ${namespace} ${DatasourceNames.Lineanames}`);\n }\n\n const address = datasource.contracts.BaseRegistrar?.address;\n if (address === undefined || Array.isArray(address)) {\n throw new Error(`BaseRegistrar contract not found or has multiple addresses for ${namespace}`);\n }\n\n return {\n chainId: datasource.chain.id,\n address,\n };\n}\n\n/**\n * Get the managed name for the Lineanames subregistry for the selected ENS namespace.\n *\n * @param namespaceId\n * @returns registrar managed name\n * @throws an error when no registrar managed name could be returned\n */\nexport function getLineanamesSubregistryManagedName(namespaceId: ENSNamespaceId): Name {\n switch (namespaceId) {\n case ENSNamespaceIds.Mainnet:\n return \"linea.eth\";\n case ENSNamespaceIds.Sepolia:\n return \"linea-sepolia.eth\";\n case ENSNamespaceIds.EnsTestEnv:\n throw new Error(\n `No registrar managed name is known for the 'Lineanames' subregistry within the \"${namespaceId}\" namespace.`,\n );\n }\n}\n","export interface RegistrationExpiryInfo {\n expiry: bigint | null;\n gracePeriod: bigint | null;\n}\n\n/**\n * Returns whether Registration is expired. If the Registration includes a Grace Period, the\n * Grace Period window is considered expired.\n */\nexport function isRegistrationExpired(info: RegistrationExpiryInfo, now: bigint): boolean {\n // no expiry, never expired\n if (info.expiry == null) return false;\n\n // otherwise check against now\n return info.expiry <= now;\n}\n\n/**\n * Returns whether Registration is fully expired. If the Registration includes a Grace Period, the\n * Grace Period window is considered NOT fully-expired.\n */\nexport function isRegistrationFullyExpired(info: RegistrationExpiryInfo, now: bigint): boolean {\n // no expiry, never expired\n if (info.expiry == null) return false;\n\n // otherwise it is expired if now >= expiry + grace\n return now >= info.expiry + (info.gracePeriod ?? 0n);\n}\n\n/**\n * Returns whether Registration is in grace period.\n */\nexport function isRegistrationInGracePeriod(info: RegistrationExpiryInfo, now: bigint): boolean {\n if (info.expiry == null) return false;\n if (info.gracePeriod == null) return false;\n\n return info.expiry <= now && info.expiry + info.gracePeriod > now;\n}\n","import { serializeRegistrarAction } from \"../../registrars\";\nimport {\n type NamedRegistrarAction,\n type RegistrarActionsResponse,\n RegistrarActionsResponseCodes,\n} from \"./response\";\nimport type {\n SerializedNamedRegistrarAction,\n SerializedRegistrarActionsResponse,\n SerializedRegistrarActionsResponseOk,\n} from \"./serialized-response\";\n\nexport function serializeNamedRegistrarAction({\n action,\n name,\n}: NamedRegistrarAction): SerializedNamedRegistrarAction {\n return {\n action: serializeRegistrarAction(action),\n name,\n };\n}\n\nexport function serializeRegistrarActionsResponse(\n response: RegistrarActionsResponse,\n): SerializedRegistrarActionsResponse {\n switch (response.responseCode) {\n case RegistrarActionsResponseCodes.Ok:\n return {\n responseCode: response.responseCode,\n registrarActions: response.registrarActions.map(serializeNamedRegistrarAction),\n pageContext: response.pageContext,\n accurateAsOf: response.accurateAsOf,\n } satisfies SerializedRegistrarActionsResponseOk;\n\n case RegistrarActionsResponseCodes.Error:\n return response;\n }\n}\n","import { prettifyError } from \"zod/v4\";\n\nimport type { ErrorResponse } from \"./response\";\nimport { ErrorResponseSchema } from \"./zod-schemas\";\n\n/**\n * Deserialize a {@link ErrorResponse} object.\n */\nexport function deserializeErrorResponse(maybeErrorResponse: unknown): ErrorResponse {\n const parsed = ErrorResponseSchema.safeParse(maybeErrorResponse);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize ErrorResponse:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n","import type {\n ResponsePageContext,\n ResponsePageContextWithNoRecords,\n ResponsePageContextWithRecords,\n} from \"./response\";\n\n/**\n * Build page context from request params and total records count.\n */\nexport function buildPageContext(\n page: number,\n recordsPerPage: number,\n totalRecords: number,\n): ResponsePageContext {\n const totalPages = Math.max(1, Math.ceil(totalRecords / recordsPerPage));\n\n if (page > totalPages) {\n throw new Error(`Invalid page: page ${page} exceeds total pages ${totalPages}.`);\n }\n\n if (totalRecords === 0) {\n return {\n page,\n recordsPerPage,\n totalRecords: 0,\n totalPages: 1,\n hasNext: false,\n hasPrev: false,\n startIndex: undefined,\n endIndex: undefined,\n } satisfies ResponsePageContextWithNoRecords;\n }\n\n const startIndex = (page - 1) * recordsPerPage;\n const maxTheoreticalIndexOnPage = startIndex + (recordsPerPage - 1);\n const endIndex = Math.min(maxTheoreticalIndexOnPage, totalRecords - 1);\n const hasNext = maxTheoreticalIndexOnPage < totalRecords - 1;\n const hasPrev = page > 1;\n\n return {\n page,\n recordsPerPage,\n totalRecords,\n totalPages,\n hasNext,\n hasPrev,\n startIndex,\n endIndex,\n } satisfies ResponsePageContextWithRecords;\n}\n","import type { ErrorResponse } from \"./api\";\n\nexport class ClientError extends Error {\n details?: unknown;\n\n constructor(message: string, details?: unknown) {\n super(message);\n this.name = \"ClientError\";\n this.details = details;\n }\n\n static fromErrorResponse({ message, details }: ErrorResponse) {\n return new ClientError(message, details);\n }\n}\n","import type {\n AggregatedReferrerMetrics,\n AwardedReferrerMetrics,\n ReferralProgramRules,\n ReferrerDetailRanked,\n ReferrerDetailUnranked,\n ReferrerLeaderboardPage,\n RevenueContribution,\n UnrankedReferrerMetrics,\n} from \"@namehash/ens-referrals\";\nimport { prettifyError } from \"zod/v4\";\n\nimport type {\n SerializedAggregatedReferrerMetrics,\n SerializedAwardedReferrerMetrics,\n SerializedReferralProgramRules,\n SerializedReferrerDetailRanked,\n SerializedReferrerDetailResponse,\n SerializedReferrerDetailUnranked,\n SerializedReferrerLeaderboardPage,\n SerializedReferrerLeaderboardPageResponse,\n SerializedUnrankedReferrerMetrics,\n} from \"./serialized-types\";\nimport type { ReferrerDetailResponse, ReferrerLeaderboardPageResponse } from \"./types\";\nimport {\n makeReferrerDetailResponseSchema,\n makeReferrerLeaderboardPageResponseSchema,\n} from \"./zod-schemas\";\n\n/**\n * Deserializes a string representation of {@link RevenueContribution} back to bigint.\n */\nfunction deserializeRevenueContribution(value: string): RevenueContribution {\n return BigInt(value);\n}\n\n/**\n * Deserializes a {@link SerializedReferralProgramRules} object.\n */\nfunction deserializeReferralProgramRules(\n rules: SerializedReferralProgramRules,\n): ReferralProgramRules {\n // All fields are already deserializable primitives\n return rules;\n}\n\n/**\n * Deserializes an {@link SerializedAwardedReferrerMetrics} object.\n */\nfunction deserializeAwardedReferrerMetrics(\n metrics: SerializedAwardedReferrerMetrics,\n): AwardedReferrerMetrics {\n return {\n referrer: metrics.referrer,\n totalReferrals: metrics.totalReferrals,\n totalIncrementalDuration: metrics.totalIncrementalDuration,\n totalRevenueContribution: deserializeRevenueContribution(metrics.totalRevenueContribution),\n score: metrics.score,\n rank: metrics.rank,\n isQualified: metrics.isQualified,\n finalScoreBoost: metrics.finalScoreBoost,\n finalScore: metrics.finalScore,\n awardPoolShare: metrics.awardPoolShare,\n awardPoolApproxValue: metrics.awardPoolApproxValue,\n };\n}\n\n/**\n * Deserializes an {@link SerializedUnrankedReferrerMetrics} object.\n */\nfunction deserializeUnrankedReferrerMetrics(\n metrics: SerializedUnrankedReferrerMetrics,\n): UnrankedReferrerMetrics {\n return {\n referrer: metrics.referrer,\n totalReferrals: metrics.totalReferrals,\n totalIncrementalDuration: metrics.totalIncrementalDuration,\n totalRevenueContribution: deserializeRevenueContribution(metrics.totalRevenueContribution),\n score: metrics.score,\n rank: metrics.rank,\n isQualified: metrics.isQualified,\n finalScoreBoost: metrics.finalScoreBoost,\n finalScore: metrics.finalScore,\n awardPoolShare: metrics.awardPoolShare,\n awardPoolApproxValue: metrics.awardPoolApproxValue,\n };\n}\n\n/**\n * Deserializes an {@link SerializedAggregatedReferrerMetrics} object.\n */\nfunction deserializeAggregatedReferrerMetrics(\n metrics: SerializedAggregatedReferrerMetrics,\n): AggregatedReferrerMetrics {\n return {\n grandTotalReferrals: metrics.grandTotalReferrals,\n grandTotalIncrementalDuration: metrics.grandTotalIncrementalDuration,\n grandTotalRevenueContribution: deserializeRevenueContribution(\n metrics.grandTotalRevenueContribution,\n ),\n grandTotalQualifiedReferrersFinalScore: metrics.grandTotalQualifiedReferrersFinalScore,\n minFinalScoreToQualify: metrics.minFinalScoreToQualify,\n };\n}\n\n/**\n * Deserializes a {@link SerializedReferrerLeaderboardPage} object.\n */\nfunction deserializeReferrerLeaderboardPage(\n page: SerializedReferrerLeaderboardPage,\n): ReferrerLeaderboardPage {\n return {\n rules: deserializeReferralProgramRules(page.rules),\n referrers: page.referrers.map(deserializeAwardedReferrerMetrics),\n aggregatedMetrics: deserializeAggregatedReferrerMetrics(page.aggregatedMetrics),\n pageContext: page.pageContext,\n accurateAsOf: page.accurateAsOf,\n };\n}\n\n/**\n * Deserializes a {@link SerializedReferrerDetailRanked} object.\n */\nfunction deserializeReferrerDetailRanked(\n detail: SerializedReferrerDetailRanked,\n): ReferrerDetailRanked {\n return {\n type: detail.type,\n rules: deserializeReferralProgramRules(detail.rules),\n referrer: deserializeAwardedReferrerMetrics(detail.referrer),\n aggregatedMetrics: deserializeAggregatedReferrerMetrics(detail.aggregatedMetrics),\n accurateAsOf: detail.accurateAsOf,\n };\n}\n\n/**\n * Deserializes a {@link SerializedReferrerDetailUnranked} object.\n */\nfunction deserializeReferrerDetailUnranked(\n detail: SerializedReferrerDetailUnranked,\n): ReferrerDetailUnranked {\n return {\n type: detail.type,\n rules: deserializeReferralProgramRules(detail.rules),\n referrer: deserializeUnrankedReferrerMetrics(detail.referrer),\n aggregatedMetrics: deserializeAggregatedReferrerMetrics(detail.aggregatedMetrics),\n accurateAsOf: detail.accurateAsOf,\n };\n}\n\n/**\n * Deserialize a {@link ReferrerLeaderboardPageResponse} object.\n *\n * Note: This function explicitly deserializes each subobject to convert string\n * RevenueContribution values back to bigint, then validates using Zod schemas\n * to enforce invariants on the data.\n */\nexport function deserializeReferrerLeaderboardPageResponse(\n maybeResponse: SerializedReferrerLeaderboardPageResponse,\n valueLabel?: string,\n): ReferrerLeaderboardPageResponse {\n let deserialized: ReferrerLeaderboardPageResponse;\n switch (maybeResponse.responseCode) {\n case \"ok\": {\n deserialized = {\n responseCode: maybeResponse.responseCode,\n data: deserializeReferrerLeaderboardPage(maybeResponse.data),\n } as ReferrerLeaderboardPageResponse;\n break;\n }\n\n case \"error\":\n deserialized = maybeResponse;\n break;\n }\n\n // Then validate the deserialized structure using zod schemas\n const schema = makeReferrerLeaderboardPageResponseSchema(valueLabel);\n const parsed = schema.safeParse(deserialized);\n\n if (parsed.error) {\n throw new Error(\n `Cannot deserialize SerializedReferrerLeaderboardPageResponse:\\n${prettifyError(parsed.error)}\\n`,\n );\n }\n\n return parsed.data;\n}\n\n/**\n * Deserialize a {@link ReferrerDetailResponse} object.\n *\n * Note: This function explicitly deserializes each subobject to convert string\n * RevenueContribution values back to bigint, then validates using Zod schemas\n * to enforce invariants on the data.\n */\nexport function deserializeReferrerDetailResponse(\n maybeResponse: SerializedReferrerDetailResponse,\n valueLabel?: string,\n): ReferrerDetailResponse {\n let deserialized: ReferrerDetailResponse;\n switch (maybeResponse.responseCode) {\n case \"ok\": {\n switch (maybeResponse.data.type) {\n case \"ranked\":\n deserialized = {\n responseCode: maybeResponse.responseCode,\n data: deserializeReferrerDetailRanked(maybeResponse.data),\n } as ReferrerDetailResponse;\n break;\n\n case \"unranked\":\n deserialized = {\n responseCode: maybeResponse.responseCode,\n data: deserializeReferrerDetailUnranked(maybeResponse.data),\n } as ReferrerDetailResponse;\n break;\n }\n break;\n }\n\n case \"error\":\n deserialized = maybeResponse;\n break;\n }\n\n // Then validate the deserialized structure using zod schemas\n const schema = makeReferrerDetailResponseSchema(valueLabel);\n const parsed = schema.safeParse(deserialized);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize ReferrerDetailResponse:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n","/**\n * All zod schemas we define must remain internal implementation details.\n * We want the freedom to move away from zod in the future without impacting\n * any users of the ensnode-sdk package.\n *\n * The only way to share Zod schemas is to re-export them from\n * `./src/internal.ts` file.\n */\n\nimport {\n REFERRERS_PER_LEADERBOARD_PAGE_MAX,\n type ReferrerDetailRanked,\n ReferrerDetailTypeIds,\n type RevenueContribution,\n} from \"@namehash/ens-referrals\";\nimport z from \"zod/v4\";\n\nimport {\n makeAccountIdSchema,\n makeDurationSchema,\n makeFiniteNonNegativeNumberSchema,\n makeLowercaseAddressSchema,\n makeNonNegativeIntegerSchema,\n makePositiveIntegerSchema,\n makeUnixTimestampSchema,\n} from \"../shared/zod-schemas\";\nimport { ReferrerDetailResponseCodes, ReferrerLeaderboardPageResponseCodes } from \"./types\";\n\n/**\n * Schema for {@link RevenueContribution}\n */\nconst makeRevenueContributionSchema = (valueLabel: string = \"RevenueContribution\") =>\n z.coerce\n .bigint({\n error: `${valueLabel} must represent a bigint.`,\n })\n .nonnegative({\n error: `${valueLabel} must not be negative.`,\n });\n\n/**\n * Schema for ReferralProgramRules\n */\nexport const makeReferralProgramRulesSchema = (valueLabel: string = \"ReferralProgramRules\") =>\n z.object({\n totalAwardPoolValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.totalAwardPoolValue`),\n maxQualifiedReferrers: makeNonNegativeIntegerSchema(`${valueLabel}.maxQualifiedReferrers`),\n startTime: makeUnixTimestampSchema(`${valueLabel}.startTime`),\n endTime: makeUnixTimestampSchema(`${valueLabel}.endTime`),\n subregistryId: makeAccountIdSchema(`${valueLabel}.subregistryId`),\n });\n\n/**\n * Schema for AwardedReferrerMetrics (with numeric rank)\n */\nexport const makeAwardedReferrerMetricsSchema = (valueLabel: string = \"AwardedReferrerMetrics\") =>\n z.object({\n referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`),\n totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`),\n totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`),\n totalRevenueContribution: makeRevenueContributionSchema(\n `${valueLabel}.totalRevenueContribution`,\n ),\n score: makeFiniteNonNegativeNumberSchema(`${valueLabel}.score`),\n rank: makePositiveIntegerSchema(`${valueLabel}.rank`),\n isQualified: z.boolean(),\n finalScoreBoost: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScoreBoost`).max(\n 1,\n `${valueLabel}.finalScoreBoost must be <= 1`,\n ),\n finalScore: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScore`),\n awardPoolShare: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolShare`).max(\n 1,\n `${valueLabel}.awardPoolShare must be <= 1`,\n ),\n awardPoolApproxValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolApproxValue`),\n });\n\n/**\n * Schema for UnrankedReferrerMetrics (with null rank)\n */\nexport const makeUnrankedReferrerMetricsSchema = (valueLabel: string = \"UnrankedReferrerMetrics\") =>\n z.object({\n referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`),\n totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`),\n totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`),\n totalRevenueContribution: makeRevenueContributionSchema(\n `${valueLabel}.totalRevenueContribution`,\n ),\n score: makeFiniteNonNegativeNumberSchema(`${valueLabel}.score`),\n rank: z.null(),\n isQualified: z.literal(false),\n finalScoreBoost: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScoreBoost`).max(\n 1,\n `${valueLabel}.finalScoreBoost must be <= 1`,\n ),\n finalScore: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScore`),\n awardPoolShare: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolShare`).max(\n 1,\n `${valueLabel}.awardPoolShare must be <= 1`,\n ),\n awardPoolApproxValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolApproxValue`),\n });\n\n/**\n * Schema for AggregatedReferrerMetrics\n */\nexport const makeAggregatedReferrerMetricsSchema = (\n valueLabel: string = \"AggregatedReferrerMetrics\",\n) =>\n z.object({\n grandTotalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.grandTotalReferrals`),\n grandTotalIncrementalDuration: makeDurationSchema(\n `${valueLabel}.grandTotalIncrementalDuration`,\n ),\n grandTotalRevenueContribution: makeRevenueContributionSchema(\n `${valueLabel}.grandTotalRevenueContribution`,\n ),\n grandTotalQualifiedReferrersFinalScore: makeFiniteNonNegativeNumberSchema(\n `${valueLabel}.grandTotalQualifiedReferrersFinalScore`,\n ),\n minFinalScoreToQualify: makeFiniteNonNegativeNumberSchema(\n `${valueLabel}.minFinalScoreToQualify`,\n ),\n });\n\nexport const makeReferrerLeaderboardPageContextSchema = (\n valueLabel: string = \"ReferrerLeaderboardPageContext\",\n) =>\n z.object({\n page: makePositiveIntegerSchema(`${valueLabel}.page`),\n recordsPerPage: makePositiveIntegerSchema(`${valueLabel}.recordsPerPage`).max(\n REFERRERS_PER_LEADERBOARD_PAGE_MAX,\n `${valueLabel}.recordsPerPage must not exceed ${REFERRERS_PER_LEADERBOARD_PAGE_MAX}`,\n ),\n totalRecords: makeNonNegativeIntegerSchema(`${valueLabel}.totalRecords`),\n totalPages: makePositiveIntegerSchema(`${valueLabel}.totalPages`),\n hasNext: z.boolean(),\n hasPrev: z.boolean(),\n startIndex: z.optional(makeNonNegativeIntegerSchema(`${valueLabel}.startIndex`)),\n endIndex: z.optional(makeNonNegativeIntegerSchema(`${valueLabel}.endIndex`)),\n });\n\n/**\n * Schema for ReferrerLeaderboardPage\n */\nexport const makeReferrerLeaderboardPageSchema = (valueLabel: string = \"ReferrerLeaderboardPage\") =>\n z.object({\n rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),\n referrers: z.array(makeAwardedReferrerMetricsSchema(`${valueLabel}.referrers[record]`)),\n aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),\n pageContext: makeReferrerLeaderboardPageContextSchema(`${valueLabel}.pageContext`),\n accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`),\n });\n\n/**\n * Schema for {@link ReferrerLeaderboardPageResponseOk}\n */\nexport const makeReferrerLeaderboardPageResponseOkSchema = (\n valueLabel: string = \"ReferrerLeaderboardPageResponseOk\",\n) =>\n z.object({\n responseCode: z.literal(ReferrerLeaderboardPageResponseCodes.Ok),\n data: makeReferrerLeaderboardPageSchema(`${valueLabel}.data`),\n });\n\n/**\n * Schema for {@link ReferrerLeaderboardPageResponseError}\n */\nexport const makeReferrerLeaderboardPageResponseErrorSchema = (\n _valueLabel: string = \"ReferrerLeaderboardPageResponseError\",\n) =>\n z.object({\n responseCode: z.literal(ReferrerLeaderboardPageResponseCodes.Error),\n error: z.string(),\n errorMessage: z.string(),\n });\n\n/**\n * Schema for {@link ReferrerLeaderboardPageResponse}\n */\nexport const makeReferrerLeaderboardPageResponseSchema = (\n valueLabel: string = \"ReferrerLeaderboardPageResponse\",\n) =>\n z.union([\n makeReferrerLeaderboardPageResponseOkSchema(valueLabel),\n makeReferrerLeaderboardPageResponseErrorSchema(valueLabel),\n ]);\n\n/**\n * Schema for {@link ReferrerDetailRanked} (with ranked metrics)\n */\nexport const makeReferrerDetailRankedSchema = (valueLabel: string = \"ReferrerDetailRanked\") =>\n z.object({\n type: z.literal(ReferrerDetailTypeIds.Ranked),\n rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),\n referrer: makeAwardedReferrerMetricsSchema(`${valueLabel}.referrer`),\n aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),\n accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`),\n });\n\n/**\n * Schema for {@link ReferrerDetailUnranked} (with unranked metrics)\n */\nexport const makeReferrerDetailUnrankedSchema = (valueLabel: string = \"ReferrerDetailUnranked\") =>\n z.object({\n type: z.literal(ReferrerDetailTypeIds.Unranked),\n rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),\n referrer: makeUnrankedReferrerMetricsSchema(`${valueLabel}.referrer`),\n aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),\n accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`),\n });\n\n/**\n * Schema for {@link ReferrerDetailResponseOk}\n * Accepts either ranked or unranked referrer detail data\n */\nexport const makeReferrerDetailResponseOkSchema = (valueLabel: string = \"ReferrerDetailResponse\") =>\n z.object({\n responseCode: z.literal(ReferrerDetailResponseCodes.Ok),\n data: z.union([\n makeReferrerDetailRankedSchema(`${valueLabel}.data`),\n makeReferrerDetailUnrankedSchema(`${valueLabel}.data`),\n ]),\n });\n\n/**\n * Schema for {@link ReferrerDetailResponseError}\n */\nexport const makeReferrerDetailResponseErrorSchema = (\n _valueLabel: string = \"ReferrerDetailResponse\",\n) =>\n z.object({\n responseCode: z.literal(ReferrerDetailResponseCodes.Error),\n error: z.string(),\n errorMessage: z.string(),\n });\n\n/**\n * Schema for {@link ReferrerDetailResponse}\n */\nexport const makeReferrerDetailResponseSchema = (valueLabel: string = \"ReferrerDetailResponse\") =>\n z.union([\n makeReferrerDetailResponseOkSchema(valueLabel),\n makeReferrerDetailResponseErrorSchema(valueLabel),\n ]);\n","import type {\n ReferrerDetail,\n ReferrerLeaderboardPage,\n ReferrerLeaderboardPageParams,\n} from \"@namehash/ens-referrals\";\nimport type { Address } from \"viem\";\n\n/**\n * Request parameters for a referrer leaderboard page query.\n */\nexport interface ReferrerLeaderboardPageRequest extends ReferrerLeaderboardPageParams {}\n\n/**\n * A status code for a referrer leaderboard page API response.\n */\nexport const ReferrerLeaderboardPageResponseCodes = {\n /**\n * Represents that the requested referrer leaderboard page is available.\n */\n Ok: \"ok\",\n\n /**\n * Represents that the referrer leaderboard data is not available.\n */\n Error: \"error\",\n} as const;\n\n/**\n * The derived string union of possible {@link ReferrerLeaderboardPageResponseCodes}.\n */\nexport type ReferrerLeaderboardPageResponseCode =\n (typeof ReferrerLeaderboardPageResponseCodes)[keyof typeof ReferrerLeaderboardPageResponseCodes];\n\n/**\n * A referrer leaderboard page response when the data is available.\n */\nexport type ReferrerLeaderboardPageResponseOk = {\n responseCode: typeof ReferrerLeaderboardPageResponseCodes.Ok;\n data: ReferrerLeaderboardPage;\n};\n\n/**\n * A referrer leaderboard page response when the data is not available.\n */\nexport type ReferrerLeaderboardPageResponseError = {\n responseCode: typeof ReferrerLeaderboardPageResponseCodes.Error;\n error: string;\n errorMessage: string;\n};\n\n/**\n * A referrer leaderboard page API response.\n *\n * Use the `responseCode` field to determine the specific type interpretation\n * at runtime.\n */\nexport type ReferrerLeaderboardPageResponse =\n | ReferrerLeaderboardPageResponseOk\n | ReferrerLeaderboardPageResponseError;\n\n/**\n * Request parameters for referrer detail query.\n */\nexport interface ReferrerDetailRequest {\n /** The Ethereum address of the referrer to query */\n referrer: Address;\n}\n\n/**\n * A status code for referrer detail API responses.\n */\nexport const ReferrerDetailResponseCodes = {\n /**\n * Represents that the referrer detail data is available.\n */\n Ok: \"ok\",\n\n /**\n * Represents that an error occurred while fetching the data.\n */\n Error: \"error\",\n} as const;\n\n/**\n * The derived string union of possible {@link ReferrerDetailResponseCodes}.\n */\nexport type ReferrerDetailResponseCode =\n (typeof ReferrerDetailResponseCodes)[keyof typeof ReferrerDetailResponseCodes];\n\n/**\n * A referrer detail response when the data is available for a referrer on the leaderboard.\n */\nexport type ReferrerDetailResponseOk = {\n responseCode: typeof ReferrerDetailResponseCodes.Ok;\n data: ReferrerDetail;\n};\n\n/**\n * A referrer detail response when an error occurs.\n */\nexport type ReferrerDetailResponseError = {\n responseCode: typeof ReferrerDetailResponseCodes.Error;\n error: string;\n errorMessage: string;\n};\n\n/**\n * A referrer detail API response.\n *\n * Use the `responseCode` field to determine the specific type interpretation\n * at runtime.\n */\nexport type ReferrerDetailResponse = ReferrerDetailResponseOk | ReferrerDetailResponseError;\n","import type {\n AggregatedReferrerMetrics,\n AwardedReferrerMetrics,\n ReferralProgramRules,\n ReferrerDetailRanked,\n ReferrerDetailUnranked,\n ReferrerLeaderboardPage,\n RevenueContribution,\n UnrankedReferrerMetrics,\n} from \"@namehash/ens-referrals\";\n\nimport type {\n SerializedAggregatedReferrerMetrics,\n SerializedAwardedReferrerMetrics,\n SerializedReferralProgramRules,\n SerializedReferrerDetailRanked,\n SerializedReferrerDetailResponse,\n SerializedReferrerDetailUnranked,\n SerializedReferrerLeaderboardPage,\n SerializedReferrerLeaderboardPageResponse,\n SerializedUnrankedReferrerMetrics,\n} from \"./serialized-types\";\nimport {\n type ReferrerDetailResponse,\n ReferrerDetailResponseCodes,\n type ReferrerLeaderboardPageResponse,\n ReferrerLeaderboardPageResponseCodes,\n} from \"./types\";\n\n/**\n * Serializes a {@link RevenueContribution} value into its string representation.\n */\nfunction serializeRevenueContribution(revenueContribution: RevenueContribution): string {\n return revenueContribution.toString();\n}\n\n/**\n * Serializes a {@link ReferralProgramRules} object.\n */\nfunction serializeReferralProgramRules(\n rules: ReferralProgramRules,\n): SerializedReferralProgramRules {\n // All fields are already serializable primitives\n return rules;\n}\n\n/**\n * Serializes an {@link AwardedReferrerMetrics} object.\n */\nfunction serializeAwardedReferrerMetrics(\n metrics: AwardedReferrerMetrics,\n): SerializedAwardedReferrerMetrics {\n return {\n referrer: metrics.referrer,\n totalReferrals: metrics.totalReferrals,\n totalIncrementalDuration: metrics.totalIncrementalDuration,\n totalRevenueContribution: serializeRevenueContribution(metrics.totalRevenueContribution),\n score: metrics.score,\n rank: metrics.rank,\n isQualified: metrics.isQualified,\n finalScoreBoost: metrics.finalScoreBoost,\n finalScore: metrics.finalScore,\n awardPoolShare: metrics.awardPoolShare,\n awardPoolApproxValue: metrics.awardPoolApproxValue,\n };\n}\n\n/**\n * Serializes an {@link UnrankedReferrerMetrics} object.\n */\nfunction serializeUnrankedReferrerMetrics(\n metrics: UnrankedReferrerMetrics,\n): SerializedUnrankedReferrerMetrics {\n return {\n referrer: metrics.referrer,\n totalReferrals: metrics.totalReferrals,\n totalIncrementalDuration: metrics.totalIncrementalDuration,\n totalRevenueContribution: serializeRevenueContribution(metrics.totalRevenueContribution),\n score: metrics.score,\n rank: metrics.rank,\n isQualified: metrics.isQualified,\n finalScoreBoost: metrics.finalScoreBoost,\n finalScore: metrics.finalScore,\n awardPoolShare: metrics.awardPoolShare,\n awardPoolApproxValue: metrics.awardPoolApproxValue,\n };\n}\n\n/**\n * Serializes an {@link AggregatedReferrerMetrics} object.\n */\nfunction serializeAggregatedReferrerMetrics(\n metrics: AggregatedReferrerMetrics,\n): SerializedAggregatedReferrerMetrics {\n return {\n grandTotalReferrals: metrics.grandTotalReferrals,\n grandTotalIncrementalDuration: metrics.grandTotalIncrementalDuration,\n grandTotalRevenueContribution: serializeRevenueContribution(\n metrics.grandTotalRevenueContribution,\n ),\n grandTotalQualifiedReferrersFinalScore: metrics.grandTotalQualifiedReferrersFinalScore,\n minFinalScoreToQualify: metrics.minFinalScoreToQualify,\n };\n}\n\n/**\n * Serializes a {@link ReferrerLeaderboardPage} object.\n */\nfunction serializeReferrerLeaderboardPage(\n page: ReferrerLeaderboardPage,\n): SerializedReferrerLeaderboardPage {\n return {\n rules: serializeReferralProgramRules(page.rules),\n referrers: page.referrers.map(serializeAwardedReferrerMetrics),\n aggregatedMetrics: serializeAggregatedReferrerMetrics(page.aggregatedMetrics),\n pageContext: page.pageContext,\n accurateAsOf: page.accurateAsOf,\n };\n}\n\n/**\n * Serializes a {@link ReferrerDetailRanked} object.\n */\nfunction serializeReferrerDetailRanked(\n detail: ReferrerDetailRanked,\n): SerializedReferrerDetailRanked {\n return {\n type: detail.type,\n rules: serializeReferralProgramRules(detail.rules),\n referrer: serializeAwardedReferrerMetrics(detail.referrer),\n aggregatedMetrics: serializeAggregatedReferrerMetrics(detail.aggregatedMetrics),\n accurateAsOf: detail.accurateAsOf,\n };\n}\n\n/**\n * Serializes a {@link ReferrerDetailUnranked} object.\n */\nfunction serializeReferrerDetailUnranked(\n detail: ReferrerDetailUnranked,\n): SerializedReferrerDetailUnranked {\n return {\n type: detail.type,\n rules: serializeReferralProgramRules(detail.rules),\n referrer: serializeUnrankedReferrerMetrics(detail.referrer),\n aggregatedMetrics: serializeAggregatedReferrerMetrics(detail.aggregatedMetrics),\n accurateAsOf: detail.accurateAsOf,\n };\n}\n\n/**\n * Serialize a {@link ReferrerLeaderboardPageResponse} object.\n */\nexport function serializeReferrerLeaderboardPageResponse(\n response: ReferrerLeaderboardPageResponse,\n): SerializedReferrerLeaderboardPageResponse {\n switch (response.responseCode) {\n case ReferrerLeaderboardPageResponseCodes.Ok:\n return {\n responseCode: response.responseCode,\n data: serializeReferrerLeaderboardPage(response.data),\n };\n\n case ReferrerLeaderboardPageResponseCodes.Error:\n return response;\n }\n}\n\n/**\n * Serialize a {@link ReferrerDetailResponse} object.\n */\nexport function serializeReferrerDetailResponse(\n response: ReferrerDetailResponse,\n): SerializedReferrerDetailResponse {\n switch (response.responseCode) {\n case ReferrerDetailResponseCodes.Ok:\n switch (response.data.type) {\n case \"ranked\":\n return {\n responseCode: response.responseCode,\n data: serializeReferrerDetailRanked(response.data),\n };\n\n case \"unranked\":\n return {\n responseCode: response.responseCode,\n data: serializeReferrerDetailUnranked(response.data),\n };\n }\n break;\n\n case ReferrerDetailResponseCodes.Error:\n return response;\n }\n}\n","import { ReferrerDetailTypeIds } from \"@namehash/ens-referrals\";\n\nimport {\n type ConfigResponse,\n deserializeConfigResponse,\n deserializedNameTokensResponse,\n deserializeErrorResponse,\n deserializeIndexingStatusResponse,\n deserializeRegistrarActionsResponse,\n type ErrorResponse,\n type IndexingStatusResponse,\n type NameTokensRequest,\n type NameTokensResponse,\n type RegistrarActionsFilter,\n RegistrarActionsFilterTypes,\n type RegistrarActionsOrder,\n RegistrarActionsOrders,\n type RegistrarActionsRequest,\n type RegistrarActionsResponse,\n type ResolvePrimaryNameRequest,\n type ResolvePrimaryNameResponse,\n type ResolvePrimaryNamesRequest,\n type ResolvePrimaryNamesResponse,\n type ResolveRecordsRequest,\n type ResolveRecordsResponse,\n type SerializedConfigResponse,\n type SerializedIndexingStatusResponse,\n type SerializedNameTokensResponse,\n type SerializedRegistrarActionsResponse,\n} from \"./api\";\nimport { ClientError } from \"./client-error\";\nimport {\n deserializeReferrerDetailResponse,\n deserializeReferrerLeaderboardPageResponse,\n type ReferrerDetailRequest,\n type ReferrerDetailResponse,\n type ReferrerLeaderboardPageRequest,\n type ReferrerLeaderboardPageResponse,\n type SerializedReferrerDetailResponse,\n type SerializedReferrerLeaderboardPageResponse,\n} from \"./ensanalytics\";\nimport type { ResolverRecordsSelection } from \"./resolution\";\n\n/**\n * Default ENSNode API endpoint URL\n */\nexport const DEFAULT_ENSNODE_API_URL = \"https://api.alpha.ensnode.io\" as const;\n\n/**\n * Configuration options for ENSNode API client\n */\nexport interface ClientOptions {\n /** The ENSNode API URL */\n url: URL;\n}\n\n/**\n * ENSNode API Client\n *\n * Provides access to the following ENSNode APIs:\n * - Resolution API\n * - ENSAnalytics API\n * - 🚧 Configuration API\n * - 🚧 Indexing Status API\n *\n * @example\n * ```typescript\n * // Create client with default options\n * const client = new ENSNodeClient();\n *\n * // Use resolution methods\n * const { records } = await client.resolveRecords(\"jesse.base.eth\", {\n * addresses: [60],\n * texts: [\"avatar\"]\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Custom configuration\n * const client = new ENSNodeClient({\n * url: new URL(\"https://my-ensnode-instance.com\"),\n * });\n * ```\n */\nexport class ENSNodeClient {\n private readonly options: ClientOptions;\n\n static defaultOptions(): ClientOptions {\n return {\n url: new URL(DEFAULT_ENSNODE_API_URL),\n };\n }\n\n constructor(options: Partial<ClientOptions> = {}) {\n this.options = {\n ...ENSNodeClient.defaultOptions(),\n ...options,\n };\n }\n\n getOptions(): Readonly<ClientOptions> {\n return Object.freeze({\n url: new URL(this.options.url.href),\n });\n }\n\n /**\n * Resolves records for an ENS name (Forward Resolution).\n *\n * The returned `name` field, if set, is guaranteed to be a [Normalized Name](https://ensnode.io/docs/reference/terminology#normalized-name).\n * If the name record returned by the resolver is not normalized, `null` is returned as if no name record was set.\n *\n * @param name The ENS Name whose records to resolve\n * @param selection selection of Resolver records\n * @param options additional options\n * @param options.accelerate whether to attempt Protocol Acceleration (default false)\n * @param options.trace whether to include a trace in the response (default false)\n * @returns ResolveRecordsResponse<SELECTION>\n * @throws If the request fails or the ENSNode API returns an error response\n *\n * @example\n * ```typescript\n * const { records } = await client.resolveRecords(\"jesse.base.eth\", {\n * addresses: [60],\n * texts: [\"avatar\", \"com.twitter\"]\n * });\n *\n * console.log(records);\n * // {\n * // addresses: {\n * // 60: \"0xabcd...\"\n * // },\n * // texts: {\n * // avatar: \"https://example.com/image.jpg\",\n * // \"com.twitter\": null, // if not set, for example\n * // }\n * // }\n * ```\n */\n async resolveRecords<SELECTION extends ResolverRecordsSelection>(\n name: ResolveRecordsRequest<SELECTION>[\"name\"],\n selection: ResolveRecordsRequest<SELECTION>[\"selection\"],\n options?: Omit<ResolveRecordsRequest<SELECTION>, \"name\" | \"selection\">,\n ): Promise<ResolveRecordsResponse<SELECTION>> {\n const url = new URL(`/api/resolve/records/${encodeURIComponent(name)}`, this.options.url);\n\n // Add query parameters based on selection\n if (selection.name) {\n url.searchParams.set(\"name\", \"true\");\n }\n\n if (selection.addresses && selection.addresses.length > 0) {\n url.searchParams.set(\"addresses\", selection.addresses.join(\",\"));\n }\n\n if (selection.texts && selection.texts.length > 0) {\n url.searchParams.set(\"texts\", selection.texts.join(\",\"));\n }\n\n if (options?.trace) url.searchParams.set(\"trace\", \"true\");\n if (options?.accelerate) url.searchParams.set(\"accelerate\", \"true\");\n\n const response = await fetch(url);\n\n if (!response.ok) {\n const error = (await response.json()) as ErrorResponse;\n throw ClientError.fromErrorResponse(error);\n }\n\n const data = await response.json();\n return data as ResolveRecordsResponse<SELECTION>;\n }\n\n /**\n * Resolves the primary name of a specified address (Reverse Resolution) on a specific chain.\n *\n * If the chainId-specific Primary Name is not defined, but the `address` specifies a valid\n * [ENSIP-19 Default Name](https://docs.ens.domains/ensip/19/#default-primary-name), the Default\n * Name will be returned. You _may_ query the Default EVM Chain Id (`0`) in order to determine the\n * `address`'s Default Name directly.\n *\n * The returned Primary Name, if set, is guaranteed to be a [Normalized Name](https://ensnode.io/docs/reference/terminology#normalized-name).\n * If the primary name set for the address is not normalized, `null` is returned as if no primary name was set.\n *\n * @param address The Address whose Primary Name to resolve\n * @param chainId The chain id within which to query the address' ENSIP-19 Multichain Primary Name\n * @param options additional options\n * @param options.accelerate whether to attempt Protocol Acceleration (default false)\n * @param options.trace whether to include a trace in the response (default false)\n * @returns ResolvePrimaryNameResponse\n * @throws If the request fails or the ENSNode API returns an error response\n *\n * @example\n * ```typescript\n * // Resolve the address' Primary Name on Ethereum Mainnet\n * const { name } = await client.resolvePrimaryName(\"0x179A862703a4adfb29896552DF9e307980D19285\", 1);\n * // name === 'gregskril.eth'\n *\n * // Resolve the address' Primary Name on Base\n * const { name } = await client.resolvePrimaryName(\"0x179A862703a4adfb29896552DF9e307980D19285\", 8453);\n * // name === 'greg.base.eth'\n *\n * // Resolve the address' Default Primary Name\n * const { name } = await client.resolvePrimaryName(\"0x179A862703a4adfb29896552DF9e307980D19285\", 0);\n * // name === 'gregskril.eth'\n * ```\n */\n async resolvePrimaryName(\n address: ResolvePrimaryNameRequest[\"address\"],\n chainId: ResolvePrimaryNameRequest[\"chainId\"],\n options?: Omit<ResolvePrimaryNameRequest, \"address\" | \"chainId\">,\n ): Promise<ResolvePrimaryNameResponse> {\n const url = new URL(`/api/resolve/primary-name/${address}/${chainId}`, this.options.url);\n\n if (options?.trace) url.searchParams.set(\"trace\", \"true\");\n if (options?.accelerate) url.searchParams.set(\"accelerate\", \"true\");\n\n const response = await fetch(url);\n\n if (!response.ok) {\n const error = (await response.json()) as ErrorResponse;\n throw ClientError.fromErrorResponse(error);\n }\n\n const data = await response.json();\n return data as ResolvePrimaryNameResponse;\n }\n\n /**\n * Resolves the primary names of a specified address across multiple chains.\n *\n * For each Primary Name, if the chainId-specific Primary Name is not defined, but the `address`\n * specifies a valid [ENSIP-19 Default Name](https://docs.ens.domains/ensip/19/#default-primary-name),\n * the Default Name will be returned. You _may not_ query the Default EVM Chain Id (`0`) directly,\n * and should rely on the aforementioned per-chain defaulting behavior.\n *\n * Each returned Primary Name, if set, is guaranteed to be a [Normalized Name](https://ensnode.io/docs/reference/terminology#normalized-name).\n * If the primary name set for the address on any chain is not normalized, `null` is returned for\n * that chain as if no primary name was set.\n *\n * @param address The Address whose Primary Names to resolve\n * @param options additional options\n * @param options.chainIds The set of chain ids within which to query the address' ENSIP-19\n * Multichain Primary Name (default: all ENSIP-19 supported chains)\n * @param options.accelerate whether to attempt Protocol Acceleration (default: true)\n * @param options.trace whether to include a trace in the response (default: false)\n * @returns ResolvePrimaryNamesResponse\n * @throws If the request fails or the ENSNode API returns an error response\n *\n * @example\n * ```typescript\n * // Resolve the address' Primary Names on all ENSIP-19 supported chain ids\n * const { names } = await client.resolvePrimaryNames(\"0x179A862703a4adfb29896552DF9e307980D19285\");\n *\n * console.log(names);\n * // {\n * // \"1\": \"gregskril.eth\", // Default Primary Name\n * // \"10\": \"gregskril.eth\", // Default Primary Name\n * // \"8453\": \"greg.base.eth\", // Base-specific Primary Name!\n * // \"42161\": \"gregskril.eth\", // Default Primary Name\n * // \"59144\": \"gregskril.eth\", // Default Primary Name\n * // \"534352\": \"gregskril.eth\" // Default Primary Name\n * // }\n *\n * // Resolve the address' Primary Names on specific chain Ids\n * const { names } = await client.resolvePrimaryNames(\"0xabcd...\", [1, 8453]);\n *\n * console.log(names);\n * // {\n * // \"1\": \"gregskril.eth\",\n * // \"8453\": \"greg.base.eth\", // base-specific Primary Name!\n * // }\n * ```\n */\n async resolvePrimaryNames(\n address: ResolvePrimaryNamesRequest[\"address\"],\n options?: Omit<ResolvePrimaryNamesRequest, \"address\">,\n ): Promise<ResolvePrimaryNamesResponse> {\n const url = new URL(`/api/resolve/primary-names/${address}`, this.options.url);\n\n if (options?.chainIds) url.searchParams.set(\"chainIds\", options.chainIds.join(\",\"));\n if (options?.trace) url.searchParams.set(\"trace\", \"true\");\n if (options?.accelerate) url.searchParams.set(\"accelerate\", \"true\");\n\n const response = await fetch(url);\n\n if (!response.ok) {\n const error = (await response.json()) as ErrorResponse;\n throw ClientError.fromErrorResponse(error);\n }\n\n const data = await response.json();\n return data as ResolvePrimaryNamesResponse;\n }\n\n /**\n * Fetch ENSNode Config\n *\n * Fetch the ENSNode's configuration.\n *\n * @returns {ConfigResponse}\n *\n * @throws if the ENSNode request fails\n * @throws if the ENSNode API returns an error response\n * @throws if the ENSNode response breaks required invariants\n */\n async config(): Promise<ConfigResponse> {\n const url = new URL(`/api/config`, this.options.url);\n\n const response = await fetch(url);\n\n // ENSNode API should always allow parsing a response as JSON object.\n // If for some reason it's not the case, throw an error.\n let responseData: unknown;\n try {\n responseData = await response.json();\n } catch {\n throw new Error(\"Malformed response data: invalid JSON\");\n }\n\n if (!response.ok) {\n const errorResponse = deserializeErrorResponse(responseData);\n throw new Error(`Fetching ENSNode Config Failed: ${errorResponse.message}`);\n }\n\n return deserializeConfigResponse(responseData as SerializedConfigResponse);\n }\n\n /**\n * Fetch ENSNode Indexing Status\n *\n * @returns {IndexingStatusResponse}\n *\n * @throws if the ENSNode request fails\n * @throws if the ENSNode API returns an error response\n * @throws if the ENSNode response breaks required invariants\n */\n async indexingStatus(): Promise<IndexingStatusResponse> {\n const url = new URL(`/api/indexing-status`, this.options.url);\n\n const response = await fetch(url);\n\n // ENSNode API should always allow parsing a response as JSON object.\n // If for some reason it's not the case, throw an error.\n let responseData: unknown;\n try {\n responseData = await response.json();\n } catch {\n throw new Error(\"Malformed response data: invalid JSON\");\n }\n\n // handle response errors accordingly\n if (!response.ok) {\n // check for a generic errorResponse\n let errorResponse: ErrorResponse | undefined;\n try {\n errorResponse = deserializeErrorResponse(responseData);\n } catch {\n // if errorResponse could not be determined,\n // it means the response includes indexing status data\n console.log(\"Indexing Status API: handling a known indexing status server error.\");\n }\n\n // however, if errorResponse was defined,\n // throw an error with the generic server error message\n if (typeof errorResponse !== \"undefined\") {\n throw new Error(`Fetching ENSNode Indexing Status Failed: ${errorResponse.message}`);\n }\n }\n\n return deserializeIndexingStatusResponse(responseData as SerializedIndexingStatusResponse);\n }\n\n /**\n * Fetch Referrer Leaderboard Page\n *\n * Retrieves a paginated list of referrer leaderboard metrics with contribution percentages.\n * Each referrer's contribution is calculated as a percentage of the grand totals across all referrers.\n *\n * @param request - Pagination parameters\n * @param request.page - The page number to retrieve (1-indexed, default: 1)\n * @param request.recordsPerPage - Number of records per page (default: 25, max: 100)\n * @returns {ReferrerLeaderboardPageResponse}\n *\n * @throws if the ENSNode request fails\n * @throws if the ENSNode API returns an error response\n * @throws if the ENSNode response breaks required invariants\n *\n * @example\n * ```typescript\n * // Get first page with default page size (25 records)\n * const response = await client.getReferrerLeaderboardPage();\n * if (response.responseCode === ReferrerLeaderboardPageResponseCodes.Ok) {\n * const {\n * aggregatedMetrics,\n * referrers,\n * rules,\n * pageContext,\n * updatedAt\n * } = response.data;\n * console.log(aggregatedMetrics);\n * console.log(referrers);\n * console.log(rules);\n * console.log(updatedAt);\n * console.log(`Page ${pageContext.page} of ${pageContext.totalPages}`);\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Get second page with 50 records per page\n * const response = await client.getReferrerLeaderboardPage({ page: 2, recordsPerPage: 50 });\n * ```\n *\n * @example\n * ```typescript\n * // Handle error response, ie. when Referrer Leaderboard is not currently available.\n * const response = await client.getReferrerLeaderboardPage();\n *\n * if (response.responseCode === ReferrerLeaderboardPageResponseCodes.Error) {\n * console.error(response.error);\n * console.error(response.errorMessage);\n * }\n * ```\n */\n async getReferrerLeaderboardPage(\n request?: ReferrerLeaderboardPageRequest,\n ): Promise<ReferrerLeaderboardPageResponse> {\n const url = new URL(`/ensanalytics/referrers`, this.options.url);\n\n if (request?.page) url.searchParams.set(\"page\", request.page.toString());\n if (request?.recordsPerPage)\n url.searchParams.set(\"recordsPerPage\", request.recordsPerPage.toString());\n\n const response = await fetch(url);\n\n // ENSNode API should always allow parsing a response as JSON object.\n // If for some reason it's not the case, throw an error.\n let responseData: unknown;\n try {\n responseData = await response.json();\n } catch {\n throw new Error(\"Malformed response data: invalid JSON\");\n }\n\n // The API can return errors with 500 status, but they're still in the\n // PaginatedAggregatedReferrersResponse format with responseCode: 'error'\n // So we don't need to check response.ok here, just deserialize and let\n // the caller handle the responseCode\n\n return deserializeReferrerLeaderboardPageResponse(\n responseData as SerializedReferrerLeaderboardPageResponse,\n );\n }\n\n /**\n * Fetch Referrer Detail\n *\n * Retrieves detailed information about a specific referrer, whether they are on the\n * leaderboard or not.\n *\n * The response data is a discriminated union type with a `type` field:\n *\n * **For referrers on the leaderboard** (`ReferrerDetailRanked`):\n * - `type`: {@link ReferrerDetailTypeIds.Ranked}\n * - `referrer`: The `AwardedReferrerMetrics` from @namehash/ens-referrals\n * - `rules`: The referral program rules\n * - `aggregatedMetrics`: Aggregated metrics for all referrers on the leaderboard\n * - `accurateAsOf`: Unix timestamp indicating when the data was last updated\n *\n * **For referrers NOT on the leaderboard** (`ReferrerDetailUnranked`):\n * - `type`: {@link ReferrerDetailTypeIds.Unranked}\n * - `referrer`: The `UnrankedReferrerMetrics` from @namehash/ens-referrals\n * - `rules`: The referral program rules\n * - `aggregatedMetrics`: Aggregated metrics for all referrers on the leaderboard\n * - `accurateAsOf`: Unix timestamp indicating when the data was last updated\n *\n * @see {@link https://www.npmjs.com/package/@namehash/ens-referrals|@namehash/ens-referrals} for calculation details\n *\n * @param request The referrer address to query\n * @returns {ReferrerDetailResponse} Returns the referrer detail response\n *\n * @throws if the ENSNode request fails\n * @throws if the response data is malformed\n *\n * @example\n * ```typescript\n * // Get referrer detail for a specific address\n * const response = await client.getReferrerDetail({\n * referrer: \"0x1234567890123456789012345678901234567890\"\n * });\n * if (response.responseCode === ReferrerDetailResponseCodes.Ok) {\n * const { type, referrer, rules, aggregatedMetrics, accurateAsOf } = response.data;\n * console.log(type); // ReferrerDetailTypeIds.Ranked or ReferrerDetailTypeIds.Unranked\n * console.log(referrer);\n * console.log(accurateAsOf);\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Use discriminated union to check if referrer is ranked\n * const response = await client.getReferrerDetail({\n * referrer: \"0x1234567890123456789012345678901234567890\"\n * });\n * if (response.responseCode === ReferrerDetailResponseCodes.Ok) {\n * if (response.data.type === ReferrerDetailTypeIds.Ranked) {\n * // TypeScript knows this is ReferrerDetailRanked\n * console.log(`Rank: ${response.data.referrer.rank}`);\n * console.log(`Qualified: ${response.data.referrer.isQualified}`);\n * console.log(`Award Pool Share: ${response.data.referrer.awardPoolShare * 100}%`);\n * } else {\n * // TypeScript knows this is ReferrerDetailUnranked\n * console.log(\"Referrer is not on the leaderboard (no referrals yet)\");\n * }\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Handle error response, ie. when Referrer Detail is not currently available.\n * const response = await client.getReferrerDetail({\n * referrer: \"0x1234567890123456789012345678901234567890\"\n * });\n *\n * if (response.responseCode === ReferrerDetailResponseCodes.Error) {\n * console.error(response.error);\n * console.error(response.errorMessage);\n * }\n * ```\n */\n async getReferrerDetail(request: ReferrerDetailRequest): Promise<ReferrerDetailResponse> {\n const url = new URL(\n `/api/ensanalytics/referrers/${encodeURIComponent(request.referrer)}`,\n this.options.url,\n );\n\n const response = await fetch(url);\n\n // ENSNode API should always allow parsing a response as JSON object.\n // If for some reason it's not the case, throw an error.\n let responseData: unknown;\n try {\n responseData = await response.json();\n } catch {\n throw new Error(\"Malformed response data: invalid JSON\");\n }\n\n // The API can return errors with 500 status, but they're still in the\n // ReferrerDetailResponse format with responseCode: 'error'\n // So we don't need to check response.ok here, just deserialize and let\n // the caller handle the responseCode\n\n return deserializeReferrerDetailResponse(responseData as SerializedReferrerDetailResponse);\n }\n\n /**\n * Fetch ENSNode Registrar Actions\n *\n * Retrieves a paginated list of registrar actions with optional filters.\n *\n * @param request is a request configuration.\n * @param request.page sets the page number to retrieve (1-indexed, default: 1)\n * @param request.recordsPerPage sets the number of records per page (default: 10, max: 100)\n * @param request.filters is an optional request filter configuration.\n * @param request.order sets the order of results in the response by field and direction.\n * @returns {RegistrarActionsResponse}\n *\n * @throws if the ENSNode request fails\n * @throws if the ENSNode API returns an error response\n * @throws if the ENSNode response breaks required invariants\n *\n * @example\n * ```ts\n * import {\n * registrarActionsFilter,\n * ENSNodeClient,\n * } from \"@ensnode/ensnode-sdk\";\n * import { namehash } from \"viem/ens\";\n *\n * const client: ENSNodeClient;\n *\n * // Get first page with default page size (10 records)\n * const response = await client.registrarActions();\n * if (response.responseCode === RegistrarActionsResponseCodes.Ok) {\n * const { registrarActions, pageContext } = response;\n * console.log(registrarActions);\n * console.log(`Page ${pageContext.page} of ${pageContext.totalPages}`);\n * console.log(`Accurate as of: ${response.accurateAsOf}`);\n * }\n *\n * // Get second page with 25 records per page\n * const response = await client.registrarActions({\n * page: 2,\n * recordsPerPage: 25,\n * });\n *\n * // get latest registrar action records associated with\n * // subregistry managing `eth` name\n * await client.registrarActions({\n * filters: [registrarActionsFilter.byParentNode(namehash('eth'))],\n * });\n *\n * // get latest registrar action records which include referral info\n * await client.registrarActions({\n * filters: [registrarActionsFilter.withReferral(true)],\n * });\n *\n * // get latest registrar action records for a specific decoded referrer\n * await client.registrarActions({\n * filters: [registrarActionsFilter.byDecodedReferrer(\"0x1234567890123456789012345678901234567890\")],\n * });\n *\n * // get latest 10 registrar action records associated with\n * // subregistry managing `base.eth` name\n * await client.registrarActions({\n * filters: [registrarActionsFilter.byParentNode(namehash('base.eth'))],\n * recordsPerPage: 10\n * });\n *\n * // get registrar actions within a specific time range\n * const beginTimestamp = 1764547200; // Dec 1, 2025, 00:00:00 UTC\n * const endTimestamp = 1767225600; // Jan 1, 2026, 00:00:00 UTC\n * await client.registrarActions({\n * filters: [\n * registrarActionsFilter.beginTimestamp(beginTimestamp),\n * registrarActionsFilter.endTimestamp(endTimestamp),\n * ],\n * });\n *\n * // get registrar actions from a specific timestamp onwards\n * await client.registrarActions({\n * filters: [registrarActionsFilter.beginTimestamp(1764547200)],\n * });\n *\n * // get registrar actions up to a specific timestamp\n * await client.registrarActions({\n * filters: [registrarActionsFilter.endTimestamp(1767225600)],\n * });\n * ```\n */\n async registrarActions(request: RegistrarActionsRequest = {}): Promise<RegistrarActionsResponse> {\n const buildUrlPath = (filters: RegistrarActionsFilter[] | undefined) => {\n const bySubregistryNodeFilter = filters?.find(\n (f) => f.filterType === RegistrarActionsFilterTypes.BySubregistryNode,\n );\n\n return bySubregistryNodeFilter\n ? new URL(`/api/registrar-actions/${bySubregistryNodeFilter.value}`, this.options.url)\n : new URL(`/api/registrar-actions`, this.options.url);\n };\n\n const buildWithReferralArg = (filters: RegistrarActionsFilter[] | undefined) => {\n const withReferralFilter = filters?.find(\n (f) => f.filterType === RegistrarActionsFilterTypes.WithEncodedReferral,\n );\n\n return withReferralFilter ? { key: \"withReferral\", value: \"true\" } : null;\n };\n\n const buildDecodedReferrerArg = (filters: RegistrarActionsFilter[] | undefined) => {\n const decodedReferrerFilter = filters?.find(\n (f) => f.filterType === RegistrarActionsFilterTypes.ByDecodedReferrer,\n );\n\n return decodedReferrerFilter\n ? { key: \"decodedReferrer\", value: decodedReferrerFilter.value }\n : null;\n };\n\n const buildBeginTimestampArg = (filters: RegistrarActionsFilter[] | undefined) => {\n const beginTimestampFilter = filters?.find(\n (f) => f.filterType === RegistrarActionsFilterTypes.BeginTimestamp,\n );\n\n return beginTimestampFilter\n ? { key: \"beginTimestamp\", value: beginTimestampFilter.value.toString() }\n : null;\n };\n\n const buildEndTimestampArg = (filters: RegistrarActionsFilter[] | undefined) => {\n const endTimestampFilter = filters?.find(\n (f) => f.filterType === RegistrarActionsFilterTypes.EndTimestamp,\n );\n\n return endTimestampFilter\n ? { key: \"endTimestamp\", value: endTimestampFilter.value.toString() }\n : null;\n };\n\n const buildOrderArg = (order: RegistrarActionsOrder) => {\n switch (order) {\n case RegistrarActionsOrders.LatestRegistrarActions: {\n const [field, direction] = order.split(\"=\");\n return {\n key: `sort[${field}]`,\n value: `${direction}`,\n };\n }\n }\n };\n\n const url = buildUrlPath(request.filters);\n\n if (request.order) {\n const orderArgs = buildOrderArg(request.order);\n\n url.searchParams.set(orderArgs.key, orderArgs.value);\n }\n\n if (request.page) {\n url.searchParams.set(\"page\", request.page.toString());\n }\n\n if (request.recordsPerPage) {\n url.searchParams.set(\"recordsPerPage\", request.recordsPerPage.toString());\n }\n\n const referralArg = buildWithReferralArg(request.filters);\n\n if (referralArg) {\n url.searchParams.set(referralArg.key, referralArg.value);\n }\n\n const decodedReferrerArg = buildDecodedReferrerArg(request.filters);\n\n if (decodedReferrerArg) {\n url.searchParams.set(decodedReferrerArg.key, decodedReferrerArg.value);\n }\n\n const beginTimestampArg = buildBeginTimestampArg(request.filters);\n\n if (beginTimestampArg) {\n url.searchParams.set(beginTimestampArg.key, beginTimestampArg.value);\n }\n\n const endTimestampArg = buildEndTimestampArg(request.filters);\n\n if (endTimestampArg) {\n url.searchParams.set(endTimestampArg.key, endTimestampArg.value);\n }\n\n const response = await fetch(url);\n\n // ENSNode API should always allow parsing a response as JSON object.\n // If for some reason it's not the case, throw an error.\n let responseData: unknown;\n try {\n responseData = await response.json();\n } catch {\n throw new Error(\"Malformed response data: invalid JSON\");\n }\n\n // handle response errors accordingly\n if (!response.ok) {\n // check for a generic errorResponse\n let errorResponse: ErrorResponse | undefined;\n try {\n errorResponse = deserializeErrorResponse(responseData);\n } catch {\n // if errorResponse could not be determined,\n // it means the response includes data\n console.log(\"Registrar Actions API: handling a known server error.\");\n }\n\n // however, if errorResponse was defined,\n // throw an error with the generic server error message\n if (typeof errorResponse !== \"undefined\") {\n throw new Error(`Fetching ENSNode Registrar Actions Failed: ${errorResponse.message}`);\n }\n }\n\n return deserializeRegistrarActionsResponse(responseData as SerializedRegistrarActionsResponse);\n }\n\n /**\n * Fetch Name Tokens for requested name.\n *\n * @param request.name - Name for which Name Tokens will be fetched.\n * @returns {NameTokensResponse}\n *\n * @throws if the ENSNode request fails\n * @throws if the ENSNode API returns an error response\n * @throws if the ENSNode response breaks required invariants\n *\n * @example\n * ```ts\n * import {\n * ENSNodeClient,\n * } from \"@ensnode/ensnode-sdk\";\n * import { namehash } from \"viem/ens\";\n *\n * const client: ENSNodeClient;\n *\n * // get latest name token records from the indexed subregistry based on the requested name\n * const response = await client.nameTokens({\n * name: \"vitalik.eth\"\n * });\n *\n * const response = await client.nameTokens({\n * domainId: \"0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835\" // namehash('vitalik.eth')\n * })\n * ```\n */\n async nameTokens(request: NameTokensRequest): Promise<NameTokensResponse> {\n const url = new URL(`/api/name-tokens`, this.options.url);\n\n if (request.name !== undefined) {\n url.searchParams.set(\"name\", request.name);\n } else if (request.domainId !== undefined) {\n url.searchParams.set(\"domainId\", request.domainId);\n }\n\n const response = await fetch(url);\n\n // ENSNode API should always allow parsing a response as JSON object.\n // If for some reason it's not the case, throw an error.\n let responseData: unknown;\n try {\n responseData = await response.json();\n } catch {\n throw new Error(\"Malformed response data: invalid JSON\");\n }\n\n // handle response errors accordingly\n if (!response.ok) {\n // check for a generic errorResponse\n let errorResponse: ErrorResponse | undefined;\n try {\n errorResponse = deserializeErrorResponse(responseData);\n } catch {\n // if errorResponse could not be determined,\n // it means the response includes data\n console.log(\"Name Tokens API: handling a known server error.\");\n }\n\n // however, if errorResponse was defined,\n // throw an error with the generic server error message\n if (typeof errorResponse !== \"undefined\") {\n throw new Error(`Fetching ENSNode Name Tokens Failed: ${errorResponse.message}`);\n }\n }\n\n return deserializedNameTokensResponse(responseData as SerializedNameTokensResponse);\n }\n}\n","import { type Address, hexToBigInt } from \"viem\";\n\nimport {\n type AccountId,\n AssetNamespaces,\n formatAccountId,\n formatAssetId,\n type LabelHash,\n type Node,\n} from \"@ensnode/ensnode-sdk\";\n\nimport type {\n CanonicalId,\n DomainId,\n ENSv1DomainId,\n ENSv2DomainId,\n PermissionsId,\n PermissionsResourceId,\n PermissionsUserId,\n RegistrationId,\n RegistryId,\n RenewalId,\n ResolverId,\n ResolverRecordsId,\n} from \"./ids\";\n\n/**\n * Formats and brands an AccountId as a RegistryId.\n */\nexport const makeRegistryId = (accountId: AccountId) => formatAccountId(accountId) as RegistryId;\n\n/**\n * Makes an ENSv1 Domain Id given the ENSv1 Domain's `node`\n */\nexport const makeENSv1DomainId = (node: Node) => node as ENSv1DomainId;\n\n/**\n * Makes an ENSv2 Domain Id given the parent `registry` and the domain's `canonicalId`.\n */\nexport const makeENSv2DomainId = (registry: AccountId, canonicalId: CanonicalId) =>\n formatAssetId({\n assetNamespace: AssetNamespaces.ERC1155,\n contract: registry,\n tokenId: canonicalId,\n }) as ENSv2DomainId;\n\n/**\n * Masks the lower 32 bits of `num`.\n */\nconst maskLower32Bits = (num: bigint) => num ^ (num & 0xffffffffn);\n\n/**\n * Computes a Domain's {@link CanonicalId} given its tokenId or LabelHash as `input`.\n */\nexport const getCanonicalId = (input: bigint | LabelHash): CanonicalId => {\n if (typeof input === \"bigint\") return maskLower32Bits(input);\n return getCanonicalId(hexToBigInt(input));\n};\n\n/**\n * Formats and brands an AccountId as a PermissionsId.\n */\nexport const makePermissionsId = (contract: AccountId) =>\n formatAccountId(contract) as PermissionsId;\n\n/**\n * Constructs a PermissionsResourceId for a given `contract`'s `resource`.\n */\nexport const makePermissionsResourceId = (contract: AccountId, resource: bigint) =>\n `${makePermissionsId(contract)}/${resource}` as PermissionsResourceId;\n\n/**\n * Constructs a PermissionsUserId for a given `contract`'s `resource`'s `user`.\n */\nexport const makePermissionsUserId = (contract: AccountId, resource: bigint, user: Address) =>\n `${makePermissionsId(contract)}/${resource}/${user}` as PermissionsUserId;\n\n/**\n * Formats and brands an AccountId as a ResolverId.\n */\nexport const makeResolverId = (contract: AccountId) => formatAccountId(contract) as ResolverId;\n\n/**\n * Constructs a ResolverRecordsId for a given `node` under `resolver`.\n */\nexport const makeResolverRecordsId = (resolver: AccountId, node: Node) =>\n `${makeResolverId(resolver)}/${node}` as ResolverRecordsId;\n\n/**\n * Constructs a RegistrationId for a `domainId`'s latest Registration.\n *\n * @dev See apps/ensindexer/src/lib/ensv2/registration-db-helpers.ts for more info.\n */\nexport const makeLatestRegistrationId = (domainId: DomainId) =>\n `${domainId}/latest` as RegistrationId;\n\n/**\n * Constructs a RegistrationId for a `domainId`'s `index`'thd Registration.\n *\n * @dev See apps/ensindexer/src/lib/ensv2/registration-db-helpers.ts for more info.\n */\nexport const makeRegistrationId = (domainId: DomainId, index: number = 0) =>\n `${domainId}/${index}` as RegistrationId;\n\n/**\n * Constructs a RenewalId for a `domainId`'s `registrationIndex`thd Registration's latest Renewal.\n *\n * @dev Forces usage of the 'pinned' RegistrationId to avoid collisions, see\n * apps/ensindexer/src/lib/ensv2/registration-db-helpers.ts for more info.\n */\nexport const makeLatestRenewalId = (domainId: DomainId, registrationIndex: number) =>\n `${makeRegistrationId(domainId, registrationIndex)}/latest` as RenewalId;\n\n/**\n * Constructs a RenewalId for a `domainId`'s `registrationIndex`thd Registration's `index`'thd Renewal.\n *\n * @dev Forces usage of the 'pinned' RegistrationId to avoid collisions, see\n * apps/ensindexer/src/lib/ensv2/registration-db-helpers.ts for more info.\n */\nexport const makeRenewalId = (domainId: DomainId, registrationIndex: number, index: number = 0) =>\n `${makeRegistrationId(domainId, registrationIndex)}/${index}` as RenewalId;\n","import type { Address } from \"viem\";\n\nimport { type ENSNamespaceId, getENSRootChainId } from \"@ensnode/datasources\";\n\nimport type { DefaultableChainId } from \"../shared\";\nimport {\n type Identity,\n ResolutionStatusIds,\n type ResolvedIdentity,\n type UnresolvedIdentity,\n} from \"./types\";\n\n/**\n * Builds an {@link UnresolvedIdentity} for the provided {@link Address},\n * {@link DefaultableChainId} and {@link ENSNamespaceId}.\n *\n * If no `chainId` is provided, uses the ENS Root Chain Id for the provided\n * `namespaceId`.\n */\nexport function buildUnresolvedIdentity(\n address: Address,\n namespaceId: ENSNamespaceId,\n chainId?: DefaultableChainId,\n): UnresolvedIdentity {\n return {\n resolutionStatus: ResolutionStatusIds.Unresolved,\n chainId: chainId ?? getENSRootChainId(namespaceId),\n address,\n };\n}\n\n/**\n * Returns whether the provided {@link Identity} is a {@link ResolvedIdentity}.\n *\n * @param identity - The {@link Identity} to check.\n * @returns Whether the provided {@link Identity} is a {@link ResolvedIdentity}.\n */\nexport function isResolvedIdentity(identity: Identity): identity is ResolvedIdentity {\n return identity.resolutionStatus !== ResolutionStatusIds.Unresolved;\n}\n","import type { Address } from \"viem\";\n\nimport type { Name } from \"../ens\";\nimport type { DefaultableChainId } from \"../shared\";\n\n/**\n * The resolution status for an `Identity`.\n */\nexport const ResolutionStatusIds = {\n /**\n * Represents that the `Identity` is not resolved yet.\n */\n Unresolved: \"unresolved\",\n\n /**\n * Represents that resolution of the `Identity` resulted in a named identity.\n */\n Named: \"named\",\n\n /**\n * Represents that resolution of the `Identity` resulted in an unnamed identity.\n */\n Unnamed: \"unnamed\",\n\n /**\n * Represents that attempted resolution of the `Identity` resulted in an error\n * and therefore it is unknown if the `Identity` resolves to a named or unnamed identity.\n */\n Unknown: \"unknown\",\n} as const;\n\n/**\n * The derived string union of possible {@link ResolutionStatusIds}.\n */\nexport type ResolutionStatusId = (typeof ResolutionStatusIds)[keyof typeof ResolutionStatusIds];\n\n/**\n * Represents an {@link Identity} that has not become a {@link ResolvedIdentity} yet.\n *\n * Invariants:\n * - `resolutionStatus` is always {@link ResolutionStatusIds.Unresolved}.\n */\nexport interface UnresolvedIdentity {\n resolutionStatus: typeof ResolutionStatusIds.Unresolved;\n\n /**\n * The {@link DefaultableChainId} for an ENSIP-19 primary name lookup of the\n * identity associated with `address`.\n */\n chainId: DefaultableChainId;\n\n /**\n * The {@link Address} of the identity.\n */\n address: Address;\n}\n\n/**\n * Represents an `Identity` that resolved to a primary name.\n *\n * Invariants:\n * - `resolutionStatus` is always {@link ResolutionStatusIds.Named}.\n */\nexport interface NamedIdentity {\n resolutionStatus: typeof ResolutionStatusIds.Named;\n\n /**\n * The {@link DefaultableChainId} for an ENSIP-19 primary name lookup of the\n * identity associated with `address`.\n */\n chainId: DefaultableChainId;\n\n /**\n * The address of the identity.\n */\n address: Address;\n\n /**\n * The ENSIP-19 primary name lookup result of `address` on `chainId`.\n */\n name: Name;\n}\n\n/**\n * Represents an `Identity` that did not resolve to a primary name.\n *\n * Invariants:\n * - `resolutionStatus` is always {@link ResolutionStatusIds.Unnamed}.\n * - `name` is always `null`.\n */\nexport interface UnnamedIdentity {\n resolutionStatus: typeof ResolutionStatusIds.Unnamed;\n\n /**\n * The {@link DefaultableChainId} for an ENSIP-19 primary name lookup of the\n * identity associated with `address`.\n */\n chainId: DefaultableChainId;\n\n /**\n * The address of the identity.\n */\n address: Address;\n\n /**\n * The ENSIP-19 primary name lookup result of `address` on `chainId`.\n */\n name: null;\n}\n\n/**\n * Represents an `Identity` that was attempted to be resolved but the resolution attempt\n * resulted in an error and therefore it is unknown if the `Identity` resolves to a named\n * or unnamed identity.\n *\n * Invariants:\n * - `resolutionStatus` is always {@link ResolutionStatusIds.Unknown}.\n */\nexport interface UnknownIdentity {\n resolutionStatus: typeof ResolutionStatusIds.Unknown;\n\n /**\n * The {@link DefaultableChainId} for an ENSIP-19 primary name lookup of the\n * identity associated with `address`.\n */\n chainId: DefaultableChainId;\n\n /**\n * The address of the identity.\n */\n address: Address;\n}\n\n/**\n * Represents an ENSIP-19 identity resolution result.\n *\n * Use the `resolutionStatus` field to determine the specific type interpretation\n * at runtime.\n */\nexport type ResolvedIdentity = NamedIdentity | UnnamedIdentity | UnknownIdentity;\n\n/**\n * Represents an ENSIP-19 identity resolution (which may or not have been\n * resolved to a result yet).\n *\n * Use the `resolutionStatus` field to determine the specific type interpretation\n * at runtime.\n */\nexport type Identity = UnresolvedIdentity | ResolvedIdentity;\n","import { mainnet } from \"viem/chains\";\n\nimport { type ENSNamespaceId, getENSRootChainId } from \"@ensnode/datasources\";\n\nimport { DEFAULT_EVM_CHAIN_ID } from \"../ens\";\nimport type { ChainId, DefaultableChainId } from \"../shared\";\n\n/**\n * Gets the \"chainId param\" that should be used for a primary name resolution\n * request.\n *\n * ENSIP-19 defines special rules for the \"chainId param\" used\n * in primary name resolutions for the case that the `chainId` is the\n * ENS Root Chain Id for the provided `namespaceId`.\n *\n * Whenever this case happens, ENSIP-19 requires that the\n * \"chainId param\" is always set to chainId: 1 (mainnet), even if the\n * `chainId` where the primary name lookup is actually happening\n * on a non-mainnet ENS Root Chain, such as on a testnet or\n * the ens-test-env.\n *\n * @param namespaceId The namespace id for the primary name lookup.\n * @param chainId The chain id where the primary name lookup will actually happen.\n * @returns The \"chainId param\" that should be used for the primary name lookup.\n */\nexport const getResolvePrimaryNameChainIdParam = (\n chainId: DefaultableChainId,\n namespaceId: ENSNamespaceId,\n): DefaultableChainId => {\n const ensRootChainId = getENSRootChainId(namespaceId);\n return chainId === ensRootChainId ? mainnet.id : chainId;\n};\n\n/**\n * Translates a `DefaultableChainId` a `ChainId`\n * such that if the provided `chainId` is `DEFAULT_EVM_CHAIN_ID`,\n * the `ChainId` of the ENS Root Chain for the provided `namespaceId` is returned.\n *\n * @param chainId The `DefaultableChainId` to translate.\n * @param namespaceId The namespace id for the translation.\n * @returns the translated `ChainId`.\n */\nexport const translateDefaultableChainIdToChainId = (\n chainId: DefaultableChainId,\n namespaceId: ENSNamespaceId,\n): ChainId => {\n return chainId === DEFAULT_EVM_CHAIN_ID ? getENSRootChainId(namespaceId) : chainId;\n};\n","import type { CoinType } from \"../ens\";\n\n/**\n * Encodes a selection of Resolver records in the context of a specific Name.\n */\nexport interface ResolverRecordsSelection {\n /**\n * Whether to fetch the name's `name` record. This value is primarily used in the context of\n * Reverse Resolution.\n *\n * @see https://docs.ens.domains/ensip/19/#reverse-resolution\n */\n name?: boolean;\n\n /**\n * Which coinTypes to fetch address records for.\n */\n addresses?: CoinType[];\n\n /**\n * Which keys to fetch text records for.\n */\n texts?: string[];\n\n // TODO: include others as/if necessary\n}\n\nexport const isSelectionEmpty = (selection: ResolverRecordsSelection) =>\n !selection.name && !selection.addresses?.length && !selection.texts?.length;\n","export const PROTOCOL_ATTRIBUTE_PREFIX = \"ens\";\nexport const ATTR_PROTOCOL_NAME = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol`;\nexport const ATTR_PROTOCOL_STEP = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol.step`;\nexport const ATTR_PROTOCOL_STEP_RESULT = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol.step.result`;\n\n/**\n * Identifiers for each traceable ENS protocol.\n */\nexport enum TraceableENSProtocol {\n ForwardResolution = \"forward-resolution\",\n ReverseResolution = \"reverse-resolution\",\n}\n\n/**\n * Encodes the set of well-known steps in the ENS Forward Resolution protocol.\n */\nexport enum ForwardResolutionProtocolStep {\n Operation = \"forward-resolution\",\n FindResolver = \"find-resolver\",\n ActiveResolverExists = \"active-resolver-exists\",\n AccelerateENSIP19ReverseResolver = \"accelerate-ensip-19-reverse-resolver\",\n AccelerateKnownOffchainLookupResolver = \"accelerate-known-offchain-lookup-resolver\",\n AccelerateKnownOnchainStaticResolver = \"accelerate-known-onchain-static-resolver\",\n RequireResolver = \"require-resolver\",\n ExecuteResolveCalls = \"execute-resolve-calls\",\n}\n\n/**\n * Encodes the set of well-known steps in the ENS Reverse Resolution protocol.\n */\nexport enum ReverseResolutionProtocolStep {\n Operation = \"reverse-resolution\",\n ResolveReverseName = \"resolve-reverse-name\",\n NameRecordExists = \"name-record-exists-check\",\n ForwardResolveAddressRecord = \"forward-resolve-address-record\",\n VerifyResolvedAddressMatchesAddress = \"verify-resolved-address-matches-address\",\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,aAAwC;;;ACAxC,IAAAC,aAAkB;;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","names":["import_v4","import_v4","import_v4","import_v4","import_viem","import_datasources","_coinTypeToEvmChainId","_evmChainIdToCoinType","import_viem","import_viem","import_viem","import_viem","import_viem","import_viem","labelToLabelHash","CaipAccountId","import_getUnixTime","import_datasources","import_viem","import_viem","import_viem","import_ens","import_viem","import_datasources","import_caip","CaipAccountId","CaipAssetId","import_datasources","PluginName","import_v4","import_v4","import_viem","isSubgraphCompatible","import_v4","import_v4","import_v4","import_v4","z","import_v4","import_viem","import_v4","import_viem","import_v4","import_caip","import_viem","import_v4","import_viem","import_datasources","z","CaipAssetId","z","import_v4","z","z","import_v4","import_ens","import_v4","import_viem","import_viem","import_viem","import_v4","import_v4","z","z","withReferral","import_datasources","import_datasources","import_datasources","import_v4","import_v4","import_v4","z","import_viem","import_datasources","import_datasources","TraceableENSProtocol","ForwardResolutionProtocolStep","ReverseResolutionProtocolStep"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/ensapi/config/deserialize.ts","../src/ensapi/config/zod-schemas.ts","../src/ensindexer/config/zod-schemas.ts","../src/shared/account-id.ts","../src/shared/address.ts","../src/shared/cache/lru-cache.ts","../src/shared/cache/swr-cache.ts","../src/shared/deserialize.ts","../src/shared/zod-schemas.ts","../src/ens/index.ts","../src/ens/coin-type.ts","../src/ens/constants.ts","../src/ens/dns-encoded-name.ts","../src/ens/labelhash.ts","../src/ens/encode-labelhash.ts","../src/ens/fuses.ts","../src/ens/is-normalized.ts","../src/ens/names.ts","../src/ens/parse-reverse-name.ts","../src/ens/reverse-name.ts","../src/ens/subname-helpers.ts","../src/ens/types.ts","../src/shared/currencies.ts","../src/shared/interpretation/reinterpretation.ts","../src/shared/datetime.ts","../src/shared/cache/ttl-cache.ts","../src/shared/collections.ts","../src/shared/datasource-contract.ts","../src/shared/interpretation/interpret-address.ts","../src/shared/interpretation/interpret-record-values.ts","../src/shared/null-bytes.ts","../src/shared/interpretation/interpret-tokenid.ts","../src/shared/interpretation/interpreted-names-and-labels.ts","../src/shared/labelhash.ts","../src/shared/numbers.ts","../src/shared/root-registry.ts","../src/shared/serialize.ts","../src/shared/types.ts","../src/shared/url.ts","../src/ensindexer/config/is-subgraph-compatible.ts","../src/ensindexer/config/types.ts","../src/ensindexer/config/validations.ts","../src/shared/config/thegraph.ts","../src/ensindexer/config/deserialize.ts","../src/ensindexer/config/label-utils.ts","../src/ensindexer/config/labelset-utils.ts","../src/ensindexer/config/parsing.ts","../src/ensindexer/config/serialize.ts","../src/ensindexer/indexing-status/deserialize.ts","../src/ensindexer/indexing-status/zod-schemas.ts","../src/ensindexer/indexing-status/types.ts","../src/shared/block-ref.ts","../src/ensindexer/indexing-status/helpers.ts","../src/ensindexer/indexing-status/validations.ts","../src/ensindexer/indexing-status/projection.ts","../src/ensindexer/indexing-status/serialize.ts","../src/ensapi/config/serialize.ts","../src/api/config/deserialize.ts","../src/api/config/serialize.ts","../src/api/indexing-status/deserialize.ts","../src/api/indexing-status/zod-schemas.ts","../src/api/indexing-status/response.ts","../src/api/indexing-status/serialize.ts","../src/api/name-tokens/deserialize.ts","../src/api/name-tokens/zod-schemas.ts","../src/tokenscope/assets.ts","../src/tokenscope/zod-schemas.ts","../src/tokenscope/name-token.ts","../src/api/shared/errors/zod-schemas.ts","../src/api/name-tokens/response.ts","../src/api/name-tokens/prerequisites.ts","../src/api/name-tokens/serialize.ts","../src/api/registrar-actions/deserialize.ts","../src/api/registrar-actions/zod-schemas.ts","../../ens-referrals/src/address.ts","../../ens-referrals/src/encoding.ts","../../ens-referrals/src/leaderboard-page.ts","../../ens-referrals/src/link.ts","../../ens-referrals/src/referrer-detail.ts","../src/registrars/zod-schemas.ts","../src/registrars/registrar-action.ts","../src/api/shared/pagination/zod-schemas.ts","../src/api/shared/pagination/request.ts","../src/api/registrar-actions/response.ts","../src/api/registrar-actions/request.ts","../src/api/registrar-actions/filters.ts","../src/api/registrar-actions/prerequisites.ts","../src/registrars/basenames-subregistry.ts","../src/registrars/ethnames-subregistry.ts","../src/registrars/lineanames-subregistry.ts","../src/registrars/registration-expiration.ts","../src/api/registrar-actions/serialize.ts","../src/api/shared/errors/deserialize.ts","../src/api/shared/pagination/build-page-context.ts","../src/client-error.ts","../src/ensanalytics/deserialize.ts","../src/ensanalytics/zod-schemas.ts","../src/ensanalytics/types.ts","../src/ensanalytics/serialize.ts","../src/client.ts","../src/ensv2/ids-lib.ts","../src/identity/identity.ts","../src/identity/types.ts","../src/resolution/ensip19-chainid.ts","../src/resolution/resolver-records-selection.ts","../src/tracing/ens-protocol-tracing.ts"],"sourcesContent":["export * from \"./api\";\nexport { type ClientOptions, ENSNodeClient } from \"./client\";\nexport * from \"./client-error\";\nexport * from \"./ens\";\nexport * from \"./ensanalytics\";\nexport * from \"./ensapi\";\nexport * from \"./ensindexer\";\nexport * from \"./ensrainbow\";\nexport * from \"./ensv2\";\nexport * from \"./identity\";\nexport * from \"./registrars\";\nexport * from \"./resolution\";\nexport * from \"./shared\";\nexport * from \"./tokenscope\";\nexport * from \"./tracing\";\n","import { prettifyError, ZodError } from \"zod/v4\";\n\nimport type { SerializedENSApiPublicConfig } from \"./serialized-types\";\nimport type { ENSApiPublicConfig } from \"./types\";\nimport { makeENSApiPublicConfigSchema } from \"./zod-schemas\";\n\n/**\n * Deserialize a {@link ENSApiPublicConfig} object.\n */\nexport function deserializeENSApiPublicConfig(\n maybeConfig: SerializedENSApiPublicConfig,\n valueLabel?: string,\n): ENSApiPublicConfig {\n const schema = makeENSApiPublicConfigSchema(valueLabel);\n try {\n return schema.parse(maybeConfig);\n } catch (error) {\n if (error instanceof ZodError) {\n throw new Error(`Cannot deserialize ENSApiPublicConfig:\\n${prettifyError(error)}\\n`);\n }\n\n throw error;\n }\n}\n","import { z } from \"zod/v4\";\n\nimport { makeENSIndexerPublicConfigSchema } from \"../../ensindexer/config/zod-schemas\";\nimport {\n TheGraphCannotFallbackReasonSchema,\n TheGraphFallbackSchema,\n} from \"../../shared/config/thegraph\";\n\nexport { TheGraphCannotFallbackReasonSchema, TheGraphFallbackSchema };\n\n/**\n * Create a Zod schema for validating a serialized ENSApiPublicConfig.\n *\n * @param valueLabel - Optional label for the value being validated (used in error messages)\n */\nexport function makeENSApiPublicConfigSchema(valueLabel?: string) {\n const label = valueLabel ?? \"ENSApiPublicConfig\";\n\n return z.strictObject({\n version: z.string().min(1, `${label}.version must be a non-empty string`),\n theGraphFallback: TheGraphFallbackSchema,\n ensIndexerPublicConfig: makeENSIndexerPublicConfigSchema(`${label}.ensIndexerPublicConfig`),\n });\n}\n","/**\n * All zod schemas we define must remain internal implementation details.\n * We want the freedom to move away from zod in the future without impacting\n * any users of the ensnode-sdk package.\n *\n * The only way to share Zod schemas is to re-export them from\n * `./src/internal.ts` file.\n */\nimport { z } from \"zod/v4\";\n\nimport { uniq } from \"../../shared\";\nimport {\n makeChainIdSchema,\n makeENSNamespaceIdSchema,\n makeNonNegativeIntegerSchema,\n makePositiveIntegerSchema,\n} from \"../../shared/zod-schemas\";\nimport type { ZodCheckFnInput } from \"../../shared/zod-types\";\nimport { isSubgraphCompatible } from \"./is-subgraph-compatible\";\nimport type { ENSIndexerPublicConfig } from \"./types\";\nimport { PluginName } from \"./types\";\nimport { invariant_ensDbVersionIsSameAsEnsIndexerVersion } from \"./validations\";\n\n/**\n * Makes a schema for parsing {@link IndexedChainIds}.\n */\nexport const makeIndexedChainIdsSchema = (valueLabel: string = \"Indexed Chain IDs\") =>\n z\n .array(makeChainIdSchema(valueLabel), {\n error: `${valueLabel} must be an array.`,\n })\n .min(1, { error: `${valueLabel} list must include at least one element.` })\n .transform((v) => new Set(v));\n\n/**\n * Makes a schema for parsing a list of strings that (for future-proofing)\n * may or may not be current {@link PluginName} values.\n *\n * The list is guaranteed to include at least one string and no duplicates.\n */\nexport const makePluginsListSchema = (valueLabel: string = \"Plugins\") =>\n z\n .array(z.string(), {\n error: `${valueLabel} must be a list of strings.`,\n })\n .min(1, {\n error: `${valueLabel} must be a list of strings with at least one string value`,\n })\n .refine((arr) => arr.length === uniq(arr).length, {\n error: `${valueLabel} cannot contain duplicate values.`,\n });\n\n/**\n * Makes a schema for parsing a name for a database schema.\n *\n * The name is guaranteed to be a non-empty string.\n */\nexport const makeDatabaseSchemaNameSchema = (valueLabel: string = \"Database schema name\") =>\n z\n .string({ error: `${valueLabel} must be a string` })\n .trim()\n .nonempty({\n error: `${valueLabel} is required and must be a non-empty string.`,\n });\n\n/**\n * Makes a schema for parsing a label set ID.\n *\n * The label set ID is guaranteed to be a string between 1-50 characters\n * containing only lowercase letters (a-z) and hyphens (-).\n *\n * @param valueLabel - The label to use in error messages (e.g., \"Label set ID\", \"LABEL_SET_ID\")\n */\nexport const makeLabelSetIdSchema = (valueLabel: string) => {\n return z\n .string({ error: `${valueLabel} must be a string` })\n .min(1, { error: `${valueLabel} must be 1-50 characters long` })\n .max(50, { error: `${valueLabel} must be 1-50 characters long` })\n .regex(/^[a-z-]+$/, {\n error: `${valueLabel} can only contain lowercase letters (a-z) and hyphens (-)`,\n });\n};\n\n/**\n * Makes a schema for parsing a label set version.\n *\n * The label set version is guaranteed to be a non-negative integer.\n *\n * @param valueLabel - The label to use in error messages (e.g., \"Label set version\", \"LABEL_SET_VERSION\")\n\n */\nexport const makeLabelSetVersionSchema = (valueLabel: string) => {\n return z.coerce\n .number({ error: `${valueLabel} must be an integer.` })\n .pipe(makeNonNegativeIntegerSchema(valueLabel));\n};\n\n/**\n * Makes a schema for parsing a label set where both label set ID and label set version are required.\n *\n * @param valueLabel - The label to use in error messages (e.g., \"Label set\", \"LABEL_SET\")\n */\nexport const makeFullyPinnedLabelSetSchema = (valueLabel: string = \"Label set\") => {\n let valueLabelLabelSetId = valueLabel;\n let valueLabelLabelSetVersion = valueLabel;\n if (valueLabel === \"LABEL_SET\") {\n valueLabelLabelSetId = \"LABEL_SET_ID\";\n valueLabelLabelSetVersion = \"LABEL_SET_VERSION\";\n } else {\n valueLabelLabelSetId = `${valueLabel}.labelSetId`;\n valueLabelLabelSetVersion = `${valueLabel}.labelSetVersion`;\n }\n return z.object({\n labelSetId: makeLabelSetIdSchema(valueLabelLabelSetId),\n labelSetVersion: makeLabelSetVersionSchema(valueLabelLabelSetVersion),\n });\n};\n\nconst makeNonEmptyStringSchema = (valueLabel: string = \"Value\") =>\n z.string().nonempty({ error: `${valueLabel} must be a non-empty string.` });\n\nexport const makeENSIndexerVersionInfoSchema = (valueLabel: string = \"Value\") =>\n z\n .strictObject(\n {\n nodejs: makeNonEmptyStringSchema(),\n ponder: makeNonEmptyStringSchema(),\n ensDb: makeNonEmptyStringSchema(),\n ensIndexer: makeNonEmptyStringSchema(),\n ensNormalize: makeNonEmptyStringSchema(),\n ensRainbow: makeNonEmptyStringSchema(),\n ensRainbowSchema: makePositiveIntegerSchema(),\n },\n {\n error: `${valueLabel} must be a valid ENSIndexerVersionInfo object.`,\n },\n )\n .check(invariant_ensDbVersionIsSameAsEnsIndexerVersion);\n\n// Invariant: If config.isSubgraphCompatible, the config must pass isSubgraphCompatible(config)\nexport function invariant_isSubgraphCompatibleRequirements(\n ctx: ZodCheckFnInput<\n Pick<ENSIndexerPublicConfig, \"namespace\" | \"plugins\" | \"isSubgraphCompatible\" | \"labelSet\">\n >,\n) {\n const { value: config } = ctx;\n\n if (config.isSubgraphCompatible && !isSubgraphCompatible(config)) {\n ctx.issues.push({\n code: \"custom\",\n input: config,\n message: `'isSubgraphCompatible' requires only the '${PluginName.Subgraph}' plugin to be active and labelSet must be {labelSetId: \"subgraph\", labelSetVersion: 0}`,\n });\n }\n}\n\n/**\n * ENSIndexer Public Config Schema\n *\n * Makes a Zod schema definition for validating all important settings used\n * during runtime of the ENSIndexer instance.\n */\nexport const makeENSIndexerPublicConfigSchema = (valueLabel: string = \"ENSIndexerPublicConfig\") =>\n z\n .object({\n labelSet: makeFullyPinnedLabelSetSchema(`${valueLabel}.labelSet`),\n indexedChainIds: makeIndexedChainIdsSchema(`${valueLabel}.indexedChainIds`),\n isSubgraphCompatible: z.boolean({ error: `${valueLabel}.isSubgraphCompatible` }),\n namespace: makeENSNamespaceIdSchema(`${valueLabel}.namespace`),\n plugins: makePluginsListSchema(`${valueLabel}.plugins`),\n databaseSchemaName: makeDatabaseSchemaNameSchema(`${valueLabel}.databaseSchemaName`),\n versionInfo: makeENSIndexerVersionInfoSchema(`${valueLabel}.versionInfo`),\n })\n /**\n * Validations\n *\n * All required data validations must be performed below.\n */\n .check(invariant_isSubgraphCompatibleRequirements);\n","import { isAddressEqual } from \"viem\";\n\nimport type { AccountId } from \"./types\";\n\n/**\n * Determines where the provided AccountId values represent the same address on the same chain.\n */\nexport const accountIdEqual = (a: AccountId, b: AccountId): boolean => {\n return a.chainId === b.chainId && isAddressEqual(a.address, b.address);\n};\n","import type { Address } from \"viem\";\n\n/**\n * Converts an EVM address to its lowercase representation.\n *\n * @param address - EVM address to convert.\n * @returns The lowercase representation of the EVM address.\n */\nexport function asLowerCaseAddress(address: Address): Address {\n return address.toLowerCase() as Address;\n}\n","import type { Cache } from \"./cache\";\n\n/**\n * Cache that maps from string -> ValueType with a LRU (least recently used) eviction policy.\n *\n * `get` and `set` are O(1) operations.\n *\n * @link https://en.wikipedia.org/wiki/Cache_replacement_policies#LRU\n */\nexport class LruCache<KeyType extends string, ValueType> implements Cache<KeyType, ValueType> {\n private readonly _cache = new Map<string, ValueType>();\n private readonly _capacity: number;\n\n /**\n * Create a new LRU cache with the given capacity.\n *\n * @param capacity The maximum number of items in the cache. If set to 0, the cache is effectively disabled.\n * @throws Error if capacity is not a non-negative integer.\n */\n public constructor(capacity: number) {\n if (!Number.isInteger(capacity)) {\n throw new Error(\n `LruCache requires capacity to be an integer but a capacity of ${capacity} was requested.`,\n );\n }\n\n if (capacity < 0) {\n throw new Error(\n `LruCache requires a non-negative capacity but a capacity of ${capacity} was requested.`,\n );\n }\n\n this._capacity = capacity;\n }\n\n public set(key: string, value: ValueType) {\n this._cache.set(key, value);\n\n if (this._cache.size > this._capacity) {\n // oldestKey is guaranteed to be defined\n const oldestKey = this._cache.keys().next().value as string;\n this._cache.delete(oldestKey);\n }\n }\n\n public get(key: string) {\n const value = this._cache.get(key);\n if (value) {\n // The key is already in the cache, move it to the end (most recent)\n this._cache.delete(key);\n this._cache.set(key, value);\n }\n return value;\n }\n\n public clear() {\n this._cache.clear();\n }\n\n public get size() {\n return this._cache.size;\n }\n\n public get capacity() {\n return this._capacity;\n }\n}\n","import { secondsToMilliseconds } from \"date-fns\";\nimport { getUnixTime } from \"date-fns/getUnixTime\";\n\nimport { durationBetween } from \"../datetime\";\nimport type { Duration, UnixTimestamp } from \"../types\";\n\n/**\n * Data structure for a single cached result.\n */\ninterface CachedResult<ValueType> {\n /**\n * The cached result of the fn, either its ValueType or Error.\n */\n result: ValueType | Error;\n\n /**\n * Unix timestamp indicating when the cached `result` was generated.\n */\n updatedAt: UnixTimestamp;\n}\n\nexport interface SWRCacheOptions<ValueType> {\n /**\n * The async function generating a value of `ValueType` to wrap with SWR caching. It may throw an\n * Error type.\n */\n fn: () => Promise<ValueType>;\n\n /**\n * Time-to-live duration of a cached result in seconds. After this duration:\n * - the currently cached result is considered \"stale\" but is still retained in the cache\n * until successfully replaced.\n * - Each time the cache is read, if the cached result is \"stale\" and no background\n * revalidation attempt is already in progress, a new background revalidation\n * attempt will be made.\n */\n ttl: Duration;\n\n /**\n * Optional time-to-proactively-revalidate duration in seconds. After a cached result is\n * initialized, and this duration has passed, attempts to asynchronously revalidate\n * the cached result will be proactively made in the background on this interval.\n */\n proactiveRevalidationInterval?: Duration;\n\n /**\n * Optional proactive initialization. Defaults to `false`.\n *\n * If `true`: The SWR cache will proactively initialize itself.\n * If `false`: The SWR cache will lazily wait to initialize itself until the first read.\n */\n proactivelyInitialize?: boolean;\n}\n\n/**\n * Stale-While-Revalidate (SWR) cache for async functions.\n *\n * This caching strategy serves cached data immediately (even if stale) while\n * asynchronously revalidating the cache in the background. This provides:\n * - Sub-millisecond response times (after first fetch)\n * - Always available data (serves stale data during revalidation)\n * - Automatic background updates via configurable intervals\n *\n * @example\n * ```typescript\n * const cache = new SWRCache({\n * fn: async () => fetch('/api/data').then(r => r.json()),\n * ttl: 60, // 1 minute TTL\n * proactiveRevalidationInterval: 300 // proactively revalidate every 5 minutes\n * });\n *\n * // Returns cached data or waits for initial fetch\n * const data = await cache.read();\n *\n * if (data instanceof Error) { ... }\n * ```\n *\n * @link https://web.dev/stale-while-revalidate/\n * @link https://datatracker.ietf.org/doc/html/rfc5861\n */\nexport class SWRCache<ValueType> {\n private cache: CachedResult<ValueType> | null = null;\n private inProgressRevalidate: Promise<void> | null = null;\n private backgroundInterval: ReturnType<typeof setInterval> | null = null;\n\n constructor(private readonly options: SWRCacheOptions<ValueType>) {\n if (options.proactiveRevalidationInterval) {\n this.backgroundInterval = setInterval(\n () => this.revalidate(),\n secondsToMilliseconds(options.proactiveRevalidationInterval),\n );\n }\n\n if (options.proactivelyInitialize) this.revalidate();\n }\n\n private async revalidate() {\n // ensure that there is exactly one in progress revalidation promise\n if (!this.inProgressRevalidate) {\n this.inProgressRevalidate = this.options\n .fn()\n .then((result) => {\n // on success, always update the cache with the latest revalidation\n this.cache = {\n result,\n updatedAt: getUnixTime(new Date()),\n };\n })\n .catch((error) => {\n // on error, only update the cache if this is the first revalidation\n if (!this.cache) {\n this.cache = {\n // ensure thrown value is always an Error instance\n result: error instanceof Error ? error : new Error(String(error)),\n updatedAt: getUnixTime(new Date()),\n };\n }\n })\n .finally(() => {\n this.inProgressRevalidate = null;\n });\n }\n\n // provide it to the caller so that it may be awaited\n return this.inProgressRevalidate;\n }\n\n /**\n * Read the most recently cached result from the `SWRCache`.\n *\n * @returns a `ValueType` that was most recently successfully returned by `fn` or `Error` if `fn`\n * has never successfully returned.\n */\n public async read(): Promise<ValueType | Error> {\n // if no cache, populate the cache by awaiting revalidation\n if (!this.cache) await this.revalidate();\n\n // after any revalidation, this.cache is always set\n // NOTE: not documenting read() as throwable because this is just for typechecking\n if (!this.cache) throw new Error(\"never\");\n\n // if ttl expired, revalidate in background\n if (durationBetween(this.cache.updatedAt, getUnixTime(new Date())) > this.options.ttl) {\n this.revalidate();\n }\n\n return this.cache.result;\n }\n\n /**\n * Destroys the background revalidation interval, if exists.\n */\n public destroy(): void {\n if (this.backgroundInterval) {\n clearInterval(this.backgroundInterval);\n this.backgroundInterval = null;\n }\n }\n}\n","import { prettifyError } from \"zod/v4\";\n\nimport type { ChainIdString, UrlString } from \"./serialized-types\";\nimport type {\n AccountId,\n BlockNumber,\n BlockRef,\n Blockrange,\n ChainId,\n Datetime,\n Duration,\n} from \"./types\";\nimport {\n makeAccountIdStringSchema,\n makeBlockNumberSchema,\n makeBlockRefSchema,\n makeBlockrangeSchema,\n makeChainIdStringSchema,\n makeDatetimeSchema,\n makeDurationSchema,\n makeUnixTimestampSchema,\n makeUrlSchema,\n} from \"./zod-schemas\";\n\nexport function deserializeChainId(maybeChainId: ChainIdString, valueLabel?: string): ChainId {\n const schema = makeChainIdStringSchema(valueLabel);\n const parsed = schema.safeParse(maybeChainId);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize ChainId:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n\nexport function deserializeDatetime(maybeDatetime: string, valueLabel?: string): Datetime {\n const schema = makeDatetimeSchema(valueLabel);\n const parsed = schema.safeParse(maybeDatetime);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize Datetime:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n\nexport function deserializeUnixTimestamp(maybeTimestamp: number, valueLabel?: string) {\n const schema = makeUnixTimestampSchema(valueLabel);\n const parsed = schema.safeParse(maybeTimestamp);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize Unix Timestamp:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n\nexport function deserializeUrl(maybeUrl: UrlString, valueLabel?: string): URL {\n const schema = makeUrlSchema(valueLabel);\n const parsed = schema.safeParse(maybeUrl);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize URL:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n\nexport function deserializeBlockNumber(maybeBlockNumber: number, valueLabel?: string): BlockNumber {\n const schema = makeBlockNumberSchema(valueLabel);\n const parsed = schema.safeParse(maybeBlockNumber);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize BlockNumber:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n\nexport function deserializeBlockrange(maybeBlockrange: Partial<Blockrange>, valueLabel?: string) {\n const schema = makeBlockrangeSchema(valueLabel);\n const parsed = schema.safeParse(maybeBlockrange);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize Blockrange:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n\nexport function deserializeBlockRef(\n maybeBlockRef: Partial<BlockRef>,\n valueLabel?: string,\n): BlockRef {\n const schema = makeBlockRefSchema(valueLabel);\n const parsed = schema.safeParse(maybeBlockRef);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize BlockRef:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n\nexport function deserializeDuration(maybeDuration: unknown, valueLabel?: string): Duration {\n const schema = makeDurationSchema(valueLabel);\n const parsed = schema.safeParse(maybeDuration);\n\n if (parsed.error) {\n throw new RangeError(`Cannot deserialize Duration:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n\nexport function parseAccountId(maybeAccountId: unknown, valueLabel?: string): AccountId {\n const schema = makeAccountIdStringSchema(valueLabel);\n const parsed = schema.safeParse(maybeAccountId);\n\n if (parsed.error) {\n throw new RangeError(`Cannot deserialize AccountId:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n","import type { CoinType } from \"@ensdomains/address-encoder\";\nimport { AccountId as CaipAccountId } from \"caip\";\nimport { type Address, type Hex, isAddress, isHex, size } from \"viem\";\n/**\n * All zod schemas we define must remain internal implementation details.\n * We want the freedom to move away from zod in the future without impacting\n * any users of the ensnode-sdk package.\n *\n * The only way to share Zod schemas is to re-export them from\n * `./src/internal.ts` file.\n */\nimport { z } from \"zod/v4\";\n\nimport { ENSNamespaceIds, type InterpretedName, Node } from \"../ens\";\nimport { asLowerCaseAddress } from \"./address\";\nimport { type CurrencyId, CurrencyIds, Price, type PriceEth } from \"./currencies\";\nimport { reinterpretName } from \"./interpretation/reinterpretation\";\nimport type { AccountIdString } from \"./serialized-types\";\nimport type {\n AccountId,\n BlockRef,\n ChainId,\n Datetime,\n DefaultableChainId,\n Duration,\n UnixTimestamp,\n} from \"./types\";\n\n/**\n * Parses a string value as a boolean.\n */\nexport const makeBooleanStringSchema = (valueLabel: string = \"Value\") =>\n z\n .string()\n .pipe(\n z.enum([\"true\", \"false\"], {\n error: `${valueLabel} must be 'true' or 'false'.`,\n }),\n )\n .transform((val) => val === \"true\");\n\n/**\n * Parses a numeric value as a finite non-negative number.\n */\nexport const makeFiniteNonNegativeNumberSchema = (valueLabel: string = \"Value\") =>\n z\n .number({\n // NOTE: Zod's implementation of `number` automatically rejects NaN and Infinity values.\n // and therefore the finite check is implicit.\n error: `${valueLabel} must be a finite number.`,\n })\n .nonnegative({\n error: `${valueLabel} must be a non-negative number (>=0).`,\n });\n\n/**\n * Parses a numeric value as an integer.\n */\nexport const makeIntegerSchema = (valueLabel: string = \"Value\") =>\n z.int({\n error: `${valueLabel} must be an integer.`,\n });\n\n/**\n * Parses a numeric value as a positive integer.\n */\nexport const makePositiveIntegerSchema = (valueLabel: string = \"Value\") =>\n makeIntegerSchema(valueLabel).positive({\n error: `${valueLabel} must be a positive integer (>0).`,\n });\n\n/**\n * Parses a numeric value as a non-negative integer.\n */\nexport const makeNonNegativeIntegerSchema = (valueLabel: string = \"Value\") =>\n makeIntegerSchema(valueLabel).nonnegative({\n error: `${valueLabel} must be a non-negative integer (>=0).`,\n });\n\n/**\n * Parses a numeric value as {@link Duration}\n */\nexport const makeDurationSchema = (valueLabel: string = \"Value\") =>\n z.coerce\n .number({\n error: `${valueLabel} must be a number.`,\n })\n .pipe(makeNonNegativeIntegerSchema(valueLabel));\n\n/**\n * Parses Chain ID\n *\n * {@link ChainId}\n */\nexport const makeChainIdSchema = (valueLabel: string = \"Chain ID\") =>\n makePositiveIntegerSchema(valueLabel).transform((val) => val as ChainId);\n\n/**\n * Parses a serialized representation of {@link ChainId}.\n */\nexport const makeChainIdStringSchema = (valueLabel: string = \"Chain ID String\") =>\n z\n .string({ error: `${valueLabel} must be a string representing a chain ID.` })\n .pipe(z.coerce.number({ error: `${valueLabel} must represent a positive integer (>0).` }))\n .pipe(makeChainIdSchema(`The numeric value represented by ${valueLabel}`));\n\n/**\n * Parses Defaultable Chain ID\n *\n * {@link DefaultableChainId}\n */\nexport const makeDefaultableChainIdSchema = (valueLabel: string = \"Defaultable Chain ID\") =>\n makeNonNegativeIntegerSchema(valueLabel).transform((val) => val as DefaultableChainId);\n\n/**\n * Parses a serialized representation of {@link DefaultableChainId}.\n */\nexport const makeDefaultableChainIdStringSchema = (\n valueLabel: string = \"Defaultable Chain ID String\",\n) =>\n z\n .string({ error: `${valueLabel} must be a string representing a chain ID.` })\n .pipe(z.coerce.number({ error: `${valueLabel} must represent a non-negative integer (>=0).` }))\n .pipe(makeDefaultableChainIdSchema(`The numeric value represented by ${valueLabel}`));\n\n/**\n * Parses {@link CoinType}.\n */\nexport const makeCoinTypeSchema = (valueLabel: string = \"Coin Type\") =>\n z\n .number({ error: `${valueLabel} must be a number.` })\n .int({ error: `${valueLabel} must be an integer.` })\n .nonnegative({ error: `${valueLabel} must be a non-negative integer (>=0).` })\n .transform((val) => val as CoinType);\n\n/**\n * Parses a serialized representation of {@link CoinType}.\n */\nexport const makeCoinTypeStringSchema = (valueLabel: string = \"Coin Type String\") =>\n z\n .string({ error: `${valueLabel} must be a string representing a coin type.` })\n .pipe(z.coerce.number({ error: `${valueLabel} must represent a non-negative integer (>=0).` }))\n .pipe(makeCoinTypeSchema(`The numeric value represented by ${valueLabel}`));\n\n/**\n * Parses a serialized representation of an EVM address into a lowercase Address.\n */\nexport const makeLowercaseAddressSchema = (valueLabel: string = \"EVM address\") =>\n z\n .string()\n .check((ctx) => {\n if (!isAddress(ctx.value)) {\n ctx.issues.push({\n code: \"custom\",\n message: `${valueLabel} must be a valid EVM address`,\n input: ctx.value,\n });\n }\n })\n .transform((val) => asLowerCaseAddress(val as Address));\n\n/**\n * Parses an ISO 8601 string representations of {@link Datetime}\n */\nexport const makeDatetimeSchema = (valueLabel: string = \"Datetime string\") =>\n z.iso\n .datetime({ error: `${valueLabel} must be a string in ISO 8601 format.` })\n .transform((v) => new Date(v));\n\n/**\n * Parses value as {@link UnixTimestamp}.\n */\nexport const makeUnixTimestampSchema = (valueLabel: string = \"Timestamp\") =>\n makeIntegerSchema(valueLabel);\n\n/**\n * Parses a string representations of {@link URL}\n */\nexport const makeUrlSchema = (valueLabel: string = \"Value\") =>\n z\n .url({\n error: `${valueLabel} must be a valid URL string (e.g., http://localhost:8080 or https://example.com).`,\n abort: true,\n })\n .transform((v) => new URL(v));\n\n/**\n * Parses a serialized representation of a comma separated list.\n */\nexport const makeCommaSeparatedList = (valueLabel: string = \"Value\") =>\n z\n .string({ error: `${valueLabel} must be a comma separated list.` })\n .transform((val) => val.split(\",\").filter(Boolean))\n .refine((val) => val.length > 0, {\n error: `${valueLabel} must be a comma separated list with at least one value.`,\n });\n\n/**\n * Parses a numeric value as a block number.\n */\nexport const makeBlockNumberSchema = (valueLabel: string = \"Block number\") =>\n makeNonNegativeIntegerSchema(valueLabel);\n\n/**\n * Parses an object value as the {@link Blockrange} object.\n */\nexport const makeBlockrangeSchema = (valueLabel: string = \"Value\") =>\n z\n .strictObject(\n {\n startBlock: makeBlockNumberSchema(`${valueLabel}.startBlock`).optional(),\n endBlock: makeBlockNumberSchema(`${valueLabel}.endBlock`).optional(),\n },\n {\n error: `${valueLabel} must be a valid Blockrange object.`,\n },\n )\n .refine(\n (v) => {\n if (v.startBlock && v.endBlock) {\n return v.startBlock <= v.endBlock;\n }\n\n return true;\n },\n { error: `${valueLabel}: startBlock must be before or equal to endBlock` },\n );\n\n/**\n * Parses an object value as the {@link BlockRef} object.\n */\nexport const makeBlockRefSchema = (valueLabel: string = \"Value\") =>\n z.strictObject(\n {\n timestamp: makeUnixTimestampSchema(`${valueLabel}.timestamp`),\n number: makeBlockNumberSchema(`${valueLabel}.number`),\n },\n {\n error: `${valueLabel} must be a valid BlockRef object.`,\n },\n );\n\n/**\n * Parses a string value as ENSNamespaceId.\n */\nexport const makeENSNamespaceIdSchema = (valueLabel: string = \"ENSNamespaceId\") =>\n z.enum(ENSNamespaceIds, {\n error() {\n return `Invalid ${valueLabel}. Supported ENS namespace IDs are: ${Object.keys(ENSNamespaceIds).join(\", \")}`;\n },\n });\n\nconst makePriceAmountSchema = (valueLabel: string = \"Amount\") =>\n z.coerce\n .bigint({\n error: `${valueLabel} must represent a bigint.`,\n })\n .nonnegative({\n error: `${valueLabel} must not be negative.`,\n });\n\nexport const makePriceCurrencySchema = (\n currency: CurrencyId,\n valueLabel: string = \"Price Currency\",\n) =>\n z.strictObject({\n amount: makePriceAmountSchema(`${valueLabel} amount`),\n\n currency: z.literal(currency, {\n error: `${valueLabel} currency must be set to '${currency}'.`,\n }),\n });\n\n/**\n * Schema for {@link Price} type.\n */\nexport const makePriceSchema = (valueLabel: string = \"Price\") =>\n z.discriminatedUnion(\n \"currency\",\n [\n makePriceCurrencySchema(CurrencyIds.ETH, valueLabel),\n makePriceCurrencySchema(CurrencyIds.USDC, valueLabel),\n makePriceCurrencySchema(CurrencyIds.DAI, valueLabel),\n ],\n { error: `${valueLabel} currency must be one of ${Object.values(CurrencyIds).join(\", \")}` },\n );\n\n/**\n * Schema for {@link PriceEth} type.\n */\nexport const makePriceEthSchema = (valueLabel: string = \"Price ETH\") =>\n makePriceCurrencySchema(CurrencyIds.ETH, valueLabel).transform((v) => v as PriceEth);\n\n/**\n * Schema for {@link AccountId} type.\n */\nexport const makeAccountIdSchema = (valueLabel: string = \"AccountId\") =>\n z.strictObject({\n chainId: makeChainIdSchema(`${valueLabel} chain ID`),\n address: makeLowercaseAddressSchema(`${valueLabel} address`),\n });\n\n/**\n * Schema for {@link AccountIdString} type.\n */\nexport const makeAccountIdStringSchema = (valueLabel: string = \"Account ID String\") =>\n z.coerce\n .string()\n .transform((v) => {\n const result = new CaipAccountId(v);\n\n return {\n chainId: Number(result.chainId.reference),\n address: result.address,\n };\n })\n .pipe(makeAccountIdSchema(valueLabel));\n\n/**\n * Make a schema for {@link Hex} representation of bytes array.\n *\n * @param {number} options.bytesCount expected count of bytes to be hex-encoded\n */\nexport const makeHexStringSchema = (\n options: { bytesCount: number },\n valueLabel: string = \"String representation of bytes array\",\n) =>\n z\n .string()\n .check(function invariant_isHexEncoded(ctx) {\n if (!isHex(ctx.value)) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `${valueLabel} must be a hexadecimal value which starts with '0x'.`,\n });\n }\n })\n .transform((v) => v as Hex)\n .check(function invariant_encodesRequiredBytesCount(ctx) {\n const expectedBytesCount = options.bytesCount;\n const actualBytesCount = size(ctx.value);\n\n if (actualBytesCount !== expectedBytesCount) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `${valueLabel} must represent exactly ${expectedBytesCount} bytes. Currently represented bytes count: ${actualBytesCount}.`,\n });\n }\n });\n\n/**\n * Make schema for {@link Node}.\n */\nexport const makeNodeSchema = (valueLabel: string = \"Node\") =>\n makeHexStringSchema({ bytesCount: 32 }, valueLabel);\n\n/**\n * Make schema for Transaction Hash\n */\nexport const makeTransactionHashSchema = (valueLabel: string = \"Transaction hash\") =>\n makeHexStringSchema({ bytesCount: 32 }, valueLabel);\n\n/**\n * Make schema for {@link ReinterpretedName}.\n */\nexport const makeReinterpretedNameSchema = (valueLabel: string = \"Reinterpreted Name\") =>\n z\n .string()\n .transform((v) => v as InterpretedName)\n .check((ctx) => {\n try {\n reinterpretName(ctx.value);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : \"Unknown error\";\n\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `${valueLabel} cannot be reinterpreted: ${errorMessage}`,\n });\n }\n })\n .transform(reinterpretName);\n","export { getENSRootChainId } from \"@ensnode/datasources\";\n\nexport * from \"./coin-type\";\nexport * from \"./constants\";\nexport * from \"./dns-encoded-name\";\nexport * from \"./encode-labelhash\";\nexport * from \"./fuses\";\nexport * from \"./is-normalized\";\nexport * from \"./labelhash\";\nexport * from \"./names\";\nexport * from \"./parse-reverse-name\";\nexport * from \"./reverse-name\";\nexport * from \"./subname-helpers\";\nexport * from \"./types\";\n","import type { CoinType, EvmCoinType } from \"@ensdomains/address-encoder\";\nimport {\n coinTypeToEvmChainId as _coinTypeToEvmChainId,\n evmChainIdToCoinType as _evmChainIdToCoinType,\n} from \"@ensdomains/address-encoder/utils\";\n\nimport type { ChainId } from \"../shared\";\n\n// re-export CoinType and EvmCoinType from @ensdomains/address-encoder\n// so consumers don't need it as a dependency\nexport type { CoinType, EvmCoinType } from \"@ensdomains/address-encoder\";\n\n/**\n * The ETH coinType.\n *\n * @see https://docs.ens.domains/ensip/9\n */\nexport const ETH_COIN_TYPE: CoinType = 60;\n\n/**\n * The 'default' chainId corresponding to the below {@link DEFAULT_EVM_COIN_TYPE} in the context of\n * ENSIP-19.\n *\n * @see https://docs.ens.domains/ensip/19\n */\nexport const DEFAULT_EVM_CHAIN_ID = 0;\n\n/**\n * ENSIP-19 EVM CoinType representing the 'default' coinType for EVM chains in ENS.\n *\n * @see https://docs.ens.domains/ensip/19/#reverse-resolution\n */\nexport const DEFAULT_EVM_COIN_TYPE = 0x8000_0000 as EvmCoinType;\n\n/**\n * Converts a CoinType to an EVM Chain Id.\n *\n * NOTE: for whatever reason @ensdomains/address-encoder#coinTypeToEvmChainId doesn't handle the\n * mainnet case so we implement that here\n *\n * @see https://docs.ens.domains/ensip/11/\n */\nexport const coinTypeToEvmChainId = (coinType: CoinType): ChainId => {\n if (coinType === ETH_COIN_TYPE) return 1;\n return _coinTypeToEvmChainId(coinType);\n};\n\n/**\n * Converts an EVM Chain Id to a CoinType.\n *\n * NOTE: for whatever reason @ensdomains/address-encoder#evmChainIdToCoinType doesn't handle the\n * mainnet case so we implement that here\n */\nexport const evmChainIdToCoinType = (chainId: ChainId): CoinType => {\n if (chainId === 1) return ETH_COIN_TYPE;\n return _evmChainIdToCoinType(chainId);\n};\n\n/**\n * Converts a bigint value representing a CoinType into a valid CoinType.\n *\n * This is useful when onchain events emit coinTypes as bigint but we want to constrain them to\n * the CoinType type.\n *\n * @throws if `value` is too large to fit in Number.MAX_SAFE_INTEGER\n */\nexport const bigintToCoinType = (value: bigint): CoinType => {\n if (value > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new Error(`'${value}' cannot represent as CoinType, it is too large.`);\n }\n\n return Number(value) as CoinType;\n};\n","import { namehash, zeroHash } from \"viem\";\n\nimport type { Node } from \"./types\";\n\nexport const ROOT_NODE: Node = namehash(\"\");\nexport const ETH_NODE: Node = namehash(\"eth\");\nexport const BASENAMES_NODE: Node = namehash(\"base.eth\");\nexport const LINEANAMES_NODE: Node = namehash(\"linea.eth\");\nexport const ADDR_REVERSE_NODE: Node = namehash(\"addr.reverse\");\n\n/**\n * NODE_ANY is a placeholder Node used in the context of DedicatedResolvers — IResolver events are\n * emitted with NODE_ANY as the `node` for which the records are issued, but the DedicatedResolver\n * returns those records regardless of the name used for record resolution.\n */\nexport const NODE_ANY: Node = zeroHash;\n\n/**\n * ROOT_RESOURCE represents the 'root' resource in an EnhancedAccessControl contract.\n */\nexport const ROOT_RESOURCE = 0n;\n","import { bytesToString, hexToBytes } from \"viem\";\n\nimport type { DNSEncodedLiteralName, DNSEncodedName, LiteralLabel } from \"./types\";\n\n/**\n * Decodes a DNS-Encoded name consisting of Literal Labels into an ordered list of Literal Labels.\n *\n * For discussion on DNS-Encoding, see the {@link DNSEncodedName} and {@link DNSEncodedLiteralName} types.\n *\n * Due to the constraints of DNS-Encoding, there is an additional guarantee that each Literal Label\n * in the resulting list is guaranteed to have a maximum byte length of 255.\n *\n * @param packet a hex string that encodes a DNSEncodedLiteralName\n * @returns A list of the LiteralLabels contained in packet\n * @throws If the packet is malformed\n * @dev This is just `decodeDNSEncodedName` with semantic input/output\n */\nexport function decodeDNSEncodedLiteralName(packet: DNSEncodedLiteralName): LiteralLabel[] {\n return decodeDNSEncodedName(packet) as LiteralLabel[];\n}\n\n/**\n * Decodes a DNS-Encoded Name into an ordered list of string segments.\n *\n * For discussion on DNS-Encoding, see the {@link DNSEncodedName} type.\n *\n * Due to the constraints of DNS-Encoding, there is an additional guarantee that each segment\n * in the resulting list is guaranteed to have a maximum byte length of 255.\n *\n * @param packet a hex string that encodes a DNSEncodedName\n * @returns A UTF-8 string array of the segments contained in packet\n * @throws If the packet is malformed\n * @dev This is the generic implementation of DNS-Encoded Name Decoding\n */\nexport function decodeDNSEncodedName(packet: DNSEncodedName): string[] {\n const segments: string[] = [];\n\n const bytes = hexToBytes(packet);\n if (bytes.length === 0) throw new Error(`Packet is empty.`);\n\n let offset = 0;\n while (offset < bytes.length) {\n // NOTE: `len` is always [0, 255] because ByteArray is array of unsigned 8-bit integers. Because\n // the length of the next label is limited to one unsigned byte, this is why labels with bytelength\n // greater than 255 cannot be DNS Encoded.\n const len = bytes[offset];\n\n // Invariant: the while conditional enforces that there's always _something_ in bytes at offset\n if (len === undefined) {\n throw new Error(`Invariant: bytes[offset] is undefined after offset < bytes.length check.`);\n }\n\n // Invariant: `len` is always [0, 255]. technically not necessary but good for clarity\n if (len < 0 || len > 255) {\n throw new Error(\n `Invariant: this should be literally impossible, but an unsigned byte was less than zero or greater than 255. The value in question is ${len}`,\n );\n }\n\n // stop condition\n if (len === 0) break;\n\n // decode to UTF-8 string\n const segment = bytesToString(bytes.subarray(offset + 1, offset + len + 1));\n\n // add to list of segments and continue decoding\n segments.push(segment);\n offset += len + 1;\n }\n\n // check for overflow\n if (offset >= bytes.length) throw new Error(`Overflow, offset >= bytes.length`);\n\n // check for junk\n if (offset !== bytes.length - 1) throw new Error(`Junk at end of name`);\n\n return segments;\n}\n","import { isHex } from \"viem\";\n\nimport type { LabelHash } from \"./types\";\n\n/**\n * Checks if the input is a {@link LabelHash}.\n *\n * @see https://ensnode.io/docs/reference/terminology#label-processing-and-classification\n */\nexport function isLabelHash(maybeLabelHash: string): maybeLabelHash is LabelHash {\n const expectedLength = maybeLabelHash.length === 66;\n const expectedEncoding = isHex(maybeLabelHash);\n const expectedCasing = maybeLabelHash === maybeLabelHash.toLowerCase();\n\n return expectedLength && expectedEncoding && expectedCasing;\n}\n","import { isLabelHash } from \"./labelhash\";\nimport type { EncodedLabelHash, LabelHash } from \"./types\";\n\n/**\n * Formats a LabelHash as an Encoded LabelHash.\n *\n * @see https://ensnode.io/docs/reference/terminology#encoded-labelhash\n *\n * @param labelHash - A 32-byte lowercase hash string starting with '0x'\n * @returns The encoded label hash in format `[hash_without_0x_prefix]`\n */\nexport const encodeLabelHash = (labelHash: LabelHash): EncodedLabelHash =>\n `[${labelHash.slice(2)}]`;\n\n/**\n * Checks if the input value is an {@link EncodedLabelHash}.\n */\nexport function isEncodedLabelHash(\n maybeEncodedLabelHash: string,\n): maybeEncodedLabelHash is EncodedLabelHash {\n const expectedFormatting =\n maybeEncodedLabelHash.startsWith(\"[\") && maybeEncodedLabelHash.endsWith(\"]\");\n const includesLabelHash = isLabelHash(`0x${maybeEncodedLabelHash.slice(1, -1)}`);\n\n return expectedFormatting && includesLabelHash;\n}\n","/**\n * The NameWrapper's PARENT_CANNOT_CONTROL fuse.\n */\nconst PARENT_CANNOT_CONTROL = 0x10000;\n\n/**\n * Determines whether `fuses` has set ('burnt') the PARENT_CANNOT_CONTROL fuse.\n */\nexport const isPccFuseSet = (fuses: number) =>\n (fuses & PARENT_CANNOT_CONTROL) === PARENT_CANNOT_CONTROL;\n","import { normalize } from \"viem/ens\";\n\nimport type { Label, Name, NormalizedName } from \"./types\";\n\n/**\n * Determines whether the Name is normalized.\n *\n * @param name - The Name to check for normalization\n * @returns True if the name is normalized according to ENS normalization rules, false otherwise\n */\nexport function isNormalizedName(name: Name): name is NormalizedName {\n try {\n return name === normalize(name);\n } catch {\n return false;\n }\n}\n\n/**\n * Determines whether the Label is normalized.\n *\n * @param label - The Label to check for normalization\n * @returns True if the label is normalized according to ENS normalization rules, false otherwise\n */\nexport function isNormalizedLabel(label: Label): boolean {\n // empty string is not a normalized label\n if (label === \"\") return false;\n\n // normalized labels do not contain periods\n if (label.includes(\".\")) return false;\n\n try {\n return label === normalize(label);\n } catch {\n return false;\n }\n}\n","import { ens_beautify } from \"@adraffy/ens-normalize\";\n\nimport { isNormalizedLabel } from \"./is-normalized\";\nimport type { Label, Name, NormalizedName } from \"./types\";\n\n/**\n * Name for the ENS Root\n */\nexport const ENS_ROOT: Name = \"\";\n\n/**\n * Constructs a name hierarchy from a given NormalizedName.\n *\n * @example\n * ```\n * getNameHierarchy(\"sub.example.eth\") -> [\"sub.example.eth\", \"example.eth\", \"eth\"]\n * ```\n *\n * @dev by restricting the input type to NormalizedName we guarantee that we can split and join\n * on '.' and receive NormalizedNames as a result\n */\nexport const getNameHierarchy = (name: NormalizedName): NormalizedName[] =>\n name.split(\".\").map((_, i, labels) => labels.slice(i).join(\".\")) as NormalizedName[];\n\n/**\n * Get FQDN of parent for a name.\n */\nexport const getParentNameFQDN = (name: Name): Name => {\n // Invariant: name is not ENS root.\n if (name === ENS_ROOT) {\n throw new Error(\"There is no parent name for ENS Root.\");\n }\n\n const labels = name.split(\".\");\n\n // For TLDs, return ENS_ROOT\n if (labels.length === 1) {\n return ENS_ROOT;\n }\n\n // Strip off the child-most label in the name to get the FQDN of the parent\n return labels.slice(1).join(\".\");\n};\n\n/**\n * Beautifies a name by converting each normalized label in the provided name to\n * its \"beautified\" form. Labels that are not normalized retain their original value.\n *\n * Invariants:\n * - The number of labels in the returned name is the same as the number of labels in the input name.\n * - The order of the labels in the returned name is the same as the order of the labels in the input name.\n * - If a label in the input is normalized, it is returned in its \"beautified\" form.\n * - If a label in the input name is not normalized, it is returned without modification.\n * - Therefore, the result of ens_normalize(beautifyName(name)) is the same as the result of ens_normalize(name).\n *\n * The \"beautified form\" of a normalized label converts special sequences of\n * emojis and other special characters to their \"beautified\" equivalents. All\n * such conversions transform X -> Y where Y is normalizable and normalizes back to X.\n * Ex: '1⃣2⃣' (normalized) to '1️⃣2️⃣' (normalizable but not normalized).\n * Ex: 'ξethereum' (normalized) to 'Ξethereum' (normalizable, but not normalized).\n * Ex: 'abc' (normalized) to 'abc' (also normalized, no conversion).\n * Ex: 'ABC' (normalizable but not normalized) to 'ABC' (no conversion).\n * Ex: 'invalid|label' (not normalizable) to 'invalid|label' (no conversion).\n * Ex: '' (unnormalized as a label) to '' (no conversion).\n *\n * @param name - The name to beautify.\n * @returns The beautified name.\n */\nexport const beautifyName = (name: Name): Name => {\n const beautifiedLabels = name.split(\".\").map((label: Label) => {\n if (isNormalizedLabel(label)) {\n return ens_beautify(label);\n } else {\n return label;\n }\n });\n return beautifiedLabels.join(\".\");\n};\n","import { type Address, hexToBigInt, isAddress } from \"viem\";\n\nimport { asLowerCaseAddress } from \"../shared\";\nimport { bigintToCoinType, type CoinType, DEFAULT_EVM_COIN_TYPE, ETH_COIN_TYPE } from \"./coin-type\";\nimport type { Label, Name } from \"./types\";\n\n/**\n * Matches an ENSIP-19 Reverse Name\n *\n * @see https://github.com/ensdomains/ens-contracts/blob/20e34971fd55f9e3b3cf4a5825d52e1504d36493/contracts/utils/ENSIP19.sol#L70\n */\nconst REVERSE_NAME_REGEX = /^([0-9a-fA-F]+)\\.([0-9a-f]{1,64}|addr|default)\\.reverse$/;\n\n/**\n * Parses an address label (hex sans prefix) into an Address.\n *\n * @param addressLabel - Lowercase hex string derived from a reverse address.\n * @throws if address is invalid\n * @see https://docs.ens.domains/ensip/19#reverse-resolution\n */\nconst parseAddressLabel = (addressLabel: Label): Address => {\n const maybeAddress = `0x${addressLabel}`;\n\n if (!isAddress(maybeAddress)) {\n throw new Error(`Invalid EVM address \"${maybeAddress}\"`);\n }\n\n return asLowerCaseAddress(maybeAddress);\n};\n\n/**\n * Parses a coinType label (hex sans prefix) into an EVMCoinType.\n *\n * @throws if coinType is invalid\n */\nconst parseCoinTypeLabel = (coinTypeLabel: Label): CoinType => {\n if (coinTypeLabel === \"default\") return DEFAULT_EVM_COIN_TYPE;\n if (coinTypeLabel === \"addr\") return ETH_COIN_TYPE;\n\n return bigintToCoinType(hexToBigInt(`0x${coinTypeLabel}`));\n};\n\n/**\n * Parse the address and coinType out of an ENSIP-19 reverse name.\n */\nexport function parseReverseName(name: Name): { address: Address; coinType: CoinType } | null {\n const match = name.match(REVERSE_NAME_REGEX);\n if (!match) return null;\n\n try {\n const [, addressLabel, coinTypeLabel] = match;\n if (!addressLabel) return null;\n if (!coinTypeLabel) return null;\n\n return {\n address: parseAddressLabel(addressLabel),\n coinType: parseCoinTypeLabel(coinTypeLabel),\n };\n } catch {\n // either of the parse methods threw, unable to parse reverse name\n return null;\n }\n}\n","import type { Address } from \"viem\";\n\nimport { type CoinType, DEFAULT_EVM_COIN_TYPE, ETH_COIN_TYPE } from \"./coin-type\";\nimport type { Label, LiteralLabel, Name } from \"./types\";\n\n/**\n * Gets the Label used for the reverse names of subnames as per ENSIP-11 & ENSIP-19.\n *\n * @see https://docs.ens.domains/ensip/19/#reverse-resolution\n */\nexport const addrReverseLabel = (address: Address): LiteralLabel =>\n address.slice(2) as LiteralLabel; // address is guaranteed to be fully lowercase\n\n/**\n * Converts `coinType` to prefix-free hex string.\n *\n * @see https://docs.ens.domains/ensip/19\n */\nexport const coinTypeReverseLabel = (coinType: CoinType): Label => coinType.toString(16);\n\n/**\n * Gets the reverse name for an address according to ENSIP-11 & ENSIP-19.\n *\n * @see https://docs.ens.domains/ensip/11#specification\n * @see https://docs.ens.domains/ensip/19#specification\n *\n * @param address - The address to get the reverse name for\n * @param coinType - The coin type to use for the reverse name\n * @returns The reverse name for the address\n *\n * @example\n * ```ts\n * reverseName(\"0x1234\", BigInt(ETH_COIN_TYPE)) // \"1234.addr.reverse\"\n * reverseName(\"0x1234\", BigInt(0x80000000)) // \"1234.default.reverse\"\n * reverseName(\"0x1234\", BigInt(0x5678)) // \"1234.5678.reverse\"\n * ```\n */\nexport function reverseName(address: Address, coinType: CoinType): Name {\n const label = addrReverseLabel(address);\n\n const middle = (() => {\n switch (coinType) {\n case ETH_COIN_TYPE:\n return \"addr\";\n case DEFAULT_EVM_COIN_TYPE:\n return \"default\";\n default:\n return coinTypeReverseLabel(coinType);\n }\n })();\n\n return `${label}.${middle}.reverse`;\n}\n","import { concat, type Hex, keccak256, toHex } from \"viem\";\n\nimport type { LabelHash, Node } from \"./types\";\n\n/**\n * Implements one step of the namehash algorithm, combining `labelHash` with `node` to produce\n * the `node` of a given subdomain. Note that the order of the arguments is 'reversed' (as compared to\n * the actual concatenation) in order to improve readability (i.e. read as [labelHash].[node]).\n */\nexport const makeSubdomainNode = (labelHash: LabelHash, node: Node): Node =>\n keccak256(concat([node, labelHash]));\n\n/**\n * Encodes a uint256 bigint as hex string sized to 32 bytes.\n * Uses include, in the context of ENS, decoding the uint256-encoded tokenId of NFT-issuing contracts\n * into Node or LabelHash, which is a common behavior in the ENS ecosystem.\n * (see NameWrapper, ETHRegistrarController)\n */\nexport const uint256ToHex32 = (num: bigint): Hex => toHex(num, { size: 32 });\n","import type { Hex } from \"viem\";\n\nimport type { DomainId } from \"../ensv2\";\n\nexport type { ENSNamespaceId } from \"@ensnode/datasources\";\n// re-export ENSNamespaceIds and ENSNamespaceId from @ensnode/datasources\n// so consumers don't need it as a dependency\nexport { ENSNamespaceIds } from \"@ensnode/datasources\";\n\n/**\n * A hash value that uniquely identifies a single ENS name.\n * Result of `namehash` function as specified in ENSIP-1.\n *\n * @example\n * ```\n * namehash(\"vitalik.eth\") === \"0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835\"\n * ```\n * @see https://docs.ens.domains/ensip/1#namehash-algorithm\n * @see https://ensnode.io/docs/reference/terminology#name-node-namehash\n */\nexport type Node = Hex;\n\n/**\n * An ENS Name that may or may not be normalized.\n *\n * @example vitalik.eth\n * @see https://ensnode.io/docs/reference/terminology#name-node-namehash\n * @see https://docs.ens.domains/ensip/15\n */\nexport type Name = string;\n\n/**\n * A Normalized Name is an ENS Name that is guaranteed to be normalized.\n *\n * @example vitalik.eth\n * @see https://ensnode.io/docs/reference/terminology#name-node-namehash\n * @see https://docs.ens.domains/ensip/15\n * @dev nominally typed to enforce usage & enhance codebase clarity\n */\nexport type NormalizedName = Name & { __brand: \"NormalizedName\" };\n\n/**\n * A LabelHash is the result of the labelhash function (which is just keccak256) on a Label.\n *\n * @example\n * ```\n * labelhash('vitalik') === '0xaf2caa1c2ca1d027f1ac823b529d0a67cd144264b2789fa2ea4d63a67c7103cc'\n * ```\n *\n * @see https://docs.ens.domains/terminology#labelhash\n * @see https://ensnode.io/docs/reference/terminology#labels-labelhashes-labelhash-function\n * @see https://ensnode.io/ensrainbow/concepts/glossary#labelhash\n */\nexport type LabelHash = Hex;\n\n/**\n * A LabelHashPath is an ordered list of LabelHashes that uniquely identify an ENS Name.\n * It is ordered in namegraph TRAVERSAL order (i.e. the opposite order of an ENS Name's labels).\n *\n * ex: example.eth's LabelHashPath is\n * [\n * '0x4f5b812789fc606be1b3b16908db13fc7a9adf7ca72641f84d75b47069d3d7f0', // 'eth'\n * '0x6fd43e7cffc31bb581d7421c8698e29aa2bd8e7186a394b85299908b4eb9b175', // 'example'\n * ]\n */\nexport type LabelHashPath = LabelHash[];\n\n/**\n * CanonicalPath is an ordered list of DomainIds describing the canonical path to a Domain.\n * It is ordered in namegraph TRAVERSAL order (i.e. the opposite order of an ENS Name's labels).\n */\nexport type CanonicalPath = DomainId[];\n\n/**\n * A Label is a single part of an ENS Name.\n *\n * @example vitalik\n *\n * @see https://docs.ens.domains/terminology#label\n * @see https://ensnode.io/docs/reference/terminology#labels-labelhashes-labelhash-function\n */\nexport type Label = string;\n\n/**\n * An EncodedLabelHash is a specially formatted (unnormalized) Label formatted\n * as a non-0x prefixed 32-byte hex string enclosed in square brackets.\n *\n * Care should be taken to distinguish Label values formatted as an\n * EncodedLabelHash as either a LiteralLabel or an InterpretedLabel:\n * - If a LiteralLabel is formatted as an EncodedLabelHash it does NOT\n * symbolically represent the encoding of a LabelHash literal.\n * - If an InterpretedLabel is formatted as an EncodedLabelHash it should be\n * interpreted as encoding a LabelHash literal.\n *\n * An InterpretedLabel may be formatted as an EncodedLabelHash if the related\n * LiteralLabel is:\n * - not a normalized label\n * - is an unknown value that could not be healed.\n * - is too long for DNS-Encoding in contexts where DNS-Encoding was required.\n *\n * @example [af2caa1c2ca1d027f1ac823b529d0a67cd144264b2789fa2ea4d63a67c7103cc]\n *\n * @see https://ensnode.io/docs/reference/terminology#encoded-labelhash\n */\nexport type EncodedLabelHash = `[${string}]`;\n\n/**\n * A Literal Label is a Label as it literally appears onchain, without any interpretation\n * or normalization processing. It may be an unnormalized label for reasons including:\n * - being an empty label,\n * - containing '.' characters,\n * - being formatted as an EncodedLabelHash (which are not normalizable). Note that\n * when LiteralLabel are formatted as an EncodedLabelHash they do NOT symbolically\n * represent the encoding of a LabelHash literal, or\n * - containing other unnormalized characters such as null bytes or other characters\n * not suitable for display.\n *\n *\n * @see https://ensnode.io/docs/reference/terminology#literal-label\n * @dev nominally typed to enforce usage & enhance codebase clarity\n */\nexport type LiteralLabel = Label & { __brand: \"LiteralLabel\" };\n\n/**\n * An Interpreted Label is a Label that is either:\n * a) a Normalized Label, or\n * b) an Unnormalizable Label exclusively for the reason that it is formatted\n * as an Encoded LabelHash that should be interpreted as encoding a\n * LabelHash literal, where the encoded LabelHash literal is the `labelhash`\n * of the related LiteralLabel.\n *\n * @see https://ensnode.io/docs/reference/terminology#interpreted-label\n * @dev nominally typed to enforce usage & enhance codebase clarity\n */\nexport type InterpretedLabel = Label & { __brand: \"InterpretedLabel\" };\n\n/**\n * A Literal Name is a Name as it literally appears onchain, composed of 0 or more Literal Labels\n * joined by dots. It may be an unnormalized name for reasons including:\n * - containing empty labels,\n * - containing LiteralLabel values formatted as an EncodedLabelHash (which are\n * not normalizable)). Note that when LiteralLabel values are formatted as an\n * EncodedLabelHash they do NOT symbolically represent the encoding of a\n * LabelHash literal, or\n * - containing other unnormalized characters such as null bytes or other characters\n * not suitable for display.\n *\n * @see https://ensnode.io/docs/reference/terminology#literal-name\n * @dev nominally typed to enforce usage & enhance codebase clarity\n */\nexport type LiteralName = Name & { __brand: \"LiteralName\" };\n\n/**\n * An Interpreted Name is a Name that is entirely composed of 0 or more Interpreted Labels.\n *\n * That is, it is either:\n * a) a Normalized Name, or\n * b) an Unnormalizable Name exclusively for the reason that it contains 1 or\n * more labels formatted as Encoded LabelHashes that should be interpreted\n * as encoding a LabelHash literal, where the encoded LabelHash literal is\n * the `labelhash` of the related LiteralLabel.\n *\n * @see https://ensnode.io/docs/reference/terminology#interpreted-name\n * @dev nominally typed to enforce usage & enhance codebase clarity\n */\nexport type InterpretedName = Name & { __brand: \"InterpretedName\" };\n\n/**\n * A Subgraph Interpreted Label is a Literal Label that is either:\n * a) (if subgraph-indexable): a Literal Label, of unknown normalization status, guaranteed to not\n * contain any of the subgraph-unindexable UTF-8 characters (and therefore guaranteed not to be\n * an Encoded LabelHash), or\n * b) (if subgraph-unindexable): an Encoded LabelHash.\n *\n * @see https://ensnode.io/docs/reference/terminology#subgraph-interpreted-label\n * @dev nominally typed to enforce usage & enhance codebase clarity\n */\nexport type SubgraphInterpretedLabel = Label & { __brand: \"SubgraphInterpretedLabel\" };\n\n/**\n * A Subgraph Interpreted Name is a name exclusively composed of 0 or more Subgraph Interpreted Labels.\n *\n * @see https://ensnode.io/docs/reference/terminology#subgraph-interpreted-name\n * @dev nominally typed to enforce usage & enhance codebase clarity\n */\nexport type SubgraphInterpretedName = Name & { __brand: \"SubgraphInterpretedName\" };\n\n/**\n * A DNS-Encoded Name as a hex string, representing the binary DNS wire format encoding\n * of a domain name. Used in ENS contracts for efficient name storage and transmission.\n * Each label is prefixed with a length byte, and the entire sequence is null-terminated.\n *\n * @example \"0x076578616d706c650365746800\" represents \"example.eth\"\n *\n * @see https://docs.ens.domains/resolution/names/#dns-encoding\n * @see https://github.com/ensdomains/ens-contracts/blob/staging/contracts/utils/NameCoder.sol\n *\n * DNS Packet Format for Domain Names:\n * - Domain names are encoded as a sequence of 0 or more labels\n * - Each label begins with a length byte (1 byte) indicating how many bytes follow for that label\n * Note how this constrains each label in DNS encoded names to a max byte length of 255 bytes.\n * - The bytes after the length byte represent the label, as a UTF-8 byte array\n * - Labels are concatenated with no separators\n * - The sequence ends with a null byte (0x00)\n *\n * Example: \"example.eth\" is encoded as:\n * [0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0x03, 'e', 't', 'h', 0x00]\n * Where 0x07 is the length of \"example\", 0x03 is the length of \"eth\", and 0x00 marks the end\n *\n * Example: \"\" (empty string, i.e. root node) is encoded as:\n * [0x00]\n *\n * Example: \"👩🏼‍❤‍💋‍👨🏼.eth\" (multi-byte unicode character) is encoded as:\n * [0x20, 240, 159, 145, 169, 240, 159, 143, 188, 226, 128, 141, 226, 157, 164, 226,\n * 128, 141, 240, 159, 146, 139, 226, 128, 141, 240, 159, 145, 168, 240, 159, 143,\n * 188, 3, 'e', 't', 'h', 0x00]\n *\n * A DNS-Encoded Name Packet may be malformed if it does not exactly follow that specification.\n * Possible reasons a DNS-Encoded Name may be malfomed include:\n * - 'empty' packet\n * - e.g. []\n * ^-- that's empty!\n * - 'length' byte overflowing packet byte length\n * - e.g. [0x06, 'e', 't', 'h', 0x00]\n * ^-- length overflows available bytes!\n * - 'junk' at the end of the dns-encoded\n * - e.g. [0x03, 'e', 't', 'h', 0x00, 0x01]\n * ^-- junk!\n *\n * @dev This type is _structurally_ typed to aid Event Argument Typing — consumers should further\n * cast the type of the event argument to a _nominally_ typed DNSEncodedName like {@link DNSEncodedLiteralName}\n * or {@link DNSEncodedPartiallyInterpretedName} depending on the context.\n */\nexport type DNSEncodedName = Hex;\n\n/**\n * A DNSEncodedName that encodes a name containing 0 or more {@link LiteralLabel}s.\n *\n * In a DNSEncodedLiteralName, all labels are Literal Labels, including any Encoded-LabelHash-looking\n * labels. Any Encoded-LabelHash-looking Literal Label values, when interpreted, will be formatted as\n * the `labelhash` of the Literal Label value.\n *\n * The NameWrapper contract emits DNSEncodedLiteralNames:\n * @see https://github.com/ensdomains/ens-contracts/blob/staging/contracts/utils/BytesUtils_LEGACY.sol\n *\n * The ThreeDNSToken contract emits DNSEncodedLiteralNames:\n * @see https://github.com/3dns-xyz/contracts/blob/44937318ae26cc036982e8c6a496cd82ebdc2b12/src/regcontrol/libraries/BytesUtils.sol\n *\n * @dev nominally typed to enforce usage & enhance codebase clarity\n */\nexport type DNSEncodedLiteralName = DNSEncodedName & { __brand: \"DNSEncodedLiteralName\" };\n\n/**\n * A DNSEncodedName that encodes a name consisting of 0 or more labels that are either:\n * a) Literal Labels, or\n * b) Encoded LabelHashes, which are already an Interpreted Label.\n *\n * In a DNSEncodedPartiallyInterpretedName, any Encoded-LabelHash-looking decoded Labels (i.e. ones\n * that match the regex /^\\[[\\da-f]{64}\\]$/) represent an Encoded LabelHash. When decoding a\n * DNSEncodedPartiallyInterpretedName, these labels are already considered Interpreted.\n *\n * NOTE: This type is unused in ENSv1, but its usage is anticipated in ENSv2 due to Encoded\n * LabelHash support in the ENSv2 implementation of the NameCoder contract.\n *\n * @see https://github.com/ensdomains/ens-contracts/blob/staging/contracts/utils/NameCoder.sol\n *\n * @dev nominally typed to enforce usage & enhance codebase clarity\n */\nexport type DNSEncodedPartiallyInterpretedName = DNSEncodedName & {\n __brand: \"DNSEncodedPartiallyInterpretedName\";\n};\n","/**\n * Identifiers for supported currencies.\n *\n * TODO: Add support for WETH\n */\nexport const CurrencyIds = {\n ETH: \"ETH\",\n USDC: \"USDC\",\n DAI: \"DAI\",\n} as const;\n\nexport type CurrencyId = (typeof CurrencyIds)[keyof typeof CurrencyIds];\n\n/**\n * The amount of the currency in the smallest unit of the currency\n * (see {@link CurrencyInfo.decimals} for the currency).\n *\n * Guaranteed to be non-negative.\n */\nexport type CurrencyAmount = bigint;\n\n/**\n * Serialized representation of {@link CurrencyAmount}.\n */\nexport type SerializedCurrencyAmount = string;\n\nexport interface PriceEth {\n currency: typeof CurrencyIds.ETH;\n\n amount: CurrencyAmount;\n}\n\nexport interface PriceDai {\n currency: typeof CurrencyIds.DAI;\n\n amount: CurrencyAmount;\n}\n\nexport interface PriceUsdc {\n currency: typeof CurrencyIds.USDC;\n\n amount: CurrencyAmount;\n}\n\nexport type Price = PriceEth | PriceDai | PriceUsdc;\n\n/**\n * Serialized representation of {@link PriceEth}.\n */\nexport interface SerializedPriceEth extends Omit<PriceEth, \"amount\"> {\n amount: SerializedCurrencyAmount;\n}\n\n/**\n * Serialized representation of {@link PriceDai}.\n */\nexport interface SerializedPriceDai extends Omit<PriceDai, \"amount\"> {\n amount: SerializedCurrencyAmount;\n}\n\n/**\n * Serialized representation of {@link PriceUsdc}.\n */\nexport interface SerializedPriceUsdc extends Omit<PriceUsdc, \"amount\"> {\n amount: SerializedCurrencyAmount;\n}\n\n/**\n * Serialized representation of {@link Price}.\n */\nexport type SerializedPrice = SerializedPriceEth | SerializedPriceDai | SerializedPriceUsdc;\n\nexport interface CurrencyInfo {\n id: CurrencyId;\n name: string;\n decimals: number;\n}\n\nconst currencyInfo: Record<CurrencyId, CurrencyInfo> = {\n [CurrencyIds.ETH]: {\n id: CurrencyIds.ETH,\n name: \"ETH\",\n decimals: 18,\n },\n [CurrencyIds.USDC]: {\n id: CurrencyIds.USDC,\n name: \"USDC\",\n decimals: 6,\n },\n [CurrencyIds.DAI]: {\n id: CurrencyIds.DAI,\n name: \"Dai Stablecoin\",\n decimals: 18,\n },\n};\n\n/**\n * Get currency info for a provided currency.\n */\nexport function getCurrencyInfo(currencyId: CurrencyId): CurrencyInfo {\n return currencyInfo[currencyId];\n}\n\n/**\n * Create price in ETH for given amount.\n */\nexport function priceEth(amount: Price[\"amount\"]): PriceEth {\n return {\n amount,\n currency: CurrencyIds.ETH,\n };\n}\n\n/**\n * Create price in USDC for given amount.\n */\nexport function priceUsdc(amount: Price[\"amount\"]): PriceUsdc {\n return {\n amount,\n currency: CurrencyIds.USDC,\n };\n}\n\n/**\n * Create price in DAI for given amount.\n */\nexport function priceDai(amount: Price[\"amount\"]): PriceDai {\n return {\n amount,\n currency: CurrencyIds.DAI,\n };\n}\n\n/**\n * Check if two prices have the same currency.\n */\nexport function isPriceCurrencyEqual(priceA: Price, priceB: Price): boolean {\n return priceA.currency === priceB.currency;\n}\n\n/**\n * Check if two {@link Price} values have the same currency and amount.\n */\nexport function isPriceEqual(priceA: Price, priceB: Price): boolean {\n return isPriceCurrencyEqual(priceA, priceB) && priceA.amount === priceB.amount;\n}\n\n/**\n * Add prices\n *\n * @param prices at least two {@link Price} values to be added together.\n * @returns total of all prices.\n * @throws if not all prices have the same currency.\n */\nexport function addPrices<const PriceType extends Price = Price>(\n ...prices: [PriceType, PriceType, ...PriceType[]]\n): PriceType {\n const firstPrice = prices[0];\n const allPricesInSameCurrency = prices.every((price) => isPriceCurrencyEqual(firstPrice, price));\n\n if (allPricesInSameCurrency === false) {\n throw new Error(\"All prices must have the same currency to be added together.\");\n }\n\n const { currency } = firstPrice;\n\n return prices.reduce(\n (acc, price) => ({\n amount: acc.amount + price.amount,\n currency,\n }),\n {\n amount: 0n,\n currency: firstPrice.currency,\n },\n ) as PriceType;\n}\n","import { labelhash as labelToLabelHash } from \"viem\";\n\nimport {\n encodeLabelHash,\n type InterpretedLabel,\n type InterpretedName,\n isEncodedLabelHash,\n isNormalizedLabel,\n} from \"../../ens\";\n\n/**\n * Reinterpret Label\n *\n * Reinterprets {@link InterpretedLabel} values received by \"External System\"\n * into {@link InterpretedLabel} values in \"Internal System\" where:\n * 1. \"External System\" is not guaranteed to be using the same ENSNormalize\n * version as \"Internal System\", and therefore the `InterpretedLabel` passed into\n * this function (from \"External System\") is not guaranteed to 100% align\n * with the invariants of an `InterpretedLabel` in \"Internal System\".\n * 2. The `InterpretedLabel` returned by this function is guaranteed to match\n * the invariants of `InterpretedLabel` in \"Internal System\".\n *\n * @returns reinterpreted label.\n * @throws an error if the provided label is an empty label\n * (and therefore violates the invariants of an InterpretedLabel).\n */\nexport function reinterpretLabel(label: InterpretedLabel): InterpretedLabel {\n // Invariant: InterpretedLabel value must never be an empty label.\n if (label === \"\") {\n throw new Error(\n `Cannot reinterpret an empty label that violates the invariants of an InterpretedLabel.`,\n );\n }\n\n // no change required for EncodedLabelHash\n if (isEncodedLabelHash(label)) return label;\n\n // no change required for NormalizedLabel\n if (isNormalizedLabel(label)) return label;\n\n // the provided `label` is unnormalized,\n // turn into an EncodedLabelHash\n return encodeLabelHash(labelToLabelHash(label)) as InterpretedLabel;\n}\n\n/**\n * Reinterpret Name\n *\n * Reinterprets {@link InterpretedName} values received by \"External System\"\n * into {@link InterpretedName} values in \"Internal System\" where:\n * 1. \"External System\" is not guaranteed to be using the same ENSNormalize\n * version as \"Internal System\", and therefore the `InterpretedName` passed into\n * this function (from \"External System\") is not guaranteed to 100% align\n * with the invariants of an `InterpretedName` in \"Internal System\".\n * 2. The `InterpretedName` returned by this function is guaranteed to match\n * the invariants of `InterpretedName` in \"Internal System\".\n */\nexport function reinterpretName(name: InterpretedName): InterpretedName {\n if (name === \"\") return name;\n\n const interpretedLabels = name.split(\".\") as InterpretedLabel[];\n const reinterpretedLabels = interpretedLabels.map(reinterpretLabel);\n const reinterpretedName = reinterpretedLabels.join(\".\") as InterpretedName;\n\n return reinterpretedName;\n}\n","import { deserializeDuration, deserializeUnixTimestamp } from \"./deserialize\";\nimport type { Duration, UnixTimestamp } from \"./types\";\n\n/**\n * Duration between two moments in time.\n */\nexport function durationBetween(start: UnixTimestamp, end: UnixTimestamp): Duration {\n return deserializeDuration(end - start, \"Duration\");\n}\n\n/**\n * Add a duration to a timestamp.\n */\nexport function addDuration(timestamp: UnixTimestamp, duration: Duration): UnixTimestamp {\n return deserializeUnixTimestamp(timestamp + duration, \"UnixTimestamp\");\n}\n","import { getUnixTime } from \"date-fns/getUnixTime\";\n\nimport { addDuration } from \"../datetime\";\nimport type { Duration, UnixTimestamp } from \"../types\";\nimport type { Cache } from \"./cache\";\n\ninterface CacheEntry<ValueType> {\n value: ValueType;\n expiresAt: UnixTimestamp;\n}\n\n/**\n * Cache that maps from string -> ValueType with TTL (time-to-live) expiration.\n *\n * Items are automatically removed when they expire.\n */\nexport class TtlCache<KeyType extends string, ValueType> implements Cache<KeyType, ValueType> {\n private readonly _cache = new Map<string, CacheEntry<ValueType>>();\n private readonly _ttl: Duration;\n\n /**\n * Create a new TTL cache with the given TTL.\n *\n * @param ttl Time-to-live duration in seconds. Items expire after this duration.\n */\n public constructor(ttl: Duration) {\n this._ttl = ttl;\n }\n\n private _cleanup(): void {\n const now = getUnixTime(new Date());\n for (const [key, entry] of this._cache.entries()) {\n if (entry.expiresAt <= now) {\n this._cache.delete(key);\n }\n }\n }\n\n public set(key: string, value: ValueType): void {\n this._cleanup();\n\n const expiresAt = addDuration(getUnixTime(new Date()), this._ttl);\n this._cache.set(key, { value, expiresAt });\n }\n\n public get(key: string): ValueType | undefined {\n this._cleanup();\n\n const entry = this._cache.get(key);\n if (!entry) {\n return undefined;\n }\n\n if (entry.expiresAt <= getUnixTime(new Date())) {\n this._cache.delete(key);\n return undefined;\n }\n\n return entry.value;\n }\n\n public clear(): void {\n this._cache.clear();\n }\n\n public get size(): number {\n this._cleanup();\n return this._cache.size;\n }\n\n public get capacity(): number {\n return Number.MAX_SAFE_INTEGER;\n }\n\n public has(key: string): boolean {\n this._cleanup();\n\n const entry = this._cache.get(key);\n if (!entry) {\n return false;\n }\n\n if (entry.expiresAt <= getUnixTime(new Date())) {\n this._cache.delete(key);\n return false;\n }\n\n return true;\n }\n\n public delete(key: string): boolean {\n return this._cache.delete(key);\n }\n}\n","/**\n * Filter out duplicates.\n */\nexport const uniq = <T>(arr: T[]): T[] => [...new Set(arr)];\n","import {\n type Datasource,\n type DatasourceName,\n type ENSNamespaceId,\n maybeGetDatasource,\n} from \"@ensnode/datasources\";\nimport { type AccountId, accountIdEqual } from \"@ensnode/ensnode-sdk\";\n\n/**\n * Gets the AccountId for the contract in the specified namespace, datasource, and\n * contract name, or undefined if it is not defined or is not a single AccountId.\n *\n * This is useful when you want to retrieve the AccountId for a contract by its name\n * where it may or may not actually be defined for the given namespace and datasource.\n *\n * @param namespaceId - The ENSNamespace identifier (e.g. 'mainnet', 'sepolia', 'ens-test-env')\n * @param datasourceName - The name of the Datasource to search for contractName in\n * @param contractName - The name of the contract to retrieve\n * @returns The AccountId of the contract with the given namespace, datasource,\n * and contract name, or undefined if it is not found or is not a single AccountId\n */\nexport const maybeGetDatasourceContract = <\n N extends ENSNamespaceId,\n D extends DatasourceName,\n C extends string,\n>(\n namespaceId: N,\n datasourceName: D,\n contractName: C,\n): AccountId | undefined => {\n const datasource = maybeGetDatasource(namespaceId, datasourceName) as Datasource | undefined;\n if (!datasource) return undefined;\n\n const address = datasource.contracts[contractName]?.address;\n if (address === undefined || Array.isArray(address)) return undefined;\n\n return {\n chainId: datasource.chain.id,\n address,\n };\n};\n\n/**\n * Gets the AccountId for the contract in the specified namespace, datasource, and\n * contract name, or throws an error if it is not defined or is not a single AccountId.\n *\n * @param namespaceId - The ENSNamespace identifier (e.g. 'mainnet', 'sepolia', 'ens-test-env')\n * @param datasourceName - The name of the Datasource to search for contractName in\n * @param contractName - The name of the contract to retrieve\n * @returns The AccountId of the contract with the given namespace, datasource,\n * and contract name\n * @throws Error if the contract is not found or is not a single AccountId\n */\nexport const getDatasourceContract = (\n namespaceId: ENSNamespaceId,\n datasourceName: DatasourceName,\n contractName: string,\n): AccountId => {\n const contract = maybeGetDatasourceContract(namespaceId, datasourceName, contractName);\n if (!contract) {\n throw new Error(\n `Expected contract not found for ${namespaceId} ${datasourceName} ${contractName}`,\n );\n }\n return contract;\n};\n\n/**\n * Makes a comparator fn for `b` against the contract described by `namespace`, `datasourceName`, and `contractName`.\n */\nexport const makeContractMatcher =\n (namespace: ENSNamespaceId, b: AccountId) =>\n (datasourceName: DatasourceName, contractName: string) => {\n const a = maybeGetDatasourceContract(namespace, datasourceName, contractName);\n return a && accountIdEqual(a, b);\n };\n","import { type Address, isAddressEqual, zeroAddress } from \"viem\";\n\n/**\n * Interprets a viem#Address. zeroAddress is interpreted as null, otherwise Address.\n */\nexport const interpretAddress = (owner: Address) =>\n isAddressEqual(zeroAddress, owner) ? null : owner;\n","import { isAddress, isAddressEqual, zeroAddress } from \"viem\";\n\nimport { asLowerCaseAddress, isNormalizedName, type NormalizedName } from \"@ensnode/ensnode-sdk\";\n\nimport { hasNullByte } from \"../null-bytes\";\n\n/**\n * Interprets a name record value string and returns null if the value is interpreted as a deletion.\n *\n * The interpreted record value is either:\n * a) null, representing a non-existant or deletion of the record, or\n * b) a normalized, non-empty-string Name.\n *\n * @param value - The name record value string to interpret.\n * @returns The interpreted name string, or null if deleted.\n */\nexport function interpretNameRecordValue(value: string): NormalizedName | null {\n // empty string is technically a normalized name, representing the ens root node, but in the\n // context of a name record value, empty string is emitted when the user un-sets the record (this\n // is because the abi of this event is only capable of expressing string values, so empty string\n // canonically represents the non-existence or deletion of the record value)\n if (value === \"\") return null;\n\n // if not normalized, is not valid `name` record value\n if (!isNormalizedName(value)) return null;\n\n // otherwise, this is a non-empty-string normalized Name that can be used as a name() record value\n return value;\n}\n\n/**\n * Interprets an address record value string and returns null if the value is interpreted as a deletion.\n *\n * The interpreted record value is either:\n * a) null, representing a non-existant or deletion of the record, or\n * i. contains null bytes\n * ii. empty string\n * iii. empty hex (0x)\n * iv. zeroAddress\n * b) an address record value that\n * i. does not contain null bytes\n * ii. (if is an EVM address) is lowercase\n *\n * @param value - The address record value to interpret.\n * @returns The interpreted address string or null if deleted.\n */\nexport function interpretAddressRecordValue(value: string): string | null {\n // TODO(null-bytes): store null bytes correctly — for now, interpret as deletion\n if (hasNullByte(value)) return null;\n\n // interpret empty string as deletion of address record\n if (value === \"\") return null;\n\n // interpret empty bytes as deletion of address record\n if (value === \"0x\") return null;\n\n // if it's not an EVM address, return as-is\n if (!isAddress(value)) return value;\n\n // interpret zeroAddress as deletion\n if (isAddressEqual(value, zeroAddress)) return null;\n\n // otherwise convert to lowercase\n return asLowerCaseAddress(value);\n}\n\n/**\n * Interprets a text record key string and returns null if the key should be ignored.\n *\n * The interpreted text record key is either:\n * a) null, representing a text record key that should be ignored, or\n * i. contains null bytes\n * ii. empty string\n * b) a text record key that\n * i. does not contain null bytes\n *\n * @param value - The text record key to interpret.\n * @returns The interpreted text string or null if ignored.\n */\nexport function interpretTextRecordKey(key: string): string | null {\n // TODO(null-bytes): store null bytes correctly — for now, ignore\n if (hasNullByte(key)) return null;\n\n // ignore empty-string keys\n if (key === \"\") return null;\n\n // otherwise return the key as-is\n return key;\n}\n\n/**\n * Interprets a text record value string and returns null if the value is interpreted as a deletion.\n *\n * The interpreted record value is either:\n * a) null, representing a non-existant or deletion of the record, or\n * i. contains null bytes\n * ii. empty string\n * b) a text record value that\n * i. does not contain null bytes\n *\n * @param value - The text record value to interpret.\n * @returns The interpreted text string or null if deleted.\n */\nexport function interpretTextRecordValue(value: string): string | null {\n // TODO(null-bytes): store null bytes correctly — for now, interpret as deletion\n if (hasNullByte(value)) return null;\n\n // interpret empty string as deletion of a text record\n if (value === \"\") return null;\n\n // otherwise return the string as-is\n return value;\n}\n","export const hasNullByte = (value: string) => value.indexOf(\"\\u0000\") !== -1;\n\nexport const stripNullBytes = (value: string) => value.replaceAll(\"\\u0000\", \"\");\n","import { type LabelHash, type Node, uint256ToHex32 } from \"../../ens\";\n\n/**\n * Decodes a uint256-encoded-LabelHash (eg. from a tokenId) into a {@link LabelHash}.\n *\n * Remember that contracts that operate in the context of a Managed Name frequently store and operate\n * over _LabelHashes_ that represent a direct subname of a Managed Name. These contracts also frequently\n * implement ERC721 or ERC1155 to represent ownership of these Names. As such, to construct the\n * ERC721/ERC1155 tokenId, they may encode the direct subnames's LabelHash as a uint256.\n *\n * This is true for the ENSv1 BaseRegistrar, RegistrarControllers, as well as any\n * contracts forked from it (which includes Basenames' and Lineanames' implementations).\n *\n * So, in order to turn the tokenId into a LabelHash, we perform the opposite operation, decoding\n * from a uint256 into a Hex (of size 32) and cast it as our semantic {@link LabelHash} type.\n *\n * @see https://github.com/ensdomains/ens-contracts/blob/db613bc/contracts/ethregistrar/ETHRegistrarController.sol#L215\n * @see https://github.com/base/basenames/blob/1b5c1ad/src/L2/RegistrarController.sol#L488\n * @see https://github.com/Consensys/linea-ens/blob/3a4f02f/packages/linea-ens-contracts/contracts/ethregistrar/ETHRegistrarController.sol#L447\n */\nexport const interpretTokenIdAsLabelHash = (tokenId: bigint): LabelHash => uint256ToHex32(tokenId);\n\n/**\n * Decodes a uint256-encoded-Node (eg. from a tokenId) into a {@link Node}.\n *\n * Contracts in the ENSv1 ecosystem frequently implement ERC721 or ERC1155 to represent\n * ownership of a Domain. As such, to construct the ERC721/ERC1155 tokenId, they may encode the\n * domain's {@link Node} as a uint256.\n *\n * This is true for the ENSv1 NameWrapper, as well as any contracts forked from it (which includes\n * Lineanames' implementation).\n *\n * So, in order to turn the tokenId into a Node, we perform the opposite operation, decoding\n * from a uint256 into a Hex (of size 32) and cast it as our semantic {@link Node} type.\n *\n * @see https://github.com/ensdomains/ens-contracts/blob/db613bc/contracts/wrapper/ERC1155Fuse.sol#L262\n */\nexport const interpretTokenIdAsNode = (tokenId: bigint): Node => uint256ToHex32(tokenId);\n","import { isHex } from \"viem\";\nimport { labelhash } from \"viem/ens\";\n\nimport {\n encodeLabelHash,\n type InterpretedLabel,\n type InterpretedName,\n isNormalizedLabel,\n type Label,\n type LabelHash,\n type LabelHashPath,\n type LiteralLabel,\n type LiteralName,\n type Name,\n} from \"../../ens\";\nimport { labelhashLiteralLabel } from \"../labelhash\";\n\n/**\n * Interprets a Literal Label, producing an Interpreted Label.\n *\n * @see https://ensnode.io/docs/reference/terminology#literal-label\n * @see https://ensnode.io/docs/reference/terminology#interpreted-label\n *\n * @param label - The Literal Label string to interpret\n * @returns The provided label if it is a normalized label, else the EncodedLabelHash of the label\n */\nexport function literalLabelToInterpretedLabel(label: LiteralLabel): InterpretedLabel {\n // if the label is normalized, good to go\n if (isNormalizedLabel(label)) return label as Label as InterpretedLabel;\n\n // otherwise, encode the labelhash of the literal Label\n return encodeLabelHash(labelhashLiteralLabel(label)) as InterpretedLabel;\n}\n\n/**\n * Interprets an ordered list of Literal Labels, producing an Interpreted Name.\n *\n * Note that it's important that the Literal Labels are provided as an array, otherwise it's\n * impossible to differentiate between 'a.label.eth' being ['a.label', 'eth'] or ['a', 'label', 'eth'].\n *\n * Note that the input is an ordered list of _Literal_ Labels: in this context, any literal label\n * that is formatted as an Encoded LabelHash will NOT be interpreted as such. Instead it will be\n * interpreted into an Encoded LabelHash that encodes the literal labelhash of the Literal Label.\n *\n * @param labels An ordered list of 0 or more Literal Labels\n * @returns An InterpretedName\n */\nexport function literalLabelsToInterpretedName(labels: LiteralLabel[]): InterpretedName {\n return labels.map(literalLabelToInterpretedLabel).join(\".\") as InterpretedName;\n}\n\n/**\n * Joins the list of Interpreted Labels with '.' to form an Interpreted Name.\n *\n * @param labels An ordered list of 0 or more Interpreted Labels\n * @returns An InterpretedName\n */\nexport function interpretedLabelsToInterpretedName(labels: InterpretedLabel[]): InterpretedName {\n return labels.join(\".\") as InterpretedName;\n}\n\n/**\n * Joins the list of Literal Labels with '.' to form a Literal Name.\n *\n * Note: LiteralLabel values may contain '.' characters, which will be preserved\n * in the resulting LiteralName. Therefore, the number of labels in the returned\n * LiteralName may be greater than the number of LiteralLabels in the input array.\n *\n * @param labels An ordered list of 0 or more Literal Labels\n * @returns An LiteralName\n */\nexport function literalLabelsToLiteralName(labels: LiteralLabel[]): LiteralName {\n return labels.join(\".\") as LiteralName;\n}\n\n/**\n * Converts an Interpreted Name into a list of Interpreted Labels.\n */\nexport function interpretedNameToInterpretedLabels(name: InterpretedName): InterpretedLabel[] {\n return name.split(\".\") as InterpretedLabel[];\n}\n\n// https://github.com/wevm/viem/blob/main/src/utils/ens/encodedLabelToLabelhash.ts\nexport function encodedLabelToLabelhash(label: string): LabelHash | null {\n if (label.length !== 66) return null;\n if (label.indexOf(\"[\") !== 0) return null;\n if (label.indexOf(\"]\") !== 65) return null;\n const hash = `0x${label.slice(1, 65)}`;\n if (!isHex(hash)) return null;\n return hash;\n}\n\nexport function isInterpetedLabel(label: Label): label is InterpretedLabel {\n // if it looks like an encoded labelhash, it must be one\n if (label.startsWith(\"[\")) {\n const labelHash = encodedLabelToLabelhash(label);\n if (labelHash === null) return false;\n }\n\n // otherwise label must be normalized\n return isNormalizedLabel(label);\n}\n\nexport function isInterpretedName(name: Name): name is InterpretedName {\n return name.split(\".\").every(isInterpetedLabel);\n}\n\n/**\n * Converts an InterpretedName into a LabelHashPath.\n */\nexport function interpretedNameToLabelHashPath(name: InterpretedName): LabelHashPath {\n return interpretedNameToInterpretedLabels(name)\n .map((label) => {\n if (!isInterpetedLabel(label)) {\n throw new Error(\n `Invariant(interpretedNameToLabelHashPath): Expected InterpretedLabel, received '${label}'.`,\n );\n }\n\n // if it looks like an encoded labelhash, return it\n const maybeLabelHash = encodedLabelToLabelhash(label);\n if (maybeLabelHash !== null) return maybeLabelHash;\n\n // otherwise, labelhash it\n return labelhash(label);\n })\n .toReversed();\n}\n","import { keccak256, stringToBytes } from \"viem\";\n\nimport type { LabelHash, LiteralLabel } from \"../ens\";\n\n/**\n * Implements the ENS `labelhash` function for Literal Labels.\n * @see https://docs.ens.domains/ensip/1\n *\n * @param label the Literal Label to hash\n * @returns the hash of the provided label\n * @dev This function is viem/ens#labelhash but without the special-case handling of Encoded LabelHashes.\n */\nexport const labelhashLiteralLabel = (label: LiteralLabel): LabelHash =>\n keccak256(stringToBytes(label));\n","/**\n * Converts a bigint value into a number value.\n *\n * @throws when value is outside the range of `Number.MIN_SAFE_INTEGER` and\n * `Number.MAX_SAFE_INTEGER`.\n */\nexport function bigIntToNumber(n: bigint): number {\n if (n < Number.MIN_SAFE_INTEGER) {\n throw new Error(\n `The bigint '${n.toString()}' value is too low to be to converted into a number.'`,\n );\n }\n\n if (n > Number.MAX_SAFE_INTEGER) {\n throw new Error(\n `The bigint '${n.toString()}' value is too high to be to converted into a number.'`,\n );\n }\n\n return Number(n);\n}\n","import { DatasourceNames, type ENSNamespaceId } from \"@ensnode/datasources\";\nimport {\n type AccountId,\n accountIdEqual,\n getDatasourceContract,\n makeRegistryId,\n} from \"@ensnode/ensnode-sdk\";\n\n//////////////\n// ENSv1\n//////////////\n\n/**\n * Gets the AccountId representing the ENSv1 Registry in the selected `namespace`.\n */\nexport const getENSv1Registry = (namespace: ENSNamespaceId) =>\n getDatasourceContract(namespace, DatasourceNames.ENSRoot, \"ENSv1Registry\");\n\n/**\n * Determines whether `contract` is the ENSv1 Registry in `namespace`.\n */\nexport const isENSv1Registry = (namespace: ENSNamespaceId, contract: AccountId) =>\n accountIdEqual(getENSv1Registry(namespace), contract);\n\n//////////////\n// ENSv2\n//////////////\n\n/**\n * Gets the AccountId representing the ENSv2 Root Registry in the selected `namespace`.\n */\nexport const getENSv2RootRegistry = (namespace: ENSNamespaceId) =>\n getDatasourceContract(namespace, DatasourceNames.ENSRoot, \"RootRegistry\");\n\n/**\n * Gets the RegistryId representing the ENSv2 Root Registry in the selected `namespace`.\n */\nexport const getENSv2RootRegistryId = (namespace: ENSNamespaceId) =>\n makeRegistryId(getENSv2RootRegistry(namespace));\n\n/**\n * Determines whether `contract` is the ENSv2 Root Registry in `namespace`.\n */\nexport const isENSv2RootRegistry = (namespace: ENSNamespaceId, contract: AccountId) =>\n accountIdEqual(getENSv2RootRegistry(namespace), contract);\n","import { AccountId as CaipAccountId, AssetId as CaipAssetId } from \"caip\";\n\nimport { uint256ToHex32 } from \"../ens\";\nimport type { Price, PriceEth, SerializedPrice, SerializedPriceEth } from \"./currencies\";\nimport type {\n AccountIdString,\n AssetIdString,\n ChainIdString,\n DatetimeISO8601,\n UrlString,\n} from \"./serialized-types\";\nimport type { AccountId, AssetId, ChainId, Datetime } from \"./types\";\n\n/**\n * Serializes a {@link ChainId} value into its string representation.\n */\nexport function serializeChainId(chainId: ChainId): ChainIdString {\n return chainId.toString();\n}\n\n/**\n * Serializes a {@link Datetime} value into its string representation.\n */\nexport function serializeDatetime(datetime: Datetime): DatetimeISO8601 {\n return datetime.toISOString();\n}\n\n/**\n * Serializes a {@link URL} value into its string representation.\n */\nexport function serializeUrl(url: URL): UrlString {\n return url.toString();\n}\n\n/**\n * Serializes a {@link Price} object.\n */\nexport function serializePrice(price: Price): SerializedPrice {\n return {\n currency: price.currency,\n amount: price.amount.toString(),\n };\n}\n\n/**\n * Serializes a {@link PriceEth} object.\n */\nexport function serializePriceEth(price: PriceEth): SerializedPriceEth {\n return serializePrice(price) as SerializedPriceEth;\n}\n\n/**\n * Format {@link AccountId} object as a string.\n *\n * Formatted as a fully lowercase CAIP-10 AccountId.\n *\n * @see https://chainagnostic.org/CAIPs/caip-10\n */\nexport function formatAccountId(accountId: AccountId): AccountIdString {\n return CaipAccountId.format({\n chainId: { namespace: \"eip155\", reference: accountId.chainId.toString() },\n address: accountId.address,\n }).toLowerCase();\n}\n\n/**\n * Format {@link AssetId} object as a string.\n *\n * Formatted as a fully lowercase CAIP-19 AssetId.\n *\n * @see https://chainagnostic.org/CAIPs/caip-19\n */\nexport function formatAssetId({\n assetNamespace,\n contract: { chainId, address },\n tokenId,\n}: AssetId): AssetIdString {\n return CaipAssetId.format({\n chainId: { namespace: \"eip155\", reference: chainId.toString() },\n assetName: { namespace: assetNamespace, reference: address },\n tokenId: uint256ToHex32(tokenId),\n }).toLowerCase();\n}\n","import type { Address } from \"viem\";\n\nimport type { DEFAULT_EVM_CHAIN_ID } from \"../ens\";\n\n/**\n * Chain ID\n *\n * Represents a unique identifier for a chain.\n * Guaranteed to be a positive integer.\n *\n * Chain id standards are organized by the Ethereum Community @ https://github.com/ethereum-lists/chains\n **/\nexport type ChainId = number;\n\n/**\n * Defaultable Chain ID\n *\n * Represents a unique identifier for a chain, or\n * the default chain as defined by ENSIP-19.\n *\n * @see https://docs.ens.domains/ensip/19/#annex-supported-chains\n *\n * Guaranteed to be a non-negative integer.\n **/\nexport type DefaultableChainId = typeof DEFAULT_EVM_CHAIN_ID | ChainId;\n\n/**\n * Represents an account (contract or EOA) at `address` on chain `chainId`.\n *\n * @see https://chainagnostic.org/CAIPs/caip-10\n */\nexport interface AccountId {\n chainId: ChainId;\n address: Address;\n}\n\n/**\n * An enum representing the possible CAIP-19 Asset Namespace values.\n *\n * @see https://chainagnostic.org/CAIPs/caip-19\n */\nexport const AssetNamespaces = {\n ERC721: \"erc721\",\n ERC1155: \"erc1155\",\n} as const;\n\nexport type AssetNamespace = (typeof AssetNamespaces)[keyof typeof AssetNamespaces];\n\n/**\n * A uint256 value that identifies a specific NFT within a NFT contract.\n */\nexport type TokenId = bigint;\n\n/**\n * Represents an Asset in `assetNamespace` by `tokenId` in `contract`.\n *\n * @see https://chainagnostic.org/CAIPs/caip-19\n */\nexport interface AssetId {\n assetNamespace: AssetNamespace;\n contract: AccountId;\n tokenId: TokenId;\n}\n\n/**\n * Block Number\n *\n * Guaranteed to be a non-negative integer.\n */\nexport type BlockNumber = number;\n\n/**\n * Datetime value\n */\nexport type Datetime = Date;\n\n/**\n * Unix timestamp value\n *\n * Represents the number of seconds that have elapsed\n * since January 1, 1970 (midnight UTC/GMT).\n *\n * Guaranteed to be an integer. May be zero or negative to represent a time at or\n * before Jan 1, 1970.\n */\nexport type UnixTimestamp = number;\n\n/**\n * Represents a URL that is used for RPC endpoints.\n */\nexport type RpcUrl = URL;\n\n/**\n * BlockRef\n *\n * Describes a block.\n *\n * We use parameter types to maintain fields layout and documentation across\n * the domain model and its serialized counterpart.\n */\nexport interface BlockRef {\n /** Block number (height) */\n number: BlockNumber;\n\n /** Block timestamp */\n timestamp: UnixTimestamp;\n}\n\n/**\n * Block range\n *\n * Represents a range of blocks\n */\nexport interface Blockrange<BlockType = BlockNumber> {\n /** Start block number */\n startBlock?: BlockType;\n\n /** End block number */\n endBlock?: BlockType;\n}\n\n/**\n * Duration\n *\n * Representing a duration in seconds.\n *\n * Guaranteed to be a non-negative integer.\n */\nexport type Duration = number;\n\n/**\n * A utility type that makes all properties of a type optional recursively,\n * including nested objects and arrays.\n *\n * @example\n * ```typescript\n * type Config = {\n * a: string;\n * b: {\n * x: number;\n * y: { z: boolean };\n * };\n * c: { id: string }[];\n * }\n *\n * type PartialConfig = DeepPartial<Config>;\n * // Results in:\n * // {\n * // a?: string;\n * // b?: {\n * // x?: number;\n * // y?: { z?: boolean };\n * // };\n * // c?: { id?: string }[];\n * // }\n *\n * // Usage:\n * const update: PartialConfig = { b: { y: { z: true } } };\n * ```\n */\nexport type DeepPartial<T> = {\n [P in keyof T]?: T[P] extends (infer U)[]\n ? DeepPartial<U>[]\n : T[P] extends object\n ? DeepPartial<T[P]>\n : T[P];\n};\n\n/**\n * Marks keys in K as required (not undefined) and not null.\n */\nexport type RequiredAndNotNull<T, K extends keyof T> = T & {\n [P in K]-?: NonNullable<T[P]>;\n};\n","export function isHttpProtocol(url: URL): boolean {\n return [\"http:\", \"https:\"].includes(url.protocol);\n}\n\nexport function isWebSocketProtocol(url: URL): boolean {\n return [\"ws:\", \"wss:\"].includes(url.protocol);\n}\n","import { ENSNamespaceIds } from \"@ensnode/datasources\";\n\nimport { type ENSIndexerPublicConfig, PluginName } from \"./types\";\n\n/**\n * Determines if the provided `config` results in indexing behavior compatible with the legacy ENS\n * Subgraph.\n *\n * @see https://ensnode.io/docs/concepts/what-is-the-ens-subgraph/\n */\nexport function isSubgraphCompatible(\n config: Pick<ENSIndexerPublicConfig, \"namespace\" | \"plugins\" | \"labelSet\">,\n): boolean {\n // 1. only the subgraph plugin is active\n const onlySubgraphPluginActivated =\n config.plugins.length === 1 && config.plugins[0] === PluginName.Subgraph;\n\n // 2. label set id must be \"subgraph\" and version must be 0\n const isSubgraphLabelSet =\n config.labelSet.labelSetId === \"subgraph\" && config.labelSet.labelSetVersion === 0;\n\n const isEnsTestEnvLabelSet =\n config.labelSet.labelSetId === \"ens-test-env\" && config.labelSet.labelSetVersion === 0;\n\n // config should be considered subgraph-compatible if in ens-test-env namespace with ens-test-env labelset\n const labelSetIsSubgraphCompatible =\n isSubgraphLabelSet || (config.namespace === ENSNamespaceIds.EnsTestEnv && isEnsTestEnvLabelSet);\n\n return onlySubgraphPluginActivated && labelSetIsSubgraphCompatible;\n}\n","import type { ENSNamespaceId } from \"@ensnode/datasources\";\n\nimport type { EnsRainbowClientLabelSet } from \"../../ensrainbow\";\nimport type { ChainId } from \"../../shared\";\n\n/**\n * A PluginName is a unique id for a 'plugin': we use the notion of\n * 'plugins' to describe bundles of indexing logic.\n */\nexport enum PluginName {\n Subgraph = \"subgraph\",\n Basenames = \"basenames\",\n Lineanames = \"lineanames\",\n ThreeDNS = \"threedns\",\n ProtocolAcceleration = \"protocol-acceleration\",\n Registrars = \"registrars\",\n TokenScope = \"tokenscope\",\n ENSv2 = \"ensv2\",\n}\n\n/**\n * Version info about ENSIndexer and its dependencies.\n */\nexport interface ENSIndexerVersionInfo {\n /**\n * Node.js runtime version\n *\n * @see https://nodejs.org/en/about/previous-releases\n **/\n nodejs: string;\n\n /**\n * Ponder framework version\n *\n * @see https://www.npmjs.com/package/ponder\n **/\n ponder: string;\n\n /**\n * ENSDb service version\n *\n * Guaranteed to be the same as {@link ENSIndexerVersionInfo.ensIndexer}.\n * */\n ensDb: string;\n\n /**\n * ENSIndexer service version\n *\n * @see https://ghcr.io/namehash/ensnode/ensindexer\n **/\n ensIndexer: string;\n\n /**\n * ENSRainbow service version\n *\n * @see https://ghcr.io/namehash/ensnode/ensindexer\n **/\n ensRainbow: string;\n\n /**\n * ENSRainbow schema version\n **/\n ensRainbowSchema: number;\n\n /**\n * ENS Normalize package version\n *\n * Available on NPM as: `@adraffy/ens-normalize`\n *\n * @see https://www.npmjs.com/package/@adraffy/ens-normalize\n **/\n ensNormalize: string;\n}\n\n/**\n * Complete public configuration object for ENSIndexer.\n *\n * We use parameter types to maintain fields layout and documentation across\n * the domain model and its serialized counterpart.\n */\nexport interface ENSIndexerPublicConfig {\n /**\n * The ENS namespace that ENSNode operates in the context of.\n *\n * See {@link ENSNamespaceIds} for available namespace identifiers.\n */\n namespace: ENSNamespaceId;\n\n /**\n * The \"fully pinned\" label set reference that ENSIndexer will request ENSRainbow use for deterministic label healing across time. This label set reference is \"fully pinned\" as it requires both the labelSetId and labelSetVersion fields to be defined.\n */\n labelSet: Required<EnsRainbowClientLabelSet>;\n\n /**\n * A Postgres database schema name. This instance of ENSIndexer will write\n * indexed data to the tables in this schema.\n *\n * Invariants:\n * - Must be a non-empty string that is a valid Postgres database schema\n * identifier.\n */\n databaseSchemaName: string;\n\n /**\n * A set of strings referring to the names of plugins that are active.\n *\n * For future-proofing, this is a list of strings that may or may\n * not be currently valid {@link PluginName} values.\n *\n * Invariants:\n * - A set of strings with at least one value.\n */\n plugins: string[];\n\n /**\n * Indexed Chain IDs\n *\n * Includes the {@link ChainId} for each chain being indexed.\n */\n indexedChainIds: Set<ChainId>;\n\n /**\n * A feature flag to enable/disable ENSIndexer's Subgraph Compatible Indexing Behavior.\n *\n * If {@link isSubgraphCompatible} is true, indexing behavior will match that of the legacy ENS\n * Subgraph.\n *\n * ENSIndexer will store and return Literal Labels and Literal Names without further interpretation.\n * @see https://ensnode.io/docs/reference/terminology#literal-label\n * @see https://ensnode.io/docs/reference/terminology#literal-name\n *\n * If {@link isSubgraphCompatible} is true, the following invariants are true for the ENSIndexerConfig:\n * 1. only the 'subgraph' plugin is enabled, and\n * 2. the labelSet must be { labelSetId: 'subgraph', labelSetVersion: 0 }\n *\n * If {@link isSubgraphCompatible} is false, ENSIndexer will additionally:\n *\n * 1. ENSIndexer will heal all subnames of addr.reverse on the ENS Root Chain.\n *\n * 2. ENSIndexer will track both the keys and the values of Resolver records.\n *\n * WARNING: Special care must be taken when interacting with indexed resolver record values. It\n * is unsafe to naively assume that indexed resolver record values are equivalent to the\n * resolver record values that would be returned through dynamic lookups via the ENS protocol.\n * For example, if a resolver implements CCIP-Read, the resolver records may not be\n * discoverable through onchain indexing.\n *\n * 3. Literal Labels and Literal Names encountered by ENSIndexer will be Interpreted.\n * @see https://ensnode.io/docs/reference/terminology#interpreted-label\n * @see https://ensnode.io/docs/reference/terminology#interpreted-name\n *\n * That is,\n * a) all Labels stored and returned by ENSIndexer will be Interpreted Labels, which are either:\n * i. normalized, or\n * ii. represented as an Encoded LabelHash of the Literal Label value found onchain, and\n * b) all Names stored and returned by ENSIndexer will be Interpreted Names, which are exclusively\n * composed of Interpreted Labels.\n */\n isSubgraphCompatible: boolean;\n\n /**\n * Version info about ENSIndexer.\n */\n versionInfo: ENSIndexerVersionInfo;\n}\n","import type { ZodCheckFnInput } from \"../../shared/zod-types\";\nimport type { ENSIndexerVersionInfo } from \"./types\";\n\n/**\n * Invariant: ensDb version is same as ensIndexer version\n */\nexport function invariant_ensDbVersionIsSameAsEnsIndexerVersion(\n ctx: ZodCheckFnInput<ENSIndexerVersionInfo>,\n) {\n const versionInfo = ctx.value;\n\n if (versionInfo.ensDb !== versionInfo.ensIndexer) {\n ctx.issues.push({\n code: \"custom\",\n input: versionInfo,\n message: \"`ensDb` version must be same as `ensIndexer` version\",\n });\n }\n}\n","import { z } from \"zod/v4\";\n\n/**\n * Reasons why TheGraph fallback cannot be used.\n */\nexport const TheGraphCannotFallbackReasonSchema = z.enum({\n NotSubgraphCompatible: \"not-subgraph-compatible\",\n NoApiKey: \"no-api-key\",\n NoSubgraphUrl: \"no-subgraph-url\",\n});\n\nexport type TheGraphCannotFallbackReason = z.infer<typeof TheGraphCannotFallbackReasonSchema>;\n\n/**\n * Configuration for TheGraph fallback behavior.\n * Indicates whether fallback to TheGraph is possible and the reason if not.\n */\nexport const TheGraphFallbackSchema = z.discriminatedUnion(\"canFallback\", [\n z.strictObject({\n canFallback: z.literal(true),\n url: z.string(),\n }),\n z.strictObject({\n canFallback: z.literal(false),\n reason: TheGraphCannotFallbackReasonSchema,\n }),\n]);\n\nexport type TheGraphFallback = z.infer<typeof TheGraphFallbackSchema>;\n","import { prettifyError } from \"zod/v4\";\n\nimport type { SerializedENSIndexerPublicConfig } from \"./serialized-types\";\nimport type { ENSIndexerPublicConfig } from \"./types\";\nimport { makeENSIndexerPublicConfigSchema } from \"./zod-schemas\";\n\n/**\n * Serialize a {@link ENSIndexerPublicConfig} object.\n */\nexport function deserializeENSIndexerPublicConfig(\n maybeConfig: SerializedENSIndexerPublicConfig,\n valueLabel?: string,\n): ENSIndexerPublicConfig {\n const schema = makeENSIndexerPublicConfigSchema(valueLabel);\n const parsed = schema.safeParse(maybeConfig);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize ENSIndexerPublicConfig:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n","import { type ByteArray, hexToBytes } from \"viem\";\n\nimport type { LabelHash } from \"../../ens\";\n\n/**\n * Converts a Labelhash to bytes, with validation\n * @param labelHash The Labelhash to convert\n * @returns A ByteArray containing the bytes\n * @throws Error if `labelHash` is not a valid 32-byte hex string\n */\nexport function labelHashToBytes(labelHash: LabelHash): ByteArray {\n try {\n if (labelHash.length !== 66) {\n throw new Error(`Invalid labelHash length ${labelHash.length} characters (expected 66)`);\n }\n if (labelHash !== labelHash.toLowerCase()) {\n throw new Error(\"Labelhash must be in lowercase\");\n }\n if (!labelHash.startsWith(\"0x\")) {\n throw new Error(\"Labelhash must be 0x-prefixed\");\n }\n const bytes = hexToBytes(labelHash);\n if (bytes.length !== 32) {\n // should be redundant but keeping it for the principle of defensive programming\n throw new Error(`Invalid labelHash length ${bytes.length} bytes (expected 32)`);\n }\n return bytes;\n } catch (e) {\n if (e instanceof Error) {\n throw e;\n }\n throw new Error(\"Invalid hex format\");\n }\n}\n","import type {\n EnsRainbowClientLabelSet,\n EnsRainbowServerLabelSet,\n LabelSetId,\n LabelSetVersion,\n} from \"../../ensrainbow\";\nimport { makeLabelSetIdSchema, makeLabelSetVersionSchema } from \"./zod-schemas\";\n\n/**\n * Builds a valid LabelSetId from a string.\n * @param maybeLabelSetId - The string to validate and convert to a LabelSetId.\n * @returns A valid LabelSetId.\n * @throws If the input string is not a valid LabelSetId.\n */\nexport function buildLabelSetId(maybeLabelSetId: string): LabelSetId {\n return makeLabelSetIdSchema(\"LabelSetId\").parse(maybeLabelSetId);\n}\n\n/**\n * Builds a valid LabelSetVersion from a number or string.\n * @param maybeLabelSetVersion - The number or string to validate and convert to a LabelSetVersion.\n * @returns A valid LabelSetVersion.\n * @throws If the input is not a valid LabelSetVersion.\n */\nexport function buildLabelSetVersion(maybeLabelSetVersion: number | string): LabelSetVersion {\n return makeLabelSetVersionSchema(\"LabelSetVersion\").parse(maybeLabelSetVersion);\n}\n\n/**\n * Builds an EnsRainbowClientLabelSet.\n * @param labelSetId - The label set ID.\n * @param labelSetVersion - The label set version.\n * @returns A valid EnsRainbowClientLabelSet object.\n * @throws If `labelSetVersion` is defined without `labelSetId`.\n */\nexport function buildEnsRainbowClientLabelSet(\n labelSetId?: LabelSetId,\n labelSetVersion?: LabelSetVersion,\n): EnsRainbowClientLabelSet {\n if (labelSetVersion !== undefined && labelSetId === undefined) {\n throw new Error(\"When a labelSetVersion is defined, labelSetId must also be defined.\");\n }\n\n return { labelSetId, labelSetVersion };\n}\n\n/**\n * Validates that the server's label set is compatible with the client's requested label set.\n * @param serverSet - The label set provided by the server.\n * @param clientSet - The label set requested by the client.\n * @throws If the server set is not compatible with the client set.\n */\nexport function validateSupportedLabelSetAndVersion(\n serverSet: EnsRainbowServerLabelSet,\n clientSet: EnsRainbowClientLabelSet,\n): void {\n if (clientSet.labelSetId === undefined) {\n // Client did not specify a label set, so any server set is acceptable.\n return;\n }\n\n if (serverSet.labelSetId !== clientSet.labelSetId) {\n throw new Error(\n `Server label set ID \"${serverSet.labelSetId}\" does not match client's requested label set ID \"${clientSet.labelSetId}\".`,\n );\n }\n\n if (\n clientSet.labelSetVersion !== undefined &&\n serverSet.highestLabelSetVersion < clientSet.labelSetVersion\n ) {\n throw new Error(\n `Server highest label set version ${serverSet.highestLabelSetVersion} is less than client's requested version ${clientSet.labelSetVersion} for label set ID \"${clientSet.labelSetId}\".`,\n );\n }\n}\n","/**\n * Parses a string into a non-negative integer.\n * @param input The string to parse\n * @returns The parsed non-negative integer\n * @throws Error if the input is not a valid non-negative integer\n */\nexport function parseNonNegativeInteger(maybeNumber: string): number {\n const trimmed = maybeNumber.trim();\n\n // Check for empty strings\n if (!trimmed) {\n throw new Error(\"Input cannot be empty\");\n }\n\n // Check for -0\n if (trimmed === \"-0\") {\n throw new Error(\"Negative zero is not a valid non-negative integer\");\n }\n\n const num = Number(maybeNumber);\n\n // Check if it's not a number\n if (Number.isNaN(num)) {\n throw new Error(`\"${maybeNumber}\" is not a valid number`);\n }\n\n // Check if it's not finite\n if (!Number.isFinite(num)) {\n throw new Error(`\"${maybeNumber}\" is not a finite number`);\n }\n\n // Check if it's not an integer\n if (!Number.isInteger(num)) {\n throw new Error(`\"${maybeNumber}\" is not an integer`);\n }\n\n // Check if it's negative\n if (num < 0) {\n throw new Error(`\"${maybeNumber}\" is not a non-negative integer`);\n }\n\n return num;\n}\n","import type { ChainId } from \"../../shared\";\nimport type {\n SerializedENSIndexerPublicConfig,\n SerializedIndexedChainIds,\n} from \"./serialized-types\";\nimport type { ENSIndexerPublicConfig } from \"./types\";\n\n/**\n * Serializes a {@link ChainConfig} object.\n */\nexport function serializeIndexedChainIds(indexedChainIds: Set<ChainId>): SerializedIndexedChainIds {\n return Array.from(indexedChainIds);\n}\n/**\n * Serialize a {@link ENSIndexerPublicConfig} object.\n */\nexport function serializeENSIndexerPublicConfig(\n config: ENSIndexerPublicConfig,\n): SerializedENSIndexerPublicConfig {\n const {\n labelSet,\n indexedChainIds,\n databaseSchemaName,\n isSubgraphCompatible,\n namespace,\n plugins,\n versionInfo,\n } = config;\n\n return {\n labelSet,\n indexedChainIds: serializeIndexedChainIds(indexedChainIds),\n databaseSchemaName,\n isSubgraphCompatible,\n namespace,\n plugins,\n versionInfo,\n } satisfies SerializedENSIndexerPublicConfig;\n}\n","import { prettifyError } from \"zod/v4\";\n\nimport type {\n SerializedChainIndexingStatusSnapshot,\n SerializedCrossChainIndexingStatusSnapshot,\n SerializedOmnichainIndexingStatusSnapshot,\n SerializedRealtimeIndexingStatusProjection,\n} from \"./serialized-types\";\nimport type {\n ChainIndexingStatusSnapshot,\n CrossChainIndexingStatusSnapshot,\n OmnichainIndexingStatusSnapshot,\n RealtimeIndexingStatusProjection,\n} from \"./types\";\nimport {\n makeChainIndexingStatusSnapshotSchema,\n makeCrossChainIndexingStatusSnapshotSchema,\n makeOmnichainIndexingStatusSnapshotSchema,\n makeRealtimeIndexingStatusProjectionSchema,\n} from \"./zod-schemas\";\n\n/**\n * Deserialize into a {@link ChainIndexingSnapshot} object.\n */\nexport function deserializeChainIndexingStatusSnapshot(\n maybeSnapshot: SerializedChainIndexingStatusSnapshot,\n valueLabel?: string,\n): ChainIndexingStatusSnapshot {\n const schema = makeChainIndexingStatusSnapshotSchema(valueLabel);\n const parsed = schema.safeParse(maybeSnapshot);\n\n if (parsed.error) {\n throw new Error(\n `Cannot deserialize into ChainIndexingStatusSnapshot:\\n${prettifyError(parsed.error)}\\n`,\n );\n }\n\n return parsed.data;\n}\n\n/**\n * Deserialize an {@link OmnichainIndexingStatusSnapshot} object.\n */\nexport function deserializeOmnichainIndexingStatusSnapshot(\n maybeSnapshot: SerializedOmnichainIndexingStatusSnapshot,\n valueLabel?: string,\n): OmnichainIndexingStatusSnapshot {\n const schema = makeOmnichainIndexingStatusSnapshotSchema(valueLabel);\n const parsed = schema.safeParse(maybeSnapshot);\n\n if (parsed.error) {\n throw new Error(\n `Cannot deserialize into OmnichainIndexingStatusSnapshot:\\n${prettifyError(parsed.error)}\\n`,\n );\n }\n\n return parsed.data;\n}\n\n/**\n * Deserialize an {@link CrossChainIndexingStatusSnapshot} object.\n */\nexport function deserializeCrossChainIndexingStatusSnapshot(\n maybeSnapshot: SerializedCrossChainIndexingStatusSnapshot,\n valueLabel?: string,\n): CrossChainIndexingStatusSnapshot {\n const schema = makeCrossChainIndexingStatusSnapshotSchema(valueLabel);\n const parsed = schema.safeParse(maybeSnapshot);\n\n if (parsed.error) {\n throw new Error(\n `Cannot deserialize into CrossChainIndexingStatusSnapshot:\\n${prettifyError(parsed.error)}\\n`,\n );\n }\n\n return parsed.data;\n}\n\n/**\n * Deserialize into a {@link RealtimeIndexingStatusProjection} object.\n */\nexport function deserializeRealtimeIndexingStatusProjection(\n maybeProjection: SerializedRealtimeIndexingStatusProjection,\n valueLabel?: string,\n): RealtimeIndexingStatusProjection {\n const schema = makeRealtimeIndexingStatusProjectionSchema(valueLabel);\n const parsed = schema.safeParse(maybeProjection);\n\n if (parsed.error) {\n throw new Error(\n `Cannot deserialize into RealtimeIndexingStatusProjection:\\n${prettifyError(parsed.error)}\\n`,\n );\n }\n\n return parsed.data;\n}\n","/**\n * All zod schemas we define must remain internal implementation details.\n * We want the freedom to move away from zod in the future without impacting\n * any users of the ensnode-sdk package.\n *\n * The only way to share Zod schemas is to re-export them from\n * `./src/internal.ts` file.\n */\nimport { z } from \"zod/v4\";\n\nimport { type ChainId, deserializeChainId } from \"../../shared\";\nimport {\n makeBlockRefSchema,\n makeChainIdStringSchema,\n makeDurationSchema,\n makeUnixTimestampSchema,\n} from \"../../shared/zod-schemas\";\nimport {\n ChainIndexingConfig,\n ChainIndexingConfigTypeIds,\n ChainIndexingStatusIds,\n type ChainIndexingStatusSnapshot,\n ChainIndexingStatusSnapshotBackfill,\n type ChainIndexingStatusSnapshotCompleted,\n ChainIndexingStatusSnapshotFollowing,\n type ChainIndexingStatusSnapshotForOmnichainIndexingStatusSnapshotBackfill,\n type ChainIndexingStatusSnapshotQueued,\n CrossChainIndexingStatusSnapshot,\n CrossChainIndexingStatusSnapshotOmnichain,\n CrossChainIndexingStrategyIds,\n OmnichainIndexingStatusIds,\n OmnichainIndexingStatusSnapshotBackfill,\n OmnichainIndexingStatusSnapshotCompleted,\n OmnichainIndexingStatusSnapshotFollowing,\n OmnichainIndexingStatusSnapshotUnstarted,\n RealtimeIndexingStatusProjection,\n} from \"./types\";\nimport {\n invariant_chainSnapshotBackfillBlocks,\n invariant_chainSnapshotCompletedBlocks,\n invariant_chainSnapshotFollowingBlocks,\n invariant_chainSnapshotQueuedBlocks,\n invariant_omnichainIndexingCursorIsEqualToHighestLatestIndexedBlockAcrossIndexedChain,\n invariant_omnichainIndexingCursorLowerThanEarliestStartBlockAcrossQueuedChains,\n invariant_omnichainIndexingCursorLowerThanOrEqualToLatestBackfillEndBlockAcrossBackfillChains,\n invariant_omnichainSnapshotStatusIsConsistentWithChainSnapshot,\n invariant_omnichainSnapshotUnstartedHasValidChains,\n invariant_omnichainStatusSnapshotBackfillHasValidChains,\n invariant_omnichainStatusSnapshotCompletedHasValidChains,\n invariant_realtimeIndexingStatusProjectionProjectedAtIsAfterOrEqualToSnapshotTime,\n invariant_realtimeIndexingStatusProjectionWorstCaseDistanceIsCorrect,\n invariant_slowestChainEqualsToOmnichainSnapshotTime,\n invariant_snapshotTimeIsTheHighestKnownBlockTimestamp,\n} from \"./validations\";\n\n/**\n * Makes Zod schema for {@link ChainIndexingConfig} type.\n */\nconst makeChainIndexingConfigSchema = (valueLabel: string = \"Value\") =>\n z.discriminatedUnion(\"configType\", [\n z.strictObject({\n configType: z.literal(ChainIndexingConfigTypeIds.Indefinite),\n startBlock: makeBlockRefSchema(valueLabel),\n }),\n z.strictObject({\n configType: z.literal(ChainIndexingConfigTypeIds.Definite),\n startBlock: makeBlockRefSchema(valueLabel),\n endBlock: makeBlockRefSchema(valueLabel),\n }),\n ]);\n\n/**\n * Makes Zod schema for {@link ChainIndexingStatusSnapshotQueued} type.\n */\nexport const makeChainIndexingStatusSnapshotQueuedSchema = (valueLabel: string = \"Value\") =>\n z\n .strictObject({\n chainStatus: z.literal(ChainIndexingStatusIds.Queued),\n config: makeChainIndexingConfigSchema(valueLabel),\n })\n .check(invariant_chainSnapshotQueuedBlocks);\n\n/**\n * Makes Zod schema for {@link ChainIndexingStatusSnapshotBackfill} type.\n */\nexport const makeChainIndexingStatusSnapshotBackfillSchema = (valueLabel: string = \"Value\") =>\n z\n .strictObject({\n chainStatus: z.literal(ChainIndexingStatusIds.Backfill),\n config: makeChainIndexingConfigSchema(valueLabel),\n latestIndexedBlock: makeBlockRefSchema(valueLabel),\n backfillEndBlock: makeBlockRefSchema(valueLabel),\n })\n .check(invariant_chainSnapshotBackfillBlocks);\n\n/**\n * Makes Zod schema for {@link ChainIndexingStatusSnapshotCompleted} type.\n */\nexport const makeChainIndexingStatusSnapshotCompletedSchema = (valueLabel: string = \"Value\") =>\n z\n .strictObject({\n chainStatus: z.literal(ChainIndexingStatusIds.Completed),\n config: z.strictObject({\n configType: z.literal(ChainIndexingConfigTypeIds.Definite),\n startBlock: makeBlockRefSchema(valueLabel),\n endBlock: makeBlockRefSchema(valueLabel),\n }),\n latestIndexedBlock: makeBlockRefSchema(valueLabel),\n })\n .check(invariant_chainSnapshotCompletedBlocks);\n\n/**\n * Makes Zod schema for {@link ChainIndexingStatusSnapshotFollowing} type.\n */\nexport const makeChainIndexingStatusSnapshotFollowingSchema = (valueLabel: string = \"Value\") =>\n z\n .strictObject({\n chainStatus: z.literal(ChainIndexingStatusIds.Following),\n config: z.strictObject({\n configType: z.literal(ChainIndexingConfigTypeIds.Indefinite),\n startBlock: makeBlockRefSchema(valueLabel),\n }),\n latestIndexedBlock: makeBlockRefSchema(valueLabel),\n latestKnownBlock: makeBlockRefSchema(valueLabel),\n })\n .check(invariant_chainSnapshotFollowingBlocks);\n\n/**\n * Makes Zod schema for {@link ChainIndexingStatusSnapshot}\n */\nexport const makeChainIndexingStatusSnapshotSchema = (valueLabel: string = \"Value\") =>\n z.discriminatedUnion(\"chainStatus\", [\n makeChainIndexingStatusSnapshotQueuedSchema(valueLabel),\n makeChainIndexingStatusSnapshotBackfillSchema(valueLabel),\n makeChainIndexingStatusSnapshotCompletedSchema(valueLabel),\n makeChainIndexingStatusSnapshotFollowingSchema(valueLabel),\n ]);\n\n/**\n * Makes Zod schema for {@link ChainIndexingStatusSnapshot} per chain.\n */\nexport const makeChainIndexingStatusesSchema = (valueLabel: string = \"Value\") =>\n z\n .record(makeChainIdStringSchema(), makeChainIndexingStatusSnapshotSchema(valueLabel), {\n error:\n \"Chains indexing statuses must be an object mapping valid chain IDs to their indexing status snapshots.\",\n })\n .transform((serializedChainsIndexingStatus) => {\n const chainsIndexingStatus = new Map<ChainId, ChainIndexingStatusSnapshot>();\n\n for (const [chainIdString, chainStatus] of Object.entries(serializedChainsIndexingStatus)) {\n chainsIndexingStatus.set(deserializeChainId(chainIdString), chainStatus);\n }\n\n return chainsIndexingStatus;\n });\n\n/**\n * Makes Zod schema for {@link OmnichainIndexingStatusSnapshotUnstarted}\n */\nconst makeOmnichainIndexingStatusSnapshotUnstartedSchema = (valueLabel?: string) =>\n z.strictObject({\n omnichainStatus: z.literal(OmnichainIndexingStatusIds.Unstarted),\n chains: makeChainIndexingStatusesSchema(valueLabel)\n .check(invariant_omnichainSnapshotUnstartedHasValidChains)\n .transform((chains) => chains as Map<ChainId, ChainIndexingStatusSnapshotQueued>),\n omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel),\n });\n\n/**\n * Makes Zod schema for {@link OmnichainIndexingStatusSnapshotBackfill}\n */\nconst makeOmnichainIndexingStatusSnapshotBackfillSchema = (valueLabel?: string) =>\n z.strictObject({\n omnichainStatus: z.literal(OmnichainIndexingStatusIds.Backfill),\n chains: makeChainIndexingStatusesSchema(valueLabel)\n .check(invariant_omnichainStatusSnapshotBackfillHasValidChains)\n .transform(\n (chains) =>\n chains as Map<\n ChainId,\n ChainIndexingStatusSnapshotForOmnichainIndexingStatusSnapshotBackfill\n >,\n ),\n omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel),\n });\n\n/**\n * Makes Zod schema for {@link OmnichainIndexingStatusSnapshotCompleted}\n */\nconst makeOmnichainIndexingStatusSnapshotCompletedSchema = (valueLabel?: string) =>\n z.strictObject({\n omnichainStatus: z.literal(OmnichainIndexingStatusIds.Completed),\n chains: makeChainIndexingStatusesSchema(valueLabel)\n .check(invariant_omnichainStatusSnapshotCompletedHasValidChains)\n .transform((chains) => chains as Map<ChainId, ChainIndexingStatusSnapshotCompleted>),\n omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel),\n });\n\n/**\n * Makes Zod schema for {@link OmnichainIndexingStatusSnapshotFollowing}\n */\nconst makeOmnichainIndexingStatusSnapshotFollowingSchema = (valueLabel?: string) =>\n z.strictObject({\n omnichainStatus: z.literal(OmnichainIndexingStatusIds.Following),\n chains: makeChainIndexingStatusesSchema(valueLabel),\n omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel),\n });\n\n/**\n * Omnichain Indexing Snapshot Schema\n *\n * Makes a Zod schema definition for validating indexing snapshot\n * across all chains indexed by ENSIndexer instance.\n */\nexport const makeOmnichainIndexingStatusSnapshotSchema = (\n valueLabel: string = \"Omnichain Indexing Snapshot\",\n) =>\n z\n .discriminatedUnion(\"omnichainStatus\", [\n makeOmnichainIndexingStatusSnapshotUnstartedSchema(valueLabel),\n makeOmnichainIndexingStatusSnapshotBackfillSchema(valueLabel),\n makeOmnichainIndexingStatusSnapshotCompletedSchema(valueLabel),\n makeOmnichainIndexingStatusSnapshotFollowingSchema(valueLabel),\n ])\n .check(invariant_omnichainSnapshotStatusIsConsistentWithChainSnapshot)\n .check(invariant_omnichainIndexingCursorLowerThanEarliestStartBlockAcrossQueuedChains)\n .check(\n invariant_omnichainIndexingCursorLowerThanOrEqualToLatestBackfillEndBlockAcrossBackfillChains,\n )\n .check(invariant_omnichainIndexingCursorIsEqualToHighestLatestIndexedBlockAcrossIndexedChain);\n\n/**\n * Makes Zod schema for {@link CrossChainIndexingStatusSnapshotOmnichain}\n */\nconst makeCrossChainIndexingStatusSnapshotOmnichainSchema = (\n valueLabel: string = \"Cross-chain Indexing Status Snapshot Omnichain\",\n) =>\n z\n .strictObject({\n strategy: z.literal(CrossChainIndexingStrategyIds.Omnichain),\n slowestChainIndexingCursor: makeUnixTimestampSchema(valueLabel),\n snapshotTime: makeUnixTimestampSchema(valueLabel),\n omnichainSnapshot: makeOmnichainIndexingStatusSnapshotSchema(valueLabel),\n })\n .check(invariant_slowestChainEqualsToOmnichainSnapshotTime)\n .check(invariant_snapshotTimeIsTheHighestKnownBlockTimestamp);\n\n/**\n * Makes Zod schema for {@link CrossChainIndexingStatusSnapshot}\n */\nexport const makeCrossChainIndexingStatusSnapshotSchema = (\n valueLabel: string = \"Cross-chain Indexing Status Snapshot\",\n) =>\n z.discriminatedUnion(\"strategy\", [\n makeCrossChainIndexingStatusSnapshotOmnichainSchema(valueLabel),\n ]);\n\n/**\n * Makes Zod schema for {@link RealtimeIndexingStatusProjection}\n */\nexport const makeRealtimeIndexingStatusProjectionSchema = (\n valueLabel: string = \"Realtime Indexing Status Projection\",\n) =>\n z\n .strictObject({\n projectedAt: makeUnixTimestampSchema(valueLabel),\n worstCaseDistance: makeDurationSchema(valueLabel),\n snapshot: makeCrossChainIndexingStatusSnapshotSchema(valueLabel),\n })\n .check(invariant_realtimeIndexingStatusProjectionProjectedAtIsAfterOrEqualToSnapshotTime)\n .check(invariant_realtimeIndexingStatusProjectionWorstCaseDistanceIsCorrect);\n","import type { BlockRef, ChainId, Duration, UnixTimestamp } from \"../../shared\";\n\n/**\n * The type of indexing configuration for a chain.\n */\nexport const ChainIndexingConfigTypeIds = {\n /**\n * Represents that indexing of the chain should be performed for an indefinite range.\n */\n Indefinite: \"indefinite\",\n\n /**\n * Represents that indexing of the chain should be performed for a definite range.\n */\n Definite: \"definite\",\n} as const;\n\n/**\n * The derived string union of possible {@link ChainIndexingConfigTypeIds}.\n */\nexport type ChainIndexingConfigTypeId =\n (typeof ChainIndexingConfigTypeIds)[keyof typeof ChainIndexingConfigTypeIds];\n\n/**\n * Chain indexing config for a chain whose indexing config `configType` is\n * {@link ChainIndexingConfigTypeIds.Indefinite}.\n *\n * Invariants:\n * - `configType` is always `ChainIndexingConfigTypeIds.Indefinite`.\n */\nexport interface ChainIndexingConfigIndefinite {\n /**\n * The type of chain indexing config.\n */\n configType: typeof ChainIndexingConfigTypeIds.Indefinite;\n\n /**\n * A {@link BlockRef} to the block where indexing of the chain should start.\n */\n startBlock: BlockRef;\n}\n\n/**\n * Chain indexing config for a chain whose indexing config `configType` is\n * {@link ChainIndexingConfigTypeIds.Definite}.\n *\n * Invariants:\n * - `configType` is always `ChainIndexingConfigTypeIds.Definite`.\n * - `startBlock` is always before or the same as `endBlock`.\n */\nexport interface ChainIndexingConfigDefinite {\n /**\n * The type of chain indexing config.\n */\n configType: typeof ChainIndexingConfigTypeIds.Definite;\n\n /**\n * A {@link BlockRef} to the block where indexing of the chain should start.\n */\n startBlock: BlockRef;\n\n /**\n * A {@link BlockRef} to the block where indexing of the chain should end.\n */\n endBlock: BlockRef;\n}\n\n/**\n * Indexing configuration for a chain.\n *\n * Use the `configType` field to determine the specific type interpretation\n * at runtime.\n */\nexport type ChainIndexingConfig = ChainIndexingConfigIndefinite | ChainIndexingConfigDefinite;\n\n/**\n * The status of indexing a chain at the time an indexing status snapshot\n * is captured.\n */\nexport const ChainIndexingStatusIds = {\n /**\n * Represents that indexing of the chain is not ready to begin yet because:\n * - ENSIndexer is in its initialization phase and the data to build a\n * \"true\" {@link ChainIndexingSnapshot} for the chain is still being loaded; or\n * - ENSIndexer is using an omnichain indexing strategy and the\n * `omnichainIndexingCursor` is <= `config.startBlock.timestamp` for the chain's\n * {@link ChainIndexingSnapshot}.\n */\n Queued: \"chain-queued\",\n\n /**\n * Represents that indexing of the chain is in progress and under a special\n * \"backfill\" phase that optimizes for accelerated indexing until reaching the\n * \"fixed target\" `backfillEndBlock`.\n */\n Backfill: \"chain-backfill\",\n\n /**\n * Represents that the \"backfill\" phase of indexing the chain is completed\n * and that the chain is configured to be indexed for an indefinite range.\n * Therefore, indexing of the chain remains indefinitely in progress where\n * ENSIndexer will continuously work to discover and index new blocks as they\n * are added to the chain across time.\n */\n Following: \"chain-following\",\n\n /**\n * Represents that indexing of the chain is completed as the chain is configured\n * to be indexed for a definite range and the indexing of all blocks through\n * that definite range is completed.\n */\n Completed: \"chain-completed\",\n} as const;\n\n/**\n * The derived string union of possible {@link ChainIndexingStatusIds}.\n */\nexport type ChainIndexingStatusId =\n (typeof ChainIndexingStatusIds)[keyof typeof ChainIndexingStatusIds];\n\n/**\n * Chain indexing status snapshot for a chain whose `chainStatus` is\n * {@link ChainIndexingStatusIds.Queued}.\n *\n * Invariants:\n * - `chainStatus` is always {@link ChainIndexingStatusIds.Queued}.\n */\nexport interface ChainIndexingStatusSnapshotQueued {\n /**\n * The status of indexing the chain at the time the indexing status snapshot\n * was captured.\n */\n chainStatus: typeof ChainIndexingStatusIds.Queued;\n\n /**\n * The indexing configuration of the chain.\n */\n config: ChainIndexingConfig;\n}\n\n/**\n * Chain indexing status snapshot for a chain whose `chainStatus` is\n * {@link ChainIndexingStatusIds.Backfill}.\n *\n * During a backfill, special performance optimizations are applied to\n * index all blocks between `config.startBlock` and `backfillEndBlock`\n * as fast as possible.\n *\n * Note how `backfillEndBlock` is a \"fixed target\" that does not change during\n * the lifetime of an ENSIndexer process instance:\n * - If the `config` is {@link ChainIndexingConfigDefinite}:\n * `backfillEndBlock` is always the same as `config.endBlock`.\n * - If the `config` is {@link ChainIndexingConfigIndefinite}:\n * `backfillEndBlock` is a {@link BlockRef} to what was the latest block on the\n * chain when the ENSIndexer process was performing its initialization. Note how\n * this means that if the backfill process takes X hours to complete, because the\n * `backfillEndBlock` is a \"fixed target\", when `chainStatus` transitions to\n * {@link ChainIndexingStatusIds.Following} the chain will be X hours behind\n * \"realtime\" indexing.\n *\n * When `latestIndexedBlock` reaches `backfillEndBlock` the backfill is complete.\n * The moment backfill is complete the `chainStatus` may not immediately transition.\n * Instead, internal processing is completed for a period of time while\n * `chainStatus` remains {@link ChainIndexingStatusIds.Backfill}. After this internal\n * processing is completed `chainStatus` will transition:\n * - to {@link ChainIndexingStatusIds.Following} if the `config` is\n * {@link ChainIndexingConfigIndefinite}.\n * - to {@link ChainIndexingStatusIds.Completed} if the `config` is\n * {@link ChainIndexingConfigDefinite}.\n *\n * Invariants:\n * - `chainStatus` is always {@link ChainIndexingStatusIds.Backfill}.\n * - `config.startBlock` is always before or the same as `latestIndexedBlock`\n * - `config.endBlock` is always the same as `backfillEndBlock` if and only if\n * the config is {@link ChainIndexingConfigDefinite}.\n * - `latestIndexedBlock` is always before or the same as `backfillEndBlock`\n */\nexport interface ChainIndexingStatusSnapshotBackfill {\n /**\n * The status of indexing the chain at the time the indexing status snapshot\n * was captured.\n */\n chainStatus: typeof ChainIndexingStatusIds.Backfill;\n\n /**\n * The indexing configuration of the chain.\n */\n config: ChainIndexingConfig;\n\n /**\n * A {@link BlockRef} to the block that was most recently indexed as of the time the\n * indexing status snapshot was captured.\n */\n latestIndexedBlock: BlockRef;\n\n /**\n * A {@link BlockRef} to the block where the backfill will end.\n */\n backfillEndBlock: BlockRef;\n}\n\n/**\n * Chain indexing status snapshot for a chain whose `chainStatus` is\n * {@link ChainIndexingStatusIds.Following}.\n *\n * Invariants:\n * - `chainStatus` is always {@link ChainIndexingStatusIds.Following}.\n * - `config` is always {@link ChainIndexingConfigIndefinite}\n * - `config.startBlock` is always before or the same as `latestIndexedBlock`\n * - `latestIndexedBlock` is always before or the same as `latestKnownBlock`\n */\nexport interface ChainIndexingStatusSnapshotFollowing {\n /**\n * The status of indexing the chain at the time the indexing status snapshot\n * was captured.\n */\n chainStatus: typeof ChainIndexingStatusIds.Following;\n\n /**\n * The indexing configuration of the chain.\n */\n config: ChainIndexingConfigIndefinite;\n\n /**\n * A {@link BlockRef} to the block that was most recently indexed as of the time the\n * indexing status snapshot was captured.\n */\n latestIndexedBlock: BlockRef;\n\n /**\n * A {@link BlockRef} to the \"highest\" block that has been discovered by RPCs\n * and stored in the RPC cache as of the time the indexing status snapshot was\n * captured.\n */\n latestKnownBlock: BlockRef;\n}\n\n/**\n * Chain indexing status snapshot for a chain whose `chainStatus` is\n * {@link ChainIndexingStatusIds.Completed}.\n *\n * After the backfill of a chain is completed, if the chain was configured\n * to be indexed for a definite range, the chain indexing status will transition to\n * {@link ChainIndexingStatusIds.Completed}.\n *\n * Invariants:\n * - `chainStatus` is always {@link ChainIndexingStatusIds.Completed}.\n * - `config` is always {@link ChainIndexingConfigDefinite}\n * - `config.startBlock` is always before or the same as `latestIndexedBlock`\n * - `latestIndexedBlock` is always the same as `config.endBlock`.\n */\nexport interface ChainIndexingStatusSnapshotCompleted {\n /**\n * The status of indexing the chain at the time the indexing status snapshot\n * was captured.\n */\n chainStatus: typeof ChainIndexingStatusIds.Completed;\n\n /**\n * The indexing configuration of the chain.\n */\n config: ChainIndexingConfigDefinite;\n\n /**\n * A {@link BlockRef} to the block that was most recently indexed as of the time the\n * indexing status snapshot was captured.\n */\n latestIndexedBlock: BlockRef;\n}\n\n/**\n * Indexing status snapshot for a single chain.\n *\n * Use the `chainStatus` field to determine the specific type interpretation\n * at runtime.\n */\nexport type ChainIndexingStatusSnapshot =\n | ChainIndexingStatusSnapshotQueued\n | ChainIndexingStatusSnapshotBackfill\n | ChainIndexingStatusSnapshotFollowing\n | ChainIndexingStatusSnapshotCompleted;\n\n/**\n * The status of omnichain indexing at the time an omnichain indexing status\n * snapshot is captured.\n */\nexport const OmnichainIndexingStatusIds = {\n /**\n * Represents that omnichain indexing is not ready to begin yet because\n * ENSIndexer is in its initialization phase and the data to build a \"true\"\n * {@link OmnichainIndexingStatusSnapshot} is still being loaded.\n */\n Unstarted: \"omnichain-unstarted\",\n\n /**\n * Represents that omnichain indexing is in an overall \"backfill\" status because\n * - At least one indexed chain has a `chainStatus` of\n * {@link ChainIndexingStatusIds.Backfill}; and\n * - No indexed chain has a `chainStatus` of {@link ChainIndexingStatusIds.Following}.\n */\n Backfill: \"omnichain-backfill\",\n\n /**\n * Represents that omnichain indexing is in an overall \"following\" status because\n * at least one indexed chain has a `chainStatus` of\n * {@link ChainIndexingStatusIds.Following}.\n */\n Following: \"omnichain-following\",\n\n /**\n * Represents that omnichain indexing has completed because all indexed chains have\n * a `chainStatus` of {@link ChainIndexingStatusIds.Completed}.\n */\n Completed: \"omnichain-completed\",\n} as const;\n\n/**\n * The derived string union of possible {@link OmnichainIndexingStatusIds}.\n */\nexport type OmnichainIndexingStatusId =\n (typeof OmnichainIndexingStatusIds)[keyof typeof OmnichainIndexingStatusIds];\n\n/**\n * Omnichain indexing status snapshot when the overall `omnichainStatus` is\n * {@link OmnichainIndexingStatusIds.Unstarted}.\n *\n * Invariants:\n * - `omnichainStatus` is always {@link OmnichainIndexingStatusIds.Unstarted}.\n * - `chains` is always a map to {@link ChainIndexingStatusSnapshotQueued} values exclusively.\n * - `omnichainIndexingCursor` is always < the `config.startBlock.timestamp` for all\n * chains with `chainStatus` of {@link ChainIndexingStatusIds.Queued}.\n */\nexport interface OmnichainIndexingStatusSnapshotUnstarted {\n /**\n * The status of omnichain indexing.\n */\n omnichainStatus: typeof OmnichainIndexingStatusIds.Unstarted;\n\n /**\n * The indexing status snapshot for each indexed chain.\n */\n chains: Map<ChainId, ChainIndexingStatusSnapshotQueued>;\n\n /**\n * The timestamp of omnichain indexing progress across all indexed chains.\n */\n omnichainIndexingCursor: UnixTimestamp;\n}\n\n/**\n * The range of {@link ChainIndexingSnapshot} types allowed when the\n * overall omnichain indexing status is {@link OmnichainIndexingStatusIds.Backfill}.\n *\n * Note that this is all of the {@link ChainIndexingSnapshot} types with the exception\n * of {@link ChainIndexingStatusSnapshotFollowing}.\n */\nexport type ChainIndexingStatusSnapshotForOmnichainIndexingStatusSnapshotBackfill =\n | ChainIndexingStatusSnapshotQueued\n | ChainIndexingStatusSnapshotBackfill\n | ChainIndexingStatusSnapshotCompleted;\n\n/**\n * Omnichain indexing status snapshot when the `omnichainStatus` is\n * {@link OmnichainIndexingStatusIds.Backfill}.\n *\n * Invariants:\n * - `omnichainStatus` is always {@link OmnichainIndexingStatusIds.Backfill}.\n * - `chains` is guaranteed to contain at least one chain with a `chainStatus` of\n * {@link ChainIndexingStatusIds.Backfill}.\n * - `chains` is guaranteed to not to contain any chain with a `chainStatus` of\n * {@link ChainIndexingStatusIds.Following}\n * - `omnichainIndexingCursor` is always < the `config.startBlock.timestamp` for all\n * chains with `chainStatus` of {@link ChainIndexingStatusIds.Queued}.\n * - `omnichainIndexingCursor` is always <= the `backfillEndBlock.timestamp` for all\n * chains with `chainStatus` of {@link ChainIndexingStatusIds.Backfill}.\n * - `omnichainIndexingCursor` is always >= the `latestIndexedBlock.timestamp` for all\n * chains with `chainStatus` of {@link ChainIndexingStatusIds.Completed}.\n * - `omnichainIndexingCursor` is always equal to the timestamp of the highest\n * `latestIndexedBlock` across all chains that have started indexing\n * (`chainStatus` is not {@link ChainIndexingStatusIds.Queued}).\n */\nexport interface OmnichainIndexingStatusSnapshotBackfill {\n /**\n * The status of omnichain indexing.\n */\n omnichainStatus: typeof OmnichainIndexingStatusIds.Backfill;\n\n /**\n * The indexing status snapshot for each indexed chain.\n */\n chains: Map<ChainId, ChainIndexingStatusSnapshotForOmnichainIndexingStatusSnapshotBackfill>;\n\n /**\n * The timestamp of omnichain indexing progress across all indexed chains.\n */\n omnichainIndexingCursor: UnixTimestamp;\n}\n\n/**\n * Omnichain indexing status snapshot when the overall `omnichainStatus` is\n * {@link OmnichainIndexingStatusIds.Following}.\n *\n * Invariants:\n * - `omnichainStatus` is always {@link OmnichainIndexingStatusIds.Following}.\n * - `chains` is guaranteed to contain at least one chain with a `status` of\n * {@link ChainIndexingStatusIds.Following}.\n * - `omnichainIndexingCursor` is always < the `config.startBlock.timestamp` for all\n * chains with `chainStatus` of {@link ChainIndexingStatusIds.Queued}.\n * - `omnichainIndexingCursor` is always <= the `backfillEndBlock.timestamp` for all\n * chains with `chainStatus` of {@link ChainIndexingStatusIds.Backfill}.\n * - `omnichainIndexingCursor` is always >= the `latestIndexedBlock.timestamp` for all\n * chains with `chainStatus` of {@link ChainIndexingStatusIds.Completed}.\n * - `omnichainIndexingCursor` is always equal to the timestamp of the highest\n * `latestIndexedBlock` across all chains that have started indexing\n * (`chainStatus` is not {@link ChainIndexingStatusIds.Queued}).\n */\nexport interface OmnichainIndexingStatusSnapshotFollowing {\n /**\n * The status of omnichain indexing.\n */\n omnichainStatus: typeof OmnichainIndexingStatusIds.Following;\n\n /**\n * The indexing status snapshot for each indexed chain.\n */\n chains: Map<ChainId, ChainIndexingStatusSnapshot>;\n\n /**\n * The timestamp of omnichain indexing progress across all indexed chains.\n */\n omnichainIndexingCursor: UnixTimestamp;\n}\n\n/**\n * Omnichain indexing status snapshot when the overall `omnichainStatus` is\n * {@link OmnichainIndexingStatusIds.Completed}.\n *\n * Invariants:\n * - `omnichainStatus` is always {@link OmnichainIndexingStatusIds.Completed}.\n * - `chains` is always a map to {@link ChainIndexingStatusSnapshotCompleted} values exclusively.\n * - `omnichainIndexingCursor` is always equal to the highest\n * `latestIndexedBlock.timestamp` for all chains.\n */\nexport interface OmnichainIndexingStatusSnapshotCompleted {\n /**\n * The status of omnichain indexing.\n */\n omnichainStatus: typeof OmnichainIndexingStatusIds.Completed;\n\n /**\n * The indexing status snapshot for each indexed chain.\n */\n chains: Map<ChainId, ChainIndexingStatusSnapshotCompleted>;\n\n /**\n * The timestamp of omnichain indexing progress across all indexed chains.\n */\n omnichainIndexingCursor: UnixTimestamp;\n}\n\n/**\n * Omnichain indexing status snapshot for one or more chains.\n *\n * Use the `omnichainStatus` field to determine the specific type interpretation\n * at runtime.\n */\nexport type OmnichainIndexingStatusSnapshot =\n | OmnichainIndexingStatusSnapshotUnstarted\n | OmnichainIndexingStatusSnapshotBackfill\n | OmnichainIndexingStatusSnapshotCompleted\n | OmnichainIndexingStatusSnapshotFollowing;\n\n/**\n * The strategy used for indexing one or more chains.\n *\n * @see https://ponder.sh/docs/api-reference/ponder/config#parameters\n */\nexport const CrossChainIndexingStrategyIds = {\n /**\n * Represents that the indexing of events across all indexed chains will\n * proceed in a deterministic \"omnichain\" ordering by block timestamp, chain ID,\n * and block number.\n *\n * This strategy is \"deterministic\" in that the order of processing cross-chain indexed\n * events and each resulting indexed data state transition recorded in ENSDb is always\n * the same for each ENSIndexer instance operating with an equivalent\n * `ENSIndexerConfig` and ENSIndexer version. However it also has the drawbacks of:\n * - increased indexing latency that must wait for the slowest indexed chain to\n * add new blocks or to discover new blocks through the configured RPCs.\n * - if any indexed chain gets \"stuck\" due to chain or RPC failures, all indexed chains\n * will be affected.\n */\n Omnichain: \"omnichain\",\n} as const;\n\n/**\n * The derived string union of possible {@link CrossChainIndexingStrategyIds}.\n */\nexport type CrossChainIndexingStrategyId =\n (typeof CrossChainIndexingStrategyIds)[keyof typeof CrossChainIndexingStrategyIds];\n\n/**\n * Cross-chain indexing status snapshot when the `strategy` is\n * {@link CrossChainIndexingStrategyId.Omnichain}.\n *\n * Invariants:\n * - `strategy` is always {@link CrossChainIndexingStrategyId.Omnichain}.\n * - `slowestChainIndexingCursor` is always equal to\n * `omnichainSnapshot.omnichainIndexingCursor`.\n * - `snapshotTime` is always >= the \"highest known block timestamp\", defined as the max of:\n * - the `slowestChainIndexingCursor`.\n * - the `config.startBlock.timestamp` for all indexed chains.\n * - the `config.endBlock.timestamp` for all indexed chains with a `config.configType` of\n * {@link ChainIndexingConfigTypeIds.Definite}.\n * - the `backfillEndBlock.timestamp` for all chains with `chainStatus` of\n * {@link ChainIndexingStatusIds.Backfill}.\n * - the `latestKnownBlock.timestamp` for all chains with `chainStatus` of\n * {@link ChainIndexingStatusIds.Following}.\n */\nexport interface CrossChainIndexingStatusSnapshotOmnichain {\n /**\n * The strategy used for indexing one or more chains.\n */\n strategy: typeof CrossChainIndexingStrategyIds.Omnichain;\n\n /**\n * The timestamp of the \"slowest\" latest indexed block timestamp\n * across all indexed chains.\n */\n slowestChainIndexingCursor: UnixTimestamp;\n\n /**\n * The timestamp when the cross-chain indexing status snapshot was generated.\n *\n * Due to possible clock skew between different systems this value must be set\n * to the max of each of the following values to ensure all invariants are followed:\n * - the current system time of the system generating this cross-chain indexing\n * status snapshot.\n * - the \"highest known block timestamp\" (see invariants above for full definition).\n */\n snapshotTime: UnixTimestamp;\n\n /**\n * The omnichain indexing status snapshot for one or more chains.\n */\n omnichainSnapshot: OmnichainIndexingStatusSnapshot;\n}\n\n/**\n * Cross-chain indexing status snapshot for one or more chains.\n *\n * Use the `strategy` field to determine the specific type interpretation\n * at runtime.\n *\n * Currently, only omnichain indexing is supported. This type could theoretically\n * be extended to support other cross-chain indexing strategies in the future,\n * such as Ponder's \"multichain\" indexing strategy that indexes each chain\n * independently without deterministic ordering.\n */\nexport type CrossChainIndexingStatusSnapshot = CrossChainIndexingStatusSnapshotOmnichain;\n\n/**\n * A \"realtime\" indexing status projection based on worst-case assumptions\n * from the `snapshot`.\n *\n * Invariants:\n * - `projectedAt` is always >= `snapshot.snapshotTime`.\n * - `worstCaseDistance` is always equal to\n * `projectedAt - snapshot.slowestChainIndexingCursor`.\n */\nexport type RealtimeIndexingStatusProjection = {\n /**\n * The timestamp representing \"now\" as of the time this projection was generated.\n */\n projectedAt: UnixTimestamp;\n\n /**\n * The distance between `projectedAt` and `snapshot.slowestChainIndexingCursor`.\n *\n * This is \"worst-case\" because it assumes all of the following:\n * - the `snapshot` (which may have `snapshot.snapshotTime < projectedAt`) is still the\n * latest snapshot and no indexing progress has been made since `snapshotTime`.\n * - each indexed chain has added a new block as of `projectedAt`.\n */\n worstCaseDistance: Duration;\n\n /**\n * The {@link CrossChainIndexingStatusSnapshot} that this projection is based on.\n */\n snapshot: CrossChainIndexingStatusSnapshot;\n};\n","import type { BlockRef } from \"./types\";\n\n/**\n * Compare two {@link BlockRef} object to check\n * if blockA is before blockB.\n */\nexport function isBefore(blockA: BlockRef, blockB: BlockRef) {\n return blockA.number < blockB.number && blockA.timestamp < blockB.timestamp;\n}\n\n/**\n * Compare two {@link BlockRef} object to check\n * if blockA is equal to blockB.\n */\nexport function isEqualTo(blockA: BlockRef, blockB: BlockRef) {\n return blockA.number === blockB.number && blockA.timestamp === blockB.timestamp;\n}\n\n/**\n * Compare two {@link BlockRef} object to check\n * if blockA is before or equal to blockB.\n */\nexport function isBeforeOrEqualTo(blockA: BlockRef, blockB: BlockRef) {\n return isBefore(blockA, blockB) || isEqualTo(blockA, blockB);\n}\n","import type { BlockRef, ChainId, UnixTimestamp } from \"../../shared\";\nimport {\n type ChainIndexingConfig,\n type ChainIndexingConfigDefinite,\n type ChainIndexingConfigIndefinite,\n ChainIndexingConfigTypeIds,\n ChainIndexingStatusIds,\n type ChainIndexingStatusSnapshot,\n type ChainIndexingStatusSnapshotCompleted,\n type ChainIndexingStatusSnapshotForOmnichainIndexingStatusSnapshotBackfill,\n type ChainIndexingStatusSnapshotQueued,\n type CrossChainIndexingStatusSnapshot,\n type OmnichainIndexingStatusId,\n OmnichainIndexingStatusIds,\n} from \"./types\";\n\n/**\n * Get {@link OmnichainIndexingStatusId} based on indexed chains' statuses.\n *\n * This function decides what is the `OmnichainIndexingStatusId` is,\n * based on provided chain indexing statuses.\n *\n * @throws an error if unable to determine overall indexing status\n */\nexport function getOmnichainIndexingStatus(\n chains: ChainIndexingStatusSnapshot[],\n): OmnichainIndexingStatusId {\n if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing(chains)) {\n return OmnichainIndexingStatusIds.Following;\n }\n\n if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill(chains)) {\n return OmnichainIndexingStatusIds.Backfill;\n }\n\n if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted(chains)) {\n return OmnichainIndexingStatusIds.Unstarted;\n }\n\n if (checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted(chains)) {\n return OmnichainIndexingStatusIds.Completed;\n }\n\n // if none of the chain statuses matched, throw an error\n throw new Error(`Unable to determine omnichain indexing status for provided chains.`);\n}\n\n/**\n * Get the timestamp of the lowest `config.startBlock` across all chains\n * in the provided array of {@link ChainIndexingStatusSnapshot}.\n *\n * Such timestamp is useful when presenting the \"lowest\" block\n * to be indexed across all chains.\n */\nexport function getTimestampForLowestOmnichainStartBlock(\n chains: ChainIndexingStatusSnapshot[],\n): UnixTimestamp {\n const earliestKnownBlockTimestamps: UnixTimestamp[] = chains.map(\n (chain) => chain.config.startBlock.timestamp,\n );\n\n return Math.min(...earliestKnownBlockTimestamps);\n}\n\n/**\n * Get the timestamp of the \"highest known block\" across all chains\n * in the provided array of {@link ChainIndexingStatusSnapshot}.\n *\n * Such timestamp is useful when presenting the \"highest known block\"\n * to be indexed across all chains.\n *\n * The \"highest known block\" for a chain depends on its status:\n * - `config.endBlock` for a \"queued\" chain,\n * - `backfillEndBlock` for a \"backfill\" chain,\n * - `latestIndexedBlock` for a \"completed\" chain,\n * - `latestKnownBlock` for a \"following\" chain.\n */\nexport function getTimestampForHighestOmnichainKnownBlock(\n chains: ChainIndexingStatusSnapshot[],\n): UnixTimestamp {\n const latestKnownBlockTimestamps: UnixTimestamp[] = [];\n\n for (const chain of chains) {\n switch (chain.chainStatus) {\n case ChainIndexingStatusIds.Queued:\n if (\n chain.config.configType === ChainIndexingConfigTypeIds.Definite &&\n chain.config.endBlock\n ) {\n latestKnownBlockTimestamps.push(chain.config.endBlock.timestamp);\n }\n break;\n\n case ChainIndexingStatusIds.Backfill:\n latestKnownBlockTimestamps.push(chain.backfillEndBlock.timestamp);\n\n break;\n\n case ChainIndexingStatusIds.Completed:\n latestKnownBlockTimestamps.push(chain.latestIndexedBlock.timestamp);\n break;\n\n case ChainIndexingStatusIds.Following:\n latestKnownBlockTimestamps.push(chain.latestKnownBlock.timestamp);\n break;\n }\n }\n\n return Math.max(...latestKnownBlockTimestamps);\n}\n\n/**\n * Get Omnichain Indexing Cursor\n *\n * The cursor tracks the \"highest\" latest indexed block timestamp across\n * all indexed chains. If all chains are queued, the cursor tracks the moment\n * just before the earliest start block timestamp across those chains.\n *\n * @throws an error if no chains are provided\n */\nexport function getOmnichainIndexingCursor(chains: ChainIndexingStatusSnapshot[]): UnixTimestamp {\n if (chains.length === 0) {\n throw new Error(`Unable to determine omnichain indexing cursor when no chains were provided.`);\n }\n\n // for omnichain indexing status snapshot 'unstarted', the cursor tracks\n // the moment just before the indexing would start from.\n if (getOmnichainIndexingStatus(chains) === OmnichainIndexingStatusIds.Unstarted) {\n const earliestStartBlockTimestamps = chains.map((chain) => chain.config.startBlock.timestamp);\n\n return Math.min(...earliestStartBlockTimestamps) - 1;\n }\n\n // otherwise, the cursor tracks the \"highest\" latest indexed block timestamp\n // across all indexed chains\n const latestIndexedBlockTimestamps = chains\n .filter((chain) => chain.chainStatus !== ChainIndexingStatusIds.Queued)\n .map((chain) => chain.latestIndexedBlock.timestamp);\n\n // Invariant: there's at least one element in `latestIndexedBlockTimestamps` array\n // This is theoretically impossible based on the 2 checks above,\n // but the invariant is explicitly added here as a formality.\n if (latestIndexedBlockTimestamps.length < 1) {\n throw new Error(\"latestIndexedBlockTimestamps array must include at least one element\");\n }\n\n return Math.max(...latestIndexedBlockTimestamps);\n}\n\n/**\n * Create {@link ChainIndexingConfig} for given block refs.\n *\n * @param startBlock required block ref\n * @param endBlock optional block ref\n */\nexport function createIndexingConfig(\n startBlock: BlockRef,\n endBlock: BlockRef | null,\n): ChainIndexingConfig {\n if (endBlock) {\n return {\n configType: ChainIndexingConfigTypeIds.Definite,\n startBlock,\n endBlock,\n } satisfies ChainIndexingConfigDefinite;\n }\n\n return {\n configType: ChainIndexingConfigTypeIds.Indefinite,\n startBlock,\n } satisfies ChainIndexingConfigIndefinite;\n}\n\n/**\n * Check if Chain Indexing Status Snapshots fit the 'unstarted' overall status\n * snapshot requirements:\n * - All chains are guaranteed to have a status of \"queued\".\n *\n * Note: This function narrows the {@link ChainIndexingStatusSnapshot} type to\n * {@link ChainIndexingStatusSnapshotQueued}.\n */\nexport function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted(\n chains: ChainIndexingStatusSnapshot[],\n): chains is ChainIndexingStatusSnapshotQueued[] {\n return chains.every((chain) => chain.chainStatus === ChainIndexingStatusIds.Queued);\n}\n\n/**\n * Check if Chain Indexing Status Snapshots fit the 'backfill' overall status\n * snapshot requirements:\n * - At least one chain is guaranteed to be in the \"backfill\" status.\n * - Each chain is guaranteed to have a status of either \"queued\",\n * \"backfill\" or \"completed\".\n *\n * Note: This function narrows the {@link ChainIndexingStatusSnapshot} type to\n * {@link ChainIndexingStatusSnapshotForOmnichainIndexingStatusSnapshotBackfill}.\n */\nexport function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill(\n chains: ChainIndexingStatusSnapshot[],\n): chains is ChainIndexingStatusSnapshotForOmnichainIndexingStatusSnapshotBackfill[] {\n const atLeastOneChainInTargetStatus = chains.some(\n (chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill,\n );\n const otherChainsHaveValidStatuses = chains.every(\n (chain) =>\n chain.chainStatus === ChainIndexingStatusIds.Queued ||\n chain.chainStatus === ChainIndexingStatusIds.Backfill ||\n chain.chainStatus === ChainIndexingStatusIds.Completed,\n );\n\n return atLeastOneChainInTargetStatus && otherChainsHaveValidStatuses;\n}\n\n/**\n * Checks if Chain Indexing Status Snapshots fit the 'completed' overall status\n * snapshot requirements:\n * - All chains are guaranteed to have a status of \"completed\".\n *\n * Note: This function narrows the {@link ChainIndexingStatusSnapshot} type to\n * {@link ChainIndexingStatusSnapshotCompleted}.\n */\nexport function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted(\n chains: ChainIndexingStatusSnapshot[],\n): chains is ChainIndexingStatusSnapshotCompleted[] {\n const allChainsHaveValidStatuses = chains.every(\n (chain) => chain.chainStatus === ChainIndexingStatusIds.Completed,\n );\n\n return allChainsHaveValidStatuses;\n}\n\n/**\n * Checks Chain Indexing Status Snapshots fit the 'following' overall status\n * snapshot requirements:\n * - At least one chain is guaranteed to be in the \"following\" status.\n * - Any other chain can have any status.\n */\nexport function checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing(\n chains: ChainIndexingStatusSnapshot[],\n): chains is ChainIndexingStatusSnapshot[] {\n const allChainsHaveValidStatuses = chains.some(\n (chain) => chain.chainStatus === ChainIndexingStatusIds.Following,\n );\n\n return allChainsHaveValidStatuses;\n}\n\n/**\n * Sort a list of [{@link ChainId}, {@link ChainIndexingStatusSnapshot}] tuples\n * by the omnichain start block timestamp in ascending order.\n */\nexport function sortChainStatusesByStartBlockAsc<\n ChainStatusType extends ChainIndexingStatusSnapshot,\n>(chains: [ChainId, ChainStatusType][]): [ChainId, ChainStatusType][] {\n // Sort the chain statuses by the omnichain first block to index timestamp\n chains.sort(\n ([, chainA], [, chainB]) =>\n chainA.config.startBlock.timestamp - chainB.config.startBlock.timestamp,\n );\n\n return chains;\n}\n\n/**\n * Gets the latest indexed {@link BlockRef} for the given {@link ChainId}.\n *\n * @returns the latest indexed {@link BlockRef} for the given {@link ChainId}, or null if the chain\n * isn't being indexed at all or is queued and therefore hasn't started indexing yet.\n */\nexport function getLatestIndexedBlockRef(\n indexingStatus: CrossChainIndexingStatusSnapshot,\n chainId: ChainId,\n): BlockRef | null {\n const chainIndexingStatus = indexingStatus.omnichainSnapshot.chains.get(chainId);\n\n if (chainIndexingStatus === undefined) {\n // chain isn't being indexed at all\n return null;\n }\n\n if (chainIndexingStatus.chainStatus === ChainIndexingStatusIds.Queued) {\n // chain is queued, so no data for the chain has been indexed yet\n return null;\n }\n\n return chainIndexingStatus.latestIndexedBlock;\n}\n","import type { ParsePayload } from \"zod/v4/core\";\n\nimport type { ChainId } from \"../../shared\";\nimport * as blockRef from \"../../shared/block-ref\";\nimport {\n checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill,\n checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted,\n checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing,\n checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted,\n getOmnichainIndexingStatus,\n} from \"./helpers\";\nimport {\n ChainIndexingConfigTypeIds,\n ChainIndexingStatusIds,\n type ChainIndexingStatusSnapshot,\n type ChainIndexingStatusSnapshotBackfill,\n type ChainIndexingStatusSnapshotCompleted,\n type ChainIndexingStatusSnapshotFollowing,\n type ChainIndexingStatusSnapshotQueued,\n type CrossChainIndexingStatusSnapshotOmnichain,\n type OmnichainIndexingStatusSnapshot,\n type OmnichainIndexingStatusSnapshotFollowing,\n type RealtimeIndexingStatusProjection,\n} from \"./types\";\n\n/**\n * Invariants for {@link ChainIndexingSnapshot}.\n */\n\n/**\n * Invariants for chain snapshot in 'queued' status:\n * - `config.endBlock` (if set) is after `config.startBlock`.\n */\nexport function invariant_chainSnapshotQueuedBlocks(\n ctx: ParsePayload<ChainIndexingStatusSnapshotQueued>,\n) {\n const { config } = ctx.value;\n\n // The `config.endBlock` does not exists for `indefinite` config type\n if (config.configType === ChainIndexingConfigTypeIds.Indefinite) {\n // invariant holds\n return;\n }\n\n if (config.endBlock && blockRef.isBeforeOrEqualTo(config.startBlock, config.endBlock) === false) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: \"`config.startBlock` must be before or same as `config.endBlock`.\",\n });\n }\n}\n\n/**\n * Invariants for chain snapshot in 'backfill' status:\n * - `config.startBlock` is before or same as `latestIndexedBlock`.\n * - `latestIndexedBlock` is before or same as `backfillEndBlock`.\n * - `backfillEndBlock` is the same as `config.endBlock` (if set).\n */\nexport function invariant_chainSnapshotBackfillBlocks(\n ctx: ParsePayload<ChainIndexingStatusSnapshotBackfill>,\n) {\n const { config, latestIndexedBlock, backfillEndBlock } = ctx.value;\n\n if (blockRef.isBeforeOrEqualTo(config.startBlock, latestIndexedBlock) === false) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: \"`config.startBlock` must be before or same as `latestIndexedBlock`.\",\n });\n }\n\n if (blockRef.isBeforeOrEqualTo(latestIndexedBlock, backfillEndBlock) === false) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: \"`latestIndexedBlock` must be before or same as `backfillEndBlock`.\",\n });\n }\n\n // The `config.endBlock` does not exists for `indefinite` config type\n if (config.configType === ChainIndexingConfigTypeIds.Indefinite) {\n // invariant holds\n return;\n }\n\n if (config.endBlock && blockRef.isEqualTo(backfillEndBlock, config.endBlock) === false) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: \"`backfillEndBlock` must be the same as `config.endBlock`.\",\n });\n }\n}\n\n/**\n * Invariants for chain snapshot in 'completed' status:\n * - `config.startBlock` is before or same as `latestIndexedBlock`.\n * - `latestIndexedBlock` is before or same as `config.endBlock`.\n */\nexport function invariant_chainSnapshotCompletedBlocks(\n ctx: ParsePayload<ChainIndexingStatusSnapshotCompleted>,\n) {\n const { config, latestIndexedBlock } = ctx.value;\n\n if (blockRef.isBeforeOrEqualTo(config.startBlock, latestIndexedBlock) === false) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: \"`config.startBlock` must be before or same as `latestIndexedBlock`.\",\n });\n }\n\n if (blockRef.isBeforeOrEqualTo(latestIndexedBlock, config.endBlock) === false) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: \"`latestIndexedBlock` must be before or same as `config.endBlock`.\",\n });\n }\n}\n\n/**\n * Invariants for chain snapshot in 'following' status:\n * - `config.startBlock` is before or same as `latestIndexedBlock`.\n * - `latestIndexedBlock` is before or same as `latestKnownBlock`.\n */\nexport function invariant_chainSnapshotFollowingBlocks(\n ctx: ParsePayload<ChainIndexingStatusSnapshotFollowing>,\n) {\n const { config, latestIndexedBlock, latestKnownBlock } = ctx.value;\n\n if (blockRef.isBeforeOrEqualTo(config.startBlock, latestIndexedBlock) === false) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: \"`config.startBlock` must be before or same as `latestIndexedBlock`.\",\n });\n }\n\n if (blockRef.isBeforeOrEqualTo(latestIndexedBlock, latestKnownBlock) === false) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: \"`latestIndexedBlock` must be before or same as `latestKnownBlock`.\",\n });\n }\n}\n\n/**\n * Invariants for {@link OmnichainIndexingSnapshot}.\n */\n\n/**\n * Invariant: For omnichain snapshot,\n * `omnichainStatus` is set based on the snapshots of individual chains.\n */\nexport function invariant_omnichainSnapshotStatusIsConsistentWithChainSnapshot(\n ctx: ParsePayload<OmnichainIndexingStatusSnapshot>,\n) {\n const snapshot = ctx.value;\n const chains = Array.from(snapshot.chains.values());\n const expectedOmnichainStatus = getOmnichainIndexingStatus(chains);\n const actualOmnichainStatus = snapshot.omnichainStatus;\n\n if (expectedOmnichainStatus !== actualOmnichainStatus) {\n ctx.issues.push({\n code: \"custom\",\n input: snapshot,\n message: `'${actualOmnichainStatus}' is an invalid omnichainStatus. Expected '${expectedOmnichainStatus}' based on the statuses of individual chains.`,\n });\n }\n}\n\n/**\n * Invariant: For omnichain status snapshot,\n * `omnichainIndexingCursor` is lower than the earliest start block\n * across all queued chains.\n *\n * Note: if there are no queued chains, the invariant holds.\n */\nexport function invariant_omnichainIndexingCursorLowerThanEarliestStartBlockAcrossQueuedChains(\n ctx: ParsePayload<OmnichainIndexingStatusSnapshot>,\n) {\n const snapshot = ctx.value;\n const queuedChains = Array.from(snapshot.chains.values()).filter(\n (chain) => chain.chainStatus === ChainIndexingStatusIds.Queued,\n );\n\n // there are no queued chains\n if (queuedChains.length === 0) {\n // the invariant holds\n return;\n }\n\n const queuedChainStartBlocks = queuedChains.map((chain) => chain.config.startBlock.timestamp);\n const queuedChainEarliestStartBlock = Math.min(...queuedChainStartBlocks);\n\n // there are queued chains\n // the invariant holds if the omnichain indexing cursor is lower than\n // the earliest start block across all queued chains\n if (snapshot.omnichainIndexingCursor >= queuedChainEarliestStartBlock) {\n ctx.issues.push({\n code: \"custom\",\n input: snapshot,\n message:\n \"`omnichainIndexingCursor` must be lower than the earliest start block across all queued chains.\",\n });\n }\n}\n\n/**\n * Invariant: For omnichain status snapshot,\n * `omnichainIndexingCursor` is lower than or equal to\n * the highest `backfillEndBlock` across all backfill chains.\n *\n * Note: if there are no backfill chains, the invariant holds.\n */\nexport function invariant_omnichainIndexingCursorLowerThanOrEqualToLatestBackfillEndBlockAcrossBackfillChains(\n ctx: ParsePayload<OmnichainIndexingStatusSnapshot>,\n) {\n const snapshot = ctx.value;\n const backfillChains = Array.from(snapshot.chains.values()).filter(\n (chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill,\n );\n\n // there are no backfill chains\n if (backfillChains.length === 0) {\n // the invariant holds\n return;\n }\n\n const backfillEndBlocks = backfillChains.map((chain) => chain.backfillEndBlock.timestamp);\n const highestBackfillEndBlock = Math.max(...backfillEndBlocks);\n\n // there are backfill chains\n // the invariant holds if the omnichainIndexingCursor is lower than or\n // equal to the highest backfillEndBlock across all backfill chains.\n if (snapshot.omnichainIndexingCursor > highestBackfillEndBlock) {\n ctx.issues.push({\n code: \"custom\",\n input: snapshot,\n message:\n \"`omnichainIndexingCursor` must be lower than or equal to the highest `backfillEndBlock` across all backfill chains.\",\n });\n }\n}\n\n/**\n * Invariant: For omnichain status snapshot,\n * `omnichainIndexingCursor` is same as the highest latestIndexedBlock\n * across all indexed chains.\n *\n * Note: if there are no indexed chains, the invariant holds.\n */\nexport function invariant_omnichainIndexingCursorIsEqualToHighestLatestIndexedBlockAcrossIndexedChain(\n ctx: ParsePayload<OmnichainIndexingStatusSnapshot>,\n) {\n const snapshot = ctx.value;\n const indexedChains = Array.from(snapshot.chains.values()).filter(\n (chain) =>\n chain.chainStatus === ChainIndexingStatusIds.Backfill ||\n chain.chainStatus === ChainIndexingStatusIds.Completed ||\n chain.chainStatus === ChainIndexingStatusIds.Following,\n );\n\n // there are no indexed chains\n if (indexedChains.length === 0) {\n // the invariant holds\n return;\n }\n\n const indexedChainLatestIndexedBlocks = indexedChains.map(\n (chain) => chain.latestIndexedBlock.timestamp,\n );\n const indexedChainHighestLatestIndexedBlock = Math.max(...indexedChainLatestIndexedBlocks);\n\n // there are indexed chains\n // the invariant holds if the omnichain indexing cursor is same as\n // the highest latestIndexedBlock across all indexed chains\n if (snapshot.omnichainIndexingCursor !== indexedChainHighestLatestIndexedBlock) {\n ctx.issues.push({\n code: \"custom\",\n input: snapshot,\n message:\n \"`omnichainIndexingCursor` must be same as the highest `latestIndexedBlock` across all indexed chains.\",\n });\n }\n}\n\n/**\n * Invariant: For omnichain status snapshot 'unstarted',\n * all chains must have \"queued\" status.\n */\nexport function invariant_omnichainSnapshotUnstartedHasValidChains(\n ctx: ParsePayload<Map<ChainId, ChainIndexingStatusSnapshot>>,\n) {\n const chains = ctx.value;\n const hasValidChains = checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotUnstarted(\n Array.from(chains.values()),\n );\n\n if (hasValidChains === false) {\n ctx.issues.push({\n code: \"custom\",\n input: chains,\n message: `For omnichain status snapshot 'unstarted', all chains must have \"queued\" status.`,\n });\n }\n}\n\n/**\n * Invariant: For omnichain status snapshot 'backfill',\n * at least one chain must be in \"backfill\" status and\n * each chain has to have a status of either \"queued\", \"backfill\"\n * or \"completed\".\n */\nexport function invariant_omnichainStatusSnapshotBackfillHasValidChains(\n ctx: ParsePayload<Map<ChainId, ChainIndexingStatusSnapshot>>,\n) {\n const chains = ctx.value;\n const hasValidChains = checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotBackfill(\n Array.from(chains.values()),\n );\n\n if (hasValidChains === false) {\n ctx.issues.push({\n code: \"custom\",\n input: chains,\n message: `For omnichain status snapshot 'backfill', at least one chain must be in \"backfill\" status and each chain has to have a status of either \"queued\", \"backfill\" or \"completed\".`,\n });\n }\n}\n\n/**\n * Invariant: For omnichain status snapshot 'completed',\n * all chains must have \"completed\" status.\n */\nexport function invariant_omnichainStatusSnapshotCompletedHasValidChains(\n ctx: ParsePayload<Map<ChainId, ChainIndexingStatusSnapshot>>,\n) {\n const chains = ctx.value;\n const hasValidChains = checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotCompleted(\n Array.from(chains.values()),\n );\n\n if (hasValidChains === false) {\n ctx.issues.push({\n code: \"custom\",\n input: chains,\n message: `For omnichain status snapshot 'completed', all chains must have \"completed\" status.`,\n });\n }\n}\n\n/**\n * Invariant: For omnichain status snapshot 'following',\n * at least one chain must be in 'following' status.\n */\nexport function invariant_omnichainStatusSnapshotFollowingHasValidChains(\n ctx: ParsePayload<OmnichainIndexingStatusSnapshotFollowing>,\n) {\n const snapshot = ctx.value;\n const hasValidChains = checkChainIndexingStatusSnapshotsForOmnichainStatusSnapshotFollowing(\n Array.from(snapshot.chains.values()),\n );\n\n if (hasValidChains === false) {\n ctx.issues.push({\n code: \"custom\",\n input: snapshot,\n message: \"For omnichainStatus 'following', at least one chain must be in 'following' status.\",\n });\n }\n}\n\n/**\n * Invariants for {@link CrossChainIndexingStatusSnapshotOmnichain}.\n */\n\n/**\n * Invariant: for cross-chain indexing status snapshot omnichain,\n * slowestChainIndexingCursor equals to omnichainSnapshot.omnichainIndexingCursor\n */\nexport function invariant_slowestChainEqualsToOmnichainSnapshotTime(\n ctx: ParsePayload<CrossChainIndexingStatusSnapshotOmnichain>,\n) {\n const { slowestChainIndexingCursor, omnichainSnapshot } = ctx.value;\n const { omnichainIndexingCursor } = omnichainSnapshot;\n\n if (slowestChainIndexingCursor !== omnichainIndexingCursor) {\n console.log(\"invariant_slowestChainEqualsToOmnichainSnapshotTime\", {\n slowestChainIndexingCursor,\n omnichainIndexingCursor,\n });\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `'slowestChainIndexingCursor' must be equal to 'omnichainSnapshot.omnichainIndexingCursor'`,\n });\n }\n}\n\n/**\n * Invariant: for cross-chain indexing status snapshot omnichain,\n * snapshotTime is greater than or equal to the \"highest known block\" timestamp.\n */\nexport function invariant_snapshotTimeIsTheHighestKnownBlockTimestamp(\n ctx: ParsePayload<CrossChainIndexingStatusSnapshotOmnichain>,\n) {\n const { snapshotTime, omnichainSnapshot } = ctx.value;\n const chains = Array.from(omnichainSnapshot.chains.values());\n\n const startBlockTimestamps = chains.map((chain) => chain.config.startBlock.timestamp);\n\n const endBlockTimestamps = chains\n .map((chain) => chain.config)\n .filter((chainConfig) => chainConfig.configType === ChainIndexingConfigTypeIds.Definite)\n .map((chainConfig) => chainConfig.endBlock.timestamp);\n\n const backfillEndBlockTimestamps = chains\n .filter((chain) => chain.chainStatus === ChainIndexingStatusIds.Backfill)\n .map((chain) => chain.backfillEndBlock.timestamp);\n\n const latestKnownBlockTimestamps = chains\n .filter((chain) => chain.chainStatus === ChainIndexingStatusIds.Following)\n .map((chain) => chain.latestKnownBlock.timestamp);\n\n const highestKnownBlockTimestamp = Math.max(\n ...startBlockTimestamps,\n ...endBlockTimestamps,\n ...backfillEndBlockTimestamps,\n ...latestKnownBlockTimestamps,\n );\n\n if (snapshotTime < highestKnownBlockTimestamp) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `'snapshotTime' (${snapshotTime}) must be greater than or equal to the \"highest known block timestamp\" (${highestKnownBlockTimestamp})`,\n });\n }\n}\n\n/**\n * Invariants for {@link RealtimeIndexingStatusProjection}.\n */\n\n/**\n * Invariant: For realtime indexing status projection,\n * `projectedAt` is after or same as `snapshot.snapshotTime`.\n */\nexport function invariant_realtimeIndexingStatusProjectionProjectedAtIsAfterOrEqualToSnapshotTime(\n ctx: ParsePayload<RealtimeIndexingStatusProjection>,\n) {\n const projection = ctx.value;\n\n const { snapshot, projectedAt } = projection;\n\n if (snapshot.snapshotTime > projectedAt) {\n ctx.issues.push({\n code: \"custom\",\n input: projection,\n message: \"`projectedAt` must be after or same as `snapshot.snapshotTime`.\",\n });\n }\n}\n\n/**\n * Invariant: For realtime indexing status projection,\n * `worstCaseDistance` is the difference between `projectedAt`\n * and `omnichainIndexingCursor`.\n */\nexport function invariant_realtimeIndexingStatusProjectionWorstCaseDistanceIsCorrect(\n ctx: ParsePayload<RealtimeIndexingStatusProjection>,\n) {\n const projection = ctx.value;\n const { projectedAt, snapshot, worstCaseDistance } = projection;\n const { omnichainSnapshot } = snapshot;\n const expectedWorstCaseDistance = projectedAt - omnichainSnapshot.omnichainIndexingCursor;\n\n if (worstCaseDistance !== expectedWorstCaseDistance) {\n ctx.issues.push({\n code: \"custom\",\n input: projection,\n message:\n \"`worstCaseDistance` must be the exact difference between `projectedAt` and `snapshot.omnichainIndexingCursor`.\",\n });\n }\n}\n","import type { UnixTimestamp } from \"../../shared\";\nimport type { CrossChainIndexingStatusSnapshot, RealtimeIndexingStatusProjection } from \"./types\";\n\n/**\n * Create realtime indexing status projection from\n * a {@link CrossChainIndexingStatusSnapshot}.\n */\nexport function createRealtimeIndexingStatusProjection(\n snapshot: CrossChainIndexingStatusSnapshot,\n now: UnixTimestamp,\n): RealtimeIndexingStatusProjection {\n /**\n * The timestamp when the realtime indexing status was projected.\n *\n * Due to possible clock skew between different systems,\n * if the \"now\" timestamp on the system generating this indexing status\n * projection is less than the snapshot time, then this value must be set to\n * equal to the whichever is higher between the `now` and\n * the snapshot time to ensure all invariants are followed.\n */\n const projectedAt = Math.max(now, snapshot.snapshotTime);\n\n return {\n projectedAt,\n worstCaseDistance: projectedAt - snapshot.slowestChainIndexingCursor,\n snapshot,\n };\n}\n","import { type ChainId, type ChainIdString, serializeChainId } from \"../../shared\";\nimport type {\n SerializedCrossChainIndexingStatusSnapshot,\n SerializedOmnichainIndexingStatusSnapshot,\n SerializedOmnichainIndexingStatusSnapshotBackfill,\n SerializedOmnichainIndexingStatusSnapshotCompleted,\n SerializedOmnichainIndexingStatusSnapshotFollowing,\n SerializedOmnichainIndexingStatusSnapshotUnstarted,\n SerializedRealtimeIndexingStatusProjection,\n} from \"./serialized-types\";\nimport {\n type ChainIndexingStatusSnapshot,\n type CrossChainIndexingStatusSnapshot,\n OmnichainIndexingStatusIds,\n type OmnichainIndexingStatusSnapshot,\n type RealtimeIndexingStatusProjection,\n} from \"./types\";\n\nexport function serializeCrossChainIndexingStatusSnapshotOmnichain({\n strategy,\n slowestChainIndexingCursor,\n snapshotTime,\n omnichainSnapshot,\n}: CrossChainIndexingStatusSnapshot): SerializedCrossChainIndexingStatusSnapshot {\n return {\n strategy,\n slowestChainIndexingCursor,\n snapshotTime,\n omnichainSnapshot: serializeOmnichainIndexingStatusSnapshot(omnichainSnapshot),\n };\n}\n\nexport function serializeRealtimeIndexingStatusProjection(\n indexingProjection: RealtimeIndexingStatusProjection,\n): SerializedRealtimeIndexingStatusProjection {\n return {\n projectedAt: indexingProjection.projectedAt,\n worstCaseDistance: indexingProjection.worstCaseDistance,\n snapshot: serializeCrossChainIndexingStatusSnapshotOmnichain(indexingProjection.snapshot),\n } satisfies SerializedRealtimeIndexingStatusProjection;\n}\n\n/**\n * Serialize chain indexing snapshots.\n */\nexport function serializeChainIndexingSnapshots<\n ChainIndexingStatusSnapshotType extends ChainIndexingStatusSnapshot,\n>(\n chains: Map<ChainId, ChainIndexingStatusSnapshotType>,\n): Record<ChainIdString, ChainIndexingStatusSnapshotType> {\n const serializedSnapshots: Record<ChainIdString, ChainIndexingStatusSnapshotType> = {};\n\n for (const [chainId, snapshot] of chains.entries()) {\n serializedSnapshots[serializeChainId(chainId)] = snapshot;\n }\n\n return serializedSnapshots;\n}\n\n/**\n * Serialize a {@link OmnichainIndexingStatusSnapshot} object.\n */\nexport function serializeOmnichainIndexingStatusSnapshot(\n indexingStatus: OmnichainIndexingStatusSnapshot,\n): SerializedOmnichainIndexingStatusSnapshot {\n switch (indexingStatus.omnichainStatus) {\n case OmnichainIndexingStatusIds.Unstarted:\n return {\n omnichainStatus: OmnichainIndexingStatusIds.Unstarted,\n chains: serializeChainIndexingSnapshots(indexingStatus.chains),\n omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor,\n } satisfies SerializedOmnichainIndexingStatusSnapshotUnstarted;\n\n case OmnichainIndexingStatusIds.Backfill:\n return {\n omnichainStatus: OmnichainIndexingStatusIds.Backfill,\n chains: serializeChainIndexingSnapshots(indexingStatus.chains),\n omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor,\n } satisfies SerializedOmnichainIndexingStatusSnapshotBackfill;\n\n case OmnichainIndexingStatusIds.Completed: {\n return {\n omnichainStatus: OmnichainIndexingStatusIds.Completed,\n chains: serializeChainIndexingSnapshots(indexingStatus.chains),\n omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor,\n } satisfies SerializedOmnichainIndexingStatusSnapshotCompleted;\n }\n\n case OmnichainIndexingStatusIds.Following:\n return {\n omnichainStatus: OmnichainIndexingStatusIds.Following,\n chains: serializeChainIndexingSnapshots(indexingStatus.chains),\n omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor,\n } satisfies SerializedOmnichainIndexingStatusSnapshotFollowing;\n }\n}\n","import { serializeENSIndexerPublicConfig } from \"../../ensindexer\";\nimport type { SerializedENSApiPublicConfig } from \"./serialized-types\";\nimport type { ENSApiPublicConfig } from \"./types\";\n\n/**\n * Serialize a {@link ENSApiPublicConfig} object.\n */\nexport function serializeENSApiPublicConfig(\n config: ENSApiPublicConfig,\n): SerializedENSApiPublicConfig {\n const { version, theGraphFallback, ensIndexerPublicConfig } = config;\n\n return {\n version,\n theGraphFallback,\n ensIndexerPublicConfig: serializeENSIndexerPublicConfig(ensIndexerPublicConfig),\n } satisfies SerializedENSApiPublicConfig;\n}\n","import { deserializeENSApiPublicConfig } from \"../../ensapi\";\nimport type { ConfigResponse } from \"./response\";\nimport type { SerializedConfigResponse } from \"./serialized-response\";\n\n/**\n * Deserialize a {@link ConfigResponse} object.\n */\nexport function deserializeConfigResponse(\n serializedResponse: SerializedConfigResponse,\n): ConfigResponse {\n return deserializeENSApiPublicConfig(serializedResponse);\n}\n","import { serializeENSApiPublicConfig } from \"../../ensapi\";\nimport type { ConfigResponse } from \"./response\";\nimport type { SerializedConfigResponse } from \"./serialized-response\";\n\nexport function serializeConfigResponse(response: ConfigResponse): SerializedConfigResponse {\n return serializeENSApiPublicConfig(response);\n}\n","import { prettifyError } from \"zod/v4\";\n\nimport type { IndexingStatusResponse } from \"./response\";\nimport type { SerializedIndexingStatusResponse } from \"./serialized-response\";\nimport { makeIndexingStatusResponseSchema } from \"./zod-schemas\";\n\n/**\n * Deserialize a {@link IndexingStatusResponse} object.\n */\nexport function deserializeIndexingStatusResponse(\n maybeResponse: SerializedIndexingStatusResponse,\n): IndexingStatusResponse {\n const parsed = makeIndexingStatusResponseSchema().safeParse(maybeResponse);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize IndexingStatusResponse:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n","import z from \"zod/v4\";\n\nimport { makeRealtimeIndexingStatusProjectionSchema } from \"../../ensindexer/indexing-status/zod-schemas\";\nimport {\n type IndexingStatusResponse,\n IndexingStatusResponseCodes,\n type IndexingStatusResponseError,\n type IndexingStatusResponseOk,\n} from \"./response\";\n\n/**\n * Schema for {@link IndexingStatusResponseOk}\n **/\nexport const makeIndexingStatusResponseOkSchema = (\n valueLabel: string = \"Indexing Status Response OK\",\n) =>\n z.strictObject({\n responseCode: z.literal(IndexingStatusResponseCodes.Ok),\n realtimeProjection: makeRealtimeIndexingStatusProjectionSchema(valueLabel),\n });\n\n/**\n * Schema for {@link IndexingStatusResponseError}\n **/\nexport const makeIndexingStatusResponseErrorSchema = (\n _valueLabel: string = \"Indexing Status Response Error\",\n) =>\n z.strictObject({\n responseCode: z.literal(IndexingStatusResponseCodes.Error),\n });\n\n/**\n * Schema for {@link IndexingStatusResponse}\n **/\nexport const makeIndexingStatusResponseSchema = (valueLabel: string = \"Indexing Status Response\") =>\n z.discriminatedUnion(\"responseCode\", [\n makeIndexingStatusResponseOkSchema(valueLabel),\n makeIndexingStatusResponseErrorSchema(valueLabel),\n ]);\n","import type { RealtimeIndexingStatusProjection } from \"../../ensindexer\";\n\n/**\n * A status code for indexing status responses.\n */\nexport const IndexingStatusResponseCodes = {\n /**\n * Represents that the indexing status is available.\n */\n Ok: \"ok\",\n\n /**\n * Represents that the indexing status is unavailable.\n */\n Error: \"error\",\n} as const;\n\n/**\n * The derived string union of possible {@link IndexingStatusResponseCodes}.\n */\nexport type IndexingStatusResponseCode =\n (typeof IndexingStatusResponseCodes)[keyof typeof IndexingStatusResponseCodes];\n\n/**\n * An indexing status response when the indexing status is available.\n */\nexport type IndexingStatusResponseOk = {\n responseCode: typeof IndexingStatusResponseCodes.Ok;\n realtimeProjection: RealtimeIndexingStatusProjection;\n};\n\n/**\n * An indexing status response when the indexing status is unavailable.\n */\nexport type IndexingStatusResponseError = {\n responseCode: typeof IndexingStatusResponseCodes.Error;\n};\n\n/**\n * Indexing status response.\n *\n * Use the `responseCode` field to determine the specific type interpretation\n * at runtime.\n */\nexport type IndexingStatusResponse = IndexingStatusResponseOk | IndexingStatusResponseError;\n","import { serializeRealtimeIndexingStatusProjection } from \"../../ensindexer\";\nimport { type IndexingStatusResponse, IndexingStatusResponseCodes } from \"./response\";\nimport type {\n SerializedIndexingStatusResponse,\n SerializedIndexingStatusResponseOk,\n} from \"./serialized-response\";\n\nexport function serializeIndexingStatusResponse(\n response: IndexingStatusResponse,\n): SerializedIndexingStatusResponse {\n switch (response.responseCode) {\n case IndexingStatusResponseCodes.Ok:\n return {\n responseCode: response.responseCode,\n realtimeProjection: serializeRealtimeIndexingStatusProjection(response.realtimeProjection),\n } satisfies SerializedIndexingStatusResponseOk;\n\n case IndexingStatusResponseCodes.Error:\n return response;\n }\n}\n","import { prettifyError } from \"zod/v4\";\n\nimport type { NameTokensResponse, SerializedNameTokensResponse } from \"../name-tokens\";\nimport { makeNameTokensResponseSchema } from \"./zod-schemas\";\n\n/**\n * Deserialize a {@link NameTokensResponse} object.\n */\nexport function deserializedNameTokensResponse(\n maybeResponse: SerializedNameTokensResponse,\n): NameTokensResponse {\n const parsed = makeNameTokensResponseSchema(\"Name Tokens Response\", false).safeParse(\n maybeResponse,\n );\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize NameTokensResponse:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n","import { namehash } from \"viem\";\nimport z from \"zod/v4\";\n\nimport {\n makeNodeSchema,\n makeReinterpretedNameSchema,\n makeUnixTimestampSchema,\n} from \"../../shared/zod-schemas\";\nimport { NameTokenOwnershipTypes } from \"../../tokenscope\";\nimport { makeNameTokenSchema } from \"../../tokenscope/zod-schemas\";\nimport { ErrorResponseSchema } from \"../shared/errors/zod-schemas\";\nimport {\n NameTokensResponse,\n NameTokensResponseCodes,\n NameTokensResponseError,\n NameTokensResponseErrorCodes,\n NameTokensResponseErrorEnsIndexerConfigUnsupported,\n NameTokensResponseErrorIndexingStatusUnsupported,\n NameTokensResponseErrorNameTokensNotIndexed,\n NameTokensResponseOk,\n type RegisteredNameTokens,\n} from \"./response\";\n\n/**\n * Schema for {@link RegisteredNameTokens}.\n */\nexport const makeRegisteredNameTokenSchema = <const SerializableType extends boolean>(\n valueLabel: string = \"Registered Name Token\",\n serializable?: SerializableType,\n) =>\n z\n .object({\n domainId: makeNodeSchema(`${valueLabel}.domainId`),\n name: makeReinterpretedNameSchema(valueLabel),\n tokens: z.array(makeNameTokenSchema(`${valueLabel}.tokens`, serializable)).nonempty(),\n expiresAt: makeUnixTimestampSchema(`${valueLabel}.expiresAt`),\n accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`),\n })\n .check(function invariant_nameIsAssociatedWithDomainId(ctx) {\n const { name, domainId } = ctx.value;\n\n if (namehash(name) !== domainId) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `'name' must be associated with 'domainId': ${domainId}`,\n });\n }\n })\n .check(\n function invariant_nameTokensOwnershipTypeNameWrapperRequiresOwnershipTypeFullyOnchainOrUnknown(\n ctx,\n ) {\n const { tokens } = ctx.value;\n const containsOwnershipNameWrapper = tokens.some(\n (t) => t.ownership.ownershipType === NameTokenOwnershipTypes.NameWrapper,\n );\n const containsOwnershipFullyOnchainOrUnknown = tokens.some(\n (t) =>\n t.ownership.ownershipType === NameTokenOwnershipTypes.FullyOnchain ||\n t.ownership.ownershipType === NameTokenOwnershipTypes.Unknown,\n );\n if (containsOwnershipNameWrapper && !containsOwnershipFullyOnchainOrUnknown) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `'tokens' must contain name token with ownership type 'fully-onchain' or 'unknown' when name token with ownership type 'namewrapper' in listed`,\n });\n }\n },\n )\n .check(function invariant_nameTokensContainAtMostOneWithOwnershipTypeEffective(ctx) {\n const { tokens } = ctx.value;\n const tokensCountWithOwnershipFullyOnchain = tokens.filter(\n (t) => t.ownership.ownershipType === NameTokenOwnershipTypes.FullyOnchain,\n ).length;\n if (tokensCountWithOwnershipFullyOnchain > 1) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `'tokens' must contain at most one name token with ownership type 'fully-onchain', current count: ${tokensCountWithOwnershipFullyOnchain}`,\n });\n }\n });\n\n/**\n * Schema for {@link NameTokensResponseOk}\n */\nexport const makeNameTokensResponseOkSchema = <const SerializableType extends boolean>(\n valueLabel: string = \"Name Tokens Response OK\",\n serializable?: SerializableType,\n) =>\n z.strictObject({\n responseCode: z.literal(NameTokensResponseCodes.Ok),\n registeredNameTokens: makeRegisteredNameTokenSchema(`${valueLabel}.nameTokens`, serializable),\n });\n\n/**\n * Schema for {@link NameTokensResponseErrorNameTokensNotIndexed}\n */\nexport const makeNameTokensResponseErrorNameTokensNotIndexedSchema = (\n _valueLabel: string = \"Name Tokens Response Error Name Not Indexed\",\n) =>\n z.strictObject({\n responseCode: z.literal(NameTokensResponseCodes.Error),\n errorCode: z.literal(NameTokensResponseErrorCodes.NameTokensNotIndexed),\n error: ErrorResponseSchema,\n });\n\n/**\n * Schema for {@link NameTokensResponseErrorEnsIndexerConfigUnsupported}\n */\nexport const makeNameTokensResponseErrorEnsIndexerConfigUnsupported = (\n _valueLabel: string = \"Name Tokens Response Error ENSIndexer Config Unsupported\",\n) =>\n z.strictObject({\n responseCode: z.literal(NameTokensResponseCodes.Error),\n errorCode: z.literal(NameTokensResponseErrorCodes.EnsIndexerConfigUnsupported),\n error: ErrorResponseSchema,\n });\n/**\n * Schema for {@link NameTokensResponseErrorIndexingStatusUnsupported}\n */\nexport const makeNameTokensResponseErrorNameIndexingStatusUnsupported = (\n _valueLabel: string = \"Name Tokens Response Error Indexing Status Unsupported\",\n) =>\n z.strictObject({\n responseCode: z.literal(NameTokensResponseCodes.Error),\n errorCode: z.literal(NameTokensResponseErrorCodes.IndexingStatusUnsupported),\n error: ErrorResponseSchema,\n });\n/**\n * Schema for {@link NameTokensResponseError}\n */\nexport const makeNameTokensResponseErrorSchema = (\n valueLabel: string = \"Name Tokens Response Error\",\n) =>\n z.discriminatedUnion(\"errorCode\", [\n makeNameTokensResponseErrorNameTokensNotIndexedSchema(valueLabel),\n makeNameTokensResponseErrorEnsIndexerConfigUnsupported(valueLabel),\n makeNameTokensResponseErrorNameIndexingStatusUnsupported(valueLabel),\n ]);\n\n/**\n * Schema for {@link NameTokensResponse}\n */\nexport const makeNameTokensResponseSchema = <const SerializableType extends boolean = false>(\n valueLabel: string = \"Name Tokens Response\",\n serializable?: SerializableType,\n) => {\n return z.discriminatedUnion(\"responseCode\", [\n makeNameTokensResponseOkSchema(valueLabel, serializable ?? false),\n makeNameTokensResponseErrorSchema(valueLabel),\n ]);\n};\n","import { type Address, type Hex, isAddressEqual, zeroAddress } from \"viem\";\nimport { prettifyError } from \"zod/v4\";\n\nimport { type Node, uint256ToHex32 } from \"../ens\";\nimport {\n type AccountId,\n type AssetId,\n type AssetNamespace,\n type ChainId,\n formatAssetId,\n type TokenId,\n} from \"../shared\";\nimport type { AssetIdString } from \"../shared/serialized-types\";\nimport { makeAssetIdSchema, makeAssetIdStringSchema } from \"./zod-schemas\";\n\n/**\n * Serialized representation of {@link TokenId}.\n */\nexport type SerializedTokenId = string;\n\n/**\n * Serialized representation of {@link AssetId}.\n */\nexport interface SerializedAssetId extends Omit<AssetId, \"tokenId\"> {\n tokenId: SerializedTokenId;\n}\n\n/**\n * Serializes {@link AssetId} object to a structured form.\n */\nexport function serializeAssetId(assetId: AssetId): SerializedAssetId {\n return {\n assetNamespace: assetId.assetNamespace,\n contract: assetId.contract,\n tokenId: uint256ToHex32(assetId.tokenId),\n };\n}\n\n/**\n * Deserialize a {@link AssetId} object.\n */\nexport function deserializeAssetId(maybeAssetId: unknown, valueLabel?: string): AssetId {\n const schema = makeAssetIdSchema(valueLabel);\n const parsed = schema.safeParse(maybeAssetId);\n\n if (parsed.error) {\n throw new RangeError(`Cannot deserialize AssetId:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n\n/**\n * Parse a stringified representation of {@link AssetId} object.\n */\nexport function parseAssetId(maybeAssetId: AssetIdString, valueLabel?: string): AssetId {\n const schema = makeAssetIdStringSchema(valueLabel);\n const parsed = schema.safeParse(maybeAssetId);\n\n if (parsed.error) {\n throw new RangeError(`Cannot parse AssetId:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n\n/**\n * Builds an AssetId for the NFT represented by the given contract,\n * tokenId, and assetNamespace.\n *\n * @param contract - The contract that manages the NFT\n * @param tokenId - The tokenId of the NFT\n * @param assetNamespace - The assetNamespace of the NFT\n * @returns The AssetId for the NFT represented by the given contract,\n * tokenId, and assetNamespace\n */\nexport const buildAssetId = (\n contract: AccountId,\n tokenId: TokenId,\n assetNamespace: AssetNamespace,\n): AssetId => {\n return {\n assetNamespace,\n contract,\n tokenId,\n };\n};\n\n/**\n * A globally unique reference to an NFT tokenizing the ownership of a domain.\n */\nexport interface DomainAssetId extends AssetId {\n /**\n * The namehash (node) of the domain who's ownership is tokenized by\n * this `AssetId`.\n */\n domainId: Node;\n}\n\n/**\n * Serialized representation of {@link DomainAssetId}.\n */\nexport interface SerializedDomainAssetId extends SerializedAssetId {\n domainId: Node;\n}\n\nexport function serializeDomainAssetId(domainAsset: DomainAssetId): SerializedDomainAssetId {\n return {\n ...serializeAssetId(domainAsset),\n domainId: domainAsset.domainId,\n };\n}\n\n/**\n * An enum representing the mint status of a DomainAssetId.\n *\n * After we index a NFT we never delete it from our index. Instead, when an\n * indexed NFT is burned onchain we retain its record and update its mint\n * status as `burned`. If a NFT is minted again after it is burned its mint\n * status is updated to `minted`.\n */\nexport const NFTMintStatuses = {\n Minted: \"minted\",\n Burned: \"burned\",\n} as const;\n\nexport type NFTMintStatus = (typeof NFTMintStatuses)[keyof typeof NFTMintStatuses];\n\n/**\n * Metadata about a NFT transfer event.\n *\n * This metadata can be used for building more helpful messages when processing\n * NFT transfer events.\n */\nexport interface NFTTransferEventMetadata {\n chainId: ChainId;\n blockNumber: bigint;\n transactionHash: Hex;\n eventHandlerName: string;\n nft: DomainAssetId;\n}\n\nexport const formatNFTTransferEventMetadata = (metadata: NFTTransferEventMetadata): string => {\n const assetIdString = formatAssetId(metadata.nft);\n\n return [\n `Event: ${metadata.eventHandlerName}`,\n `Chain ID: ${metadata.chainId}`,\n `Block Number: ${metadata.blockNumber}`,\n `Transaction Hash: ${metadata.transactionHash}`,\n `NFT: ${assetIdString}`,\n ]\n .map((line) => ` - ${line}`)\n .join(\"\\n\");\n};\n\n/**\n * An enum representing the type of transfer that has occurred to a DomainAssetId.\n */\nexport const NFTTransferTypes = {\n /**\n * Initial transfer from zeroAddress to a non-zeroAddress\n * Can happen at most once to a NFT AssetId\n *\n * Invariants:\n * - NFT is not indexed and therefore has no previous mint status or owner\n * - new NFT mint status is `minted`\n * - new NFT owner is a non-zeroAddress\n */\n Mint: \"mint\",\n\n /**\n * Subsequent transfer from zeroAddress to a non-zeroAddress\n * Can happen any number of times to a NFT AssetId as it passes in a cycle from\n * mint -> burn -> remint -> burn -> remint -> ...\n *\n * Invariants:\n * - NFT is indexed\n * - previous NFT mint status was `burned`\n * - previous NFT owner is the zeroAddress\n * - new NFT mint status is `minted`\n * - new NFT owner is a non-zeroAddress\n */\n Remint: \"remint\",\n\n /**\n * Special transfer type for improperly implemented NFT contracts that allow a NFT\n * that is currently minted to be reminted before an intermediate burn.\n *\n * Transfer from zeroAddress to non-zeroAddress for an indexed NFT where the\n * previously indexed nft had status `minted` with a non-zeroAddress owner.\n *\n * Invariants:\n * - NFT is indexed\n * - previous NFT mint status was `minted`\n * - previous NFT owner was a non-zeroAddress\n * - new NFT mint status is `minted`\n * - new NFT owner is a non-zeroAddress\n */\n MintedRemint: \"minted-remint\",\n\n /**\n * Transfer from a non-zeroAddress to zeroAddress\n *\n * Invariants:\n * - NFT is indexed\n * - previous NFT mint status was `minted`\n * - previous NFT owner is a non-zeroAddress\n * - new NFT mint status is `burned`\n * - new NFT owner is the zeroAddress\n */\n Burn: \"burn\",\n\n /**\n * Transfer from a non-zeroAddress to a distinct non-zeroAddress\n *\n * Invariants:\n * - NFT is indexed\n * - previous and new NFT mint status is `minted`\n * - previous and new NFT owner are distinct non-zeroAddress\n */\n Transfer: \"transfer\",\n\n /**\n * Transfer from a non-zeroAddress to the same non-zeroAddress\n *\n * Invariants:\n * - NFT is indexed\n * - previous and new NFT mint status is `minted`\n * - previous and new NFT owner are equivalent non-zeroAddress\n */\n SelfTransfer: \"self-transfer\",\n\n /**\n * Transfer from zeroAddress to zeroAddress for an indexed NFT\n *\n * Invariants:\n * - NFT is indexed\n * - previous and new NFT mint status is `burned`\n * - previous and new NFT owner are zeroAddress\n */\n RemintBurn: \"remint-burn\",\n\n /**\n * Special transfer type for improperly implemented NFT contracts that allow a NFT\n * that is currently minted to be reminted again before an intermediate burn.\n *\n * Transfer from zeroAddress to zeroAddress for an indexed NFT where the\n * previously indexed nft had status `minted` with a non-zeroAddress owner.\n *\n * Invariants:\n * - NFT is indexed\n * - previous NFT mint status was `minted`\n * - previous NFT owner was a non-zeroAddress\n * - new NFT mint status is `burned`\n * - new NFT owner is the zeroAddress\n */\n MintedRemintBurn: \"minted-remint-burn\",\n\n /**\n * Transfer from zeroAddress to zeroAddress for an unindexed NFT\n *\n * Invariants:\n * - NFT is not indexed and therefore has no previous mint status or owner\n * - NFT should remain unindexed and without any mint status or owner\n */\n MintBurn: \"mint-burn\",\n} as const;\n\nexport type NFTTransferType = (typeof NFTTransferTypes)[keyof typeof NFTTransferTypes];\n\nexport const getNFTTransferType = (\n from: Address,\n to: Address,\n allowMintedRemint: boolean,\n metadata: NFTTransferEventMetadata,\n currentlyIndexedOwner?: Address,\n): NFTTransferType => {\n const isIndexed = currentlyIndexedOwner !== undefined;\n const isIndexedAsMinted = isIndexed && !isAddressEqual(currentlyIndexedOwner, zeroAddress);\n\n // a transfer from the zeroAddress to a non-zeroAddress represents minting\n const isMint = isAddressEqual(from, zeroAddress);\n\n // a transfer from a non-zeroAddress to the zeroAddress represents burning\n const isBurn = isAddressEqual(to, zeroAddress);\n\n // it's possible to transfer to and from the same address\n const isSelfTransfer = isAddressEqual(from, to);\n\n if (isIndexed && !isAddressEqual(currentlyIndexedOwner, from)) {\n if (isMint && allowMintedRemint) {\n // special case to allow minted remint from improperly implemented NFT contracts\n } else {\n throw new Error(\n `Error: Sending from ${from} conflicts with currently indexed owner ${currentlyIndexedOwner}.\\n${formatNFTTransferEventMetadata(metadata)}`,\n );\n }\n }\n\n if (isSelfTransfer) {\n if (isMint) {\n // a self-transfer to and from the zeroAddress represents either mint-burn, remint-burn,\n // or minted-remint-burn\n if (!isIndexed) {\n // mint-burn with !isIndexed && !isIndexedAsMinted\n return NFTTransferTypes.MintBurn;\n } else if (!isIndexedAsMinted) {\n // remint-burn with isIndexed && !isIndexedAsMinted\n return NFTTransferTypes.RemintBurn;\n } else if (allowMintedRemint) {\n // minted-remint-burn with isIndexed && isIndexedAsMinted && allowMintedRemint\n //\n // this is a non-standard special case for improperly implemented NFT contracts\n // that allow a NFT that is currently minted to be reminted again before an\n // intermediate burn.\n //\n // this is a self-transfer from zeroAddress to zeroAddress for an indexed NFT\n // where the previously indexed nft had status `minted` with a non-zeroAddress owner.\n return NFTTransferTypes.MintedRemintBurn;\n } else {\n // remint-burn with isIndexed && isIndexedAsMinted && !allowMintedRemint\n // invalid state transition to be minted and then remint again\n throw new Error(\n `Error: Invalid state transition from minted -> remint-burn\\n${formatNFTTransferEventMetadata(metadata)}`,\n );\n }\n } else {\n // a self-transfer to and from the same non-zero address\n if (!isIndexed) {\n // self-transfer with !isIndexed && !isIndexedAsMinted\n // this branch is unreachable because:\n // - from !== zeroAddress; and\n // - !isIndexedAsMinted requires that from === zeroAddress\n // throw an error to validate above assertions\n throw new Error(\n `Error: Invalid state transition from unindexed -> self-transfer\\n${formatNFTTransferEventMetadata(metadata)}`,\n );\n } else if (!isIndexedAsMinted) {\n // self-transfer with isIndexed && !isIndexedAsMinted\n throw new Error(\n `Error: invalid state transition from burned -> self-transfer\\n${formatNFTTransferEventMetadata(metadata)}`,\n );\n } else {\n // self-transfer with isIndexed && isIndexedAsMinted\n return NFTTransferTypes.SelfTransfer;\n }\n }\n } else if (isMint) {\n if (!isIndexed) {\n // mint with !isIndexed && !isIndexedAsMinted\n return NFTTransferTypes.Mint;\n } else if (!isIndexedAsMinted) {\n // mint with isIndexed && !isIndexedAsMinted\n return NFTTransferTypes.Remint;\n } else if (allowMintedRemint) {\n // mint with isIndexed && isIndexedAsMinted && allowMintedRemint\n //\n // this is a non-standard special case for improperly implemented NFT contracts\n // that allow a NFT that is currently minted to be reminted again before an\n // intermediate burn.\n //\n // this is a transfer from zeroAddress to non-zeroAddress for an indexed NFT\n // where the previously indexed nft had status `minted` with a non-zeroAddress owner.\n return NFTTransferTypes.MintedRemint;\n } else {\n // mint with isIndexed && isIndexedAsMinted && !allowMintedRemint\n throw new Error(\n `Error: Invalid state transition from minted -> mint\\n${formatNFTTransferEventMetadata(metadata)}`,\n );\n }\n } else if (isBurn) {\n if (!isIndexed) {\n // burn with !isIndexed && !isIndexedAsMinted\n throw new Error(\n `Error: Invalid state transition from unindexed -> burn\\n${formatNFTTransferEventMetadata(metadata)}`,\n );\n } else if (!isIndexedAsMinted) {\n // burn with isIndexed && !isIndexedAsMinted\n throw new Error(\n `Error: Invalid state transition from burned -> burn\\n${formatNFTTransferEventMetadata(metadata)}`,\n );\n } else {\n // burn with isIndexed && isIndexedAsMinted\n return NFTTransferTypes.Burn;\n }\n } else {\n // a transfer from a non-zeroAddress to a non-zeroAddress represents a transfer\n if (!isIndexed) {\n // transfer with !isIndexed && !isIndexedAsMinted\n throw new Error(\n `Error: Invalid state transition from unindexed -> transfer\\n${formatNFTTransferEventMetadata(metadata)}`,\n );\n } else if (!isIndexedAsMinted) {\n // transfer with isIndexed && !isIndexedAsMinted\n throw new Error(\n `Error: Invalid state transition from burned -> transfer\\n${formatNFTTransferEventMetadata(metadata)}`,\n );\n } else {\n // transfer with isIndexed && isIndexedAsMinted\n return NFTTransferTypes.Transfer;\n }\n }\n};\n","import { AssetId as CaipAssetId } from \"caip\";\nimport { zeroAddress } from \"viem\";\nimport z from \"zod/v4\";\nimport type { ParsePayload } from \"zod/v4/core\";\n\nimport { type AssetId, AssetNamespaces } from \"../shared/types\";\nimport { makeAccountIdSchema, makeNodeSchema } from \"../shared/zod-schemas\";\nimport { type DomainAssetId, NFTMintStatuses, type SerializedAssetId } from \"./assets\";\nimport {\n type NameToken,\n type NameTokenOwnershipBurned,\n type NameTokenOwnershipFullyOnchain,\n type NameTokenOwnershipNameWrapper,\n NameTokenOwnershipTypes,\n type NameTokenOwnershipUnknown,\n} from \"./name-token\";\n\nconst tokenIdSchemaSerializable = z.string();\nconst tokenIdSchemaNative = z.preprocess(\n (v) => (typeof v === \"string\" ? BigInt(v) : v),\n z.bigint().positive(),\n);\n\nexport function makeTokenIdSchema<const SerializableType extends boolean>(\n _valueLabel: string,\n serializable: SerializableType,\n): SerializableType extends true ? typeof tokenIdSchemaSerializable : typeof tokenIdSchemaNative;\nexport function makeTokenIdSchema(\n _valueLabel: string = \"Token ID Schema\",\n serializable: true | false = false,\n): typeof tokenIdSchemaSerializable | typeof tokenIdSchemaNative {\n if (serializable) {\n return tokenIdSchemaSerializable;\n } else {\n return tokenIdSchemaNative;\n }\n}\n\n/**\n * Make schema for {@link AssetId}.\n *\n */\nexport const makeAssetIdSchema = <const SerializableType extends boolean = false>(\n valueLabel: string = \"Asset ID Schema\",\n serializable?: SerializableType,\n) => {\n return z.object({\n assetNamespace: z.enum(AssetNamespaces),\n contract: makeAccountIdSchema(valueLabel),\n tokenId: makeTokenIdSchema(valueLabel, serializable ?? false),\n });\n};\n\n/**\n * Make schema for {@link AssetIdString}.\n */\nexport const makeAssetIdStringSchema = (valueLabel: string = \"Asset ID String Schema\") =>\n z.preprocess((v) => {\n if (typeof v === \"string\") {\n const result = new CaipAssetId(v);\n return {\n assetNamespace: result.assetName.namespace,\n contract: {\n chainId: Number(result.chainId.reference),\n address: result.assetName.reference,\n },\n tokenId: result.tokenId,\n } as SerializedAssetId;\n }\n\n return v;\n }, makeAssetIdSchema(valueLabel));\n\n/**\n * Make schema for {@link DomainAssetId}.\n */\nexport const makeDomainAssetSchema = (valueLabel: string = \"Domain Asset Schema\") =>\n makeAssetIdSchema(valueLabel).extend({\n domainId: makeNodeSchema(`${valueLabel}.domainId`),\n });\n\nfunction invariant_nameTokenOwnershipHasNonZeroAddressOwner(\n ctx: ParsePayload<\n NameTokenOwnershipNameWrapper | NameTokenOwnershipFullyOnchain | NameTokenOwnershipUnknown\n >,\n) {\n const ownership = ctx.value;\n if (ctx.value.owner.address === zeroAddress) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `Name Token Ownership with '${ownership.ownershipType}' must have 'address' other than the zero address.`,\n });\n }\n}\n\nexport const makeNameTokenOwnershipNameWrapperSchema = (\n valueLabel: string = \"Name Token Ownership NameWrapper\",\n) =>\n z\n .object({\n ownershipType: z.literal(NameTokenOwnershipTypes.NameWrapper),\n owner: makeAccountIdSchema(`${valueLabel}.owner`),\n })\n .check(invariant_nameTokenOwnershipHasNonZeroAddressOwner);\n\nexport const makeNameTokenOwnershipFullyOnchainSchema = (\n valueLabel: string = \"Name Token Ownership Fully Onchain\",\n) =>\n z\n .object({\n ownershipType: z.literal(NameTokenOwnershipTypes.FullyOnchain),\n owner: makeAccountIdSchema(`${valueLabel}.owner`),\n })\n .check(invariant_nameTokenOwnershipHasNonZeroAddressOwner);\n\nexport const makeNameTokenOwnershipBurnedSchema = (\n valueLabel: string = \"Name Token Ownership Burned\",\n) =>\n z\n .object({\n ownershipType: z.literal(NameTokenOwnershipTypes.Burned),\n owner: makeAccountIdSchema(`${valueLabel}.owner`),\n })\n .check(invariant_nameTokenOwnershipHasZeroAddressOwner);\n\nexport const makeNameTokenOwnershipUnknownSchema = (\n valueLabel: string = \"Name Token Ownership Unknown\",\n) =>\n z\n .object({\n ownershipType: z.literal(NameTokenOwnershipTypes.Unknown),\n owner: makeAccountIdSchema(`${valueLabel}.owner`),\n })\n .check(invariant_nameTokenOwnershipHasNonZeroAddressOwner);\n\nfunction invariant_nameTokenOwnershipHasZeroAddressOwner(\n ctx: ParsePayload<NameTokenOwnershipBurned>,\n) {\n const ownership = ctx.value;\n if (ctx.value.owner.address !== zeroAddress) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `Name Token Ownership with '${ownership.ownershipType}' must have 'address' set to the zero address.`,\n });\n }\n}\n\nexport const makeNameTokenOwnershipSchema = (valueLabel: string = \"Name Token Ownership\") =>\n z.discriminatedUnion(\"ownershipType\", [\n makeNameTokenOwnershipNameWrapperSchema(valueLabel),\n makeNameTokenOwnershipFullyOnchainSchema(valueLabel),\n makeNameTokenOwnershipBurnedSchema(valueLabel),\n makeNameTokenOwnershipUnknownSchema(valueLabel),\n ]);\n\n/**\n * Make schema for {@link NameToken}.\n */\nexport const makeNameTokenSchema = <const SerializableType extends boolean>(\n valueLabel: string = \"Name Token Schema\",\n serializable?: SerializableType,\n) =>\n z.object({\n token: makeAssetIdSchema(`${valueLabel}.token`, serializable),\n\n ownership: makeNameTokenOwnershipSchema(`${valueLabel}.ownership`),\n\n mintStatus: z.enum(NFTMintStatuses),\n });\n","import { isAddressEqual, zeroAddress } from \"viem\";\n\nimport { DatasourceNames, type ENSNamespaceId } from \"@ensnode/datasources\";\n\nimport { getParentNameFQDN, type InterpretedName } from \"../ens\";\nimport { type AccountId, accountIdEqual } from \"../shared\";\nimport { getDatasourceContract, maybeGetDatasourceContract } from \"../shared/datasource-contract\";\nimport type { AssetId } from \"../shared/types\";\nimport { type NFTMintStatus, type SerializedAssetId, serializeAssetId } from \"./assets\";\n\n/**\n * An enum representing the possible Name Token Ownership types.\n */\nexport const NameTokenOwnershipTypes = {\n /**\n * Name Token is owned by NameWrapper account.\n */\n NameWrapper: \"namewrapper\",\n\n /**\n * Name Token is owned fully onchain.\n *\n * This ownership type can only apply to direct subnames of `.eth`\n */\n FullyOnchain: \"fully-onchain\",\n\n /**\n * Name Token ownership has been transferred to the null address.\n */\n Burned: \"burned\",\n\n /**\n * Name Token ownership is unknown.\n */\n Unknown: \"unknown\",\n} as const;\n\nexport type NameTokenOwnershipType =\n (typeof NameTokenOwnershipTypes)[keyof typeof NameTokenOwnershipTypes];\n\nexport interface NameTokenOwnershipNameWrapper {\n ownershipType: typeof NameTokenOwnershipTypes.NameWrapper;\n\n /**\n * Owner\n *\n * Guarantees:\n * - `owner.address` is not the zero address.\n * - `owner.chainId` is same as the chainId of the associated NFT,\n * even if that NFT has been burned.\n */\n owner: AccountId;\n}\n\nexport interface NameTokenOwnershipFullyOnchain {\n ownershipType: typeof NameTokenOwnershipTypes.FullyOnchain;\n\n /**\n * Owner\n *\n * Guarantees:\n * - `owner.address` is not the zero address.\n * - `owner.chainId` is same as the chainId of the associated NFT,\n * even if that NFT has been burned.\n */\n owner: AccountId;\n}\n\nexport interface NameTokenOwnershipBurned {\n ownershipType: typeof NameTokenOwnershipTypes.Burned;\n\n /**\n * Owner\n *\n * Guarantees:\n * - `owner.address` is the zero address.\n * - `owner.chainId` is same as the chainId of the associated NFT,\n * even if that NFT has been burned.\n */\n owner: AccountId;\n}\n\nexport interface NameTokenOwnershipUnknown {\n ownershipType: typeof NameTokenOwnershipTypes.Unknown;\n\n /**\n * Owner\n *\n * Guarantees:\n * - `owner.address` is the zero address.\n * - `owner.chainId` is same as the chainId of the associated NFT,\n * even if that NFT has been burned.\n */\n owner: AccountId;\n}\n\nexport type NameTokenOwnership =\n | NameTokenOwnershipNameWrapper\n | NameTokenOwnershipFullyOnchain\n | NameTokenOwnershipBurned\n | NameTokenOwnershipUnknown;\n\nexport interface NameToken {\n /**\n * Token\n *\n * References the NFT that currently or previously tokenized ownership of\n * `name`.\n */\n token: AssetId;\n\n /**\n * Owner\n *\n * Identifies the ownership state of the token.\n *\n * Guarantees:\n * - The `ownership.owner.chainId` of this address is the same as is referenced\n * in `domainAsset.contract.chainId`.\n */\n ownership: NameTokenOwnership;\n\n /**\n * The mint status of the token.\n *\n * After ENSNode indexes the token for a name, even if that token is burned,\n * ENSNode will never forget how the token once represented the name.\n * When the token for a name is burned, ENSNode remembers this token but\n * updates its `mintStatus` to `burned`. If this token becomes minted again\n * after it was burned, its `mintStatus` is updated to `minted` again.\n *\n * NOTE: Tokens managed by the .eth BaseRegistrar for\n * direct subnames of .eth can only be burned when undergoing\n * a state transition of `minted` -> `burned` -> `minted` all within\n * the same registrar action for the case that a direct subname of .eth\n * has expired and has been fully released and is now being registered again.\n * Since all of those mint status state transitions are processed within\n * a single block, once the token managed by the .eth BaseRegistrar for\n * a direct subname of .eth has been minted, our state model will forever\n * represent it as `minted`.\n *\n * Guarantees:\n * - The `mintStatus` will be burned if and only\n * if `ownership.ownershipType` is `NameTokenOwnershipTypes.Burned`.\n */\n mintStatus: NFTMintStatus;\n}\n\n/**\n * Serialized representation of {@link NameToken}.\n */\nexport interface SerializedNameToken extends Omit<NameToken, \"token\"> {\n token: SerializedAssetId;\n}\n\nexport function serializeNameToken(nameToken: NameToken): SerializedNameToken {\n return {\n token: serializeAssetId(nameToken.token),\n ownership: nameToken.ownership,\n mintStatus: nameToken.mintStatus,\n };\n}\n\n/**\n * Get all NameWrapper accounts within provided ENS Namespace.\n *\n * Guaranteed to return at least one account for ENSRoot Datasource.\n */\nexport function getNameWrapperAccounts(namespaceId: ENSNamespaceId): [AccountId, ...AccountId[]] {\n const ethnamesNameWrapperAccount = getDatasourceContract(\n namespaceId,\n DatasourceNames.ENSRoot,\n \"NameWrapper\",\n );\n\n const lineanamesNameWrapperAccount = maybeGetDatasourceContract(\n namespaceId,\n DatasourceNames.Lineanames,\n \"NameWrapper\",\n );\n\n const nameWrapperAccounts: [AccountId, ...AccountId[]] = [\n // NameWrapper for direct subnames of .eth is defined for all ENS namespaces\n ethnamesNameWrapperAccount,\n ];\n\n if (lineanamesNameWrapperAccount) {\n // NameWrapper for Lineanames is only defined for some ENS namespaces\n nameWrapperAccounts.push(lineanamesNameWrapperAccount);\n }\n\n return nameWrapperAccounts;\n}\n\n/**\n * Get name token ownership for provided owner account within selected ENS Namespace.\n */\nexport function getNameTokenOwnership(\n namespaceId: ENSNamespaceId,\n name: InterpretedName,\n owner: AccountId,\n): NameTokenOwnership {\n const nameWrapperAccounts = getNameWrapperAccounts(namespaceId);\n const hasNameWrapperOwnership = nameWrapperAccounts.some((nameWrapperAccount) =>\n accountIdEqual(owner, nameWrapperAccount),\n );\n\n if (hasNameWrapperOwnership) {\n return {\n ownershipType: NameTokenOwnershipTypes.NameWrapper,\n owner,\n } satisfies NameTokenOwnershipNameWrapper;\n }\n\n if (isAddressEqual(owner.address, zeroAddress)) {\n return {\n ownershipType: NameTokenOwnershipTypes.Burned,\n owner,\n } satisfies NameTokenOwnershipBurned;\n }\n\n const parentName = getParentNameFQDN(name);\n\n // set ownershipType as 'fully-onchain' if `name` is a direct subname of .eth\n if (parentName === \"eth\") {\n return {\n ownershipType: NameTokenOwnershipTypes.FullyOnchain,\n owner,\n } satisfies NameTokenOwnershipFullyOnchain;\n }\n\n return {\n ownershipType: NameTokenOwnershipTypes.Unknown,\n owner,\n } satisfies NameTokenOwnershipUnknown;\n}\n","import z from \"zod/v4\";\n\nimport type { ErrorResponse } from \"./response\";\n\n/**\n * Schema for {@link ErrorResponse}.\n */\nexport const ErrorResponseSchema = z.object({\n message: z.string(),\n details: z.optional(z.unknown()),\n});\n","import type { UnixTimestamp } from \"@namehash/ens-referrals\";\n\nimport type { InterpretedName, Node } from \"../../ens\";\nimport type { NameToken, NameTokenOwnershipTypes } from \"../../tokenscope\";\nimport type { ErrorResponse } from \"../shared/errors\";\n\n/**\n * A status code for Name Tokens API responses.\n */\nexport const NameTokensResponseCodes = {\n /**\n * Represents a response when Name Tokens API can respond with requested data.\n */\n Ok: \"ok\",\n\n /**\n * Represents a response when Name Tokens API could not respond with requested data.\n */\n Error: \"error\",\n} as const;\n\n/**\n * The derived string union of possible {@link NameTokensResponseCodes}.\n */\nexport type NameTokensResponseCode =\n (typeof NameTokensResponseCodes)[keyof typeof NameTokensResponseCodes];\n\n/**\n * Error codes for Name Tokens API responses with 'error' response code.\n */\nexport const NameTokensResponseErrorCodes = {\n /**\n * Name tokens not indexed\n *\n * Represents an error when tokens for the requested name are not indexed by\n * the ENSNode instance's configuration.\n */\n NameTokensNotIndexed: \"name-tokens-not-indexed\",\n\n /**\n * Unsupported ENSIndexer Config\n *\n * Represents a prerequisites error when connected ENSIndexer config lacks\n * params required to enable Name Tokens API.\n */\n EnsIndexerConfigUnsupported: \"unsupported-ensindexer-config\",\n\n /**\n * Unsupported Indexing Status\n *\n * Represents a prerequisites error when Indexing Status has not yet reached\n * status required to enable Name Tokens API.\n */\n IndexingStatusUnsupported: \"unsupported-indexing-status\",\n} as const;\n\n/**\n * The derived string union of possible {@link NameTokensResponseErrorCodes}.\n */\nexport type NameTokensResponseErrorCode =\n (typeof NameTokensResponseErrorCodes)[keyof typeof NameTokensResponseErrorCodes];\n\n/**\n * Name Tokens for a name who's tokens are configured to\n * be indexed by the ENSNode instance's configuration.\n */\nexport interface RegisteredNameTokens {\n /**\n * Domain ID\n */\n domainId: Node;\n\n /**\n * Name\n *\n * FQDN of the name associated with `domainId`.\n *\n * Guarantees:\n * - `namehash(name)` is always `domainId`.\n */\n name: InterpretedName;\n\n /**\n * Name Tokens associated with the `domainId`.\n *\n * It contains every tokenized representation of `name` that\n * has ever been indexed for the given name as of `accurateAsOf`,\n * even if the given token has been burned or expired.\n *\n * Guarantees:\n * - Always includes at least one name token.\n * - When it includes more than one name token, it means that:\n * 1) More than 1 distinct tokenized representation of the ownership of\n * the `name` has been indexed as of `accurateAsOf`.\n * 2) All possible permutations of mint statuses of these tokens are\n * possible:\n * a) Multiple could be actively minted.\n * b) Multiple could be burned.\n * c) Some could be burned, others could be minted.\n * - Order of name tokens follows the order of onchain events that were\n * indexed when a token was minted, or burned.\n * - Each name token has a distinct `token` value which references\n * the NFT that currently or previously tokenized ownership of `name`.\n * - Each name token has ownership type (`ownership.ownershipType`) assigned:\n * - If there's a name token with ownership type\n * {@link NameTokenOwnershipTypes.NameWrapper}, it means that there must be also\n * another name token with ownership type either\n * {@link NameTokenOwnershipTypes.FullyOnchain}, or\n * {@link NameTokenOwnershipTypes.Unknown}.\n * - There can be at most one name token with ownership type\n * {@link NameTokenOwnershipTypes.FullyOnchain}.\n * - There can be any number of name tokens with ownership type\n * {@link NameTokenOwnershipTypes.Burned}.\n *\n * NOTE: It can be useful to get tokenized representations of the name that\n * are now burned: This can be helpful for looking up historical activity for\n * the name, including past buy orders, sell orders, and sales.\n *\n * How will the direct subnames of .eth that are wrapped by the NameWrapper\n * be represented?\n * 1) A direct subname of .eth that has been registered but\n * has never been wrapped by the NameWrapper, and:\n * a) Is still actively minted (independent of its expiry state).\n * b) Has been burned by sending it to the null address.\n * 2) A direct subname of .eth that has been registered and\n * has been wrapped by the NameWrapper, and:\n * a) Is still actively wrapped by the NameWrapper (independent of its\n * expiry state).\n * b) Is no longer wrapped by the NameWrapper, but is still actively\n * minted by the BaseRegistrar (independent of its expiry state).\n * c) Is no longer wrapped by the NameWrapper, and is also no longer\n * minted by the BaseRegistrar (both tokens now burned by sending to\n * the null address).\n */\n tokens: NameToken[];\n\n /**\n * Expiry date for the Registration Lifecycle\n *\n * The latest Registration Lifecycle for a node referenced in `domainId`.\n */\n expiresAt: UnixTimestamp;\n\n /**\n * The {@link UnixTimestamp} of when the data used to build the {@link NameTokensResponseOk.nameTokens} was accurate as of.\n */\n accurateAsOf: UnixTimestamp;\n}\n\n/**\n * A response when Name Tokens API can respond with requested data.\n */\nexport type NameTokensResponseOk = {\n responseCode: typeof NameTokensResponseCodes.Ok;\n\n /**\n * Name Tokens for the requested name.\n */\n registeredNameTokens: RegisteredNameTokens;\n};\n\n/**\n * Represents an error response when requested name was not indexed by ENSNode.\n */\nexport interface NameTokensResponseErrorNameTokensNotIndexed {\n responseCode: typeof NameTokensResponseCodes.Error;\n errorCode: typeof NameTokensResponseErrorCodes.NameTokensNotIndexed;\n error: ErrorResponse;\n}\n\n/**\n * Represents an error response when connected ENSIndexer config lacks\n * params required to enable Name Tokens API.\n */\nexport interface NameTokensResponseErrorEnsIndexerConfigUnsupported {\n responseCode: typeof NameTokensResponseCodes.Error;\n errorCode: typeof NameTokensResponseErrorCodes.EnsIndexerConfigUnsupported;\n error: ErrorResponse;\n}\n\n/**\n * Represents an error response when Indexing Status has not yet reached\n * status required to enable Name Tokens API.\n */\nexport interface NameTokensResponseErrorIndexingStatusUnsupported {\n responseCode: typeof NameTokensResponseCodes.Error;\n errorCode: typeof NameTokensResponseErrorCodes.IndexingStatusUnsupported;\n error: ErrorResponse;\n}\n\nexport type NameTokensResponseError =\n | NameTokensResponseErrorNameTokensNotIndexed\n | NameTokensResponseErrorEnsIndexerConfigUnsupported\n | NameTokensResponseErrorIndexingStatusUnsupported;\n\n/**\n * Name Tokens response.\n *\n * Use the `responseCode` field to determine the specific type interpretation\n * at runtime.\n */\nexport type NameTokensResponse = NameTokensResponseOk | NameTokensResponseError;\n","import {\n type ENSIndexerPublicConfig,\n type OmnichainIndexingStatusId,\n OmnichainIndexingStatusIds,\n PluginName,\n} from \"../../ensindexer\";\n\nexport const nameTokensPrerequisites = Object.freeze({\n /**\n * Required plugins to enable Name Tokens API routes.\n *\n * 1. `registrars` plugin is required so that data in the `registrationLifecycles`\n * table is populated.\n * 2. `tokenscope` plugin is required so that data in the `nameTokens`\n * table is populated.\n */\n requiredPlugins: [PluginName.Registrars, PluginName.TokenScope] as const,\n\n /**\n * Check if provided ENSApiPublicConfig supports the Name Tokens API.\n */\n hasEnsIndexerConfigSupport(config: ENSIndexerPublicConfig): boolean {\n return nameTokensPrerequisites.requiredPlugins.every((plugin) =>\n config.plugins.includes(plugin),\n );\n },\n /**\n * Required Indexing Status IDs\n *\n * Database indexes are created by the time the omnichain indexing status\n * is either `completed` or `following`.\n */\n supportedIndexingStatusIds: [\n OmnichainIndexingStatusIds.Completed,\n OmnichainIndexingStatusIds.Following,\n ],\n\n /**\n * Check if provided indexing status supports the Name Tokens API.\n */\n hasIndexingStatusSupport(omnichainIndexingStatusId: OmnichainIndexingStatusId): boolean {\n return nameTokensPrerequisites.supportedIndexingStatusIds.some(\n (supportedIndexingStatusId) => supportedIndexingStatusId === omnichainIndexingStatusId,\n );\n },\n});\n","import { serializeNameToken } from \"../../tokenscope\";\nimport {\n type NameTokensResponse,\n NameTokensResponseCodes,\n type RegisteredNameTokens,\n} from \"./response\";\nimport type {\n SerializedNameTokensResponse,\n SerializedNameTokensResponseOk,\n SerializedRegisteredNameTokens,\n} from \"./serialized-response\";\n\nexport function serializeRegisteredNameTokens({\n domainId,\n name,\n tokens,\n expiresAt,\n accurateAsOf,\n}: RegisteredNameTokens): SerializedRegisteredNameTokens {\n return {\n domainId,\n name,\n tokens: tokens.map(serializeNameToken),\n expiresAt,\n accurateAsOf,\n };\n}\n\nexport function serializeNameTokensResponse(\n response: NameTokensResponse,\n): SerializedNameTokensResponse {\n switch (response.responseCode) {\n case NameTokensResponseCodes.Ok:\n return {\n responseCode: response.responseCode,\n registeredNameTokens: serializeRegisteredNameTokens(response.registeredNameTokens),\n } satisfies SerializedNameTokensResponseOk;\n\n case NameTokensResponseCodes.Error:\n return response;\n }\n}\n","import { prettifyError } from \"zod/v4\";\n\nimport type { RegistrarActionsResponse } from \"./response\";\nimport type { SerializedRegistrarActionsResponse } from \"./serialized-response\";\nimport { makeRegistrarActionsResponseSchema } from \"./zod-schemas\";\n\n/**\n * Deserialize a {@link RegistrarActionsResponse} object.\n */\nexport function deserializeRegistrarActionsResponse(\n maybeResponse: SerializedRegistrarActionsResponse,\n): RegistrarActionsResponse {\n const parsed = makeRegistrarActionsResponseSchema().safeParse(maybeResponse);\n\n if (parsed.error) {\n throw new Error(\n `Cannot deserialize RegistrarActionsResponse:\\n${prettifyError(parsed.error)}\\n`,\n );\n }\n\n return parsed.data;\n}\n","import { namehash } from \"viem/ens\";\nimport z from \"zod/v4\";\nimport type { ParsePayload } from \"zod/v4/core\";\n\nimport { makeRegistrarActionSchema } from \"../../registrars/zod-schemas\";\nimport { makeReinterpretedNameSchema, makeUnixTimestampSchema } from \"../../shared/zod-schemas\";\nimport { ErrorResponseSchema } from \"../shared/errors/zod-schemas\";\nimport { makeResponsePageContextSchema } from \"../shared/pagination/zod-schemas\";\nimport { type NamedRegistrarAction, RegistrarActionsResponseCodes } from \"./response\";\n\nfunction invariant_registrationLifecycleNodeMatchesName(ctx: ParsePayload<NamedRegistrarAction>) {\n const { name, action } = ctx.value;\n const expectedNode = action.registrationLifecycle.node;\n const actualNode = namehash(name);\n\n if (actualNode !== expectedNode) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `The 'action.registrationLifecycle.node' must match namehash of 'name'`,\n });\n }\n}\n\n/**\n * Schema for {@link NamedRegistrarAction}.\n */\nexport const makeNamedRegistrarActionSchema = (valueLabel: string = \"Named Registrar Action\") =>\n z\n .object({\n action: makeRegistrarActionSchema(valueLabel),\n name: makeReinterpretedNameSchema(valueLabel),\n })\n .check(invariant_registrationLifecycleNodeMatchesName);\n\n/**\n * Schema for {@link RegistrarActionsResponseOk}\n */\nexport const makeRegistrarActionsResponseOkSchema = (\n valueLabel: string = \"Registrar Actions Response OK\",\n) =>\n z.object({\n responseCode: z.literal(RegistrarActionsResponseCodes.Ok),\n registrarActions: z.array(makeNamedRegistrarActionSchema(valueLabel)),\n pageContext: makeResponsePageContextSchema(`${valueLabel}.pageContext`),\n accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`).optional(),\n });\n\n/**\n * Schema for {@link RegistrarActionsResponseError}\n */\nexport const makeRegistrarActionsResponseErrorSchema = (\n _valueLabel: string = \"Registrar Actions Response Error\",\n) =>\n z.strictObject({\n responseCode: z.literal(RegistrarActionsResponseCodes.Error),\n error: ErrorResponseSchema,\n });\n\n/**\n * Schema for {@link RegistrarActionsResponse}\n */\nexport const makeRegistrarActionsResponseSchema = (\n valueLabel: string = \"Registrar Actions Response\",\n) =>\n z.discriminatedUnion(\"responseCode\", [\n makeRegistrarActionsResponseOkSchema(valueLabel),\n makeRegistrarActionsResponseErrorSchema(valueLabel),\n ]);\n","import { type Address, isAddress } from \"viem\";\n\nexport const validateLowercaseAddress = (address: Address): void => {\n if (!isAddress(address, { strict: false })) {\n throw new Error(`Invalid address: ${address}. Address must be a valid EVM address.`);\n }\n\n if (address !== address.toLowerCase()) {\n throw new Error(`Invalid address: ${address}. Address must be in lowercase format.`);\n }\n};\n\nexport const normalizeAddress = (address: Address): Address => {\n return address.toLowerCase() as Address;\n};\n","import { type Address, getAddress, type Hex, pad, size, slice, zeroAddress } from \"viem\";\n\n/**\n * Encoded Referrer\n *\n * Represents a \"raw\" ENS referrer value.\n *\n * Guaranteed to be a hex string representation of a 32-byte value.\n * For ENS Holiday Awards a correctly encoded referrer is\n * a left-padded lowercase EVM address.\n */\nexport type EncodedReferrer = Hex;\n\n/**\n * Encoded Referrer byte offset for ENS Holiday Awards.\n *\n * The count of left-padded bytes in an {@link EncodedReferrer} value for ENS Holiday Awards.\n */\nexport const ENCODED_REFERRER_BYTE_OFFSET = 12;\n\n/**\n * Encoded Referrer byte length\n *\n * The count of bytes the {@link EncodedReferrer} value consists of.\n */\nexport const ENCODED_REFERRER_BYTE_LENGTH = 32;\n\n/**\n * Encoded Referrer Padding for ENS Holiday Awards\n *\n * The initial bytes of correctly encoded referrer value for ENS Holiday Awards.\n */\nexport const EXPECTED_ENCODED_REFERRER_PADDING: Hex = pad(\"0x\", {\n size: ENCODED_REFERRER_BYTE_OFFSET,\n dir: \"left\",\n});\n\n/**\n * Zero Encoded Referrer\n *\n * Guaranteed to be a hex string representation of a 32-byte zero value.\n */\nexport const ZERO_ENCODED_REFERRER: EncodedReferrer = pad(\"0x\", {\n size: ENCODED_REFERRER_BYTE_LENGTH,\n dir: \"left\",\n});\n\n/**\n * Build an {@link EncodedReferrer} value for the given {@link Address}\n * according to the subjective referrer encoding used for ENS Holiday Awards.\n */\nexport function buildEncodedReferrer(address: Address): EncodedReferrer {\n const lowercaseAddress = address.toLowerCase() as Address;\n\n return pad(lowercaseAddress, { size: ENCODED_REFERRER_BYTE_LENGTH, dir: \"left\" });\n}\n\n/**\n * Decode an {@link EncodedReferrer} value into a checksummed {@link Address}\n * according to the subjective referrer encoding used for ENS Holiday Awards.\n *\n * @param encodedReferrer - The \"raw\" {@link EncodedReferrer} value to decode.\n * @returns The decoded referrer checksummed address.\n * @throws when encodedReferrer value is not represented by\n * {@link ENCODED_REFERRER_BYTE_LENGTH} bytes.\n * @throws when decodedReferrer is not a valid EVM address.\n */\nexport function decodeEncodedReferrer(encodedReferrer: EncodedReferrer): Address {\n // Invariant: encoded referrer must be of expected size\n if (size(encodedReferrer) !== ENCODED_REFERRER_BYTE_LENGTH) {\n throw new Error(\n `Encoded referrer value must be represented by ${ENCODED_REFERRER_BYTE_LENGTH} bytes.`,\n );\n }\n\n const padding = slice(encodedReferrer, 0, ENCODED_REFERRER_BYTE_OFFSET);\n\n // return zero address if the padding of encoded referrer is not correct\n // for ENS Holiday Awards\n if (padding !== EXPECTED_ENCODED_REFERRER_PADDING) {\n return zeroAddress;\n }\n\n const decodedReferrer = slice(encodedReferrer, ENCODED_REFERRER_BYTE_OFFSET);\n\n try {\n // return checksummed address\n return getAddress(decodedReferrer);\n } catch {\n throw new Error(`Decoded referrer value must be a valid EVM address.`);\n }\n}\n","import type { AggregatedReferrerMetrics } from \"./aggregations\";\nimport type { ReferrerLeaderboard } from \"./leaderboard\";\nimport { isNonNegativeInteger, isPositiveInteger } from \"./number\";\nimport type { AwardedReferrerMetrics } from \"./referrer-metrics\";\nimport type { ReferralProgramRules } from \"./rules\";\nimport type { UnixTimestamp } from \"./time\";\n\n/**\n * The default number of referrers per leaderboard page.\n */\nexport const REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT = 25;\n\n/**\n * The maximum number of referrers per leaderboard page.\n */\n\nexport const REFERRERS_PER_LEADERBOARD_PAGE_MAX = 100;\n\n/**\n * Pagination params for leaderboard queries.\n */\nexport interface ReferrerLeaderboardPageParams {\n /**\n * Requested referrer leaderboard page number (1-indexed)\n * @invariant Must be a positive integer (>= 1)\n * @default 1\n */\n page?: number;\n\n /**\n * Maximum number of referrers to return per leaderboard page\n * @invariant Must be a positive integer (>= 1) and less than or equal to {@link REFERRERS_PER_LEADERBOARD_PAGE_MAX}\n * @default {@link REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT}\n */\n recordsPerPage?: number;\n}\n\nconst validateReferrerLeaderboardPageParams = (params: ReferrerLeaderboardPageParams): void => {\n if (params.page !== undefined && !isPositiveInteger(params.page)) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageParams: ${params.page}. page must be a positive integer.`,\n );\n }\n if (params.recordsPerPage !== undefined && !isPositiveInteger(params.recordsPerPage)) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageParams: ${params.recordsPerPage}. recordsPerPage must be a positive integer.`,\n );\n }\n if (\n params.recordsPerPage !== undefined &&\n params.recordsPerPage > REFERRERS_PER_LEADERBOARD_PAGE_MAX\n ) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageParams: ${params.recordsPerPage}. recordsPerPage must be less than or equal to ${REFERRERS_PER_LEADERBOARD_PAGE_MAX}.`,\n );\n }\n};\n\nexport const buildReferrerLeaderboardPageParams = (\n params: ReferrerLeaderboardPageParams,\n): Required<ReferrerLeaderboardPageParams> => {\n const result = {\n page: params.page ?? 1,\n recordsPerPage: params.recordsPerPage ?? REFERRERS_PER_LEADERBOARD_PAGE_DEFAULT,\n } satisfies Required<ReferrerLeaderboardPageParams>;\n validateReferrerLeaderboardPageParams(result);\n return result;\n};\n\nexport interface ReferrerLeaderboardPageContext extends Required<ReferrerLeaderboardPageParams> {\n /**\n * Total number of referrers across all leaderboard pages\n * @invariant Guaranteed to be a non-negative integer (>= 0)\n */\n totalRecords: number;\n\n /**\n * Total number of pages in the leaderboard\n * @invariant Guaranteed to be a positive integer (>= 1)\n */\n totalPages: number;\n\n /**\n * Indicates if there is a next page available\n * @invariant true if and only if (`page` * `recordsPerPage` < `total`)\n */\n hasNext: boolean;\n\n /**\n * Indicates if there is a previous page available\n * @invariant true if and only if (`page` > 1)\n */\n hasPrev: boolean;\n\n /**\n * The start index of the referrers on the page (0-indexed)\n *\n * `undefined` if and only if `totalRecords` is 0.\n *\n * @invariant Guaranteed to be a non-negative integer (>= 0)\n */\n startIndex?: number;\n\n /**\n * The end index of the referrers on the page (0-indexed)\n *\n * `undefined` if and only if `totalRecords` is 0.\n *\n * @invariant Guaranteed to be a non-negative integer (>= 0)\n * @invariant If `totalRecords` is > 0:\n * - Guaranteed to be greater than or equal to `startIndex`.\n * - Guaranteed to be less than `totalRecords`.\n */\n endIndex?: number;\n}\n\nexport const validateReferrerLeaderboardPageContext = (\n context: ReferrerLeaderboardPageContext,\n): void => {\n validateReferrerLeaderboardPageParams(context);\n if (!isNonNegativeInteger(context.totalRecords)) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: total must be a non-negative integer but is ${context.totalRecords}.`,\n );\n }\n const startIndex = (context.page - 1) * context.recordsPerPage;\n const endIndex = startIndex + context.recordsPerPage;\n\n if (!context.hasNext && endIndex < context.totalRecords) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: if hasNext is false, endIndex (${endIndex}) must be greater than or equal to total (${context.totalRecords}).`,\n );\n } else if (context.hasNext && context.page * context.recordsPerPage >= context.totalRecords) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: if hasNext is true, endIndex (${endIndex}) must be less than total (${context.totalRecords}).`,\n );\n }\n if (!context.hasPrev && context.page !== 1) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: if hasPrev is false, page must be the first page (1) but is ${context.page}.`,\n );\n } else if (context.hasPrev && context.page === 1) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: if hasPrev is true, page must not be the first page (1) but is ${context.page}.`,\n );\n }\n};\n\nexport const buildReferrerLeaderboardPageContext = (\n optionalParams: ReferrerLeaderboardPageParams,\n leaderboard: ReferrerLeaderboard,\n): ReferrerLeaderboardPageContext => {\n const materializedParams = buildReferrerLeaderboardPageParams(optionalParams);\n\n const totalRecords = leaderboard.referrers.size;\n\n const totalPages = Math.max(1, Math.ceil(totalRecords / materializedParams.recordsPerPage));\n\n if (materializedParams.page > totalPages) {\n throw new Error(\n `Invalid ReferrerLeaderboardPageContext: page ${materializedParams.page} exceeds total pages ${totalPages}.`,\n );\n }\n\n if (totalRecords === 0) {\n return {\n ...materializedParams,\n totalRecords: 0,\n totalPages: 1,\n hasNext: false,\n hasPrev: false,\n startIndex: undefined,\n endIndex: undefined,\n } satisfies ReferrerLeaderboardPageContext;\n }\n\n const startIndex = (materializedParams.page - 1) * materializedParams.recordsPerPage;\n const maxTheoreticalIndexOnPage = startIndex + (materializedParams.recordsPerPage - 1);\n const endIndex = Math.min(maxTheoreticalIndexOnPage, totalRecords - 1);\n const hasNext = maxTheoreticalIndexOnPage < totalRecords - 1;\n const hasPrev = materializedParams.page > 1;\n\n const result = {\n ...materializedParams,\n totalRecords,\n totalPages,\n hasNext,\n hasPrev,\n startIndex,\n endIndex,\n } satisfies ReferrerLeaderboardPageContext;\n validateReferrerLeaderboardPageContext(result);\n return result;\n};\n\n/**\n * A page of referrers from the referrer leaderboard.\n */\nexport interface ReferrerLeaderboardPage {\n /**\n * The {@link ReferralProgramRules} used to generate the {@link ReferrerLeaderboard}\n * that this {@link ReferrerLeaderboardPage} comes from.\n */\n rules: ReferralProgramRules;\n\n /**\n * Ordered list of {@link AwardedReferrerMetrics} for the {@link ReferrerLeaderboardPage}\n * described by `pageContext` within the related {@link ReferrerLeaderboard}.\n *\n * @invariant Array will be empty if `pageContext.totalRecords` is 0.\n * @invariant Array entries are ordered by `rank` (descending).\n */\n referrers: AwardedReferrerMetrics[];\n\n /**\n * Aggregated metrics for all referrers on the leaderboard.\n */\n aggregatedMetrics: AggregatedReferrerMetrics;\n\n /**\n * The {@link ReferrerLeaderboardPageContext} of this {@link ReferrerLeaderboardPage} relative to the overall\n * {@link ReferrerLeaderboard}.\n */\n pageContext: ReferrerLeaderboardPageContext;\n\n /**\n * The {@link UnixTimestamp} of when the data used to build the {@link ReferrerLeaderboardPage} was accurate as of.\n */\n accurateAsOf: UnixTimestamp;\n}\n\nexport const getReferrerLeaderboardPage = (\n pageParams: ReferrerLeaderboardPageParams,\n leaderboard: ReferrerLeaderboard,\n): ReferrerLeaderboardPage => {\n const pageContext = buildReferrerLeaderboardPageContext(pageParams, leaderboard);\n\n let referrers: AwardedReferrerMetrics[];\n\n if (\n pageContext.totalRecords > 0 &&\n typeof pageContext.startIndex !== \"undefined\" &&\n typeof pageContext.endIndex !== \"undefined\"\n ) {\n // extract the referrers from the leaderboard in the range specified by `pageContext`.\n referrers = Array.from(leaderboard.referrers.values()).slice(\n pageContext.startIndex,\n pageContext.endIndex + 1, // For `slice`, this is exclusive of the element at the index 'end'. We need it to be inclusive, hence plus one.\n );\n } else {\n referrers = [];\n }\n\n return {\n rules: leaderboard.rules,\n referrers,\n aggregatedMetrics: leaderboard.aggregatedMetrics,\n pageContext,\n accurateAsOf: leaderboard.accurateAsOf,\n };\n};\n","import { type Address, getAddress } from \"viem\";\n\n/**\n * Build a URL to the official ENS manager app\n * where the given {@link Address} is set as the referrer.\n */\nexport function buildEnsReferralUrl(address: Address): URL {\n const ensAppUrl = new URL(\"https://app.ens.domains\");\n\n ensAppUrl.searchParams.set(\"referrer\", getAddress(address));\n\n return ensAppUrl;\n}\n","import type { Address } from \"viem\";\n\nimport type { AggregatedReferrerMetrics } from \"./aggregations\";\nimport type { ReferrerLeaderboard } from \"./leaderboard\";\nimport {\n type AwardedReferrerMetrics,\n buildUnrankedReferrerMetrics,\n type UnrankedReferrerMetrics,\n} from \"./referrer-metrics\";\nimport type { ReferralProgramRules } from \"./rules\";\nimport type { UnixTimestamp } from \"./time\";\n\n/**\n * The type of referrer detail data.\n */\nexport const ReferrerDetailTypeIds = {\n /**\n * Represents a referrer who is ranked on the leaderboard.\n */\n Ranked: \"ranked\",\n\n /**\n * Represents a referrer who is not ranked on the leaderboard.\n */\n Unranked: \"unranked\",\n} as const;\n\n/**\n * The derived string union of possible {@link ReferrerDetailTypeIds}.\n */\nexport type ReferrerDetailTypeId =\n (typeof ReferrerDetailTypeIds)[keyof typeof ReferrerDetailTypeIds];\n\n/**\n * Referrer detail data for a specific referrer address on the leaderboard.\n *\n * Includes the referrer's awarded metrics from the leaderboard plus timestamp.\n *\n * Invariants:\n * - `type` is always {@link ReferrerDetailTypeIds.Ranked}.\n *\n * @see {@link AwardedReferrerMetrics}\n */\nexport interface ReferrerDetailRanked {\n /**\n * The type of referrer detail data.\n */\n type: typeof ReferrerDetailTypeIds.Ranked;\n\n /**\n * The {@link ReferralProgramRules} used to calculate the {@link AwardedReferrerMetrics}.\n */\n rules: ReferralProgramRules;\n\n /**\n * The awarded referrer metrics from the leaderboard.\n *\n * Contains all calculated metrics including score, rank, qualification status,\n * and award pool share information.\n */\n referrer: AwardedReferrerMetrics;\n\n /**\n * Aggregated metrics for all referrers on the leaderboard.\n */\n aggregatedMetrics: AggregatedReferrerMetrics;\n\n /**\n * The {@link UnixTimestamp} of when the data used to build the {@link ReferrerDetailData} was accurate as of.\n */\n accurateAsOf: UnixTimestamp;\n}\n\n/**\n * Referrer detail data for a specific referrer address NOT on the leaderboard.\n *\n * Includes the referrer's unranked metrics (with null rank and isQualified: false) plus timestamp.\n *\n * Invariants:\n * - `type` is always {@link ReferrerDetailTypeIds.Unranked}.\n *\n * @see {@link UnrankedReferrerMetrics}\n */\nexport interface ReferrerDetailUnranked {\n /**\n * The type of referrer detail data.\n */\n type: typeof ReferrerDetailTypeIds.Unranked;\n\n /**\n * The {@link ReferralProgramRules} used to calculate the {@link UnrankedReferrerMetrics}.\n */\n rules: ReferralProgramRules;\n\n /**\n * The unranked referrer metrics (not on the leaderboard).\n *\n * Contains all calculated metrics with rank set to null and isQualified set to false.\n */\n referrer: UnrankedReferrerMetrics;\n\n /**\n * Aggregated metrics for all referrers on the leaderboard.\n */\n aggregatedMetrics: AggregatedReferrerMetrics;\n\n /**\n * The {@link UnixTimestamp} of when the data used to build the {@link UnrankedReferrerDetailData} was accurate as of.\n */\n accurateAsOf: UnixTimestamp;\n}\n\n/**\n * Referrer detail data for a specific referrer address.\n *\n * Use the `type` field to determine the specific type interpretation\n * at runtime.\n */\nexport type ReferrerDetail = ReferrerDetailRanked | ReferrerDetailUnranked;\n\n/**\n * Get the detail for a specific referrer from the leaderboard.\n *\n * Returns a {@link ReferrerDetailRanked} if the referrer is on the leaderboard,\n * or a {@link ReferrerDetailUnranked} if the referrer has no referrals.\n *\n * @param referrer - The referrer address to look up\n * @param leaderboard - The referrer leaderboard to query\n * @returns The appropriate {@link ReferrerDetail} (ranked or unranked)\n */\nexport const getReferrerDetail = (\n referrer: Address,\n leaderboard: ReferrerLeaderboard,\n): ReferrerDetail => {\n const awardedReferrerMetrics = leaderboard.referrers.get(referrer);\n\n // If referrer is on the leaderboard, return their ranked metrics\n if (awardedReferrerMetrics) {\n return {\n type: ReferrerDetailTypeIds.Ranked,\n rules: leaderboard.rules,\n referrer: awardedReferrerMetrics,\n aggregatedMetrics: leaderboard.aggregatedMetrics,\n accurateAsOf: leaderboard.accurateAsOf,\n };\n }\n\n // If referrer not found, return an unranked referrer record\n return {\n type: ReferrerDetailTypeIds.Unranked,\n rules: leaderboard.rules,\n referrer: buildUnrankedReferrerMetrics(referrer),\n aggregatedMetrics: leaderboard.aggregatedMetrics,\n accurateAsOf: leaderboard.accurateAsOf,\n };\n};\n","import { decodeEncodedReferrer, ENCODED_REFERRER_BYTE_LENGTH } from \"@namehash/ens-referrals\";\nimport type { Address } from \"viem\";\nimport { z } from \"zod/v4\";\nimport type { ParsePayload } from \"zod/v4/core\";\n\nimport { addPrices, isPriceEqual } from \"../shared\";\nimport {\n makeAccountIdSchema,\n makeBlockRefSchema,\n makeDurationSchema,\n makeHexStringSchema,\n makeLowercaseAddressSchema,\n makeNodeSchema,\n makePriceEthSchema,\n makeTransactionHashSchema,\n makeUnixTimestampSchema,\n} from \"../shared/zod-schemas\";\nimport {\n type RegistrarAction,\n type RegistrarActionEventId,\n RegistrarActionPricing,\n type RegistrarActionPricingAvailable,\n type RegistrarActionPricingUnknown,\n type RegistrarActionReferralAvailable,\n RegistrarActionTypes,\n} from \"./registrar-action\";\nimport type { RegistrationLifecycle } from \"./registration-lifecycle\";\nimport { Subregistry } from \"./subregistry\";\n\n/**\n * Schema for parsing objects into {@link Subregistry}.\n */\nconst makeSubregistrySchema = (valueLabel: string = \"Subregistry\") =>\n z.object({\n subregistryId: makeAccountIdSchema(`${valueLabel} Subregistry ID`),\n node: makeNodeSchema(`${valueLabel} Node`),\n });\n\n/**\n * Schema for parsing objects into {@link RegistrationLifecycle}.\n */\nexport const makeRegistrationLifecycleSchema = (valueLabel: string = \"Registration Lifecycle\") =>\n z.object({\n subregistry: makeSubregistrySchema(`${valueLabel} Subregistry`),\n node: makeNodeSchema(`${valueLabel} Node`),\n expiresAt: makeUnixTimestampSchema(`${valueLabel} Expires at`),\n });\n\n/** Invariant: total is sum of baseCost and premium */\nfunction invariant_registrarActionPricingTotalIsSumOfBaseCostAndPremium(\n ctx: ParsePayload<RegistrarActionPricingAvailable>,\n) {\n const { baseCost, premium, total } = ctx.value;\n const actualTotal = addPrices(baseCost, premium);\n\n if (!isPriceEqual(actualTotal, total)) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `'total' must be equal to the sum of 'baseCost' and 'premium'`,\n });\n }\n}\n\n/**\n * Schema for parsing objects into {@link RegistrarActionPricing}.\n */\nconst makeRegistrarActionPricingSchema = (valueLabel: string = \"Registrar Action Pricing\") =>\n z.union([\n // pricing available\n z\n .object({\n baseCost: makePriceEthSchema(`${valueLabel} Base Cost`),\n premium: makePriceEthSchema(`${valueLabel} Premium`),\n total: makePriceEthSchema(`${valueLabel} Total`),\n })\n .check(invariant_registrarActionPricingTotalIsSumOfBaseCostAndPremium)\n .transform((v) => v as RegistrarActionPricingAvailable),\n\n // pricing unknown\n z\n .object({\n baseCost: z.null(),\n premium: z.null(),\n total: z.null(),\n })\n .transform((v) => v as RegistrarActionPricingUnknown),\n ]);\n\n/** Invariant: decodedReferrer is based on encodedReferrer */\nfunction invariant_registrarActionDecodedReferrerBasedOnRawReferrer(\n ctx: ParsePayload<RegistrarActionReferralAvailable>,\n) {\n const { encodedReferrer, decodedReferrer } = ctx.value;\n\n try {\n // decodeEncodedReferrer returns checksummed address, but ENSNode work on lowercase address values\n // so we lowercase the result before using for checks\n const expectedDecodedReferrer = decodeEncodedReferrer(encodedReferrer).toLowerCase() as Address;\n\n if (decodedReferrer !== expectedDecodedReferrer) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `'decodedReferrer' must be based on 'encodedReferrer'`,\n });\n }\n } catch (error) {\n // in case decoding the encodedReferrer value could not succeed\n // pass the decoding error message\n const errorMessage = error instanceof Error ? error.message : \"Unknown error\";\n\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: errorMessage,\n });\n }\n}\n\nconst makeRegistrarActionReferralSchema = (valueLabel: string = \"Registrar Action Referral\") =>\n z.union([\n // referral available\n z\n .object({\n encodedReferrer: makeHexStringSchema(\n { bytesCount: ENCODED_REFERRER_BYTE_LENGTH },\n `${valueLabel} Encoded Referrer`,\n ),\n decodedReferrer: makeLowercaseAddressSchema(`${valueLabel} Decoded Referrer`),\n })\n .check(invariant_registrarActionDecodedReferrerBasedOnRawReferrer),\n\n // referral not applicable\n z.object({\n encodedReferrer: z.null(),\n decodedReferrer: z.null(),\n }),\n ]);\n\nfunction invariant_eventIdsInitialElementIsTheActionId(\n ctx: ParsePayload<Pick<RegistrarAction, \"id\" | \"eventIds\">>,\n) {\n const { id, eventIds } = ctx.value;\n\n if (eventIds[0] !== id) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: \"The initial element of `eventIds` must be the `id` value\",\n });\n }\n}\n\nconst EventIdSchema = z.string().nonempty();\n\nconst EventIdsSchema = z\n .array(EventIdSchema)\n .min(1)\n .transform((v) => v as [RegistrarActionEventId, ...RegistrarActionEventId[]]);\n\nexport const makeBaseRegistrarActionSchema = (valueLabel: string = \"Base Registrar Action\") =>\n z\n .object({\n id: EventIdSchema,\n incrementalDuration: makeDurationSchema(`${valueLabel} Incremental Duration`),\n registrant: makeLowercaseAddressSchema(`${valueLabel} Registrant`),\n registrationLifecycle: makeRegistrationLifecycleSchema(\n `${valueLabel} Registration Lifecycle`,\n ),\n pricing: makeRegistrarActionPricingSchema(`${valueLabel} Pricing`),\n referral: makeRegistrarActionReferralSchema(`${valueLabel} Referral`),\n block: makeBlockRefSchema(`${valueLabel} Block`),\n transactionHash: makeTransactionHashSchema(`${valueLabel} Transaction Hash`),\n eventIds: EventIdsSchema,\n })\n .check(invariant_eventIdsInitialElementIsTheActionId);\n\nexport const makeRegistrarActionRegistrationSchema = (valueLabel: string = \"Registration \") =>\n makeBaseRegistrarActionSchema(valueLabel).extend({\n type: z.literal(RegistrarActionTypes.Registration),\n });\n\nexport const makeRegistrarActionRenewalSchema = (valueLabel: string = \"Renewal\") =>\n makeBaseRegistrarActionSchema(valueLabel).extend({\n type: z.literal(RegistrarActionTypes.Renewal),\n });\n\n/**\n * Schema for {@link RegistrarAction}.\n */\nexport const makeRegistrarActionSchema = (valueLabel: string = \"Registrar Action\") =>\n z.discriminatedUnion(\"type\", [\n makeRegistrarActionRegistrationSchema(`${valueLabel} Registration`),\n makeRegistrarActionRenewalSchema(`${valueLabel} Renewal`),\n ]);\n","import type { EncodedReferrer } from \"@namehash/ens-referrals\";\n\nexport type { EncodedReferrer } from \"@namehash/ens-referrals\";\nexport { decodeEncodedReferrer, ZERO_ENCODED_REFERRER } from \"@namehash/ens-referrals\";\n\nimport type { Address, Hash } from \"viem\";\n\nimport {\n type BlockRef,\n type Duration,\n type PriceEth,\n type SerializedPriceEth,\n serializePriceEth,\n} from \"../shared\";\nimport type { RegistrationLifecycle } from \"./registration-lifecycle\";\n\n/**\n * Globally unique, deterministic ID of an indexed onchain event\n * associated with the \"logical registrar action\".\n */\nexport type RegistrarActionEventId = string;\n\n/**\n * Types of \"logical registrar action\".\n */\nexport const RegistrarActionTypes = {\n Registration: \"registration\",\n Renewal: \"renewal\",\n} as const;\n\nexport type RegistrarActionType = (typeof RegistrarActionTypes)[keyof typeof RegistrarActionTypes];\n\n/**\n * Pricing information for a \"logical registrar action\".\n */\nexport interface RegistrarActionPricingAvailable {\n /**\n * Base cost\n *\n * Base cost (before any `premium`) of Ether measured in units of Wei\n * paid to execute the \"logical registrar action\".\n *\n * May be 0.\n */\n baseCost: PriceEth;\n\n /**\n * Premium\n *\n * \"premium\" cost (in excesses of the `baseCost`) of Ether measured in\n * units of Wei paid to execute the \"logical registrar action\".\n *\n * May be 0.\n */\n premium: PriceEth;\n\n /**\n * Total\n *\n * Total cost of Ether measured in units of Wei paid to execute\n * the \"logical registrar action\".\n *\n * May be 0.\n */\n total: PriceEth;\n}\n\n/**\n * Pricing information for a \"logical registrar action\" when\n * there is no known pricing data.\n */\nexport interface RegistrarActionPricingUnknown {\n /**\n * Base cost\n *\n * Base cost (before any `premium`) of Ether measured in units of Wei\n * paid to execute the \"logical registrar action\".\n */\n baseCost: null;\n\n /**\n * Premium\n *\n * \"premium\" cost (in excesses of the `baseCost`) of Ether measured in\n * units of Wei paid to execute the \"logical registrar action\".\n */\n premium: null;\n\n /**\n * Total\n *\n * Total cost of Ether measured in units of Wei paid to execute\n * the \"logical registrar action\".\n */\n total: null;\n}\n\nexport type RegistrarActionPricing =\n | RegistrarActionPricingAvailable\n | RegistrarActionPricingUnknown;\n\nexport function isRegistrarActionPricingAvailable(\n registrarActionPricing: RegistrarActionPricing,\n): registrarActionPricing is RegistrarActionPricingAvailable {\n const { baseCost, premium, total } = registrarActionPricing;\n\n return baseCost !== null && premium !== null && total !== null;\n}\n\n/**\n * * Referral information for performing a \"logical registrar action\".\n */\nexport interface RegistrarActionReferralAvailable {\n /**\n * Encoded Referrer\n *\n * Represents the \"raw\" 32-byte \"referrer\" value emitted onchain in\n * association with the registrar action.\n */\n encodedReferrer: EncodedReferrer;\n\n /**\n * Decoded Referrer\n *\n * Decoded referrer according to the subjective interpretation of\n * `encodedReferrer` defined for ENS Holiday Awards.\n *\n * Identifies the interpreted address of the referrer.\n * The \"chainId\" of this address is the same as is referenced in\n * `subregistryId`.\n *\n * May be the \"zero address\" to represent that an `encodedReferrer` is\n * defined but that it is interpreted as no referrer.\n */\n decodedReferrer: Address;\n}\n\n/**\n * Referral information for performing a \"logical registrar action\" when\n * registrar controller does not implement referrals.\n */\nexport interface RegistrarActionReferralNotApplicable {\n /**\n * Encoded Referrer\n *\n * Represents the \"raw\" 32-byte \"referrer\" value emitted onchain in\n * association with the registrar action.\n */\n encodedReferrer: null;\n\n /**\n * Decoded Referrer\n *\n * Decoded referrer according to the subjective interpretation of\n * `encodedReferrer` defined for ENS Holiday Awards.\n *\n */\n decodedReferrer: null;\n}\n\nexport type RegistrarActionReferral =\n | RegistrarActionReferralAvailable\n | RegistrarActionReferralNotApplicable;\n\nexport function isRegistrarActionReferralAvailable(\n registrarActionReferral: RegistrarActionReferral,\n): registrarActionReferral is RegistrarActionReferralAvailable {\n const { encodedReferrer, decodedReferrer } = registrarActionReferral;\n\n return encodedReferrer !== null && decodedReferrer !== null;\n}\n\n/**\n * \"Logical registrar action\"\n *\n * Represents a state of \"logical registrar action\". May be built using data\n * from multiple events within the same \"logical\" registration / renewal action.\n */\nexport interface RegistrarAction {\n /**\n * \"Logical registrar action\" ID\n *\n * The `id` value is a deterministic and globally unique identifier for\n * the \"logical registrar action\".\n *\n * The `id` value represents the *initial* onchain event associated with\n * the \"logical registrar action\", but the full state of\n * the \"logical registrar action\" is an aggregate across each of\n * the onchain events referenced in the `eventIds` field.\n *\n * Guaranteed to be the very first element in `eventIds` array.\n */\n id: RegistrarActionEventId;\n\n /**\n * The type of the \"logical registrar action\".\n */\n type: RegistrarActionType;\n\n /**\n *\n * Incremental Duration\n *\n * If `type` is \"registration\":\n * - Represents the duration between `block.timestamp` and\n * the initial `registrationLifecycle.expiresAt` value that the associated\n * \"registration lifecycle\" will be initialized with.\n * If `type` is \"renewal\":\n * - Represents the incremental increase in duration made to\n * the `registrationLifecycle.expiresAt` value in the associated\n * \"registration lifecycle\".\n *\n * A \"registration lifecycle\" may be extended via renewal even after it\n * expires if it is still within its grace period.\n *\n * Consider the following scenario:\n *\n * The \"registration lifecycle\" of a direct subname of .eth is scheduled to\n * expire on Jan 1, midnight UTC. It is currently 30 days after this\n * expiration time. Therefore, there are currently another 60 days of grace\n * period remaining for this name. Anyone can still make a renewal to\n * extend the \"registration lifecycle\" of this name.\n *\n * Given this scenario, consider the following examples:\n *\n * 1. If a renewal is made with 10 days incremental duration,\n * the \"registration lifecycle\" for this name will remain in\n * an \"expired\" state, but it will now have another 70 days of\n * grace period remaining.\n *\n * 2. If a renewal is made with 50 days incremental duration,\n * the \"registration lifecycle\" for this name will no longer be\n * \"expired\" and will become \"active\", but the \"registration lifecycle\"\n * will now be scheduled to expire again in 20 days.\n *\n * After the \"registration lifecycle\" for a name becomes expired by more\n * than its grace period, it can no longer be renewed by anyone and is\n * considered \"released\". The name must first be registered again, starting\n * a new \"registration lifecycle\" of\n * active / expired / grace period / released.\n *\n * May be 0.\n *\n * Guaranteed to be a non-negative bigint value.\n */\n incrementalDuration: Duration;\n\n /**\n * Registrant\n *\n * Identifies the address that initiated the \"logical registrar action\" and\n * is paying the `pricing.total` cost (if applicable).\n *\n * It may not be the owner of the name:\n * 1. When a name is registered, the initial owner of the name may be\n * distinct from the registrant.\n * 2. There are no restrictions on who may renew a name.\n * Therefore the owner of the name may be distinct from the registrant.\n *\n * The \"chainId\" of this address is the same as is referenced in\n * `registrationLifecycle.subregistry.subregistryId`.\n */\n registrant: Address;\n\n /**\n * Registration Lifecycle associated with this \"logical registrar action\".\n */\n registrationLifecycle: RegistrationLifecycle;\n\n /**\n * Pricing information associated with this \"logical registrar action\".\n */\n pricing: RegistrarActionPricing;\n\n /**\n * Referral information associated with this \"logical registrar action\".\n */\n referral: RegistrarActionReferral;\n\n /**\n * Block ref\n *\n * References the block where the \"logical registrar action\" was executed.\n *\n * The \"chainId\" of this block is the same as is referenced in\n * `registrationLifecycle.subregistry.subregistryId`.\n */\n block: BlockRef;\n\n /**\n * Transaction hash\n *\n * Transaction hash of the transaction associated with\n * the \"logical registrar action\".\n *\n * The \"chainId\" of this transaction is the same as is referenced in\n * `registrationLifecycle.subregistry.subregistryId`.\n *\n * Note that a single transaction may be associated with any number of\n * \"logical registrar actions\".\n */\n transactionHash: Hash;\n\n /**\n * Event IDs\n *\n * Array of the eventIds that have contributed to the state of\n * the \"logical registrar action\" record.\n *\n * Each eventId is a deterministic and globally unique onchain event\n * identifier.\n *\n * Guarantees:\n * - Each eventId is of events that occurred within the block\n * referenced by `block.number`.\n * - At least 1 eventId.\n * - Ordered chronologically (ascending) by logIndex within `block.number`.\n * - The first element in the array is equal to the `id` of\n * the overall \"logical registrar action\" record.\n *\n * The following ideas are not generalized for ENS overall but happen to\n * be a characteristic of the scope of our current indexing logic:\n * 1. These id's always reference events emitted by\n * a related \"BaseRegistrar\" contract.\n * 2. These id's optionally reference events emitted by\n * a related \"Registrar Controller\" contract. This is because our\n * current indexing logic doesn't guarantee to index\n * all \"Registrar Controller\" contracts.\n */\n eventIds: [RegistrarActionEventId, ...RegistrarActionEventId[]];\n}\n\n/**\n * Serialized representation of {@link RegistrarActionPricingUnknown}.\n */\nexport type SerializedRegistrarActionPricingUnknown = RegistrarActionPricingUnknown;\n\n/**\n * Serialized representation of {@link RegistrarActionPricingAvailable}.\n */\nexport interface SerializedRegistrarActionPricingAvailable {\n baseCost: SerializedPriceEth;\n\n premium: SerializedPriceEth;\n\n total: SerializedPriceEth;\n}\n\n/**\n * Serialized representation of {@link RegistrarActionPricing}.\n */\nexport type SerializedRegistrarActionPricing =\n | SerializedRegistrarActionPricingAvailable\n | SerializedRegistrarActionPricingUnknown;\n\n/**\n * Serialized representation of {@link RegistrarAction}.\n */\nexport interface SerializedRegistrarAction extends Omit<RegistrarAction, \"pricing\"> {\n pricing: SerializedRegistrarActionPricing;\n}\n\nexport function serializeRegistrarActionPricing(\n pricing: RegistrarActionPricing,\n): SerializedRegistrarActionPricing {\n if (isRegistrarActionPricingAvailable(pricing)) {\n return {\n baseCost: serializePriceEth(pricing.baseCost),\n premium: serializePriceEth(pricing.premium),\n total: serializePriceEth(pricing.total),\n } satisfies SerializedRegistrarActionPricingAvailable;\n }\n\n return pricing satisfies SerializedRegistrarActionPricingUnknown;\n}\n\nexport function serializeRegistrarAction(\n registrarAction: RegistrarAction,\n): SerializedRegistrarAction {\n return {\n id: registrarAction.id,\n type: registrarAction.type,\n incrementalDuration: registrarAction.incrementalDuration,\n registrant: registrarAction.registrant,\n registrationLifecycle: registrarAction.registrationLifecycle,\n pricing: serializeRegistrarActionPricing(registrarAction.pricing),\n referral: registrarAction.referral,\n block: registrarAction.block,\n transactionHash: registrarAction.transactionHash,\n eventIds: registrarAction.eventIds,\n };\n}\n","import z from \"zod/v4\";\nimport type { ParsePayload } from \"zod/v4/core\";\n\nimport {\n makeNonNegativeIntegerSchema,\n makePositiveIntegerSchema,\n} from \"../../../shared/zod-schemas\";\nimport { RECORDS_PER_PAGE_MAX, RequestPageParams } from \"./request\";\nimport {\n ResponsePageContext,\n ResponsePageContextWithNoRecords,\n type ResponsePageContextWithRecords,\n} from \"./response\";\n\n/**\n * Schema for {@link RequestPageParams}\n */\nexport const makeRequestPageParamsSchema = (valueLabel: string = \"RequestPageParams\") =>\n z.object({\n page: makePositiveIntegerSchema(`${valueLabel}.page`),\n recordsPerPage: makePositiveIntegerSchema(`${valueLabel}.recordsPerPage`).max(\n RECORDS_PER_PAGE_MAX,\n `${valueLabel}.recordsPerPage must not exceed ${RECORDS_PER_PAGE_MAX}`,\n ),\n });\n\n/**\n * Schema for {@link ResponsePageContextWithNoRecords}\n */\nexport const makeResponsePageContextSchemaWithNoRecords = (\n valueLabel: string = \"ResponsePageContextWithNoRecords\",\n) =>\n z\n .object({\n totalRecords: z.literal(0),\n totalPages: z.literal(1),\n hasNext: z.literal(false),\n hasPrev: z.literal(false),\n startIndex: z.undefined(),\n endIndex: z.undefined(),\n })\n .extend(makeRequestPageParamsSchema(valueLabel).shape);\n\nfunction invariant_responsePageWithRecordsIsCorrect(\n ctx: ParsePayload<ResponsePageContextWithRecords>,\n) {\n const { hasNext, hasPrev, recordsPerPage, page, totalRecords, startIndex, endIndex } = ctx.value;\n\n const expectedHasNext = page * recordsPerPage < totalRecords;\n if (hasNext !== expectedHasNext) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `hasNext must be equal to '${expectedHasNext ? \"true\" : \"false\"}'`,\n });\n }\n\n const expectedHasPrev = page > 1;\n if (hasPrev !== expectedHasPrev) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `hasPrev must be equal to '${expectedHasPrev ? \"true\" : \"false\"}'`,\n });\n }\n\n if (endIndex < startIndex) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `endIndex must be greater than or equal to startIndex`,\n });\n }\n\n if (endIndex >= totalRecords) {\n ctx.issues.push({\n code: \"custom\",\n input: ctx.value,\n message: `endIndex must be lower than totalRecords`,\n });\n }\n}\n\n/**\n * Schema for {@link ResponsePageContextWithRecords}\n */\nexport const makeResponsePageContextSchemaWithRecords = (\n valueLabel: string = \"ResponsePageContextWithRecords\",\n) =>\n z\n .object({\n totalRecords: makePositiveIntegerSchema(`${valueLabel}.totalRecords`),\n totalPages: makePositiveIntegerSchema(`${valueLabel}.totalPages`),\n hasNext: z.boolean(),\n hasPrev: z.boolean(),\n startIndex: makeNonNegativeIntegerSchema(`${valueLabel}.startIndex`),\n endIndex: makeNonNegativeIntegerSchema(`${valueLabel}.endIndex`),\n })\n .extend(makeRequestPageParamsSchema(valueLabel).shape)\n .check(invariant_responsePageWithRecordsIsCorrect);\n\n/**\n * Schema for {@link ResponsePageContext}\n */\nexport const makeResponsePageContextSchema = (valueLabel: string = \"ResponsePageContext\") =>\n z.union([\n makeResponsePageContextSchemaWithNoRecords(valueLabel),\n makeResponsePageContextSchemaWithRecords(valueLabel),\n ]);\n","export const RECORDS_PER_PAGE_DEFAULT = 10;\n\nexport const RECORDS_PER_PAGE_MAX = 100;\n\n/**\n * Request page params.\n */\nexport interface RequestPageParams {\n /**\n * Requested page number (1-indexed)\n * @invariant Must be a positive integer (>= 1)\n * @default 1\n */\n page?: number;\n\n /**\n * Maximum number of records to return per page\n * @invariant Must be a positive integer (>= 1) and less than or equal to {@link RECORDS_PER_PAGE_MAX}\n * @default {@link RECORDS_PER_PAGE_DEFAULT}\n */\n recordsPerPage?: number;\n}\n","import type { InterpretedName } from \"../../ens\";\nimport type { RegistrarAction } from \"../../registrars\";\nimport type { UnixTimestamp } from \"../../shared\";\nimport type { IndexingStatusResponseCodes } from \"../indexing-status\";\nimport type { ErrorResponse } from \"../shared/errors\";\nimport type { ResponsePageContext } from \"../shared/pagination\";\n\n/**\n * A status code for Registrar Actions API responses.\n */\nexport const RegistrarActionsResponseCodes = {\n /**\n * Represents that Registrar Actions are available.\n */\n Ok: \"ok\",\n\n /**\n * Represents that Registrar Actions are unavailable.\n */\n Error: \"error\",\n} as const;\n\n/**\n * The derived string union of possible {@link RegistrarActionsResponseCodes}.\n */\nexport type RegistrarActionsResponseCode =\n (typeof RegistrarActionsResponseCodes)[keyof typeof RegistrarActionsResponseCodes];\n\n/**\n * \"Logical registrar action\" with its associated name.\n */\nexport interface NamedRegistrarAction {\n action: RegistrarAction;\n\n /**\n * Name\n *\n * FQDN of the name associated with `action`.\n *\n * Guarantees:\n * - `namehash(name)` is always `action.registrationLifecycle.node`.\n */\n name: InterpretedName;\n}\n\n/**\n * A response when Registrar Actions are available.\n */\nexport type RegistrarActionsResponseOk = {\n responseCode: typeof RegistrarActionsResponseCodes.Ok;\n registrarActions: NamedRegistrarAction[];\n pageContext: ResponsePageContext;\n\n /**\n * The {@link UnixTimestamp} of when the data used to build the list of {@link NamedRegistrarAction} was accurate as of.\n *\n * @remarks\n * **Note:** This value represents the `slowestChainIndexingCursor` from the latest omnichain indexing status\n * snapshot captured by ENSApi. The state returned in the response is guaranteed to be accurate as of this\n * timestamp but may be from a timestamp higher than this value.\n *\n * **Temporary:** This field is currently optional to maintain backward compatibility with ENS Awards\n * using older snapshot NPM packages. This will be changed to required in a future release.\n * See: https://github.com/namehash/ensnode/issues/1497\n */\n accurateAsOf?: UnixTimestamp;\n};\n\n/**\n * A response when Registrar Actions are unavailable.\n */\nexport interface RegistrarActionsResponseError {\n responseCode: typeof IndexingStatusResponseCodes.Error;\n error: ErrorResponse;\n}\n\n/**\n * Registrar Actions response.\n *\n * Use the `responseCode` field to determine the specific type interpretation\n * at runtime.\n */\nexport type RegistrarActionsResponse = RegistrarActionsResponseOk | RegistrarActionsResponseError;\n","import type { Address } from \"viem\";\n\nimport type { Node } from \"../../ens\";\nimport type { UnixTimestamp } from \"../../shared\";\nimport type { RequestPageParams } from \"../shared/pagination\";\n\n/**\n * Records Filters: Filter Types\n */\nexport const RegistrarActionsFilterTypes = {\n BySubregistryNode: \"bySubregistryNode\",\n WithEncodedReferral: \"withEncodedReferral\",\n ByDecodedReferrer: \"byDecodedReferrer\",\n BeginTimestamp: \"beginTimestamp\",\n EndTimestamp: \"endTimestamp\",\n} as const;\n\nexport type RegistrarActionsFilterType =\n (typeof RegistrarActionsFilterTypes)[keyof typeof RegistrarActionsFilterTypes];\n\nexport type RegistrarActionsFilterBySubregistryNode = {\n filterType: typeof RegistrarActionsFilterTypes.BySubregistryNode;\n value: Node;\n};\n\nexport type RegistrarActionsFilterWithEncodedReferral = {\n filterType: typeof RegistrarActionsFilterTypes.WithEncodedReferral;\n};\n\nexport type RegistrarActionsFilterByDecodedReferrer = {\n filterType: typeof RegistrarActionsFilterTypes.ByDecodedReferrer;\n value: Address;\n};\n\nexport type RegistrarActionsFilterBeginTimestamp = {\n filterType: typeof RegistrarActionsFilterTypes.BeginTimestamp;\n value: UnixTimestamp;\n};\n\nexport type RegistrarActionsFilterEndTimestamp = {\n filterType: typeof RegistrarActionsFilterTypes.EndTimestamp;\n value: UnixTimestamp;\n};\n\nexport type RegistrarActionsFilter =\n | RegistrarActionsFilterBySubregistryNode\n | RegistrarActionsFilterWithEncodedReferral\n | RegistrarActionsFilterByDecodedReferrer\n | RegistrarActionsFilterBeginTimestamp\n | RegistrarActionsFilterEndTimestamp;\n\n/**\n * Records Orders\n */\nexport const RegistrarActionsOrders = {\n LatestRegistrarActions: \"orderBy[timestamp]=desc\",\n} as const;\n\nexport type RegistrarActionsOrder =\n (typeof RegistrarActionsOrders)[keyof typeof RegistrarActionsOrders];\n\n/**\n * Represents a request to Registrar Actions API.\n */\nexport interface RegistrarActionsRequest extends RequestPageParams {\n /**\n * Filters to be applied while generating results.\n */\n filters?: RegistrarActionsFilter[];\n\n /**\n * Order applied while generating results.\n */\n order?: RegistrarActionsOrder;\n}\n","import type { Address } from \"viem\";\n\nimport type { Node } from \"../../ens\";\nimport type { UnixTimestamp } from \"../../shared\";\nimport {\n type RegistrarActionsFilter,\n type RegistrarActionsFilterBeginTimestamp,\n type RegistrarActionsFilterByDecodedReferrer,\n type RegistrarActionsFilterEndTimestamp,\n RegistrarActionsFilterTypes,\n type RegistrarActionsFilterWithEncodedReferral,\n} from \"./request\";\n\n/**\n * Build a \"parent node\" filter object for Registrar Actions query.\n */\nfunction byParentNode(parentNode: Node): RegistrarActionsFilter;\nfunction byParentNode(parentNode: undefined): undefined;\nfunction byParentNode(parentNode: Node | undefined): RegistrarActionsFilter | undefined {\n if (typeof parentNode === \"undefined\") {\n return undefined;\n }\n\n return {\n filterType: RegistrarActionsFilterTypes.BySubregistryNode,\n value: parentNode,\n };\n}\n\n/**\n * Build a \"with referral\" filter object for Registrar Actions query.\n */\nfunction withReferral(withReferral: true): RegistrarActionsFilter;\nfunction withReferral(withReferral: false | undefined): undefined;\nfunction withReferral(withReferral: boolean | undefined): RegistrarActionsFilter | undefined {\n if (!withReferral) {\n return undefined;\n }\n\n return {\n filterType: RegistrarActionsFilterTypes.WithEncodedReferral,\n } satisfies RegistrarActionsFilterWithEncodedReferral;\n}\n\n/**\n * Build a \"decoded referrer\" filter object for Registrar Actions query.\n */\nfunction byDecodedReferrer(decodedReferrer: Address): RegistrarActionsFilter;\nfunction byDecodedReferrer(decodedReferrer: undefined): undefined;\nfunction byDecodedReferrer(\n decodedReferrer: Address | undefined,\n): RegistrarActionsFilter | undefined {\n if (typeof decodedReferrer === \"undefined\") {\n return undefined;\n }\n\n return {\n filterType: RegistrarActionsFilterTypes.ByDecodedReferrer,\n value: decodedReferrer,\n } satisfies RegistrarActionsFilterByDecodedReferrer;\n}\n\n/**\n * Build a \"begin timestamp\" filter object for Registrar Actions query.\n *\n * Filters registrar actions to only include those at or after the specified timestamp (inclusive).\n */\nfunction beginTimestamp(timestamp: UnixTimestamp): RegistrarActionsFilter;\nfunction beginTimestamp(timestamp: undefined): undefined;\nfunction beginTimestamp(timestamp: UnixTimestamp | undefined): RegistrarActionsFilter | undefined {\n if (typeof timestamp === \"undefined\") {\n return undefined;\n }\n\n return {\n filterType: RegistrarActionsFilterTypes.BeginTimestamp,\n value: timestamp,\n } satisfies RegistrarActionsFilterBeginTimestamp;\n}\n\n/**\n * Build an \"end timestamp\" filter object for Registrar Actions query.\n *\n * Filters registrar actions to only include those at or before the specified timestamp (inclusive).\n */\nfunction endTimestamp(timestamp: UnixTimestamp): RegistrarActionsFilter;\nfunction endTimestamp(timestamp: undefined): undefined;\nfunction endTimestamp(timestamp: UnixTimestamp | undefined): RegistrarActionsFilter | undefined {\n if (typeof timestamp === \"undefined\") {\n return undefined;\n }\n\n return {\n filterType: RegistrarActionsFilterTypes.EndTimestamp,\n value: timestamp,\n } satisfies RegistrarActionsFilterEndTimestamp;\n}\n\nexport const registrarActionsFilter = {\n byParentNode,\n withReferral,\n byDecodedReferrer,\n beginTimestamp,\n endTimestamp,\n};\n","import {\n type ENSIndexerPublicConfig,\n type OmnichainIndexingStatusId,\n OmnichainIndexingStatusIds,\n PluginName,\n} from \"../../ensindexer\";\n\nexport const registrarActionsPrerequisites = Object.freeze({\n /**\n * Required plugins to enable Registrar Actions API routes.\n *\n * 1. `registrars` plugin is required so that data in the `registrarActions`\n * table is populated.\n * 2. `subgraph`, `basenames`, and `lineanames` are required to get the data\n * for the name associated with each registrar action.\n * 3. In theory not all of `subgraph`, `basenames`, and `lineanames` plugins\n * might be required. Ex: At least one, but the current logic in\n * the `registrars` plugin always indexes registrar actions across\n * Ethnames (subgraph), Basenames, and Lineanames and therefore we need to\n * ensure each value in the registrar actions table has\n * an associated record in the domains table.\n */\n requiredPlugins: [\n PluginName.Subgraph,\n PluginName.Basenames,\n PluginName.Lineanames,\n PluginName.Registrars,\n ] as const,\n\n /**\n * Check if provided ENSApiPublicConfig supports the Registrar Actions API.\n */\n hasEnsIndexerConfigSupport(config: ENSIndexerPublicConfig): boolean {\n return registrarActionsPrerequisites.requiredPlugins.every((plugin) =>\n config.plugins.includes(plugin),\n );\n },\n /**\n * Required Indexing Status IDs\n *\n * Database indexes are created by the time the omnichain indexing status\n * is either `completed` or `following`.\n */\n supportedIndexingStatusIds: [\n OmnichainIndexingStatusIds.Completed,\n OmnichainIndexingStatusIds.Following,\n ],\n\n /**\n * Check if provided indexing status supports the Registrar Actions API.\n */\n hasIndexingStatusSupport(omnichainIndexingStatusId: OmnichainIndexingStatusId): boolean {\n return registrarActionsPrerequisites.supportedIndexingStatusIds.some(\n (supportedIndexingStatusId) => supportedIndexingStatusId === omnichainIndexingStatusId,\n );\n },\n});\n","import {\n DatasourceNames,\n type ENSNamespaceId,\n ENSNamespaceIds,\n maybeGetDatasource,\n} from \"@ensnode/datasources\";\n\nimport type { Name } from \"../ens\";\nimport type { AccountId } from \"../shared\";\n\n/**\n * Gets the SubregistryId (an AccountId) of the Basenames Subregistry contract (this is the\n * \"BaseRegistrar\" contract for Basenames) for the provided namespace.\n *\n * @param namespace The ENS namespace to get the Basenames Subregistry ID for\n * @returns The AccountId for the Basenames Subregistry contract for the provided namespace.\n * @throws Error if the contract is not found for the given namespace.\n */\nexport function getBasenamesSubregistryId(namespace: ENSNamespaceId): AccountId {\n const datasource = maybeGetDatasource(namespace, DatasourceNames.Basenames);\n if (!datasource) {\n throw new Error(`Datasource not found for ${namespace} ${DatasourceNames.Basenames}`);\n }\n\n const address = datasource.contracts.BaseRegistrar?.address;\n if (address === undefined || Array.isArray(address)) {\n throw new Error(`BaseRegistrar contract not found or has multiple addresses for ${namespace}`);\n }\n\n return {\n chainId: datasource.chain.id,\n address,\n };\n}\n\n/**\n * Get the managed name for the Basenames subregistry for the selected ENS namespace.\n *\n * @param namespaceId\n * @returns registrar managed name\n * @throws an error when no registrar managed name could be returned\n */\nexport function getBasenamesSubregistryManagedName(namespaceId: ENSNamespaceId): Name {\n switch (namespaceId) {\n case ENSNamespaceIds.Mainnet:\n return \"base.eth\";\n case ENSNamespaceIds.Sepolia:\n return \"basetest.eth\";\n case ENSNamespaceIds.EnsTestEnv:\n throw new Error(\n `No registrar managed name is known for the 'basenames' subregistry within the \"${namespaceId}\" namespace.`,\n );\n }\n}\n","import {\n DatasourceNames,\n type ENSNamespaceId,\n ENSNamespaceIds,\n maybeGetDatasource,\n} from \"@ensnode/datasources\";\n\nimport type { Name } from \"../ens\";\nimport type { AccountId } from \"../shared\";\n\n/**\n * Gets the SubregistryId (an AccountId) of the Ethnames Subregistry contract (this is the\n * \"BaseRegistrar\" contract for direct subnames of .eth) for the provided namespace.\n *\n * @param namespace The ENS namespace to get the Ethnames Subregistry ID for\n * @returns The AccountId for the Ethnames Subregistry contract for the provided namespace.\n * @throws Error if the contract is not found for the given namespace.\n */\nexport function getEthnamesSubregistryId(namespace: ENSNamespaceId): AccountId {\n const datasource = maybeGetDatasource(namespace, DatasourceNames.ENSRoot);\n if (!datasource) {\n throw new Error(`Datasource not found for ${namespace} ${DatasourceNames.ENSRoot}`);\n }\n\n const address = datasource.contracts.BaseRegistrar?.address;\n if (address === undefined || Array.isArray(address)) {\n throw new Error(`BaseRegistrar contract not found or has multiple addresses for ${namespace}`);\n }\n\n return {\n chainId: datasource.chain.id,\n address,\n };\n}\n\n/**\n * Get the managed name for the Ethnames subregistry for the selected ENS namespace.\n *\n * @param namespaceId\n * @returns registrar managed name\n */\nexport function getEthnamesSubregistryManagedName(namespaceId: ENSNamespaceId): Name {\n switch (namespaceId) {\n case ENSNamespaceIds.Mainnet:\n case ENSNamespaceIds.Sepolia:\n case ENSNamespaceIds.EnsTestEnv:\n return \"eth\";\n }\n}\n","import {\n DatasourceNames,\n type ENSNamespaceId,\n ENSNamespaceIds,\n maybeGetDatasource,\n} from \"@ensnode/datasources\";\n\nimport type { Name } from \"../ens\";\nimport type { AccountId } from \"../shared\";\n\n/**\n * Gets the SubregistryId (an AccountId) of the Lineanames Subregistry contract (this is the\n * \"BaseRegistrar\" contract for Lineanames) for the provided namespace.\n *\n * @param namespace The ENS namespace to get the Lineanames Subregistry ID for\n * @returns The AccountId for the Lineanames Subregistry contract for the provided namespace.\n * @throws Error if the contract is not found for the given namespace.\n */\nexport function getLineanamesSubregistryId(namespace: ENSNamespaceId): AccountId {\n const datasource = maybeGetDatasource(namespace, DatasourceNames.Lineanames);\n if (!datasource) {\n throw new Error(`Datasource not found for ${namespace} ${DatasourceNames.Lineanames}`);\n }\n\n const address = datasource.contracts.BaseRegistrar?.address;\n if (address === undefined || Array.isArray(address)) {\n throw new Error(`BaseRegistrar contract not found or has multiple addresses for ${namespace}`);\n }\n\n return {\n chainId: datasource.chain.id,\n address,\n };\n}\n\n/**\n * Get the managed name for the Lineanames subregistry for the selected ENS namespace.\n *\n * @param namespaceId\n * @returns registrar managed name\n * @throws an error when no registrar managed name could be returned\n */\nexport function getLineanamesSubregistryManagedName(namespaceId: ENSNamespaceId): Name {\n switch (namespaceId) {\n case ENSNamespaceIds.Mainnet:\n return \"linea.eth\";\n case ENSNamespaceIds.Sepolia:\n return \"linea-sepolia.eth\";\n case ENSNamespaceIds.EnsTestEnv:\n throw new Error(\n `No registrar managed name is known for the 'Lineanames' subregistry within the \"${namespaceId}\" namespace.`,\n );\n }\n}\n","export interface RegistrationExpiryInfo {\n expiry: bigint | null;\n gracePeriod: bigint | null;\n}\n\n/**\n * Returns whether Registration is expired. If the Registration includes a Grace Period, the\n * Grace Period window is considered expired.\n */\nexport function isRegistrationExpired(info: RegistrationExpiryInfo, now: bigint): boolean {\n // no expiry, never expired\n if (info.expiry == null) return false;\n\n // otherwise check against now\n return info.expiry <= now;\n}\n\n/**\n * Returns whether Registration is fully expired. If the Registration includes a Grace Period, the\n * Grace Period window is considered NOT fully-expired.\n */\nexport function isRegistrationFullyExpired(info: RegistrationExpiryInfo, now: bigint): boolean {\n // no expiry, never expired\n if (info.expiry == null) return false;\n\n // otherwise it is expired if now >= expiry + grace\n return now >= info.expiry + (info.gracePeriod ?? 0n);\n}\n\n/**\n * Returns whether Registration is in grace period.\n */\nexport function isRegistrationInGracePeriod(info: RegistrationExpiryInfo, now: bigint): boolean {\n if (info.expiry == null) return false;\n if (info.gracePeriod == null) return false;\n\n return info.expiry <= now && info.expiry + info.gracePeriod > now;\n}\n","import { serializeRegistrarAction } from \"../../registrars\";\nimport {\n type NamedRegistrarAction,\n type RegistrarActionsResponse,\n RegistrarActionsResponseCodes,\n} from \"./response\";\nimport type {\n SerializedNamedRegistrarAction,\n SerializedRegistrarActionsResponse,\n SerializedRegistrarActionsResponseOk,\n} from \"./serialized-response\";\n\nexport function serializeNamedRegistrarAction({\n action,\n name,\n}: NamedRegistrarAction): SerializedNamedRegistrarAction {\n return {\n action: serializeRegistrarAction(action),\n name,\n };\n}\n\nexport function serializeRegistrarActionsResponse(\n response: RegistrarActionsResponse,\n): SerializedRegistrarActionsResponse {\n switch (response.responseCode) {\n case RegistrarActionsResponseCodes.Ok:\n return {\n responseCode: response.responseCode,\n registrarActions: response.registrarActions.map(serializeNamedRegistrarAction),\n pageContext: response.pageContext,\n accurateAsOf: response.accurateAsOf,\n } satisfies SerializedRegistrarActionsResponseOk;\n\n case RegistrarActionsResponseCodes.Error:\n return response;\n }\n}\n","import { prettifyError } from \"zod/v4\";\n\nimport type { ErrorResponse } from \"./response\";\nimport { ErrorResponseSchema } from \"./zod-schemas\";\n\n/**\n * Deserialize a {@link ErrorResponse} object.\n */\nexport function deserializeErrorResponse(maybeErrorResponse: unknown): ErrorResponse {\n const parsed = ErrorResponseSchema.safeParse(maybeErrorResponse);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize ErrorResponse:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n","import type {\n ResponsePageContext,\n ResponsePageContextWithNoRecords,\n ResponsePageContextWithRecords,\n} from \"./response\";\n\n/**\n * Build page context from request params and total records count.\n */\nexport function buildPageContext(\n page: number,\n recordsPerPage: number,\n totalRecords: number,\n): ResponsePageContext {\n const totalPages = Math.max(1, Math.ceil(totalRecords / recordsPerPage));\n\n if (page > totalPages) {\n throw new Error(`Invalid page: page ${page} exceeds total pages ${totalPages}.`);\n }\n\n if (totalRecords === 0) {\n return {\n page,\n recordsPerPage,\n totalRecords: 0,\n totalPages: 1,\n hasNext: false,\n hasPrev: false,\n startIndex: undefined,\n endIndex: undefined,\n } satisfies ResponsePageContextWithNoRecords;\n }\n\n const startIndex = (page - 1) * recordsPerPage;\n const maxTheoreticalIndexOnPage = startIndex + (recordsPerPage - 1);\n const endIndex = Math.min(maxTheoreticalIndexOnPage, totalRecords - 1);\n const hasNext = maxTheoreticalIndexOnPage < totalRecords - 1;\n const hasPrev = page > 1;\n\n return {\n page,\n recordsPerPage,\n totalRecords,\n totalPages,\n hasNext,\n hasPrev,\n startIndex,\n endIndex,\n } satisfies ResponsePageContextWithRecords;\n}\n","import type { ErrorResponse } from \"./api\";\n\nexport class ClientError extends Error {\n details?: unknown;\n\n constructor(message: string, details?: unknown) {\n super(message);\n this.name = \"ClientError\";\n this.details = details;\n }\n\n static fromErrorResponse({ message, details }: ErrorResponse) {\n return new ClientError(message, details);\n }\n}\n","import type {\n AggregatedReferrerMetrics,\n AwardedReferrerMetrics,\n ReferralProgramRules,\n ReferrerDetailRanked,\n ReferrerDetailUnranked,\n ReferrerLeaderboardPage,\n RevenueContribution,\n UnrankedReferrerMetrics,\n} from \"@namehash/ens-referrals\";\nimport { prettifyError } from \"zod/v4\";\n\nimport type {\n SerializedAggregatedReferrerMetrics,\n SerializedAwardedReferrerMetrics,\n SerializedReferralProgramRules,\n SerializedReferrerDetailRanked,\n SerializedReferrerDetailResponse,\n SerializedReferrerDetailUnranked,\n SerializedReferrerLeaderboardPage,\n SerializedReferrerLeaderboardPageResponse,\n SerializedUnrankedReferrerMetrics,\n} from \"./serialized-types\";\nimport type { ReferrerDetailResponse, ReferrerLeaderboardPageResponse } from \"./types\";\nimport {\n makeReferrerDetailResponseSchema,\n makeReferrerLeaderboardPageResponseSchema,\n} from \"./zod-schemas\";\n\n/**\n * Deserializes a string representation of {@link RevenueContribution} back to bigint.\n */\nfunction deserializeRevenueContribution(value: string): RevenueContribution {\n return BigInt(value);\n}\n\n/**\n * Deserializes a {@link SerializedReferralProgramRules} object.\n */\nfunction deserializeReferralProgramRules(\n rules: SerializedReferralProgramRules,\n): ReferralProgramRules {\n // All fields are already deserializable primitives\n return rules;\n}\n\n/**\n * Deserializes an {@link SerializedAwardedReferrerMetrics} object.\n */\nfunction deserializeAwardedReferrerMetrics(\n metrics: SerializedAwardedReferrerMetrics,\n): AwardedReferrerMetrics {\n return {\n referrer: metrics.referrer,\n totalReferrals: metrics.totalReferrals,\n totalIncrementalDuration: metrics.totalIncrementalDuration,\n totalRevenueContribution: deserializeRevenueContribution(metrics.totalRevenueContribution),\n score: metrics.score,\n rank: metrics.rank,\n isQualified: metrics.isQualified,\n finalScoreBoost: metrics.finalScoreBoost,\n finalScore: metrics.finalScore,\n awardPoolShare: metrics.awardPoolShare,\n awardPoolApproxValue: metrics.awardPoolApproxValue,\n };\n}\n\n/**\n * Deserializes an {@link SerializedUnrankedReferrerMetrics} object.\n */\nfunction deserializeUnrankedReferrerMetrics(\n metrics: SerializedUnrankedReferrerMetrics,\n): UnrankedReferrerMetrics {\n return {\n referrer: metrics.referrer,\n totalReferrals: metrics.totalReferrals,\n totalIncrementalDuration: metrics.totalIncrementalDuration,\n totalRevenueContribution: deserializeRevenueContribution(metrics.totalRevenueContribution),\n score: metrics.score,\n rank: metrics.rank,\n isQualified: metrics.isQualified,\n finalScoreBoost: metrics.finalScoreBoost,\n finalScore: metrics.finalScore,\n awardPoolShare: metrics.awardPoolShare,\n awardPoolApproxValue: metrics.awardPoolApproxValue,\n };\n}\n\n/**\n * Deserializes an {@link SerializedAggregatedReferrerMetrics} object.\n */\nfunction deserializeAggregatedReferrerMetrics(\n metrics: SerializedAggregatedReferrerMetrics,\n): AggregatedReferrerMetrics {\n return {\n grandTotalReferrals: metrics.grandTotalReferrals,\n grandTotalIncrementalDuration: metrics.grandTotalIncrementalDuration,\n grandTotalRevenueContribution: deserializeRevenueContribution(\n metrics.grandTotalRevenueContribution,\n ),\n grandTotalQualifiedReferrersFinalScore: metrics.grandTotalQualifiedReferrersFinalScore,\n minFinalScoreToQualify: metrics.minFinalScoreToQualify,\n };\n}\n\n/**\n * Deserializes a {@link SerializedReferrerLeaderboardPage} object.\n */\nfunction deserializeReferrerLeaderboardPage(\n page: SerializedReferrerLeaderboardPage,\n): ReferrerLeaderboardPage {\n return {\n rules: deserializeReferralProgramRules(page.rules),\n referrers: page.referrers.map(deserializeAwardedReferrerMetrics),\n aggregatedMetrics: deserializeAggregatedReferrerMetrics(page.aggregatedMetrics),\n pageContext: page.pageContext,\n accurateAsOf: page.accurateAsOf,\n };\n}\n\n/**\n * Deserializes a {@link SerializedReferrerDetailRanked} object.\n */\nfunction deserializeReferrerDetailRanked(\n detail: SerializedReferrerDetailRanked,\n): ReferrerDetailRanked {\n return {\n type: detail.type,\n rules: deserializeReferralProgramRules(detail.rules),\n referrer: deserializeAwardedReferrerMetrics(detail.referrer),\n aggregatedMetrics: deserializeAggregatedReferrerMetrics(detail.aggregatedMetrics),\n accurateAsOf: detail.accurateAsOf,\n };\n}\n\n/**\n * Deserializes a {@link SerializedReferrerDetailUnranked} object.\n */\nfunction deserializeReferrerDetailUnranked(\n detail: SerializedReferrerDetailUnranked,\n): ReferrerDetailUnranked {\n return {\n type: detail.type,\n rules: deserializeReferralProgramRules(detail.rules),\n referrer: deserializeUnrankedReferrerMetrics(detail.referrer),\n aggregatedMetrics: deserializeAggregatedReferrerMetrics(detail.aggregatedMetrics),\n accurateAsOf: detail.accurateAsOf,\n };\n}\n\n/**\n * Deserialize a {@link ReferrerLeaderboardPageResponse} object.\n *\n * Note: This function explicitly deserializes each subobject to convert string\n * RevenueContribution values back to bigint, then validates using Zod schemas\n * to enforce invariants on the data.\n */\nexport function deserializeReferrerLeaderboardPageResponse(\n maybeResponse: SerializedReferrerLeaderboardPageResponse,\n valueLabel?: string,\n): ReferrerLeaderboardPageResponse {\n let deserialized: ReferrerLeaderboardPageResponse;\n switch (maybeResponse.responseCode) {\n case \"ok\": {\n deserialized = {\n responseCode: maybeResponse.responseCode,\n data: deserializeReferrerLeaderboardPage(maybeResponse.data),\n } as ReferrerLeaderboardPageResponse;\n break;\n }\n\n case \"error\":\n deserialized = maybeResponse;\n break;\n }\n\n // Then validate the deserialized structure using zod schemas\n const schema = makeReferrerLeaderboardPageResponseSchema(valueLabel);\n const parsed = schema.safeParse(deserialized);\n\n if (parsed.error) {\n throw new Error(\n `Cannot deserialize SerializedReferrerLeaderboardPageResponse:\\n${prettifyError(parsed.error)}\\n`,\n );\n }\n\n return parsed.data;\n}\n\n/**\n * Deserialize a {@link ReferrerDetailResponse} object.\n *\n * Note: This function explicitly deserializes each subobject to convert string\n * RevenueContribution values back to bigint, then validates using Zod schemas\n * to enforce invariants on the data.\n */\nexport function deserializeReferrerDetailResponse(\n maybeResponse: SerializedReferrerDetailResponse,\n valueLabel?: string,\n): ReferrerDetailResponse {\n let deserialized: ReferrerDetailResponse;\n switch (maybeResponse.responseCode) {\n case \"ok\": {\n switch (maybeResponse.data.type) {\n case \"ranked\":\n deserialized = {\n responseCode: maybeResponse.responseCode,\n data: deserializeReferrerDetailRanked(maybeResponse.data),\n } as ReferrerDetailResponse;\n break;\n\n case \"unranked\":\n deserialized = {\n responseCode: maybeResponse.responseCode,\n data: deserializeReferrerDetailUnranked(maybeResponse.data),\n } as ReferrerDetailResponse;\n break;\n }\n break;\n }\n\n case \"error\":\n deserialized = maybeResponse;\n break;\n }\n\n // Then validate the deserialized structure using zod schemas\n const schema = makeReferrerDetailResponseSchema(valueLabel);\n const parsed = schema.safeParse(deserialized);\n\n if (parsed.error) {\n throw new Error(`Cannot deserialize ReferrerDetailResponse:\\n${prettifyError(parsed.error)}\\n`);\n }\n\n return parsed.data;\n}\n","/**\n * All zod schemas we define must remain internal implementation details.\n * We want the freedom to move away from zod in the future without impacting\n * any users of the ensnode-sdk package.\n *\n * The only way to share Zod schemas is to re-export them from\n * `./src/internal.ts` file.\n */\n\nimport {\n REFERRERS_PER_LEADERBOARD_PAGE_MAX,\n type ReferrerDetailRanked,\n ReferrerDetailTypeIds,\n type RevenueContribution,\n} from \"@namehash/ens-referrals\";\nimport z from \"zod/v4\";\n\nimport {\n makeAccountIdSchema,\n makeDurationSchema,\n makeFiniteNonNegativeNumberSchema,\n makeLowercaseAddressSchema,\n makeNonNegativeIntegerSchema,\n makePositiveIntegerSchema,\n makeUnixTimestampSchema,\n} from \"../shared/zod-schemas\";\nimport { ReferrerDetailResponseCodes, ReferrerLeaderboardPageResponseCodes } from \"./types\";\n\n/**\n * Schema for {@link RevenueContribution}\n */\nconst makeRevenueContributionSchema = (valueLabel: string = \"RevenueContribution\") =>\n z.coerce\n .bigint({\n error: `${valueLabel} must represent a bigint.`,\n })\n .nonnegative({\n error: `${valueLabel} must not be negative.`,\n });\n\n/**\n * Schema for ReferralProgramRules\n */\nexport const makeReferralProgramRulesSchema = (valueLabel: string = \"ReferralProgramRules\") =>\n z.object({\n totalAwardPoolValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.totalAwardPoolValue`),\n maxQualifiedReferrers: makeNonNegativeIntegerSchema(`${valueLabel}.maxQualifiedReferrers`),\n startTime: makeUnixTimestampSchema(`${valueLabel}.startTime`),\n endTime: makeUnixTimestampSchema(`${valueLabel}.endTime`),\n subregistryId: makeAccountIdSchema(`${valueLabel}.subregistryId`),\n });\n\n/**\n * Schema for AwardedReferrerMetrics (with numeric rank)\n */\nexport const makeAwardedReferrerMetricsSchema = (valueLabel: string = \"AwardedReferrerMetrics\") =>\n z.object({\n referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`),\n totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`),\n totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`),\n totalRevenueContribution: makeRevenueContributionSchema(\n `${valueLabel}.totalRevenueContribution`,\n ),\n score: makeFiniteNonNegativeNumberSchema(`${valueLabel}.score`),\n rank: makePositiveIntegerSchema(`${valueLabel}.rank`),\n isQualified: z.boolean(),\n finalScoreBoost: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScoreBoost`).max(\n 1,\n `${valueLabel}.finalScoreBoost must be <= 1`,\n ),\n finalScore: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScore`),\n awardPoolShare: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolShare`).max(\n 1,\n `${valueLabel}.awardPoolShare must be <= 1`,\n ),\n awardPoolApproxValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolApproxValue`),\n });\n\n/**\n * Schema for UnrankedReferrerMetrics (with null rank)\n */\nexport const makeUnrankedReferrerMetricsSchema = (valueLabel: string = \"UnrankedReferrerMetrics\") =>\n z.object({\n referrer: makeLowercaseAddressSchema(`${valueLabel}.referrer`),\n totalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.totalReferrals`),\n totalIncrementalDuration: makeDurationSchema(`${valueLabel}.totalIncrementalDuration`),\n totalRevenueContribution: makeRevenueContributionSchema(\n `${valueLabel}.totalRevenueContribution`,\n ),\n score: makeFiniteNonNegativeNumberSchema(`${valueLabel}.score`),\n rank: z.null(),\n isQualified: z.literal(false),\n finalScoreBoost: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScoreBoost`).max(\n 1,\n `${valueLabel}.finalScoreBoost must be <= 1`,\n ),\n finalScore: makeFiniteNonNegativeNumberSchema(`${valueLabel}.finalScore`),\n awardPoolShare: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolShare`).max(\n 1,\n `${valueLabel}.awardPoolShare must be <= 1`,\n ),\n awardPoolApproxValue: makeFiniteNonNegativeNumberSchema(`${valueLabel}.awardPoolApproxValue`),\n });\n\n/**\n * Schema for AggregatedReferrerMetrics\n */\nexport const makeAggregatedReferrerMetricsSchema = (\n valueLabel: string = \"AggregatedReferrerMetrics\",\n) =>\n z.object({\n grandTotalReferrals: makeNonNegativeIntegerSchema(`${valueLabel}.grandTotalReferrals`),\n grandTotalIncrementalDuration: makeDurationSchema(\n `${valueLabel}.grandTotalIncrementalDuration`,\n ),\n grandTotalRevenueContribution: makeRevenueContributionSchema(\n `${valueLabel}.grandTotalRevenueContribution`,\n ),\n grandTotalQualifiedReferrersFinalScore: makeFiniteNonNegativeNumberSchema(\n `${valueLabel}.grandTotalQualifiedReferrersFinalScore`,\n ),\n minFinalScoreToQualify: makeFiniteNonNegativeNumberSchema(\n `${valueLabel}.minFinalScoreToQualify`,\n ),\n });\n\nexport const makeReferrerLeaderboardPageContextSchema = (\n valueLabel: string = \"ReferrerLeaderboardPageContext\",\n) =>\n z.object({\n page: makePositiveIntegerSchema(`${valueLabel}.page`),\n recordsPerPage: makePositiveIntegerSchema(`${valueLabel}.recordsPerPage`).max(\n REFERRERS_PER_LEADERBOARD_PAGE_MAX,\n `${valueLabel}.recordsPerPage must not exceed ${REFERRERS_PER_LEADERBOARD_PAGE_MAX}`,\n ),\n totalRecords: makeNonNegativeIntegerSchema(`${valueLabel}.totalRecords`),\n totalPages: makePositiveIntegerSchema(`${valueLabel}.totalPages`),\n hasNext: z.boolean(),\n hasPrev: z.boolean(),\n startIndex: z.optional(makeNonNegativeIntegerSchema(`${valueLabel}.startIndex`)),\n endIndex: z.optional(makeNonNegativeIntegerSchema(`${valueLabel}.endIndex`)),\n });\n\n/**\n * Schema for ReferrerLeaderboardPage\n */\nexport const makeReferrerLeaderboardPageSchema = (valueLabel: string = \"ReferrerLeaderboardPage\") =>\n z.object({\n rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),\n referrers: z.array(makeAwardedReferrerMetricsSchema(`${valueLabel}.referrers[record]`)),\n aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),\n pageContext: makeReferrerLeaderboardPageContextSchema(`${valueLabel}.pageContext`),\n accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`),\n });\n\n/**\n * Schema for {@link ReferrerLeaderboardPageResponseOk}\n */\nexport const makeReferrerLeaderboardPageResponseOkSchema = (\n valueLabel: string = \"ReferrerLeaderboardPageResponseOk\",\n) =>\n z.object({\n responseCode: z.literal(ReferrerLeaderboardPageResponseCodes.Ok),\n data: makeReferrerLeaderboardPageSchema(`${valueLabel}.data`),\n });\n\n/**\n * Schema for {@link ReferrerLeaderboardPageResponseError}\n */\nexport const makeReferrerLeaderboardPageResponseErrorSchema = (\n _valueLabel: string = \"ReferrerLeaderboardPageResponseError\",\n) =>\n z.object({\n responseCode: z.literal(ReferrerLeaderboardPageResponseCodes.Error),\n error: z.string(),\n errorMessage: z.string(),\n });\n\n/**\n * Schema for {@link ReferrerLeaderboardPageResponse}\n */\nexport const makeReferrerLeaderboardPageResponseSchema = (\n valueLabel: string = \"ReferrerLeaderboardPageResponse\",\n) =>\n z.union([\n makeReferrerLeaderboardPageResponseOkSchema(valueLabel),\n makeReferrerLeaderboardPageResponseErrorSchema(valueLabel),\n ]);\n\n/**\n * Schema for {@link ReferrerDetailRanked} (with ranked metrics)\n */\nexport const makeReferrerDetailRankedSchema = (valueLabel: string = \"ReferrerDetailRanked\") =>\n z.object({\n type: z.literal(ReferrerDetailTypeIds.Ranked),\n rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),\n referrer: makeAwardedReferrerMetricsSchema(`${valueLabel}.referrer`),\n aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),\n accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`),\n });\n\n/**\n * Schema for {@link ReferrerDetailUnranked} (with unranked metrics)\n */\nexport const makeReferrerDetailUnrankedSchema = (valueLabel: string = \"ReferrerDetailUnranked\") =>\n z.object({\n type: z.literal(ReferrerDetailTypeIds.Unranked),\n rules: makeReferralProgramRulesSchema(`${valueLabel}.rules`),\n referrer: makeUnrankedReferrerMetricsSchema(`${valueLabel}.referrer`),\n aggregatedMetrics: makeAggregatedReferrerMetricsSchema(`${valueLabel}.aggregatedMetrics`),\n accurateAsOf: makeUnixTimestampSchema(`${valueLabel}.accurateAsOf`),\n });\n\n/**\n * Schema for {@link ReferrerDetailResponseOk}\n * Accepts either ranked or unranked referrer detail data\n */\nexport const makeReferrerDetailResponseOkSchema = (valueLabel: string = \"ReferrerDetailResponse\") =>\n z.object({\n responseCode: z.literal(ReferrerDetailResponseCodes.Ok),\n data: z.union([\n makeReferrerDetailRankedSchema(`${valueLabel}.data`),\n makeReferrerDetailUnrankedSchema(`${valueLabel}.data`),\n ]),\n });\n\n/**\n * Schema for {@link ReferrerDetailResponseError}\n */\nexport const makeReferrerDetailResponseErrorSchema = (\n _valueLabel: string = \"ReferrerDetailResponse\",\n) =>\n z.object({\n responseCode: z.literal(ReferrerDetailResponseCodes.Error),\n error: z.string(),\n errorMessage: z.string(),\n });\n\n/**\n * Schema for {@link ReferrerDetailResponse}\n */\nexport const makeReferrerDetailResponseSchema = (valueLabel: string = \"ReferrerDetailResponse\") =>\n z.union([\n makeReferrerDetailResponseOkSchema(valueLabel),\n makeReferrerDetailResponseErrorSchema(valueLabel),\n ]);\n","import type {\n ReferrerDetail,\n ReferrerLeaderboardPage,\n ReferrerLeaderboardPageParams,\n} from \"@namehash/ens-referrals\";\nimport type { Address } from \"viem\";\n\n/**\n * Request parameters for a referrer leaderboard page query.\n */\nexport interface ReferrerLeaderboardPageRequest extends ReferrerLeaderboardPageParams {}\n\n/**\n * A status code for a referrer leaderboard page API response.\n */\nexport const ReferrerLeaderboardPageResponseCodes = {\n /**\n * Represents that the requested referrer leaderboard page is available.\n */\n Ok: \"ok\",\n\n /**\n * Represents that the referrer leaderboard data is not available.\n */\n Error: \"error\",\n} as const;\n\n/**\n * The derived string union of possible {@link ReferrerLeaderboardPageResponseCodes}.\n */\nexport type ReferrerLeaderboardPageResponseCode =\n (typeof ReferrerLeaderboardPageResponseCodes)[keyof typeof ReferrerLeaderboardPageResponseCodes];\n\n/**\n * A referrer leaderboard page response when the data is available.\n */\nexport type ReferrerLeaderboardPageResponseOk = {\n responseCode: typeof ReferrerLeaderboardPageResponseCodes.Ok;\n data: ReferrerLeaderboardPage;\n};\n\n/**\n * A referrer leaderboard page response when the data is not available.\n */\nexport type ReferrerLeaderboardPageResponseError = {\n responseCode: typeof ReferrerLeaderboardPageResponseCodes.Error;\n error: string;\n errorMessage: string;\n};\n\n/**\n * A referrer leaderboard page API response.\n *\n * Use the `responseCode` field to determine the specific type interpretation\n * at runtime.\n */\nexport type ReferrerLeaderboardPageResponse =\n | ReferrerLeaderboardPageResponseOk\n | ReferrerLeaderboardPageResponseError;\n\n/**\n * Request parameters for referrer detail query.\n */\nexport interface ReferrerDetailRequest {\n /** The Ethereum address of the referrer to query */\n referrer: Address;\n}\n\n/**\n * A status code for referrer detail API responses.\n */\nexport const ReferrerDetailResponseCodes = {\n /**\n * Represents that the referrer detail data is available.\n */\n Ok: \"ok\",\n\n /**\n * Represents that an error occurred while fetching the data.\n */\n Error: \"error\",\n} as const;\n\n/**\n * The derived string union of possible {@link ReferrerDetailResponseCodes}.\n */\nexport type ReferrerDetailResponseCode =\n (typeof ReferrerDetailResponseCodes)[keyof typeof ReferrerDetailResponseCodes];\n\n/**\n * A referrer detail response when the data is available for a referrer on the leaderboard.\n */\nexport type ReferrerDetailResponseOk = {\n responseCode: typeof ReferrerDetailResponseCodes.Ok;\n data: ReferrerDetail;\n};\n\n/**\n * A referrer detail response when an error occurs.\n */\nexport type ReferrerDetailResponseError = {\n responseCode: typeof ReferrerDetailResponseCodes.Error;\n error: string;\n errorMessage: string;\n};\n\n/**\n * A referrer detail API response.\n *\n * Use the `responseCode` field to determine the specific type interpretation\n * at runtime.\n */\nexport type ReferrerDetailResponse = ReferrerDetailResponseOk | ReferrerDetailResponseError;\n","import type {\n AggregatedReferrerMetrics,\n AwardedReferrerMetrics,\n ReferralProgramRules,\n ReferrerDetailRanked,\n ReferrerDetailUnranked,\n ReferrerLeaderboardPage,\n RevenueContribution,\n UnrankedReferrerMetrics,\n} from \"@namehash/ens-referrals\";\n\nimport type {\n SerializedAggregatedReferrerMetrics,\n SerializedAwardedReferrerMetrics,\n SerializedReferralProgramRules,\n SerializedReferrerDetailRanked,\n SerializedReferrerDetailResponse,\n SerializedReferrerDetailUnranked,\n SerializedReferrerLeaderboardPage,\n SerializedReferrerLeaderboardPageResponse,\n SerializedUnrankedReferrerMetrics,\n} from \"./serialized-types\";\nimport {\n type ReferrerDetailResponse,\n ReferrerDetailResponseCodes,\n type ReferrerLeaderboardPageResponse,\n ReferrerLeaderboardPageResponseCodes,\n} from \"./types\";\n\n/**\n * Serializes a {@link RevenueContribution} value into its string representation.\n */\nfunction serializeRevenueContribution(revenueContribution: RevenueContribution): string {\n return revenueContribution.toString();\n}\n\n/**\n * Serializes a {@link ReferralProgramRules} object.\n */\nfunction serializeReferralProgramRules(\n rules: ReferralProgramRules,\n): SerializedReferralProgramRules {\n // All fields are already serializable primitives\n return rules;\n}\n\n/**\n * Serializes an {@link AwardedReferrerMetrics} object.\n */\nfunction serializeAwardedReferrerMetrics(\n metrics: AwardedReferrerMetrics,\n): SerializedAwardedReferrerMetrics {\n return {\n referrer: metrics.referrer,\n totalReferrals: metrics.totalReferrals,\n totalIncrementalDuration: metrics.totalIncrementalDuration,\n totalRevenueContribution: serializeRevenueContribution(metrics.totalRevenueContribution),\n score: metrics.score,\n rank: metrics.rank,\n isQualified: metrics.isQualified,\n finalScoreBoost: metrics.finalScoreBoost,\n finalScore: metrics.finalScore,\n awardPoolShare: metrics.awardPoolShare,\n awardPoolApproxValue: metrics.awardPoolApproxValue,\n };\n}\n\n/**\n * Serializes an {@link UnrankedReferrerMetrics} object.\n */\nfunction serializeUnrankedReferrerMetrics(\n metrics: UnrankedReferrerMetrics,\n): SerializedUnrankedReferrerMetrics {\n return {\n referrer: metrics.referrer,\n totalReferrals: metrics.totalReferrals,\n totalIncrementalDuration: metrics.totalIncrementalDuration,\n totalRevenueContribution: serializeRevenueContribution(metrics.totalRevenueContribution),\n score: metrics.score,\n rank: metrics.rank,\n isQualified: metrics.isQualified,\n finalScoreBoost: metrics.finalScoreBoost,\n finalScore: metrics.finalScore,\n awardPoolShare: metrics.awardPoolShare,\n awardPoolApproxValue: metrics.awardPoolApproxValue,\n };\n}\n\n/**\n * Serializes an {@link AggregatedReferrerMetrics} object.\n */\nfunction serializeAggregatedReferrerMetrics(\n metrics: AggregatedReferrerMetrics,\n): SerializedAggregatedReferrerMetrics {\n return {\n grandTotalReferrals: metrics.grandTotalReferrals,\n grandTotalIncrementalDuration: metrics.grandTotalIncrementalDuration,\n grandTotalRevenueContribution: serializeRevenueContribution(\n metrics.grandTotalRevenueContribution,\n ),\n grandTotalQualifiedReferrersFinalScore: metrics.grandTotalQualifiedReferrersFinalScore,\n minFinalScoreToQualify: metrics.minFinalScoreToQualify,\n };\n}\n\n/**\n * Serializes a {@link ReferrerLeaderboardPage} object.\n */\nfunction serializeReferrerLeaderboardPage(\n page: ReferrerLeaderboardPage,\n): SerializedReferrerLeaderboardPage {\n return {\n rules: serializeReferralProgramRules(page.rules),\n referrers: page.referrers.map(serializeAwardedReferrerMetrics),\n aggregatedMetrics: serializeAggregatedReferrerMetrics(page.aggregatedMetrics),\n pageContext: page.pageContext,\n accurateAsOf: page.accurateAsOf,\n };\n}\n\n/**\n * Serializes a {@link ReferrerDetailRanked} object.\n */\nfunction serializeReferrerDetailRanked(\n detail: ReferrerDetailRanked,\n): SerializedReferrerDetailRanked {\n return {\n type: detail.type,\n rules: serializeReferralProgramRules(detail.rules),\n referrer: serializeAwardedReferrerMetrics(detail.referrer),\n aggregatedMetrics: serializeAggregatedReferrerMetrics(detail.aggregatedMetrics),\n accurateAsOf: detail.accurateAsOf,\n };\n}\n\n/**\n * Serializes a {@link ReferrerDetailUnranked} object.\n */\nfunction serializeReferrerDetailUnranked(\n detail: ReferrerDetailUnranked,\n): SerializedReferrerDetailUnranked {\n return {\n type: detail.type,\n rules: serializeReferralProgramRules(detail.rules),\n referrer: serializeUnrankedReferrerMetrics(detail.referrer),\n aggregatedMetrics: serializeAggregatedReferrerMetrics(detail.aggregatedMetrics),\n accurateAsOf: detail.accurateAsOf,\n };\n}\n\n/**\n * Serialize a {@link ReferrerLeaderboardPageResponse} object.\n */\nexport function serializeReferrerLeaderboardPageResponse(\n response: ReferrerLeaderboardPageResponse,\n): SerializedReferrerLeaderboardPageResponse {\n switch (response.responseCode) {\n case ReferrerLeaderboardPageResponseCodes.Ok:\n return {\n responseCode: response.responseCode,\n data: serializeReferrerLeaderboardPage(response.data),\n };\n\n case ReferrerLeaderboardPageResponseCodes.Error:\n return response;\n }\n}\n\n/**\n * Serialize a {@link ReferrerDetailResponse} object.\n */\nexport function serializeReferrerDetailResponse(\n response: ReferrerDetailResponse,\n): SerializedReferrerDetailResponse {\n switch (response.responseCode) {\n case ReferrerDetailResponseCodes.Ok:\n switch (response.data.type) {\n case \"ranked\":\n return {\n responseCode: response.responseCode,\n data: serializeReferrerDetailRanked(response.data),\n };\n\n case \"unranked\":\n return {\n responseCode: response.responseCode,\n data: serializeReferrerDetailUnranked(response.data),\n };\n }\n break;\n\n case ReferrerDetailResponseCodes.Error:\n return response;\n }\n}\n","import { ReferrerDetailTypeIds } from \"@namehash/ens-referrals\";\n\nimport {\n type ConfigResponse,\n deserializeConfigResponse,\n deserializedNameTokensResponse,\n deserializeErrorResponse,\n deserializeIndexingStatusResponse,\n deserializeRegistrarActionsResponse,\n type ErrorResponse,\n type IndexingStatusResponse,\n type NameTokensRequest,\n type NameTokensResponse,\n type RegistrarActionsFilter,\n RegistrarActionsFilterTypes,\n type RegistrarActionsOrder,\n RegistrarActionsOrders,\n type RegistrarActionsRequest,\n type RegistrarActionsResponse,\n type ResolvePrimaryNameRequest,\n type ResolvePrimaryNameResponse,\n type ResolvePrimaryNamesRequest,\n type ResolvePrimaryNamesResponse,\n type ResolveRecordsRequest,\n type ResolveRecordsResponse,\n type SerializedConfigResponse,\n type SerializedIndexingStatusResponse,\n type SerializedNameTokensResponse,\n type SerializedRegistrarActionsResponse,\n} from \"./api\";\nimport { ClientError } from \"./client-error\";\nimport {\n deserializeReferrerDetailResponse,\n deserializeReferrerLeaderboardPageResponse,\n type ReferrerDetailRequest,\n type ReferrerDetailResponse,\n type ReferrerLeaderboardPageRequest,\n type ReferrerLeaderboardPageResponse,\n type SerializedReferrerDetailResponse,\n type SerializedReferrerLeaderboardPageResponse,\n} from \"./ensanalytics\";\nimport type { ResolverRecordsSelection } from \"./resolution\";\n\n/**\n * Default ENSNode API endpoint URL\n */\nexport const DEFAULT_ENSNODE_API_URL = \"https://api.alpha.ensnode.io\" as const;\n\n/**\n * Configuration options for ENSNode API client\n */\nexport interface ClientOptions {\n /** The ENSNode API URL */\n url: URL;\n}\n\n/**\n * ENSNode API Client\n *\n * Provides access to the following ENSNode APIs:\n * - Resolution API\n * - ENSAnalytics API\n * - 🚧 Configuration API\n * - 🚧 Indexing Status API\n *\n * @example\n * ```typescript\n * // Create client with default options\n * const client = new ENSNodeClient();\n *\n * // Use resolution methods\n * const { records } = await client.resolveRecords(\"jesse.base.eth\", {\n * addresses: [60],\n * texts: [\"avatar\"]\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Custom configuration\n * const client = new ENSNodeClient({\n * url: new URL(\"https://my-ensnode-instance.com\"),\n * });\n * ```\n */\nexport class ENSNodeClient {\n private readonly options: ClientOptions;\n\n static defaultOptions(): ClientOptions {\n return {\n url: new URL(DEFAULT_ENSNODE_API_URL),\n };\n }\n\n constructor(options: Partial<ClientOptions> = {}) {\n this.options = {\n ...ENSNodeClient.defaultOptions(),\n ...options,\n };\n }\n\n getOptions(): Readonly<ClientOptions> {\n return Object.freeze({\n url: new URL(this.options.url.href),\n });\n }\n\n /**\n * Resolves records for an ENS name (Forward Resolution).\n *\n * The returned `name` field, if set, is guaranteed to be a [Normalized Name](https://ensnode.io/docs/reference/terminology#normalized-name).\n * If the name record returned by the resolver is not normalized, `null` is returned as if no name record was set.\n *\n * @param name The ENS Name whose records to resolve\n * @param selection selection of Resolver records\n * @param options additional options\n * @param options.accelerate whether to attempt Protocol Acceleration (default false)\n * @param options.trace whether to include a trace in the response (default false)\n * @returns ResolveRecordsResponse<SELECTION>\n * @throws If the request fails or the ENSNode API returns an error response\n *\n * @example\n * ```typescript\n * const { records } = await client.resolveRecords(\"jesse.base.eth\", {\n * addresses: [60],\n * texts: [\"avatar\", \"com.twitter\"]\n * });\n *\n * console.log(records);\n * // {\n * // addresses: {\n * // 60: \"0xabcd...\"\n * // },\n * // texts: {\n * // avatar: \"https://example.com/image.jpg\",\n * // \"com.twitter\": null, // if not set, for example\n * // }\n * // }\n * ```\n */\n async resolveRecords<SELECTION extends ResolverRecordsSelection>(\n name: ResolveRecordsRequest<SELECTION>[\"name\"],\n selection: ResolveRecordsRequest<SELECTION>[\"selection\"],\n options?: Omit<ResolveRecordsRequest<SELECTION>, \"name\" | \"selection\">,\n ): Promise<ResolveRecordsResponse<SELECTION>> {\n const url = new URL(`/api/resolve/records/${encodeURIComponent(name)}`, this.options.url);\n\n // Add query parameters based on selection\n if (selection.name) {\n url.searchParams.set(\"name\", \"true\");\n }\n\n if (selection.addresses && selection.addresses.length > 0) {\n url.searchParams.set(\"addresses\", selection.addresses.join(\",\"));\n }\n\n if (selection.texts && selection.texts.length > 0) {\n url.searchParams.set(\"texts\", selection.texts.join(\",\"));\n }\n\n if (options?.trace) url.searchParams.set(\"trace\", \"true\");\n if (options?.accelerate) url.searchParams.set(\"accelerate\", \"true\");\n\n const response = await fetch(url);\n\n if (!response.ok) {\n const error = (await response.json()) as ErrorResponse;\n throw ClientError.fromErrorResponse(error);\n }\n\n const data = await response.json();\n return data as ResolveRecordsResponse<SELECTION>;\n }\n\n /**\n * Resolves the primary name of a specified address (Reverse Resolution) on a specific chain.\n *\n * If the chainId-specific Primary Name is not defined, but the `address` specifies a valid\n * [ENSIP-19 Default Name](https://docs.ens.domains/ensip/19/#default-primary-name), the Default\n * Name will be returned. You _may_ query the Default EVM Chain Id (`0`) in order to determine the\n * `address`'s Default Name directly.\n *\n * The returned Primary Name, if set, is guaranteed to be a [Normalized Name](https://ensnode.io/docs/reference/terminology#normalized-name).\n * If the primary name set for the address is not normalized, `null` is returned as if no primary name was set.\n *\n * @param address The Address whose Primary Name to resolve\n * @param chainId The chain id within which to query the address' ENSIP-19 Multichain Primary Name\n * @param options additional options\n * @param options.accelerate whether to attempt Protocol Acceleration (default false)\n * @param options.trace whether to include a trace in the response (default false)\n * @returns ResolvePrimaryNameResponse\n * @throws If the request fails or the ENSNode API returns an error response\n *\n * @example\n * ```typescript\n * // Resolve the address' Primary Name on Ethereum Mainnet\n * const { name } = await client.resolvePrimaryName(\"0x179A862703a4adfb29896552DF9e307980D19285\", 1);\n * // name === 'gregskril.eth'\n *\n * // Resolve the address' Primary Name on Base\n * const { name } = await client.resolvePrimaryName(\"0x179A862703a4adfb29896552DF9e307980D19285\", 8453);\n * // name === 'greg.base.eth'\n *\n * // Resolve the address' Default Primary Name\n * const { name } = await client.resolvePrimaryName(\"0x179A862703a4adfb29896552DF9e307980D19285\", 0);\n * // name === 'gregskril.eth'\n * ```\n */\n async resolvePrimaryName(\n address: ResolvePrimaryNameRequest[\"address\"],\n chainId: ResolvePrimaryNameRequest[\"chainId\"],\n options?: Omit<ResolvePrimaryNameRequest, \"address\" | \"chainId\">,\n ): Promise<ResolvePrimaryNameResponse> {\n const url = new URL(`/api/resolve/primary-name/${address}/${chainId}`, this.options.url);\n\n if (options?.trace) url.searchParams.set(\"trace\", \"true\");\n if (options?.accelerate) url.searchParams.set(\"accelerate\", \"true\");\n\n const response = await fetch(url);\n\n if (!response.ok) {\n const error = (await response.json()) as ErrorResponse;\n throw ClientError.fromErrorResponse(error);\n }\n\n const data = await response.json();\n return data as ResolvePrimaryNameResponse;\n }\n\n /**\n * Resolves the primary names of a specified address across multiple chains.\n *\n * For each Primary Name, if the chainId-specific Primary Name is not defined, but the `address`\n * specifies a valid [ENSIP-19 Default Name](https://docs.ens.domains/ensip/19/#default-primary-name),\n * the Default Name will be returned. You _may not_ query the Default EVM Chain Id (`0`) directly,\n * and should rely on the aforementioned per-chain defaulting behavior.\n *\n * Each returned Primary Name, if set, is guaranteed to be a [Normalized Name](https://ensnode.io/docs/reference/terminology#normalized-name).\n * If the primary name set for the address on any chain is not normalized, `null` is returned for\n * that chain as if no primary name was set.\n *\n * @param address The Address whose Primary Names to resolve\n * @param options additional options\n * @param options.chainIds The set of chain ids within which to query the address' ENSIP-19\n * Multichain Primary Name (default: all ENSIP-19 supported chains)\n * @param options.accelerate whether to attempt Protocol Acceleration (default: true)\n * @param options.trace whether to include a trace in the response (default: false)\n * @returns ResolvePrimaryNamesResponse\n * @throws If the request fails or the ENSNode API returns an error response\n *\n * @example\n * ```typescript\n * // Resolve the address' Primary Names on all ENSIP-19 supported chain ids\n * const { names } = await client.resolvePrimaryNames(\"0x179A862703a4adfb29896552DF9e307980D19285\");\n *\n * console.log(names);\n * // {\n * // \"1\": \"gregskril.eth\", // Default Primary Name\n * // \"10\": \"gregskril.eth\", // Default Primary Name\n * // \"8453\": \"greg.base.eth\", // Base-specific Primary Name!\n * // \"42161\": \"gregskril.eth\", // Default Primary Name\n * // \"59144\": \"gregskril.eth\", // Default Primary Name\n * // \"534352\": \"gregskril.eth\" // Default Primary Name\n * // }\n *\n * // Resolve the address' Primary Names on specific chain Ids\n * const { names } = await client.resolvePrimaryNames(\"0xabcd...\", [1, 8453]);\n *\n * console.log(names);\n * // {\n * // \"1\": \"gregskril.eth\",\n * // \"8453\": \"greg.base.eth\", // base-specific Primary Name!\n * // }\n * ```\n */\n async resolvePrimaryNames(\n address: ResolvePrimaryNamesRequest[\"address\"],\n options?: Omit<ResolvePrimaryNamesRequest, \"address\">,\n ): Promise<ResolvePrimaryNamesResponse> {\n const url = new URL(`/api/resolve/primary-names/${address}`, this.options.url);\n\n if (options?.chainIds) url.searchParams.set(\"chainIds\", options.chainIds.join(\",\"));\n if (options?.trace) url.searchParams.set(\"trace\", \"true\");\n if (options?.accelerate) url.searchParams.set(\"accelerate\", \"true\");\n\n const response = await fetch(url);\n\n if (!response.ok) {\n const error = (await response.json()) as ErrorResponse;\n throw ClientError.fromErrorResponse(error);\n }\n\n const data = await response.json();\n return data as ResolvePrimaryNamesResponse;\n }\n\n /**\n * Fetch ENSNode Config\n *\n * Fetch the ENSNode's configuration.\n *\n * @returns {ConfigResponse}\n *\n * @throws if the ENSNode request fails\n * @throws if the ENSNode API returns an error response\n * @throws if the ENSNode response breaks required invariants\n */\n async config(): Promise<ConfigResponse> {\n const url = new URL(`/api/config`, this.options.url);\n\n const response = await fetch(url);\n\n // ENSNode API should always allow parsing a response as JSON object.\n // If for some reason it's not the case, throw an error.\n let responseData: unknown;\n try {\n responseData = await response.json();\n } catch {\n throw new Error(\"Malformed response data: invalid JSON\");\n }\n\n if (!response.ok) {\n const errorResponse = deserializeErrorResponse(responseData);\n throw new Error(`Fetching ENSNode Config Failed: ${errorResponse.message}`);\n }\n\n return deserializeConfigResponse(responseData as SerializedConfigResponse);\n }\n\n /**\n * Fetch ENSNode Indexing Status\n *\n * @returns {IndexingStatusResponse}\n *\n * @throws if the ENSNode request fails\n * @throws if the ENSNode API returns an error response\n * @throws if the ENSNode response breaks required invariants\n */\n async indexingStatus(): Promise<IndexingStatusResponse> {\n const url = new URL(`/api/indexing-status`, this.options.url);\n\n const response = await fetch(url);\n\n // ENSNode API should always allow parsing a response as JSON object.\n // If for some reason it's not the case, throw an error.\n let responseData: unknown;\n try {\n responseData = await response.json();\n } catch {\n throw new Error(\"Malformed response data: invalid JSON\");\n }\n\n // handle response errors accordingly\n if (!response.ok) {\n // check for a generic errorResponse\n let errorResponse: ErrorResponse | undefined;\n try {\n errorResponse = deserializeErrorResponse(responseData);\n } catch {\n // if errorResponse could not be determined,\n // it means the response includes indexing status data\n console.log(\"Indexing Status API: handling a known indexing status server error.\");\n }\n\n // however, if errorResponse was defined,\n // throw an error with the generic server error message\n if (typeof errorResponse !== \"undefined\") {\n throw new Error(`Fetching ENSNode Indexing Status Failed: ${errorResponse.message}`);\n }\n }\n\n return deserializeIndexingStatusResponse(responseData as SerializedIndexingStatusResponse);\n }\n\n /**\n * Fetch Referrer Leaderboard Page\n *\n * Retrieves a paginated list of referrer leaderboard metrics with contribution percentages.\n * Each referrer's contribution is calculated as a percentage of the grand totals across all referrers.\n *\n * @param request - Pagination parameters\n * @param request.page - The page number to retrieve (1-indexed, default: 1)\n * @param request.recordsPerPage - Number of records per page (default: 25, max: 100)\n * @returns {ReferrerLeaderboardPageResponse}\n *\n * @throws if the ENSNode request fails\n * @throws if the ENSNode API returns an error response\n * @throws if the ENSNode response breaks required invariants\n *\n * @example\n * ```typescript\n * // Get first page with default page size (25 records)\n * const response = await client.getReferrerLeaderboardPage();\n * if (response.responseCode === ReferrerLeaderboardPageResponseCodes.Ok) {\n * const {\n * aggregatedMetrics,\n * referrers,\n * rules,\n * pageContext,\n * updatedAt\n * } = response.data;\n * console.log(aggregatedMetrics);\n * console.log(referrers);\n * console.log(rules);\n * console.log(updatedAt);\n * console.log(`Page ${pageContext.page} of ${pageContext.totalPages}`);\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Get second page with 50 records per page\n * const response = await client.getReferrerLeaderboardPage({ page: 2, recordsPerPage: 50 });\n * ```\n *\n * @example\n * ```typescript\n * // Handle error response, ie. when Referrer Leaderboard is not currently available.\n * const response = await client.getReferrerLeaderboardPage();\n *\n * if (response.responseCode === ReferrerLeaderboardPageResponseCodes.Error) {\n * console.error(response.error);\n * console.error(response.errorMessage);\n * }\n * ```\n */\n async getReferrerLeaderboardPage(\n request?: ReferrerLeaderboardPageRequest,\n ): Promise<ReferrerLeaderboardPageResponse> {\n const url = new URL(`/ensanalytics/referrers`, this.options.url);\n\n if (request?.page) url.searchParams.set(\"page\", request.page.toString());\n if (request?.recordsPerPage)\n url.searchParams.set(\"recordsPerPage\", request.recordsPerPage.toString());\n\n const response = await fetch(url);\n\n // ENSNode API should always allow parsing a response as JSON object.\n // If for some reason it's not the case, throw an error.\n let responseData: unknown;\n try {\n responseData = await response.json();\n } catch {\n throw new Error(\"Malformed response data: invalid JSON\");\n }\n\n // The API can return errors with 500 status, but they're still in the\n // PaginatedAggregatedReferrersResponse format with responseCode: 'error'\n // So we don't need to check response.ok here, just deserialize and let\n // the caller handle the responseCode\n\n return deserializeReferrerLeaderboardPageResponse(\n responseData as SerializedReferrerLeaderboardPageResponse,\n );\n }\n\n /**\n * Fetch Referrer Detail\n *\n * Retrieves detailed information about a specific referrer, whether they are on the\n * leaderboard or not.\n *\n * The response data is a discriminated union type with a `type` field:\n *\n * **For referrers on the leaderboard** (`ReferrerDetailRanked`):\n * - `type`: {@link ReferrerDetailTypeIds.Ranked}\n * - `referrer`: The `AwardedReferrerMetrics` from @namehash/ens-referrals\n * - `rules`: The referral program rules\n * - `aggregatedMetrics`: Aggregated metrics for all referrers on the leaderboard\n * - `accurateAsOf`: Unix timestamp indicating when the data was last updated\n *\n * **For referrers NOT on the leaderboard** (`ReferrerDetailUnranked`):\n * - `type`: {@link ReferrerDetailTypeIds.Unranked}\n * - `referrer`: The `UnrankedReferrerMetrics` from @namehash/ens-referrals\n * - `rules`: The referral program rules\n * - `aggregatedMetrics`: Aggregated metrics for all referrers on the leaderboard\n * - `accurateAsOf`: Unix timestamp indicating when the data was last updated\n *\n * @see {@link https://www.npmjs.com/package/@namehash/ens-referrals|@namehash/ens-referrals} for calculation details\n *\n * @param request The referrer address to query\n * @returns {ReferrerDetailResponse} Returns the referrer detail response\n *\n * @throws if the ENSNode request fails\n * @throws if the response data is malformed\n *\n * @example\n * ```typescript\n * // Get referrer detail for a specific address\n * const response = await client.getReferrerDetail({\n * referrer: \"0x1234567890123456789012345678901234567890\"\n * });\n * if (response.responseCode === ReferrerDetailResponseCodes.Ok) {\n * const { type, referrer, rules, aggregatedMetrics, accurateAsOf } = response.data;\n * console.log(type); // ReferrerDetailTypeIds.Ranked or ReferrerDetailTypeIds.Unranked\n * console.log(referrer);\n * console.log(accurateAsOf);\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Use discriminated union to check if referrer is ranked\n * const response = await client.getReferrerDetail({\n * referrer: \"0x1234567890123456789012345678901234567890\"\n * });\n * if (response.responseCode === ReferrerDetailResponseCodes.Ok) {\n * if (response.data.type === ReferrerDetailTypeIds.Ranked) {\n * // TypeScript knows this is ReferrerDetailRanked\n * console.log(`Rank: ${response.data.referrer.rank}`);\n * console.log(`Qualified: ${response.data.referrer.isQualified}`);\n * console.log(`Award Pool Share: ${response.data.referrer.awardPoolShare * 100}%`);\n * } else {\n * // TypeScript knows this is ReferrerDetailUnranked\n * console.log(\"Referrer is not on the leaderboard (no referrals yet)\");\n * }\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Handle error response, ie. when Referrer Detail is not currently available.\n * const response = await client.getReferrerDetail({\n * referrer: \"0x1234567890123456789012345678901234567890\"\n * });\n *\n * if (response.responseCode === ReferrerDetailResponseCodes.Error) {\n * console.error(response.error);\n * console.error(response.errorMessage);\n * }\n * ```\n */\n async getReferrerDetail(request: ReferrerDetailRequest): Promise<ReferrerDetailResponse> {\n const url = new URL(\n `/api/ensanalytics/referrers/${encodeURIComponent(request.referrer)}`,\n this.options.url,\n );\n\n const response = await fetch(url);\n\n // ENSNode API should always allow parsing a response as JSON object.\n // If for some reason it's not the case, throw an error.\n let responseData: unknown;\n try {\n responseData = await response.json();\n } catch {\n throw new Error(\"Malformed response data: invalid JSON\");\n }\n\n // The API can return errors with 500 status, but they're still in the\n // ReferrerDetailResponse format with responseCode: 'error'\n // So we don't need to check response.ok here, just deserialize and let\n // the caller handle the responseCode\n\n return deserializeReferrerDetailResponse(responseData as SerializedReferrerDetailResponse);\n }\n\n /**\n * Fetch ENSNode Registrar Actions\n *\n * Retrieves a paginated list of registrar actions with optional filters.\n *\n * @param request is a request configuration.\n * @param request.page sets the page number to retrieve (1-indexed, default: 1)\n * @param request.recordsPerPage sets the number of records per page (default: 10, max: 100)\n * @param request.filters is an optional request filter configuration.\n * @param request.order sets the order of results in the response by field and direction.\n * @returns {RegistrarActionsResponse}\n *\n * @throws if the ENSNode request fails\n * @throws if the ENSNode API returns an error response\n * @throws if the ENSNode response breaks required invariants\n *\n * @example\n * ```ts\n * import {\n * registrarActionsFilter,\n * ENSNodeClient,\n * } from \"@ensnode/ensnode-sdk\";\n * import { namehash } from \"viem/ens\";\n *\n * const client: ENSNodeClient;\n *\n * // Get first page with default page size (10 records)\n * const response = await client.registrarActions();\n * if (response.responseCode === RegistrarActionsResponseCodes.Ok) {\n * const { registrarActions, pageContext } = response;\n * console.log(registrarActions);\n * console.log(`Page ${pageContext.page} of ${pageContext.totalPages}`);\n * console.log(`Accurate as of: ${response.accurateAsOf}`);\n * }\n *\n * // Get second page with 25 records per page\n * const response = await client.registrarActions({\n * page: 2,\n * recordsPerPage: 25,\n * });\n *\n * // get latest registrar action records associated with\n * // subregistry managing `eth` name\n * await client.registrarActions({\n * filters: [registrarActionsFilter.byParentNode(namehash('eth'))],\n * });\n *\n * // get latest registrar action records which include referral info\n * await client.registrarActions({\n * filters: [registrarActionsFilter.withReferral(true)],\n * });\n *\n * // get latest registrar action records for a specific decoded referrer\n * await client.registrarActions({\n * filters: [registrarActionsFilter.byDecodedReferrer(\"0x1234567890123456789012345678901234567890\")],\n * });\n *\n * // get latest 10 registrar action records associated with\n * // subregistry managing `base.eth` name\n * await client.registrarActions({\n * filters: [registrarActionsFilter.byParentNode(namehash('base.eth'))],\n * recordsPerPage: 10\n * });\n *\n * // get registrar actions within a specific time range\n * const beginTimestamp = 1764547200; // Dec 1, 2025, 00:00:00 UTC\n * const endTimestamp = 1767225600; // Jan 1, 2026, 00:00:00 UTC\n * await client.registrarActions({\n * filters: [\n * registrarActionsFilter.beginTimestamp(beginTimestamp),\n * registrarActionsFilter.endTimestamp(endTimestamp),\n * ],\n * });\n *\n * // get registrar actions from a specific timestamp onwards\n * await client.registrarActions({\n * filters: [registrarActionsFilter.beginTimestamp(1764547200)],\n * });\n *\n * // get registrar actions up to a specific timestamp\n * await client.registrarActions({\n * filters: [registrarActionsFilter.endTimestamp(1767225600)],\n * });\n * ```\n */\n async registrarActions(request: RegistrarActionsRequest = {}): Promise<RegistrarActionsResponse> {\n const buildUrlPath = (filters: RegistrarActionsFilter[] | undefined) => {\n const bySubregistryNodeFilter = filters?.find(\n (f) => f.filterType === RegistrarActionsFilterTypes.BySubregistryNode,\n );\n\n return bySubregistryNodeFilter\n ? new URL(`/api/registrar-actions/${bySubregistryNodeFilter.value}`, this.options.url)\n : new URL(`/api/registrar-actions`, this.options.url);\n };\n\n const buildWithReferralArg = (filters: RegistrarActionsFilter[] | undefined) => {\n const withReferralFilter = filters?.find(\n (f) => f.filterType === RegistrarActionsFilterTypes.WithEncodedReferral,\n );\n\n return withReferralFilter ? { key: \"withReferral\", value: \"true\" } : null;\n };\n\n const buildDecodedReferrerArg = (filters: RegistrarActionsFilter[] | undefined) => {\n const decodedReferrerFilter = filters?.find(\n (f) => f.filterType === RegistrarActionsFilterTypes.ByDecodedReferrer,\n );\n\n return decodedReferrerFilter\n ? { key: \"decodedReferrer\", value: decodedReferrerFilter.value }\n : null;\n };\n\n const buildBeginTimestampArg = (filters: RegistrarActionsFilter[] | undefined) => {\n const beginTimestampFilter = filters?.find(\n (f) => f.filterType === RegistrarActionsFilterTypes.BeginTimestamp,\n );\n\n return beginTimestampFilter\n ? { key: \"beginTimestamp\", value: beginTimestampFilter.value.toString() }\n : null;\n };\n\n const buildEndTimestampArg = (filters: RegistrarActionsFilter[] | undefined) => {\n const endTimestampFilter = filters?.find(\n (f) => f.filterType === RegistrarActionsFilterTypes.EndTimestamp,\n );\n\n return endTimestampFilter\n ? { key: \"endTimestamp\", value: endTimestampFilter.value.toString() }\n : null;\n };\n\n const buildOrderArg = (order: RegistrarActionsOrder) => {\n switch (order) {\n case RegistrarActionsOrders.LatestRegistrarActions: {\n const [field, direction] = order.split(\"=\");\n return {\n key: `sort[${field}]`,\n value: `${direction}`,\n };\n }\n }\n };\n\n const url = buildUrlPath(request.filters);\n\n if (request.order) {\n const orderArgs = buildOrderArg(request.order);\n\n url.searchParams.set(orderArgs.key, orderArgs.value);\n }\n\n if (request.page) {\n url.searchParams.set(\"page\", request.page.toString());\n }\n\n if (request.recordsPerPage) {\n url.searchParams.set(\"recordsPerPage\", request.recordsPerPage.toString());\n }\n\n const referralArg = buildWithReferralArg(request.filters);\n\n if (referralArg) {\n url.searchParams.set(referralArg.key, referralArg.value);\n }\n\n const decodedReferrerArg = buildDecodedReferrerArg(request.filters);\n\n if (decodedReferrerArg) {\n url.searchParams.set(decodedReferrerArg.key, decodedReferrerArg.value);\n }\n\n const beginTimestampArg = buildBeginTimestampArg(request.filters);\n\n if (beginTimestampArg) {\n url.searchParams.set(beginTimestampArg.key, beginTimestampArg.value);\n }\n\n const endTimestampArg = buildEndTimestampArg(request.filters);\n\n if (endTimestampArg) {\n url.searchParams.set(endTimestampArg.key, endTimestampArg.value);\n }\n\n const response = await fetch(url);\n\n // ENSNode API should always allow parsing a response as JSON object.\n // If for some reason it's not the case, throw an error.\n let responseData: unknown;\n try {\n responseData = await response.json();\n } catch {\n throw new Error(\"Malformed response data: invalid JSON\");\n }\n\n // handle response errors accordingly\n if (!response.ok) {\n // check for a generic errorResponse\n let errorResponse: ErrorResponse | undefined;\n try {\n errorResponse = deserializeErrorResponse(responseData);\n } catch {\n // if errorResponse could not be determined,\n // it means the response includes data\n console.log(\"Registrar Actions API: handling a known server error.\");\n }\n\n // however, if errorResponse was defined,\n // throw an error with the generic server error message\n if (typeof errorResponse !== \"undefined\") {\n throw new Error(`Fetching ENSNode Registrar Actions Failed: ${errorResponse.message}`);\n }\n }\n\n return deserializeRegistrarActionsResponse(responseData as SerializedRegistrarActionsResponse);\n }\n\n /**\n * Fetch Name Tokens for requested name.\n *\n * @param request.name - Name for which Name Tokens will be fetched.\n * @returns {NameTokensResponse}\n *\n * @throws if the ENSNode request fails\n * @throws if the ENSNode API returns an error response\n * @throws if the ENSNode response breaks required invariants\n *\n * @example\n * ```ts\n * import {\n * ENSNodeClient,\n * } from \"@ensnode/ensnode-sdk\";\n * import { namehash } from \"viem/ens\";\n *\n * const client: ENSNodeClient;\n *\n * // get latest name token records from the indexed subregistry based on the requested name\n * const response = await client.nameTokens({\n * name: \"vitalik.eth\"\n * });\n *\n * const response = await client.nameTokens({\n * domainId: \"0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835\" // namehash('vitalik.eth')\n * })\n * ```\n */\n async nameTokens(request: NameTokensRequest): Promise<NameTokensResponse> {\n const url = new URL(`/api/name-tokens`, this.options.url);\n\n if (request.name !== undefined) {\n url.searchParams.set(\"name\", request.name);\n } else if (request.domainId !== undefined) {\n url.searchParams.set(\"domainId\", request.domainId);\n }\n\n const response = await fetch(url);\n\n // ENSNode API should always allow parsing a response as JSON object.\n // If for some reason it's not the case, throw an error.\n let responseData: unknown;\n try {\n responseData = await response.json();\n } catch {\n throw new Error(\"Malformed response data: invalid JSON\");\n }\n\n // handle response errors accordingly\n if (!response.ok) {\n // check for a generic errorResponse\n let errorResponse: ErrorResponse | undefined;\n try {\n errorResponse = deserializeErrorResponse(responseData);\n } catch {\n // if errorResponse could not be determined,\n // it means the response includes data\n console.log(\"Name Tokens API: handling a known server error.\");\n }\n\n // however, if errorResponse was defined,\n // throw an error with the generic server error message\n if (typeof errorResponse !== \"undefined\") {\n throw new Error(`Fetching ENSNode Name Tokens Failed: ${errorResponse.message}`);\n }\n }\n\n return deserializedNameTokensResponse(responseData as SerializedNameTokensResponse);\n }\n}\n","import { type Address, hexToBigInt } from \"viem\";\n\nimport {\n type AccountId,\n AssetNamespaces,\n formatAccountId,\n formatAssetId,\n type LabelHash,\n type Node,\n} from \"@ensnode/ensnode-sdk\";\n\nimport type {\n CanonicalId,\n DomainId,\n ENSv1DomainId,\n ENSv2DomainId,\n PermissionsId,\n PermissionsResourceId,\n PermissionsUserId,\n RegistrationId,\n RegistryId,\n RenewalId,\n ResolverId,\n ResolverRecordsId,\n} from \"./ids\";\n\n/**\n * Formats and brands an AccountId as a RegistryId.\n */\nexport const makeRegistryId = (accountId: AccountId) => formatAccountId(accountId) as RegistryId;\n\n/**\n * Makes an ENSv1 Domain Id given the ENSv1 Domain's `node`\n */\nexport const makeENSv1DomainId = (node: Node) => node as ENSv1DomainId;\n\n/**\n * Makes an ENSv2 Domain Id given the parent `registry` and the domain's `canonicalId`.\n */\nexport const makeENSv2DomainId = (registry: AccountId, canonicalId: CanonicalId) =>\n formatAssetId({\n assetNamespace: AssetNamespaces.ERC1155,\n contract: registry,\n tokenId: canonicalId,\n }) as ENSv2DomainId;\n\n/**\n * Masks the lower 32 bits of `num`.\n */\nconst maskLower32Bits = (num: bigint) => num ^ (num & 0xffffffffn);\n\n/**\n * Computes a Domain's {@link CanonicalId} given its tokenId or LabelHash as `input`.\n */\nexport const getCanonicalId = (input: bigint | LabelHash): CanonicalId => {\n if (typeof input === \"bigint\") return maskLower32Bits(input);\n return getCanonicalId(hexToBigInt(input));\n};\n\n/**\n * Formats and brands an AccountId as a PermissionsId.\n */\nexport const makePermissionsId = (contract: AccountId) =>\n formatAccountId(contract) as PermissionsId;\n\n/**\n * Constructs a PermissionsResourceId for a given `contract`'s `resource`.\n */\nexport const makePermissionsResourceId = (contract: AccountId, resource: bigint) =>\n `${makePermissionsId(contract)}/${resource}` as PermissionsResourceId;\n\n/**\n * Constructs a PermissionsUserId for a given `contract`'s `resource`'s `user`.\n */\nexport const makePermissionsUserId = (contract: AccountId, resource: bigint, user: Address) =>\n `${makePermissionsId(contract)}/${resource}/${user}` as PermissionsUserId;\n\n/**\n * Formats and brands an AccountId as a ResolverId.\n */\nexport const makeResolverId = (contract: AccountId) => formatAccountId(contract) as ResolverId;\n\n/**\n * Constructs a ResolverRecordsId for a given `node` under `resolver`.\n */\nexport const makeResolverRecordsId = (resolver: AccountId, node: Node) =>\n `${makeResolverId(resolver)}/${node}` as ResolverRecordsId;\n\n/**\n * Constructs a RegistrationId for a `domainId`'s latest Registration.\n *\n * @dev See apps/ensindexer/src/lib/ensv2/registration-db-helpers.ts for more info.\n */\nexport const makeLatestRegistrationId = (domainId: DomainId) =>\n `${domainId}/latest` as RegistrationId;\n\n/**\n * Constructs a RegistrationId for a `domainId`'s `index`'thd Registration.\n *\n * @dev See apps/ensindexer/src/lib/ensv2/registration-db-helpers.ts for more info.\n */\nexport const makeRegistrationId = (domainId: DomainId, index: number = 0) =>\n `${domainId}/${index}` as RegistrationId;\n\n/**\n * Constructs a RenewalId for a `domainId`'s `registrationIndex`thd Registration's latest Renewal.\n *\n * @dev Forces usage of the 'pinned' RegistrationId to avoid collisions, see\n * apps/ensindexer/src/lib/ensv2/registration-db-helpers.ts for more info.\n */\nexport const makeLatestRenewalId = (domainId: DomainId, registrationIndex: number) =>\n `${makeRegistrationId(domainId, registrationIndex)}/latest` as RenewalId;\n\n/**\n * Constructs a RenewalId for a `domainId`'s `registrationIndex`thd Registration's `index`'thd Renewal.\n *\n * @dev Forces usage of the 'pinned' RegistrationId to avoid collisions, see\n * apps/ensindexer/src/lib/ensv2/registration-db-helpers.ts for more info.\n */\nexport const makeRenewalId = (domainId: DomainId, registrationIndex: number, index: number = 0) =>\n `${makeRegistrationId(domainId, registrationIndex)}/${index}` as RenewalId;\n","import type { Address } from \"viem\";\n\nimport { type ENSNamespaceId, getENSRootChainId } from \"@ensnode/datasources\";\n\nimport type { DefaultableChainId } from \"../shared\";\nimport {\n type Identity,\n ResolutionStatusIds,\n type ResolvedIdentity,\n type UnresolvedIdentity,\n} from \"./types\";\n\n/**\n * Builds an {@link UnresolvedIdentity} for the provided {@link Address},\n * {@link DefaultableChainId} and {@link ENSNamespaceId}.\n *\n * If no `chainId` is provided, uses the ENS Root Chain Id for the provided\n * `namespaceId`.\n */\nexport function buildUnresolvedIdentity(\n address: Address,\n namespaceId: ENSNamespaceId,\n chainId?: DefaultableChainId,\n): UnresolvedIdentity {\n return {\n resolutionStatus: ResolutionStatusIds.Unresolved,\n chainId: chainId ?? getENSRootChainId(namespaceId),\n address,\n };\n}\n\n/**\n * Returns whether the provided {@link Identity} is a {@link ResolvedIdentity}.\n *\n * @param identity - The {@link Identity} to check.\n * @returns Whether the provided {@link Identity} is a {@link ResolvedIdentity}.\n */\nexport function isResolvedIdentity(identity: Identity): identity is ResolvedIdentity {\n return identity.resolutionStatus !== ResolutionStatusIds.Unresolved;\n}\n","import type { Address } from \"viem\";\n\nimport type { Name } from \"../ens\";\nimport type { DefaultableChainId } from \"../shared\";\n\n/**\n * The resolution status for an `Identity`.\n */\nexport const ResolutionStatusIds = {\n /**\n * Represents that the `Identity` is not resolved yet.\n */\n Unresolved: \"unresolved\",\n\n /**\n * Represents that resolution of the `Identity` resulted in a named identity.\n */\n Named: \"named\",\n\n /**\n * Represents that resolution of the `Identity` resulted in an unnamed identity.\n */\n Unnamed: \"unnamed\",\n\n /**\n * Represents that attempted resolution of the `Identity` resulted in an error\n * and therefore it is unknown if the `Identity` resolves to a named or unnamed identity.\n */\n Unknown: \"unknown\",\n} as const;\n\n/**\n * The derived string union of possible {@link ResolutionStatusIds}.\n */\nexport type ResolutionStatusId = (typeof ResolutionStatusIds)[keyof typeof ResolutionStatusIds];\n\n/**\n * Represents an {@link Identity} that has not become a {@link ResolvedIdentity} yet.\n *\n * Invariants:\n * - `resolutionStatus` is always {@link ResolutionStatusIds.Unresolved}.\n */\nexport interface UnresolvedIdentity {\n resolutionStatus: typeof ResolutionStatusIds.Unresolved;\n\n /**\n * The {@link DefaultableChainId} for an ENSIP-19 primary name lookup of the\n * identity associated with `address`.\n */\n chainId: DefaultableChainId;\n\n /**\n * The {@link Address} of the identity.\n */\n address: Address;\n}\n\n/**\n * Represents an `Identity` that resolved to a primary name.\n *\n * Invariants:\n * - `resolutionStatus` is always {@link ResolutionStatusIds.Named}.\n */\nexport interface NamedIdentity {\n resolutionStatus: typeof ResolutionStatusIds.Named;\n\n /**\n * The {@link DefaultableChainId} for an ENSIP-19 primary name lookup of the\n * identity associated with `address`.\n */\n chainId: DefaultableChainId;\n\n /**\n * The address of the identity.\n */\n address: Address;\n\n /**\n * The ENSIP-19 primary name lookup result of `address` on `chainId`.\n */\n name: Name;\n}\n\n/**\n * Represents an `Identity` that did not resolve to a primary name.\n *\n * Invariants:\n * - `resolutionStatus` is always {@link ResolutionStatusIds.Unnamed}.\n * - `name` is always `null`.\n */\nexport interface UnnamedIdentity {\n resolutionStatus: typeof ResolutionStatusIds.Unnamed;\n\n /**\n * The {@link DefaultableChainId} for an ENSIP-19 primary name lookup of the\n * identity associated with `address`.\n */\n chainId: DefaultableChainId;\n\n /**\n * The address of the identity.\n */\n address: Address;\n\n /**\n * The ENSIP-19 primary name lookup result of `address` on `chainId`.\n */\n name: null;\n}\n\n/**\n * Represents an `Identity` that was attempted to be resolved but the resolution attempt\n * resulted in an error and therefore it is unknown if the `Identity` resolves to a named\n * or unnamed identity.\n *\n * Invariants:\n * - `resolutionStatus` is always {@link ResolutionStatusIds.Unknown}.\n */\nexport interface UnknownIdentity {\n resolutionStatus: typeof ResolutionStatusIds.Unknown;\n\n /**\n * The {@link DefaultableChainId} for an ENSIP-19 primary name lookup of the\n * identity associated with `address`.\n */\n chainId: DefaultableChainId;\n\n /**\n * The address of the identity.\n */\n address: Address;\n}\n\n/**\n * Represents an ENSIP-19 identity resolution result.\n *\n * Use the `resolutionStatus` field to determine the specific type interpretation\n * at runtime.\n */\nexport type ResolvedIdentity = NamedIdentity | UnnamedIdentity | UnknownIdentity;\n\n/**\n * Represents an ENSIP-19 identity resolution (which may or not have been\n * resolved to a result yet).\n *\n * Use the `resolutionStatus` field to determine the specific type interpretation\n * at runtime.\n */\nexport type Identity = UnresolvedIdentity | ResolvedIdentity;\n","import { mainnet } from \"viem/chains\";\n\nimport { type ENSNamespaceId, getENSRootChainId } from \"@ensnode/datasources\";\n\nimport { DEFAULT_EVM_CHAIN_ID } from \"../ens\";\nimport type { ChainId, DefaultableChainId } from \"../shared\";\n\n/**\n * Gets the \"chainId param\" that should be used for a primary name resolution\n * request.\n *\n * ENSIP-19 defines special rules for the \"chainId param\" used\n * in primary name resolutions for the case that the `chainId` is the\n * ENS Root Chain Id for the provided `namespaceId`.\n *\n * Whenever this case happens, ENSIP-19 requires that the\n * \"chainId param\" is always set to chainId: 1 (mainnet), even if the\n * `chainId` where the primary name lookup is actually happening\n * on a non-mainnet ENS Root Chain, such as on a testnet or\n * the ens-test-env.\n *\n * @param namespaceId The namespace id for the primary name lookup.\n * @param chainId The chain id where the primary name lookup will actually happen.\n * @returns The \"chainId param\" that should be used for the primary name lookup.\n */\nexport const getResolvePrimaryNameChainIdParam = (\n chainId: DefaultableChainId,\n namespaceId: ENSNamespaceId,\n): DefaultableChainId => {\n const ensRootChainId = getENSRootChainId(namespaceId);\n return chainId === ensRootChainId ? mainnet.id : chainId;\n};\n\n/**\n * Translates a `DefaultableChainId` a `ChainId`\n * such that if the provided `chainId` is `DEFAULT_EVM_CHAIN_ID`,\n * the `ChainId` of the ENS Root Chain for the provided `namespaceId` is returned.\n *\n * @param chainId The `DefaultableChainId` to translate.\n * @param namespaceId The namespace id for the translation.\n * @returns the translated `ChainId`.\n */\nexport const translateDefaultableChainIdToChainId = (\n chainId: DefaultableChainId,\n namespaceId: ENSNamespaceId,\n): ChainId => {\n return chainId === DEFAULT_EVM_CHAIN_ID ? getENSRootChainId(namespaceId) : chainId;\n};\n","import type { CoinType } from \"../ens\";\n\n/**\n * Encodes a selection of Resolver records in the context of a specific Name.\n */\nexport interface ResolverRecordsSelection {\n /**\n * Whether to fetch the name's `name` record. This value is primarily used in the context of\n * Reverse Resolution.\n *\n * @see https://docs.ens.domains/ensip/19/#reverse-resolution\n */\n name?: boolean;\n\n /**\n * Which coinTypes to fetch address records for.\n */\n addresses?: CoinType[];\n\n /**\n * Which keys to fetch text records for.\n */\n texts?: string[];\n\n // TODO: include others as/if necessary\n}\n\nexport const isSelectionEmpty = (selection: ResolverRecordsSelection) =>\n !selection.name && !selection.addresses?.length && !selection.texts?.length;\n","export const PROTOCOL_ATTRIBUTE_PREFIX = \"ens\";\nexport const ATTR_PROTOCOL_NAME = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol`;\nexport const ATTR_PROTOCOL_STEP = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol.step`;\nexport const ATTR_PROTOCOL_STEP_RESULT = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol.step.result`;\n\n/**\n * Identifiers for each traceable ENS protocol.\n */\nexport enum TraceableENSProtocol {\n ForwardResolution = \"forward-resolution\",\n ReverseResolution = \"reverse-resolution\",\n}\n\n/**\n * Encodes the set of well-known steps in the ENS Forward Resolution protocol.\n */\nexport enum ForwardResolutionProtocolStep {\n Operation = \"forward-resolution\",\n FindResolver = \"find-resolver\",\n ActiveResolverExists = \"active-resolver-exists\",\n AccelerateENSIP19ReverseResolver = \"accelerate-ensip-19-reverse-resolver\",\n AccelerateKnownOffchainLookupResolver = \"accelerate-known-offchain-lookup-resolver\",\n AccelerateKnownOnchainStaticResolver = \"accelerate-known-onchain-static-resolver\",\n RequireResolver = \"require-resolver\",\n ExecuteResolveCalls = \"execute-resolve-calls\",\n}\n\n/**\n * Encodes the set of well-known steps in the ENS Reverse Resolution protocol.\n */\nexport enum ReverseResolutionProtocolStep {\n Operation = \"reverse-resolution\",\n ResolveReverseName = \"resolve-reverse-name\",\n NameRecordExists = \"name-record-exists-check\",\n ForwardResolveAddressRecord = \"forward-resolve-address-record\",\n VerifyResolvedAddressMatchesAddress = \"verify-resolved-address-matches-address\",\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,aAAwC;;;ACAxC,IAAAC,aAAkB;;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","names":["import_v4","import_v4","import_v4","import_v4","import_viem","import_datasources","_coinTypeToEvmChainId","_evmChainIdToCoinType","import_viem","import_viem","import_viem","import_viem","import_viem","import_viem","labelToLabelHash","CaipAccountId","import_getUnixTime","import_datasources","import_viem","import_viem","import_viem","import_ens","import_viem","import_datasources","import_caip","CaipAccountId","CaipAssetId","import_datasources","PluginName","import_v4","import_v4","import_viem","isSubgraphCompatible","import_v4","import_v4","import_v4","import_v4","z","import_v4","import_viem","import_v4","import_viem","import_v4","import_caip","import_viem","import_v4","import_viem","import_datasources","z","CaipAssetId","z","import_v4","z","z","import_v4","import_ens","import_v4","import_viem","import_viem","import_viem","import_v4","import_v4","z","z","withReferral","import_datasources","import_datasources","import_datasources","import_v4","import_v4","import_v4","z","import_viem","import_datasources","import_datasources","TraceableENSProtocol","ForwardResolutionProtocolStep","ReverseResolutionProtocolStep"]}