@ensnode/ensnode-sdk 0.35.0 → 0.36.0

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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ens/constants.ts","../src/ens/subname-helpers.ts","../src/ens/coin-type.ts","../src/ens/reverse-name.ts","../src/ens/names.ts","../src/ens/types.ts","../src/ens/parse-reverse-name.ts","../src/ens/is-normalized.ts","../src/ens/encode-labelhash.ts","../src/ensindexer/config/deserialize.ts","../src/ensindexer/config/zod-schemas.ts","../src/shared/cache.ts","../src/shared/collections.ts","../src/shared/serialize.ts","../src/shared/deserialize.ts","../src/shared/zod-schemas.ts","../src/shared/account-id.ts","../src/shared/interpretation.ts","../src/ensindexer/config/types.ts","../src/ensindexer/config/helpers.ts","../src/ensindexer/config/serialize.ts","../src/ensindexer/config/labelset-utils.ts","../src/ensindexer/config/label-utils.ts","../src/ensindexer/config/parsing.ts","../src/ensindexer/indexing-status/deserialize.ts","../src/ensindexer/indexing-status/zod-schemas.ts","../src/shared/block-ref.ts","../src/ensindexer/indexing-status/types.ts","../src/ensindexer/indexing-status/helpers.ts","../src/ensindexer/indexing-status/serialize.ts","../src/tracing/index.ts","../src/api/helpers.ts","../src/api/zod-schemas.ts","../src/api/types.ts","../src/client-error.ts","../src/client.ts","../src/resolution/resolver-records-selection.ts","../src/resolution/default-records-selection.ts"],"sourcesContent":["import { namehash } from \"viem\";\n\nimport type { Node } from \"./types\";\n\nexport const ROOT_NODE: Node = namehash(\"\");\nexport const ETH_NODE = namehash(\"eth\");\nexport const BASENAMES_NODE = namehash(\"base.eth\");\nexport const LINEANAMES_NODE = namehash(\"linea.eth\");\n\n/**\n * A set of nodes whose children are used for reverse resolution.\n *\n * Useful for identifying if a domain is used for reverse resolution.\n * See apps/ensindexer/src/handlers/Registry.ts for context.\n */\nexport const REVERSE_ROOT_NODES: Set<Node> = new Set([namehash(\"addr.reverse\")]);\n","import { Address, Hex, concat, isAddress, isHash, keccak256, toHex } from \"viem\";\n\nimport { labelhash } from \"viem/ens\";\nimport { addrReverseLabel } from \"./reverse-name\";\nimport type { Label, 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 * Attempt to heal the labelHash of an addr.reverse subname using an address that might be related to the subname.\n *\n * @throws if maybeReverseAddress is not a valid Address\n * @throws if labelHash is not a valid Labelhash\n *\n * @returns the original label if healed, otherwise null\n */\nexport const maybeHealLabelByReverseAddress = ({\n maybeReverseAddress,\n labelHash,\n}: {\n /** The address that is possibly associated with the addr.reverse subname */\n maybeReverseAddress: Address;\n\n /** The labelhash of the addr.reverse subname */\n labelHash: LabelHash;\n}): string | null => {\n // check if required arguments are valid\n if (!isAddress(maybeReverseAddress)) {\n throw new Error(\n `Invalid reverse address: '${maybeReverseAddress}'. Must be a valid EVM Address.`,\n );\n }\n\n if (!isHash(labelHash)) {\n throw new Error(\n `Invalid labelHash: '${labelHash}'. Must start with '0x' and represent 32 bytes.`,\n );\n }\n\n // derive the assumed label from the normalized address\n const assumedLabel = addrReverseLabel(maybeReverseAddress);\n\n // if labelHash of the assumed label matches the provided labelHash, heal\n if (labelhash(assumedLabel) === labelHash) return assumedLabel;\n\n // otherwise, healing did not succeed\n // TODO: log the event args for analysis and debugging\n return null;\n};\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\n/**\n * These characters are prohibited in normalized ENS names per the ENSIP-15\n * standard (https://docs.ens.domains/ensip/15). Names containing labels with\n * one or more of these characters are unusable by any app implementing\n * ENSIP-15 (e.g., via https://github.com/adraffy/ens-normalize.js\n * or https://github.com/namehash/ens-normalize-python).\n *\n * While many other characters (beyond these 4) are not supported by\n * ENSIP-15, only the following 4 characters are classified as \"unindexable\" due\n * to specific indexing concerns.\n *\n * Onchain ENS contracts do not enforce ENSIP-15 normalization for reasons\n * including the gas costs of enforcement. This allows unnormalized labels\n * containing these characters to exist onchain. Such labels must be handled\n * carefully by indexers to avoid conflicts.\n *\n * Some indexed labels are \"unknown\" (or \"unindexable\") but still require a\n * representation within indexed data. For this purpose, a special \"unknown\n * label\" format is defined (an EncodedLabelHash) that represents these labels in the format of\n * \"[{labelHash}]\" where {labelHash} is the labelHash of the unknown label.\n * When an indexed label is in this format it is necessary to distinguish an\n * \"unknown\" label containing a labelHash, from an unnormalized label literal\n * that is formatted to appear like an \"unknown\" label. For example, if the\n * unnormalized label literal\n * \"[24695ee963d29f0f52edfdea1e830d2fcfc9052d5ba70b194bddd0afbbc89765]\"\n * is indexed, it will be considered \"unindexable\" (due to the square bracket\n * characters) and therefore be represented as the following \"unknown\" label instead\n * \"[80968d00b78a91f47b233eaa213576293d16dadcbbdceb257bca94b08451ba7f]\"\n * which encodes the labelHash of the unnormalized label literal in\n * square brackets.\n */\nconst UNINDEXABLE_LABEL_CHARACTERS = [\n \"\\0\", // null byte: PostgreSQL does not allow storing this character in text fields.\n \".\", // conflicts with ENS label separator logic.\n \"[\", // conflicts with \"unknown label\" representations.\n \"]\", // conflicts with \"unknown label\" representations.\n];\n\nconst UNINDEXABLE_LABEL_CHARACTER_CODES = new Set(\n UNINDEXABLE_LABEL_CHARACTERS.map((char) => char.charCodeAt(0)),\n);\n\n/**\n * Check if any characters in `label` are \"unindexable\".\n *\n * Related logic in ENS Subgraph:\n * https://github.com/ensdomains/ens-subgraph/blob/c844791/src/utils.ts#L68\n *\n * @param label - The label to check. Note:\n * A `null` value for `label` represents an unhealable labelhash.\n *\n * @returns `true` if the label is indexable, `false` otherwise.\n */\nexport const isLabelIndexable = (label: Label | null): label is Label => {\n if (!label) return false;\n\n for (let i = 0; i < label.length; i++) {\n if (UNINDEXABLE_LABEL_CHARACTER_CODES.has(label.charCodeAt(i))) return false;\n }\n\n return true;\n};\n","import type { CoinType, EvmCoinType } from \"@ensdomains/address-encoder\";\nimport {\n coinTypeToEvmChainId as _coinTypeToEvmChainId,\n evmChainIdToCoinType as _evmChainIdToCoinType,\n} from \"@ensdomains/address-encoder/utils\";\nimport { 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: ChainId = 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 { Address } from \"viem\";\n\nimport { CoinType, DEFAULT_EVM_COIN_TYPE, ETH_COIN_TYPE } from \"./coin-type\";\nimport type { Label, 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): Label => address.slice(2).toLowerCase();\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 type { Name } from \"./types\";\n\n/**\n * Constructs a name hierarchy from a given Name.\n * i.e. sub.example.eth -> [sub.example.eth, example.eth, eth]\n */\nexport const getNameHierarchy = (name: Name): Name[] =>\n name.split(\".\").map((_, i, labels) => labels.slice(i).join(\".\"));\n","import type { Hex } from \"viem\";\n\n// re-export ENSNamespaceIds and ENSNamespaceId from @ensnode/datasources\n// so consumers don't need it as a dependency\nexport { ENSNamespaceIds } from \"@ensnode/datasources\";\nexport type { ENSNamespaceId } 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 * @link https://docs.ens.domains/ensip/1#namehash-algorithm\n */\nexport type Node = Hex;\n\n/**\n * A Name represents a human-readable ENS name.\n *\n * ex: vitalik.eth\n */\nexport type Name = string;\n\n/**\n * A LabelHash is the result of the labelhash function (which is just keccak256) on a Label.\n *\n * @link https://docs.ens.domains/terminology#labelhash\n */\nexport type LabelHash = Hex;\n\n/**\n * A Label is a single part of an ENS Name.\n *\n * @link https://docs.ens.domains/terminology#label\n */\nexport type Label = string;\n\n/**\n * An EncodedLabelHash is a specially formatted unnormalized Label that should be interpreted as a\n * LabelHash literal, particularly for use within an ENS Name.\n *\n * @example [abcd]\n * @example [abcd].example.eth\n */\nexport type EncodedLabelHash = `[${string}]`;\n","import { Address, getAddress, hexToBigInt } from \"viem\";\nimport { CoinType, DEFAULT_EVM_COIN_TYPE, ETH_COIN_TYPE, bigintToCoinType } from \"./coin-type\";\nimport { 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 * @throws if address is invalid\n */\nconst parseAddressLabel = (addressLabel: Label): Address => getAddress(`0x${addressLabel}`);\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 { normalize } from \"viem/ens\";\n\nimport type { Label, Name } 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): boolean {\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 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 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","import { prettifyError } from \"zod/v4\";\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","/**\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\";\nimport { uniq } from \"../../shared\";\nimport {\n ZodCheckFnInput,\n makeChainIdSchema,\n makeENSNamespaceIdSchema,\n makeNonNegativeIntegerSchema,\n makePositiveIntegerSchema,\n makeUrlSchema,\n} from \"../../shared/zod-schemas\";\nimport { isSubgraphCompatible } from \"./helpers\";\nimport { PluginName } from \"./types\";\nimport type { ENSIndexerPublicConfig } from \"./types\";\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 {@link PluginName} items.\n *\n * The list is guaranteed to include at least one item exists, and no duplicates.\n */\nexport const makePluginsListSchema = (valueLabel: string = \"Plugins\") =>\n z\n .array(\n z.enum(PluginName, {\n error: `${valueLabel} must be a list with at least one valid plugin name. Valid plugins are: ${Object.values(\n PluginName,\n ).join(\", \")}`,\n }),\n )\n .min(1, {\n error: `${valueLabel} must be a list with at least one valid plugin name. Valid plugins are: ${Object.values(\n PluginName,\n ).join(\", \")}`,\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 makeDependencyInfoSchema = (valueLabel: string = \"Value\") =>\n z.strictObject(\n {\n nodejs: makeNonEmptyStringSchema(),\n ponder: makeNonEmptyStringSchema(),\n ensRainbow: makeNonEmptyStringSchema(),\n ensRainbowSchema: makePositiveIntegerSchema(),\n },\n {\n error: `${valueLabel} must be a valid DependencyInfo object.`,\n },\n );\n\n// Invariant: ReverseResolvers plugin requires indexAdditionalResolverRecords\nexport function invariant_reverseResolversPluginNeedsResolverRecords(\n ctx: ZodCheckFnInput<Pick<ENSIndexerPublicConfig, \"plugins\" | \"indexAdditionalResolverRecords\">>,\n) {\n const { value: config } = ctx;\n\n const reverseResolversPluginActive = config.plugins.includes(PluginName.ReverseResolvers);\n\n if (reverseResolversPluginActive && !config.indexAdditionalResolverRecords) {\n ctx.issues.push({\n code: \"custom\",\n input: config,\n message: `The '${PluginName.ReverseResolvers}' plugin requires 'indexAdditionalResolverRecords' to be 'true'.`,\n });\n }\n}\n\n// Invariant: isSubgraphCompatible requires Subgraph plugin only, no extra indexing features, and subgraph label set\nexport function invariant_isSubgraphCompatibleRequirements(\n ctx: ZodCheckFnInput<\n Pick<\n ENSIndexerPublicConfig,\n | \"plugins\"\n | \"isSubgraphCompatible\"\n | \"healReverseAddresses\"\n | \"indexAdditionalResolverRecords\"\n | \"replaceUnnormalized\"\n | \"labelSet\"\n >\n >,\n) {\n const { value: config } = ctx;\n\n if (config.isSubgraphCompatible !== isSubgraphCompatible(config)) {\n const message = config.isSubgraphCompatible\n ? `'isSubgraphCompatible' requires only the '${PluginName.Subgraph}' plugin to be active, 'indexAdditionalResolverRecords', 'healReverseAddresses', and 'replaceUnnormalized' must be set to 'false', and labelSet must be {labelSetId: \"subgraph\", labelSetVersion: 0}`\n : `'indexAdditionalResolverRecords', 'healReverseAddresses', and 'replaceUnnormalized' were set to 'false', the only active plugin was the '${PluginName.Subgraph}' plugin, and labelSet was {labelSetId: \"subgraph\", labelSetVersion: 0}. The 'isSubgraphCompatible' must be set to 'true'`;\n\n ctx.issues.push({\n code: \"custom\",\n input: config,\n message,\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 ensAdminUrl: makeUrlSchema(`${valueLabel}.ensAdminUrl`),\n ensNodePublicUrl: makeUrlSchema(`${valueLabel}.ensNodePublicUrl`),\n labelSet: makeFullyPinnedLabelSetSchema(`${valueLabel}.labelSet`),\n healReverseAddresses: z.boolean({ error: `${valueLabel}.healReverseAddresses` }),\n indexAdditionalResolverRecords: z.boolean({\n error: `${valueLabel}.indexAdditionalResolverRecords`,\n }),\n replaceUnnormalized: z.boolean({ error: `${valueLabel}.replaceUnnormalized` }),\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 dependencyInfo: makeDependencyInfoSchema(`${valueLabel}.dependencyInfo`),\n })\n /**\n * Validations\n *\n * All required data validations must be performed below.\n */\n .check(invariant_reverseResolversPluginNeedsResolverRecords)\n .check(invariant_isSubgraphCompatibleRequirements);\n","/**\n * Cache that maps from string -> ValueType.\n */\nexport interface Cache<KeyType extends string, ValueType> {\n /**\n * Store a value in the cache with the given key.\n *\n * @param key Cache key\n * @param value Value to store\n */\n set(key: KeyType, value: ValueType): void;\n\n /**\n * Retrieve a value from the cache with the given key.\n *\n * @param key Cache key\n * @returns The cached value if it exists, otherwise undefined\n */\n get(key: KeyType): ValueType | undefined;\n\n /**\n * Clear the cache.\n */\n clear(): void;\n\n /**\n * The current number of items in the cache. Always a non-negative integer.\n */\n get size(): number;\n\n /**\n * The maximum number of items in the cache. Always a non-negative integer that is >= size().\n */\n get capacity(): number;\n}\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","/**\n * Filter out duplicates.\n */\nexport const uniq = <T>(arr: T[]): T[] => [...new Set(arr)];\n","import type { ChainIdString, DatetimeISO8601, UrlString } from \"./serialized-types\";\nimport type { 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","import { prettifyError } from \"zod/v4\";\nimport type { ChainIdString, UrlString } from \"./serialized-types\";\nimport type { BlockNumber, BlockRef, Blockrange, ChainId, Datetime, Duration } from \"./types\";\nimport {\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: string, 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","/**\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\";\nimport { ENSNamespaceIds } from \"../ens\";\nimport type { BlockRef, Datetime, Duration, UnixTimestamp } from \"./types\";\n\n/**\n * Zod `.check()` function input.\n */\nexport type ZodCheckFnInput<T> = z.core.ParsePayload<T>;\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 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);\n\n/**\n * Parses a string 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 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 })\n .transform((v) => new URL(v));\n\n/**\n * Parses a string 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\n/**\n * Parses a numeric value as a port number.\n */\nexport const makePortSchema = (valueLabel: string = \"Port\") =>\n makePositiveIntegerSchema(valueLabel).max(65535, {\n error: `${valueLabel} must be an integer between 1 and 65535.`,\n });\n","import { isAddressEqual } from \"viem\";\nimport { 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 { labelhash } from \"viem\";\n\nimport {\n type EncodedLabelHash,\n type Label,\n type Name,\n encodeLabelHash,\n isNormalizedLabel,\n isNormalizedName,\n} from \"../ens\";\n\n/**\n * Transforms a Literal Label into 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 normalized, else the EncodedLabelHash of the label\n */\nexport function interpretLiteralLabel(label: Label): Label | EncodedLabelHash {\n // if the label is normalized, good to go\n if (isNormalizedLabel(label)) return label;\n\n // otherwise (includes empty string label), interpret as EncodedLabelHash\n return encodeLabelHash(labelhash(label));\n}\n\n/**\n * Transforms a Literal Name into an Interpreted Name.\n *\n * @see https://ensnode.io/docs/reference/terminology#literal-name\n * @see https://ensnode.io/docs/reference/terminology#interpreted-name\n *\n * If the name provided to this function contains empty-string labels (i.e 'this..name'),\n * then the empty string labels will be Interpreted. Empty-string is not a normalizable name, so the\n * label will be replaced with its Encoded LabelHash representation (i.e. )\n *\n * @param name - The Literal Name string to interpret\n * @returns The provided name if it is normalized, else converts each label in name that is not a\n * normalized label into an Interpreted Label\n */\nexport function interpretLiteralName(name: Name): Name {\n // if the name is already normalized (includes empty string), good to go\n if (isNormalizedName(name)) return name;\n\n // otherwise ensure the name is composed of Interpreted Labels\n return name.split(\".\").map(interpretLiteralLabel).join(\".\");\n}\n","import { ENSNamespaceId } from \"@ensnode/datasources\";\n\nimport type { EnsRainbowClientLabelSet } from \"../../ensrainbow\";\nimport { 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 ReverseResolvers = \"reverse-resolvers\",\n Referrals = \"referrals\",\n TokenScope = \"tokenscope\",\n}\n\n/**\n * Information about ENSIndexer's dependencies.\n */\nexport interface DependencyInfo {\n /** Node.js runtime version */\n nodejs: string;\n\n /** Ponder framework version */\n ponder: string;\n\n /** ENSRainbow service version */\n ensRainbow: string;\n\n /** ENSRainbow schema version */\n ensRainbowSchema: number;\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 * An ENSAdmin URL\n *\n * The ENSNode root api route `/` redirects to {@link ensAdminUrl},\n * configuring ENSAdmin with an entry for this instance of ENSNode,\n * identified by {@link ensNodePublicUrl}.\n *\n * @see https://ensnode.io/ensadmin/overview/what-is-ensadmin\n */\n ensAdminUrl: URL;\n\n /**\n * The publicly accessible endpoint of the ENSNode API\n * (ex: http://localhost:42069).\n *\n * ENSAdmin will use this url to connect to the ENSNode api for querying\n * state about the ENSNode instance.\n */\n ensNodePublicUrl: URL;\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 {@link PluginName}s indicating which plugins to activate.\n *\n * Invariants:\n * - A set of valid {@link PluginName}s with at least one value\n */\n plugins: PluginName[];\n\n /**\n * Enable or disable healing of addr.reverse subnames.\n * If this is set to true, ENSIndexer will attempt to heal subnames of\n * addr.reverse.\n */\n healReverseAddresses: boolean;\n\n /**\n * Enable or disable the indexing of Resolver record values.\n * If this is set to false, ENSIndexer will apply subgraph-backwards\n * compatible logic that only tracks the keys of Resolver records.\n * If this is set to true, ENSIndexer will track both the keys and the values\n * of Resolver records.\n *\n * WARNING: Special care must be taken when interacting with indexed resolver\n * record values. It is unsafe to naively assume that indexed resolver record\n * values are equivalent to the resolver record values that would be returned\n * through dynamic lookups via the ENS protocol. For example, if a resolver\n * implements CCIP-Read, the resolver records may not be discoverable through\n * onchain indexing. This feature is under R&D. At this time we do not\n * recommend anyone directly use indexed resolver record values in their\n * applications. Features are planned in the ENSNode roadmap that will\n * provide safe use of indexed resolver record values (in appropriate\n * contexts).\n *\n * Note that enabling {@link indexAdditionalResolverRecords} results in indexed data becoming a\n * _superset_ of the Subgraph. For exact data-level backwards compatibility with the ENS Subgraph,\n * {@link indexAdditionalResolverRecords} should be `false`.\n */\n indexAdditionalResolverRecords: boolean;\n\n /**\n * Controls ENSIndexer's handling of Literal Labels and Literal Names\n * This configuration only applies to the Subgraph datamodel and Subgraph Compatible GraphQL API responses.\n *\n * When set to true, all Literal Labels and Literal Names encountered by ENSIndexer will be Interpreted.\n * - https://ensnode.io/docs/reference/terminology#interpreted-label\n * - https://ensnode.io/docs/reference/terminology#interpreted-name\n *\n * That is,\n * 1) all Labels stored and returned by ENSIndexer will either be normalized or represented as an Encoded\n * LabelHash, and\n * 2) all Names stored and returned by ENSIndexer will either be normalized or consist of Labels that\n * may be represented as an Encoded LabelHash of the Literal Label value found onchain.\n *\n * When set to false, ENSIndexer will store and return Literal Labels and Literal Names without further\n * interpretation.\n * - https://ensnode.io/docs/reference/terminology#literal-label\n * - https://ensnode.io/docs/reference/terminology#literal-name\n *\n * NOTE: {@link replaceUnnormalized} must be `false` for subgraph compatible indexing behavior.\n */\n replaceUnnormalized: boolean;\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 flag derived from the built config indicating whether ENSIndexer is operating in a\n * subgraph-compatible way. This flag is true if:\n * a) only the subgraph plugin is activated,\n * b) healReverseAddresess is false, and\n * c) indexRecordValues is false\n *\n * If {@link isSubgraphCompatible} is true, ENSIndexer will:\n * 1) use subgraph-compatible IDs for entities and events\n * 2) limit indexing behavior to subgraph indexing semantics\n */\n isSubgraphCompatible: boolean;\n\n /**\n * Information about the ENSIndexer instance dependencies.\n */\n dependencyInfo: DependencyInfo;\n}\n","import { type ENSIndexerPublicConfig, PluginName } from \"./types\";\n\n/**\n * Determines if the provided `config` produces an index equivalent to the ENS Subgraph.\n *\n * @see https://ensnode.io/docs/reference/subgraph-compatibility/\n */\nexport function isSubgraphCompatible(\n config: Pick<\n ENSIndexerPublicConfig,\n | \"plugins\"\n | \"healReverseAddresses\"\n | \"indexAdditionalResolverRecords\"\n | \"replaceUnnormalized\"\n | \"labelSet\"\n >,\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. healReverseAddresses = false\n // 3. indexAdditionalResolverRecords = false\n // 4. replaceUnnormalized = false\n const indexingBehaviorIsSubgraphCompatible =\n !config.healReverseAddresses &&\n !config.indexAdditionalResolverRecords &&\n !config.replaceUnnormalized;\n\n // 5. label set id must be \"subgraph\" and version must be 0\n const labelSetIsSubgraphCompatible =\n config.labelSet.labelSetId === \"subgraph\" && config.labelSet.labelSetVersion === 0;\n\n return (\n onlySubgraphPluginActivated &&\n indexingBehaviorIsSubgraphCompatible &&\n labelSetIsSubgraphCompatible\n );\n}\n","import { ChainId } from \"../../shared\";\nimport { serializeUrl } from \"../../shared/serialize\";\nimport { SerializedENSIndexerPublicConfig, SerializedIndexedChainIds } from \"./serialized-types\";\nimport { 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 ensAdminUrl,\n ensNodePublicUrl,\n labelSet,\n indexedChainIds,\n databaseSchemaName,\n healReverseAddresses,\n indexAdditionalResolverRecords,\n replaceUnnormalized,\n isSubgraphCompatible,\n namespace,\n plugins,\n dependencyInfo,\n } = config;\n\n return {\n ensAdminUrl: serializeUrl(ensAdminUrl),\n ensNodePublicUrl: serializeUrl(ensNodePublicUrl),\n labelSet,\n indexedChainIds: serializeIndexedChainIds(indexedChainIds),\n databaseSchemaName,\n healReverseAddresses,\n indexAdditionalResolverRecords,\n replaceUnnormalized,\n isSubgraphCompatible,\n namespace,\n plugins,\n dependencyInfo,\n } satisfies SerializedENSIndexerPublicConfig;\n}\n","import {\n type EnsRainbowClientLabelSet,\n type EnsRainbowServerLabelSet,\n type LabelSetId,\n type 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","import { ByteArray, hexToBytes } from \"viem\";\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","/**\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 { prettifyError } from \"zod/v4\";\nimport { SerializedENSIndexerOverallIndexingStatus } from \"./serialized-types\";\nimport { ENSIndexerOverallIndexingStatus } from \"./types\";\nimport { makeENSIndexerIndexingStatusSchema } from \"./zod-schemas\";\n\n/**\n * Serialize a {@link ENSIndexerOverallIndexingStatus} object.\n */\nexport function deserializeENSIndexerIndexingStatus(\n maybeStatus: SerializedENSIndexerOverallIndexingStatus,\n valueLabel?: string,\n): ENSIndexerOverallIndexingStatus {\n const schema = makeENSIndexerIndexingStatusSchema(valueLabel);\n const parsed = schema.safeParse(maybeStatus);\n\n if (parsed.error) {\n throw new Error(\n `Cannot deserialize ENSIndexerIndexingStatus:\\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\";\nimport { ChainId, deserializeChainId } from \"../../shared\";\nimport * as blockRef from \"../../shared/block-ref\";\nimport {\n makeBlockRefSchema,\n makeChainIdStringSchema,\n makeDurationSchema,\n makeUnixTimestampSchema,\n} from \"../../shared/zod-schemas\";\nimport {\n checkChainIndexingStatusesForBackfillOverallStatus,\n checkChainIndexingStatusesForCompletedOverallStatus,\n checkChainIndexingStatusesForFollowingOverallStatus,\n checkChainIndexingStatusesForUnstartedOverallStatus,\n getOverallApproxRealtimeDistance,\n getOverallIndexingStatus,\n getStandbyChains,\n} from \"./helpers\";\nimport {\n ChainIndexingBackfillStatus,\n ChainIndexingCompletedStatus,\n ChainIndexingConfig,\n ChainIndexingFollowingStatus,\n ChainIndexingStatus,\n ChainIndexingStatusForBackfillOverallStatus,\n ChainIndexingStatusIds,\n ChainIndexingStrategyIds,\n ChainIndexingUnstartedStatus,\n ENSIndexerOverallIndexingBackfillStatus,\n ENSIndexerOverallIndexingCompletedStatus,\n ENSIndexerOverallIndexingErrorStatus,\n ENSIndexerOverallIndexingFollowingStatus,\n ENSIndexerOverallIndexingUnstartedStatus,\n OverallIndexingStatusIds,\n} from \"./types\";\n\n/**\n * Makes Zod schema for {@link ChainIndexingConfig} type.\n */\nconst makeChainIndexingConfigSchema = (valueLabel: string = \"Value\") =>\n z.discriminatedUnion(\"strategy\", [\n z.strictObject({\n strategy: z.literal(ChainIndexingStrategyIds.Indefinite),\n startBlock: makeBlockRefSchema(valueLabel),\n endBlock: z.null(),\n }),\n z.strictObject({\n strategy: z.literal(ChainIndexingStrategyIds.Definite),\n startBlock: makeBlockRefSchema(valueLabel),\n endBlock: makeBlockRefSchema(valueLabel),\n }),\n ]);\n\n/**\n * Makes Zod schema for {@link ChainIndexingUnstartedStatus} type.\n */\nexport const makeChainIndexingUnstartedStatusSchema = (valueLabel: string = \"Value\") =>\n z\n .strictObject({\n status: z.literal(ChainIndexingStatusIds.Unstarted),\n config: makeChainIndexingConfigSchema(valueLabel),\n })\n .refine(\n ({ config }) =>\n config.endBlock === null || blockRef.isBeforeOrEqualTo(config.startBlock, config.endBlock),\n {\n error: `config.startBlock must be before or same as config.endBlock.`,\n },\n );\n\n/**\n * Makes Zod schema for {@link ChainIndexingBackfillStatus} type.\n */\nexport const makeChainIndexingBackfillStatusSchema = (valueLabel: string = \"Value\") =>\n z\n .strictObject({\n status: z.literal(ChainIndexingStatusIds.Backfill),\n config: makeChainIndexingConfigSchema(valueLabel),\n latestIndexedBlock: makeBlockRefSchema(valueLabel),\n latestSyncedBlock: makeBlockRefSchema(valueLabel),\n backfillEndBlock: makeBlockRefSchema(valueLabel),\n })\n .refine(\n ({ config, latestIndexedBlock }) =>\n blockRef.isBeforeOrEqualTo(config.startBlock, latestIndexedBlock),\n {\n error: `config.startBlock must be before or same as latestIndexedBlock.`,\n },\n )\n .refine(\n ({ latestIndexedBlock, latestSyncedBlock }) =>\n blockRef.isBeforeOrEqualTo(latestIndexedBlock, latestSyncedBlock),\n {\n error: `latestIndexedBlock must be before or same as latestSyncedBlock.`,\n },\n )\n .refine(\n ({ latestSyncedBlock, backfillEndBlock }) =>\n blockRef.isBeforeOrEqualTo(latestSyncedBlock, backfillEndBlock),\n {\n error: `latestSyncedBlock must be before or same as backfillEndBlock.`,\n },\n )\n .refine(\n ({ config, backfillEndBlock }) =>\n config.endBlock === null || blockRef.isEqualTo(backfillEndBlock, config.endBlock),\n {\n error: `backfillEndBlock must be the same as config.endBlock.`,\n },\n );\n\n/**\n * Makes Zod schema for {@link ChainIndexingFollowingStatus} type.\n */\nexport const makeChainIndexingFollowingStatusSchema = (valueLabel: string = \"Value\") =>\n z\n .strictObject({\n status: z.literal(ChainIndexingStatusIds.Following),\n config: z.strictObject({\n strategy: z.literal(ChainIndexingStrategyIds.Indefinite),\n startBlock: makeBlockRefSchema(valueLabel),\n }),\n latestIndexedBlock: makeBlockRefSchema(valueLabel),\n latestKnownBlock: makeBlockRefSchema(valueLabel),\n approxRealtimeDistance: makeDurationSchema(valueLabel),\n })\n .refine(\n ({ config, latestIndexedBlock }) =>\n blockRef.isBeforeOrEqualTo(config.startBlock, latestIndexedBlock),\n {\n error: `config.startBlock must be before or same as latestIndexedBlock.`,\n },\n )\n .refine(\n ({ latestIndexedBlock, latestKnownBlock }) =>\n blockRef.isBeforeOrEqualTo(latestIndexedBlock, latestKnownBlock),\n {\n error: `latestIndexedBlock must be before or same as latestKnownBlock.`,\n },\n );\n\n/**\n * Makes Zod schema for {@link ChainIndexingCompletedStatus} type.\n */\nexport const makeChainIndexingCompletedStatusSchema = (valueLabel: string = \"Value\") =>\n z\n .strictObject({\n status: z.literal(ChainIndexingStatusIds.Completed),\n config: z.strictObject({\n strategy: z.literal(ChainIndexingStrategyIds.Definite),\n startBlock: makeBlockRefSchema(valueLabel),\n endBlock: makeBlockRefSchema(valueLabel),\n }),\n latestIndexedBlock: makeBlockRefSchema(valueLabel),\n })\n .refine(\n ({ config, latestIndexedBlock }) =>\n blockRef.isBeforeOrEqualTo(config.startBlock, latestIndexedBlock),\n {\n error: `config.startBlock must be before or same as latestIndexedBlock.`,\n },\n )\n .refine(\n ({ config, latestIndexedBlock }) =>\n blockRef.isBeforeOrEqualTo(latestIndexedBlock, config.endBlock),\n {\n error: `latestIndexedBlock must be before or same as config.endBlock.`,\n },\n );\n\n/**\n * Makes Zod schema for {@link ChainIndexingStatus}\n */\nexport const makeChainIndexingStatusSchema = (valueLabel: string = \"Value\") =>\n z.discriminatedUnion(\"status\", [\n makeChainIndexingUnstartedStatusSchema(valueLabel),\n makeChainIndexingBackfillStatusSchema(valueLabel),\n makeChainIndexingFollowingStatusSchema(valueLabel),\n makeChainIndexingCompletedStatusSchema(valueLabel),\n ]);\n\n/**\n * Makes Zod schema for {@link ChainIndexingStatus} per chain.\n */\nexport const makeChainIndexingStatusesSchema = (valueLabel: string = \"Value\") =>\n z\n .record(makeChainIdStringSchema(), makeChainIndexingStatusSchema(valueLabel), {\n error: \"Chains configuration must be an object mapping valid chain IDs to their configs.\",\n })\n .transform((serializedChainsIndexingStatus) => {\n const chainsIndexingStatus = new Map<ChainId, ChainIndexingStatus>();\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 ENSIndexerOverallIndexingUnstartedStatus}\n */\nconst makeUnstartedOverallStatusSchema = (valueLabel?: string) =>\n z\n .strictObject({\n overallStatus: z.literal(OverallIndexingStatusIds.Unstarted),\n chains: makeChainIndexingStatusesSchema(valueLabel)\n .refine(\n (chains) =>\n checkChainIndexingStatusesForUnstartedOverallStatus(Array.from(chains.values())),\n {\n error: `${valueLabel} at least one chain must be in \"unstarted\" status and\neach chain has to have a status of either \"unstarted\", or \"completed\"`,\n },\n )\n .transform((chains) => chains as Map<ChainId, ChainIndexingUnstartedStatus>),\n })\n .refine(\n (indexingStatus) => {\n const chains = Array.from(indexingStatus.chains.values());\n\n return getOverallIndexingStatus(chains) === indexingStatus.overallStatus;\n },\n { error: `${valueLabel} is an invalid overallStatus.` },\n );\n\n/**\n * Makes Zod schema for {@link ENSIndexerOverallIndexingBackfillStatus}\n */\nconst makeBackfillOverallStatusSchema = (valueLabel?: string) =>\n z\n .strictObject({\n overallStatus: z.literal(OverallIndexingStatusIds.Backfill),\n chains: makeChainIndexingStatusesSchema(valueLabel)\n .refine(\n (chains) =>\n checkChainIndexingStatusesForBackfillOverallStatus(Array.from(chains.values())),\n {\n error: `${valueLabel} at least one chain must be in \"backfill\" status and\neach chain has to have a status of either \"unstarted\", \"backfill\" or \"completed\"`,\n },\n )\n .transform((chains) => chains as Map<ChainId, ChainIndexingStatusForBackfillOverallStatus>),\n omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel),\n })\n .refine(\n (indexingStatus) => {\n const chains = Array.from(indexingStatus.chains.values());\n\n return getOverallIndexingStatus(chains) === indexingStatus.overallStatus;\n },\n { error: `${valueLabel} is an invalid overallStatus.` },\n )\n .refine(\n (indexingStatus) => {\n const chains = Array.from(indexingStatus.chains.values());\n\n const standbyChainStartBlocks = getStandbyChains(chains).map(\n (chain) => chain.config.startBlock.timestamp,\n );\n\n const standbyChainEarliestStartBlocks = Math.min(...standbyChainStartBlocks);\n\n return indexingStatus.omnichainIndexingCursor <= standbyChainEarliestStartBlocks;\n },\n {\n error:\n \"omnichainIndexingCursor must be lower than or equal to the earliest config.startBlock across all standby chains\",\n },\n );\n\n/**\n * Makes Zod schema for {@link ENSIndexerOverallIndexingCompletedStatus}\n */\nconst makeCompletedOverallStatusSchema = (valueLabel?: string) =>\n z\n .strictObject({\n overallStatus: z.literal(OverallIndexingStatusIds.Completed),\n chains: makeChainIndexingStatusesSchema(valueLabel)\n .refine(\n (chains) =>\n checkChainIndexingStatusesForCompletedOverallStatus(Array.from(chains.values())),\n {\n error: `${valueLabel} all chains must have \"completed\" status`,\n },\n )\n .transform((chains) => chains as Map<ChainId, ChainIndexingCompletedStatus>),\n })\n .refine(\n (indexingStatus) => {\n const chains = Array.from(indexingStatus.chains.values());\n\n return getOverallIndexingStatus(chains) === indexingStatus.overallStatus;\n },\n { error: `${valueLabel} is an invalid overallStatus.` },\n );\n\n/**\n * Makes Zod schema for {@link ENSIndexerOverallIndexingFollowingStatus}\n */\nconst makeFollowingOverallStatusSchema = (valueLabel?: string) =>\n z\n .strictObject({\n overallStatus: z.literal(OverallIndexingStatusIds.Following),\n chains: makeChainIndexingStatusesSchema(valueLabel),\n overallApproxRealtimeDistance: makeDurationSchema(valueLabel),\n omnichainIndexingCursor: makeUnixTimestampSchema(valueLabel),\n })\n .refine(\n (indexingStatus) => {\n const chains = Array.from(indexingStatus.chains.values());\n\n return getOverallIndexingStatus(chains) === indexingStatus.overallStatus;\n },\n { error: `${valueLabel} is an invalid overallStatus.` },\n )\n .refine(\n (indexingStatus) =>\n checkChainIndexingStatusesForFollowingOverallStatus(\n Array.from(indexingStatus.chains.values()),\n ),\n {\n error: `${valueLabel} at least one chain must be in \"following\" status`,\n },\n )\n .refine(\n (indexingStatus) => {\n const chains = Array.from(indexingStatus.chains.values());\n\n return (\n getOverallApproxRealtimeDistance(chains) === indexingStatus.overallApproxRealtimeDistance\n );\n },\n { error: `${valueLabel} is an invalid overallApproxRealtimeDistance.` },\n )\n .refine(\n (indexingStatus) => {\n const chains = Array.from(indexingStatus.chains.values());\n\n const standbyChainStartBlocks = getStandbyChains(chains).map(\n (chain) => chain.config.startBlock.timestamp,\n );\n\n const standbyChainEarliestStartBlocks = Math.min(...standbyChainStartBlocks);\n\n return indexingStatus.omnichainIndexingCursor <= standbyChainEarliestStartBlocks;\n },\n {\n error:\n \"omnichainIndexingCursor must be lower than or equal to the earliest config.startBlock across all standby chains\",\n },\n );\n\n/**\n * Makes Zod schema for {@link ENSIndexerOverallIndexingErrorStatus}\n */\nconst makeErrorSchemaOverallStatusSchema = (valueLabel?: string) =>\n z.strictObject({\n overallStatus: z.literal(OverallIndexingStatusIds.IndexerError),\n });\n\n/**\n * ENSIndexer Overall Indexing Status Schema\n *\n * Makes a Zod schema definition for validating indexing status\n * across all chains indexed by ENSIndexer instance.\n */\nexport const makeENSIndexerIndexingStatusSchema = (\n valueLabel: string = \"ENSIndexerIndexingStatus\",\n) =>\n z.discriminatedUnion(\"overallStatus\", [\n makeUnstartedOverallStatusSchema(valueLabel),\n makeBackfillOverallStatusSchema(valueLabel),\n makeCompletedOverallStatusSchema(valueLabel),\n makeFollowingOverallStatusSchema(valueLabel),\n makeErrorSchemaOverallStatusSchema(valueLabel),\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, Duration, UnixTimestamp } from \"../../shared\";\n\nexport const ChainIndexingStatusIds = {\n Unstarted: \"unstarted\",\n Backfill: \"backfill\",\n Following: \"following\",\n Completed: \"completed\",\n} as const;\n\n/**\n * ChainIndexingStatusId is the derived string union of possible Chain Indexing Status identifiers.\n */\nexport type ChainIndexingStatusId =\n (typeof ChainIndexingStatusIds)[keyof typeof ChainIndexingStatusIds];\n\nexport const OverallIndexingStatusIds = {\n Unstarted: \"unstarted\",\n Backfill: \"backfill\",\n Following: \"following\",\n Completed: \"completed\",\n IndexerError: \"indexer-error\",\n} as const;\n\n/**\n * OverallIndexingStatusId is the derived string union of possible Overall Indexing Status identifiers.\n */\nexport type OverallIndexingStatusId =\n (typeof OverallIndexingStatusIds)[keyof typeof OverallIndexingStatusIds];\n\nexport const ChainIndexingStrategyIds = {\n Indefinite: \"indefinite\",\n Definite: \"definite\",\n} as const;\n\n/**\n * ChainIndexingStrategyIds is the derived string union of possible Chain Indexing Strategy identifiers.\n */\nexport type ChainIndexingStrategyId =\n (typeof ChainIndexingStrategyIds)[keyof typeof ChainIndexingStrategyIds];\n\n/**\n * Chain Indexing Indefinite Config\n *\n * Configures a chain to be indexed for an indefinite range.\n */\nexport interface ChainIndexingIndefiniteConfig {\n /**\n * Chain indexing strategy.\n */\n strategy: typeof ChainIndexingStrategyIds.Indefinite;\n\n /**\n * The block where indexing of the chain starts.\n *\n * An indexed chain always has its `startBlock` defined.\n */\n startBlock: BlockRef;\n\n /**\n * Indefinite chain indexing configs always have a null `endBlock`.\n */\n endBlock?: null;\n}\n\n/**\n * Chain Indexing Definite Config\n *\n * Configures a chain to be indexed for a definite range.\n *\n * Invariants:\n * - `startBlock` is always before or the same as `endBlock`\n */\nexport interface ChainIndexingDefiniteConfig {\n /**\n * Chain indexing strategy.\n */\n strategy: typeof ChainIndexingStrategyIds.Definite;\n\n /**\n * The block where indexing of the chain starts.\n *\n * `startBlock` must always be defined.\n */\n startBlock: BlockRef;\n\n /**\n * The block where indexing of the chain ends.\n *\n * Definite chain indexing configs always have a defined `endBlock`.\n */\n endBlock: BlockRef;\n}\n\n/**\n * Chain Indexing Config\n *\n * Configuration of an indexed chain.\n */\nexport type ChainIndexingConfig = ChainIndexingIndefiniteConfig | ChainIndexingDefiniteConfig;\n\n/**\n * Chain Indexing Status: Unstarted\n *\n * Notes:\n * - The \"unstarted\" status applies when using omnichain ordering and\n * the omnichainIndexingCursor from the overall indexing status <= config.startBlock.timestamp.\n */\nexport interface ChainIndexingUnstartedStatus {\n status: typeof ChainIndexingStatusIds.Unstarted;\n config: ChainIndexingConfig;\n}\n\n/**\n * Chain Indexing Status: 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 * Notes:\n * - The backfillEndBlock is either config.endBlock (if present) or\n * the latest block on the chain when the ENSIndexer process started up.\n * Note how this means the backfillEndBlock is always a \"fixed target\".\n * - When latestIndexedBlock reaches backfillEndBlock, the backfill is complete.\n * The moment backfill is complete the status does not immediately transition.\n * Instead, internal processing is completed for a period of time while\n * the status remains \"backfill\". After this internal processing is completed\n * the status will change to \"following\" or \"completed\" depending on\n * the configured indexing strategy. If the strategy is indefinite,\n * changes to \"following\", else if the strategy is definite, changes to\n * \"completed\".\n *\n * Invariants:\n * - `config.startBlock` is always before or the same as `latestIndexedBlock`\n * - `latestIndexedBlock` is always before or the same as `latestSyncedBlock`\n * - `latestSyncedBlock` is always before or the same as `backfillEndBlock`\n * - `backfillEndBlock` is the same as `config.endBlock` if and only if\n * the config is definite.\n */\nexport interface ChainIndexingBackfillStatus {\n status: typeof ChainIndexingStatusIds.Backfill;\n config: ChainIndexingConfig;\n\n /**\n * The block that was most recently indexed.\n */\n latestIndexedBlock: BlockRef;\n\n /**\n * The \"highest\" block that has been synced into RPC cache. Backfill indexing\n * is accelerated by cached RPC calls through this block height.\n */\n latestSyncedBlock: BlockRef;\n\n /**\n * The block that is the target for finishing the backfill.\n */\n backfillEndBlock: BlockRef;\n}\n\n/**\n * Chain Indexing Status: Following\n *\n * Following occurs after the backfill of a chain is completed and represents\n * the process of indefinitely following (and indexing!) new blocks as they are\n * added to the indexed chain across time.\n *\n * Invariants:\n * - `config.startBlock` is always before or the same as `latestIndexedBlock`\n * - `latestIndexedBlock` is always before or the same as `latestKnownBlock`\n */\nexport interface ChainIndexingFollowingStatus {\n status: typeof ChainIndexingStatusIds.Following;\n\n config: ChainIndexingIndefiniteConfig;\n\n /**\n * The block that was most recently indexed.\n */\n latestIndexedBlock: BlockRef;\n\n /**\n * The \"highest\" block that has been fetched by RPC calls and stored in\n * the RPC cache as part of the indexing process.\n */\n latestKnownBlock: BlockRef;\n\n /**\n * The number of seconds between `latestIndexedBlock.timestamp` and\n * the current time in ENSIndexer. This represents the upper-bound worst case\n * distance approximation between the latest block on the chain (independent\n * of it becoming known to us) and the latest block that has completed\n * indexing. The true distance to the latest block on the chain will be less\n * if the latest block on the chain was not issued at the current second.\n */\n approxRealtimeDistance: Duration;\n}\n\n/**\n * Chain Indexing Status: Completed\n *\n * Indexing of a chain is completed after the backfill when the chain is\n * not configured to be indefinitely indexed.\n *\n * Invariants:\n * - `config.startBlock` is always before or the same as `latestIndexedBlock`\n * - `latestIndexedBlock` is always the same as `config.endBlock`.\n */\nexport interface ChainIndexingCompletedStatus {\n status: typeof ChainIndexingStatusIds.Completed;\n config: ChainIndexingDefiniteConfig;\n\n /**\n * The block that was most recently indexed.\n */\n latestIndexedBlock: BlockRef;\n}\n\n/**\n * Chain Indexing Status\n *\n * Use the `status` field to determine the correct type interpretation at runtime.\n */\nexport type ChainIndexingStatus =\n | ChainIndexingUnstartedStatus\n | ChainIndexingBackfillStatus\n | ChainIndexingFollowingStatus\n | ChainIndexingCompletedStatus;\n\n/**\n * Chain Indexing Status: Active\n *\n * Represents a chain where indexing is currently active.\n * The `latestIndexedBlock` field will be available.\n */\nexport type ChainIndexingActiveStatus = ChainIndexingBackfillStatus | ChainIndexingFollowingStatus;\n\n/**\n * Chain Indexing Status: Standby\n *\n * Represents a chain where indexing is currently on standby (not happening).\n * The `latestIndexedBlock` field will not be available.\n */\nexport type ChainIndexingStandbyStatus =\n | ChainIndexingUnstartedStatus\n | ChainIndexingCompletedStatus;\n\n/**\n * ENSIndexer Overall Indexing Status: Unstarted\n *\n * Describes the current state of indexing operations across all indexed chains\n * when the overall indexing status is {@link OverallIndexingStatusIds.Unstarted}.\n */\nexport interface ENSIndexerOverallIndexingUnstartedStatus {\n /**\n * Overall Indexing Status\n */\n overallStatus: typeof OverallIndexingStatusIds.Unstarted;\n\n /**\n * Indexing Status for each chain.\n *\n * Each chain is guaranteed to have the \"unstarted\" status.\n * It's impossible for any chain to have status other than \"unstarted\".\n */\n chains: Map<ChainId, ChainIndexingUnstartedStatus>;\n}\n\n/**\n * Chain Indexing Status allowed when overall status is 'backfill'.\n */\nexport type ChainIndexingStatusForBackfillOverallStatus =\n | ChainIndexingUnstartedStatus\n | ChainIndexingBackfillStatus\n | ChainIndexingCompletedStatus;\n\n/**\n * ENSIndexer Overall Indexing Status: Backfill\n *\n * Describes the current state of indexing operations across all indexed chains\n * when the overall indexing status is {@link OverallIndexingStatusIds.Backfill}.\n */\nexport interface ENSIndexerOverallIndexingBackfillStatus {\n /**\n * Overall Indexing Status\n */\n overallStatus: typeof OverallIndexingStatusIds.Backfill;\n\n /**\n * Omnichain Indexing Cursor\n *\n * Identifies the timestamp of the progress of omnichain indexing across\n * all chains in {@link ChainIndexingBackfillStatus} status.\n *\n * Invariants:\n * - the cursor value is guaranteed to be lower than or equal to\n * the timestamp of the earliest `config.startBlock` across all chains\n * in {@link ChainIndexingStandbyStatus} status.\n */\n omnichainIndexingCursor: UnixTimestamp;\n\n /**\n * Indexing Status for each chain.\n *\n * At least one chain is guaranteed to be in the \"backfill\" status.\n * Each chain is guaranteed to have a status of either \"unstarted\",\n * \"backfill\" or \"completed\". It's impossible for any chain to be\n * in the \"following\" status.\n */\n chains: Map<ChainId, ChainIndexingStatusForBackfillOverallStatus>;\n}\n\n/**\n * ENSIndexer Overall Indexing Status: Completed\n *\n * Describes the final state of indexing operations across all indexed chains\n * when all indexed chains are configured for a definite indexing strategy and\n * all indexing of that definite range is completed.\n */\nexport interface ENSIndexerOverallIndexingCompletedStatus {\n /**\n * Overall Indexing Status\n */\n overallStatus: typeof OverallIndexingStatusIds.Completed;\n\n /**\n * Indexing Status for each chain.\n *\n * Each chain is guaranteed to have the \"completed\" status.\n * It's impossible for any chain to have status other than \"completed\".\n */\n chains: Map<ChainId, ChainIndexingCompletedStatus>;\n}\n\n/**\n * ENSIndexer Overall Indexing Status: Following\n *\n * Describes the state when the overall indexing status is\n * {@link OverallIndexingStatusIds.Following}.\n */\nexport interface ENSIndexerOverallIndexingFollowingStatus {\n /**\n * Overall Indexing Status\n */\n overallStatus: typeof OverallIndexingStatusIds.Following;\n\n /**\n * Omnichain Indexing Cursor\n *\n * Identifies the timestamp of the progress of omnichain indexing across\n * all chains in {@link ChainIndexingActiveStatus} status.\n *\n * Invariants:\n * - the cursor value is guaranteed to be lower than or equal to\n * the timestamp of the earliest `config.startBlock` across all chains\n * in {@link ChainIndexingStandbyStatus} status.\n */\n omnichainIndexingCursor: UnixTimestamp;\n\n /**\n * Indexing Status for each chain.\n *\n * At least one chain is guaranteed to be in the \"following\" status.\n * Each chain is guaranteed to have a status of either \"unstarted\",\n * \"backfill\", \"following\" or \"completed\".\n */\n chains: Map<ChainId, ChainIndexingStatus>;\n\n /**\n * The maximum\n * {@link ChainIndexingFollowingStatus.approxRealtimeDistance} value\n * across all chains with status: 'following'.\n */\n overallApproxRealtimeDistance: Duration;\n}\n\n/**\n * ENSIndexer Overall Indexing Status: Error\n *\n * Describes the state when ENSIndexer failed to return the indexing status for\n * all indexed chains.\n *\n * This state suggests an error with the \"primary\" ENSIndexer.\n */\nexport interface ENSIndexerOverallIndexingErrorStatus {\n /**\n * Overall Indexing Status\n */\n overallStatus: typeof OverallIndexingStatusIds.IndexerError;\n}\n\n/**\n * ENSIndexer Overall Indexing Status\n *\n * Describes the overall state of indexing operations.\n */\nexport type ENSIndexerOverallIndexingStatus =\n | ENSIndexerOverallIndexingUnstartedStatus\n | ENSIndexerOverallIndexingBackfillStatus\n | ENSIndexerOverallIndexingCompletedStatus\n | ENSIndexerOverallIndexingFollowingStatus\n | ENSIndexerOverallIndexingErrorStatus;\n","import { BlockRef, ChainId, Duration, UnixTimestamp } from \"../../shared\";\nimport {\n ChainIndexingActiveStatus,\n ChainIndexingCompletedStatus,\n ChainIndexingConfig,\n ChainIndexingDefiniteConfig,\n ChainIndexingIndefiniteConfig,\n ChainIndexingStandbyStatus,\n ChainIndexingStatus,\n ChainIndexingStatusForBackfillOverallStatus,\n ChainIndexingStatusIds,\n ChainIndexingStrategyIds,\n ChainIndexingUnstartedStatus,\n OverallIndexingStatusId,\n OverallIndexingStatusIds,\n} from \"./types\";\n\n/**\n * Get {@link OverallIndexingStatusId} based on indexed chains' statuses.\n *\n * This function decides what is the current overall indexing status,\n * based on provided chain indexing statuses. The fact that chain indexing\n * statuses were provided to this function guarantees there was no indexer\n * error, and that the overall indexing status is never\n * an {@link OverallIndexingStatusIds.IndexerError}\n */\nexport function getOverallIndexingStatus(\n chains: ChainIndexingStatus[],\n): Exclude<OverallIndexingStatusId, typeof OverallIndexingStatusIds.IndexerError> {\n const chainStatuses = chains.map((chain) => chain.status);\n\n let overallStatus: OverallIndexingStatusId;\n\n if (chainStatuses.some((chainStatus) => chainStatus === ChainIndexingStatusIds.Following)) {\n overallStatus = OverallIndexingStatusIds.Following;\n } else if (chainStatuses.some((chainStatus) => chainStatus === ChainIndexingStatusIds.Backfill)) {\n overallStatus = OverallIndexingStatusIds.Backfill;\n } else if (\n chainStatuses.some((chainStatus) => chainStatus === ChainIndexingStatusIds.Unstarted)\n ) {\n overallStatus = OverallIndexingStatusIds.Unstarted;\n } else {\n overallStatus = OverallIndexingStatusIds.Completed;\n }\n\n return overallStatus;\n}\n\n/**\n * Get overall approximate realtime distance across all indexed chains.\n *\n * @throws an error if none of the indexed chains was in the 'following' status.\n */\nexport function getOverallApproxRealtimeDistance(chains: ChainIndexingStatus[]): Duration {\n const chainApproxRealtimeDistances = chains\n .filter((chain) => chain.status === ChainIndexingStatusIds.Following)\n .map((chain) => chain.approxRealtimeDistance);\n\n if (chainApproxRealtimeDistances.length === 0) {\n throw new Error(\n `The overall approximate realtime distance value is undefined if no indexed chain is in the '${OverallIndexingStatusIds.Following}' status`,\n );\n }\n\n const approxRealtimeDistance = Math.max(...chainApproxRealtimeDistances);\n\n return approxRealtimeDistance;\n}\n\n/**\n * Get lowest of the highest end block across all chains which status is\n * {@link ChainIndexingStatus}.\n */\nexport function getTimestampForLowestOmnichainStartBlock(\n chains: ChainIndexingStatus[],\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 timestamp of the highest known block across all chains which status is\n * {@link ChainIndexingStatusForBackfillOverallStatus}.\n */\nexport function getTimestampForHighestOmnichainKnownBlock(\n chains: ChainIndexingStatus[],\n): UnixTimestamp {\n const latestKnownBlockTimestamps: UnixTimestamp[] = [];\n\n for (const chain of chains) {\n switch (chain.status) {\n case ChainIndexingStatusIds.Unstarted:\n if (chain.config.endBlock) {\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 across all chains which status is\n * {@link ChainIndexingActiveStatus}.\n */\nexport function getOmnichainIndexingCursor(chains: ChainIndexingActiveStatus[]): UnixTimestamp {\n return Math.min(...chains.map((chain) => chain.latestIndexedBlock.timestamp));\n}\n\n/**\n * Get all chains which status is {@link ChainIndexingActiveStatus}.\n */\nexport function getActiveChains(chains: ChainIndexingStatus[]): ChainIndexingActiveStatus[] {\n return chains.filter(\n (chain) =>\n chain.status === ChainIndexingStatusIds.Backfill ||\n chain.status === ChainIndexingStatusIds.Following,\n );\n}\n\n/**\n * Get all chains which status is {@link ChainIndexingStandbyStatus}.\n */\nexport function getStandbyChains(chains: ChainIndexingStatus[]): ChainIndexingStandbyStatus[] {\n return chains.filter(\n (chain) =>\n chain.status === ChainIndexingStatusIds.Unstarted ||\n chain.status === ChainIndexingStatusIds.Completed,\n );\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 strategy: ChainIndexingStrategyIds.Definite,\n startBlock,\n endBlock,\n } satisfies ChainIndexingDefiniteConfig;\n }\n\n return {\n strategy: ChainIndexingStrategyIds.Indefinite,\n startBlock,\n endBlock: null,\n } satisfies ChainIndexingIndefiniteConfig;\n}\n\n/**\n * Check if Chain Indexing Statuses fit the 'unstarted' overall status\n * requirements:\n * - All chains are guaranteed to have a status of \"unstarted\".\n *\n * Note: This function narrows the {@link ChainIndexingStatus} type to\n * {@link ChainIndexingUnstartedStatus}.\n */\nexport function checkChainIndexingStatusesForUnstartedOverallStatus(\n chains: ChainIndexingStatus[],\n): chains is ChainIndexingUnstartedStatus[] {\n return chains.every((chain) => chain.status === ChainIndexingStatusIds.Unstarted);\n}\n\n/**\n * Check if Chain Indexing Statuses fit the 'backfill' overall status\n * 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 \"unstarted\",\n * \"backfill\" or \"completed\".\n *\n * Note: This function narrows the {@linkChainIndexingStatus} type to\n * {@link ChainIndexingStatusForBackfillOverallStatus}.\n */\nexport function checkChainIndexingStatusesForBackfillOverallStatus(\n chains: ChainIndexingStatus[],\n): chains is ChainIndexingStatusForBackfillOverallStatus[] {\n const atLeastOneChainInTargetStatus = chains.some(\n (chain) => chain.status === ChainIndexingStatusIds.Backfill,\n );\n const otherChainsHaveValidStatuses = chains.every(\n (chain) =>\n chain.status === ChainIndexingStatusIds.Unstarted ||\n chain.status === ChainIndexingStatusIds.Backfill ||\n chain.status === ChainIndexingStatusIds.Completed,\n );\n\n return atLeastOneChainInTargetStatus && otherChainsHaveValidStatuses;\n}\n\n/**\n * Checks if Chain Indexing Statuses fit the 'completed' overall status\n * requirements:\n * - All chains are guaranteed to have a status of \"completed\".\n *\n * Note: This function narrows the {@linkChainIndexingStatus} type to\n * {@link ChainIndexingCompletedStatus}.\n */\nexport function checkChainIndexingStatusesForCompletedOverallStatus(\n chains: ChainIndexingStatus[],\n): chains is ChainIndexingCompletedStatus[] {\n const allChainsHaveValidStatuses = chains.every(\n (chain) => chain.status === ChainIndexingStatusIds.Completed,\n );\n\n return allChainsHaveValidStatuses;\n}\n\n/**\n * Checks Chain Indexing Statuses fit the 'following' overall status\n * 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 checkChainIndexingStatusesForFollowingOverallStatus(\n chains: ChainIndexingStatus[],\n): chains is ChainIndexingStatus[] {\n const allChainsHaveValidStatuses = chains.some(\n (chain) => chain.status === ChainIndexingStatusIds.Following,\n );\n\n return allChainsHaveValidStatuses;\n}\n\n/**\n * Sort a list of [{@link ChainId}, {@link ChainIndexingStatus}] tuples\n * by the omnichain start block timestamp in ascending order.\n */\nexport function sortAscChainStatusesByStartBlock<ChainStatusType extends ChainIndexingStatus>(\n chains: [ChainId, ChainStatusType][],\n): [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","import { ChainId, ChainIdString, serializeChainId } from \"../../shared\";\nimport {\n SerializedENSIndexerOverallIndexingBackfillStatus,\n SerializedENSIndexerOverallIndexingCompletedStatus,\n SerializedENSIndexerOverallIndexingErrorStatus,\n SerializedENSIndexerOverallIndexingFollowingStatus,\n SerializedENSIndexerOverallIndexingStatus,\n SerializedENSIndexerOverallIndexingUnstartedStatus,\n} from \"./serialized-types\";\nimport {\n ChainIndexingStatus,\n ENSIndexerOverallIndexingStatus,\n OverallIndexingStatusIds,\n} from \"./types\";\n\n/**\n * Serialize chain indexing statuses.\n */\nexport function serializeChainIndexingStatuses<ChainIndexingStatusType extends ChainIndexingStatus>(\n chainIndexingStatuses: Map<ChainId, ChainIndexingStatusType>,\n): Record<ChainIdString, ChainIndexingStatusType> {\n const serializedChainsIndexingStatuses: Record<ChainIdString, ChainIndexingStatusType> = {};\n\n for (const [chainId, chainIndexingStatus] of chainIndexingStatuses.entries()) {\n serializedChainsIndexingStatuses[serializeChainId(chainId)] = chainIndexingStatus;\n }\n\n return serializedChainsIndexingStatuses;\n}\n\n/**\n * Serialize a {@link ENSIndexerIndexingStatus} object.\n */\nexport function serializeENSIndexerIndexingStatus(\n indexingStatus: ENSIndexerOverallIndexingStatus,\n): SerializedENSIndexerOverallIndexingStatus {\n switch (indexingStatus.overallStatus) {\n case OverallIndexingStatusIds.IndexerError:\n return {\n overallStatus: OverallIndexingStatusIds.IndexerError,\n } satisfies SerializedENSIndexerOverallIndexingErrorStatus;\n\n case OverallIndexingStatusIds.Unstarted:\n return {\n overallStatus: OverallIndexingStatusIds.Unstarted,\n chains: serializeChainIndexingStatuses(indexingStatus.chains),\n } satisfies SerializedENSIndexerOverallIndexingUnstartedStatus;\n\n case OverallIndexingStatusIds.Backfill:\n return {\n overallStatus: OverallIndexingStatusIds.Backfill,\n chains: serializeChainIndexingStatuses(indexingStatus.chains),\n omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor,\n } satisfies SerializedENSIndexerOverallIndexingBackfillStatus;\n\n case OverallIndexingStatusIds.Completed: {\n return {\n overallStatus: OverallIndexingStatusIds.Completed,\n chains: serializeChainIndexingStatuses(indexingStatus.chains),\n } satisfies SerializedENSIndexerOverallIndexingCompletedStatus;\n }\n\n case OverallIndexingStatusIds.Following:\n return {\n overallStatus: OverallIndexingStatusIds.Following,\n chains: serializeChainIndexingStatuses(indexingStatus.chains),\n overallApproxRealtimeDistance: indexingStatus.overallApproxRealtimeDistance,\n omnichainIndexingCursor: indexingStatus.omnichainIndexingCursor,\n } satisfies SerializedENSIndexerOverallIndexingFollowingStatus;\n }\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\nexport 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\ninterface SpanAttributes {\n [key: string]: unknown;\n}\n\ninterface SpanEvent {\n name: string;\n attributes: SpanAttributes;\n time: number;\n}\n\nexport interface ProtocolSpan {\n scope: string;\n id: string;\n traceId: string;\n parentSpanContext:\n | {\n traceId: string;\n spanId: string;\n }\n | undefined;\n name: string;\n timestamp: number;\n duration: number;\n attributes: SpanAttributes;\n status: { code: number; message?: string };\n events: SpanEvent[];\n}\n\nexport type ProtocolSpanTreeNode = ProtocolSpan & { children: ProtocolSpanTreeNode[] };\nexport type ProtocolTrace = ProtocolSpanTreeNode[];\n","import { prettifyError } from \"zod/v4\";\nimport { ErrorResponse } from \"./types\";\nimport { ErrorResponseSchema } from \"./zod-schemas\";\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 z from \"zod/v4\";\n\nexport const ErrorResponseSchema = z.object({\n message: z.string(),\n details: z.optional(z.unknown()),\n});\n","import type { ENSIndexerOverallIndexingStatus, ENSIndexerPublicConfig } from \"../ensindexer\";\nimport type {\n ForwardResolutionArgs,\n MultichainPrimaryNameResolutionArgs,\n MultichainPrimaryNameResolutionResult,\n ResolverRecordsResponse,\n ResolverRecordsSelection,\n ReverseResolutionArgs,\n ReverseResolutionResult,\n} from \"../resolution\";\nimport type { Duration } from \"../shared\";\nimport type { ProtocolTrace } from \"../tracing\";\n\n/**\n * API Error Response Type\n */\nexport interface ErrorResponse {\n message: string;\n details?: unknown; // subject to change\n}\n\nexport interface TraceableRequest {\n trace?: boolean;\n}\n\nexport interface TraceableResponse {\n trace?: ProtocolTrace;\n}\n\nexport interface AcceleratableRequest {\n accelerate?: boolean;\n}\n\nexport interface AcceleratableResponse {\n accelerationAttempted: boolean;\n}\n\n/**\n * Resolve Records Request Type\n */\nexport interface ResolveRecordsRequest<SELECTION extends ResolverRecordsSelection>\n extends ForwardResolutionArgs<SELECTION>,\n AcceleratableRequest,\n TraceableRequest {}\n\n/**\n * Resolve Records Response Type\n */\nexport interface ResolveRecordsResponse<SELECTION extends ResolverRecordsSelection>\n extends AcceleratableResponse,\n TraceableResponse {\n records: ResolverRecordsResponse<SELECTION>;\n}\n\n/**\n * Resolve Primary Name Request Type\n */\nexport interface ResolvePrimaryNameRequest\n extends ReverseResolutionArgs,\n AcceleratableRequest,\n TraceableRequest {}\n\n/**\n * Resolve Primary Name Response Type\n */\nexport interface ResolvePrimaryNameResponse extends AcceleratableResponse, TraceableResponse {\n name: ReverseResolutionResult;\n}\n\nexport interface ResolvePrimaryNamesRequest\n extends MultichainPrimaryNameResolutionArgs,\n AcceleratableRequest,\n TraceableRequest {}\n\nexport interface ResolvePrimaryNamesResponse extends AcceleratableResponse, TraceableResponse {\n names: MultichainPrimaryNameResolutionResult;\n}\n\n/**\n * ENSIndexer Public Config Response\n */\nexport type ConfigResponse = ENSIndexerPublicConfig;\n\n/**\n * ENSIndexer Overall Indexing Status Request\n */\nexport interface IndexingStatusRequest {\n /**\n * Max Realtime Distance (optional)\n *\n * A duration value in seconds, representing the max allowed distance\n * between the latest indexed block of each chain and the “tip” of\n * all indexed chains. Setting this parameter influences the HTTP response\n * code as follows:\n * - Success (200 OK): The latest indexed block of each chain\n * is within the requested distance from realtime.\n * - Service Unavailable (503): The latest indexed block of each chain\n * is NOT within the requested distance from realtime.\n */\n maxRealtimeDistance?: Duration;\n}\n\n/**\n * ENSIndexer Overall Indexing Status Response\n */\nexport type IndexingStatusResponse = ENSIndexerOverallIndexingStatus;\n\n/**\n * ENSIndexer Overall Indexing Status Response Codes\n *\n * Define a custom response code for known responses.\n */\nexport const IndexingStatusResponseCodes = {\n IndexerError: 512,\n RequestedDistanceNotAchievedError: 513,\n} as const;\n","import { 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 { deserializeErrorResponse } from \"./api\";\nimport {\n type ConfigResponse,\n type ErrorResponse,\n type IndexingStatusRequest,\n type IndexingStatusResponse,\n IndexingStatusResponseCodes,\n type ResolvePrimaryNameRequest,\n type ResolvePrimaryNameResponse,\n type ResolvePrimaryNamesRequest,\n type ResolvePrimaryNamesResponse,\n type ResolveRecordsRequest,\n type ResolveRecordsResponse,\n} from \"./api/types\";\nimport { ClientError } from \"./client-error\";\nimport {\n type SerializedENSIndexerOverallIndexingStatus,\n type SerializedENSIndexerPublicConfig,\n deserializeENSIndexerIndexingStatus,\n deserializeENSIndexerPublicConfig,\n} from \"./ensindexer\";\nimport { 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 * - 🚧 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 `address` 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_ query the Default EVM Chain Id (`0`) in order to\n * determine the `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 * If the `address` specifies a valid [ENSIP-19 Default Name](https://docs.ens.domains/ensip/19/#default-primary-name),\n * the Default Name will be returned for all chainIds for which there is not a chain-specific\n * Primary Name. To avoid misuse, you _may not_ query the Default EVM Chain Id (`0`) directly, and\n * 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 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\",\n * // \"10\": \"gregskril.eth\",\n * // \"8453\": \"greg.base.eth\", // base-specific Primary Name!\n * // \"42161\": \"gregskril.eth\",\n * // \"59144\": \"gregskril.eth\",\n * // \"534352\": \"gregskril.eth\"\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 let responseData: unknown;\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 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 deserializeENSIndexerPublicConfig(responseData as SerializedENSIndexerPublicConfig);\n }\n\n /**\n * Fetch ENSNode Indexing Status\n *\n * Fetch the ENSNode's multichain indexing status.\n *\n * @param options additional options\n * @param options.maxRealtimeDistance the max allowed distance between the\n * latest indexed block of each chain and the \"tip\" of all indexed chains.\n * Setting this parameter influences the HTTP response code as follows:\n * - Success (200 OK): The latest indexed block of each chain is within the\n * requested distance from realtime.\n * - Service Unavailable (503): The latest indexed block of each chain is NOT\n * within the requested distance from realtime.\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(options?: IndexingStatusRequest): Promise<IndexingStatusResponse> {\n const url = new URL(`/api/indexing-status`, this.options.url);\n\n if (typeof options?.maxRealtimeDistance !== \"undefined\") {\n url.searchParams.set(\"maxRealtimeDistance\", `${options.maxRealtimeDistance}`);\n }\n\n const response = await fetch(url);\n\n let responseData: unknown;\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 try {\n responseData = await response.json();\n } catch {\n throw new Error(\"Malformed response data: invalid JSON\");\n }\n\n // handle application errors accordingly\n if (!response.ok) {\n switch (response.status) {\n case IndexingStatusResponseCodes.IndexerError: {\n console.error(\"Indexing Status API: indexer error\");\n return deserializeENSIndexerIndexingStatus(\n responseData as SerializedENSIndexerOverallIndexingStatus,\n );\n }\n\n case IndexingStatusResponseCodes.RequestedDistanceNotAchievedError: {\n console.error(\n \"Indexing Status API: Requested realtime indexing distance not achieved error\",\n );\n return deserializeENSIndexerIndexingStatus(\n responseData as SerializedENSIndexerOverallIndexingStatus,\n );\n }\n\n default: {\n const errorResponse = deserializeErrorResponse(responseData);\n throw new Error(`Fetching ENSNode Indexing Status Failed: ${errorResponse.message}`);\n }\n }\n }\n\n return deserializeENSIndexerIndexingStatus(\n responseData as SerializedENSIndexerOverallIndexingStatus,\n );\n }\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","import {\n DatasourceNames,\n ENSNamespaceId,\n ENSNamespaceIds,\n maybeGetDatasource,\n} from \"@ensnode/datasources\";\nimport { ETH_COIN_TYPE, evmChainIdToCoinType } from \"../ens\";\nimport { uniq } from \"../shared\";\nimport type { ResolverRecordsSelection } from \"./resolver-records-selection\";\n\nconst getENSIP19SupportedCoinTypes = (namespace: ENSNamespaceId) =>\n uniq(\n [\n maybeGetDatasource(namespace, DatasourceNames.ReverseResolverBase),\n maybeGetDatasource(namespace, DatasourceNames.ReverseResolverLinea),\n maybeGetDatasource(namespace, DatasourceNames.ReverseResolverOptimism),\n maybeGetDatasource(namespace, DatasourceNames.ReverseResolverArbitrum),\n maybeGetDatasource(namespace, DatasourceNames.ReverseResolverScroll),\n ]\n .filter((ds) => ds !== undefined)\n .map((ds) => ds.chain.id),\n ).map(evmChainIdToCoinType);\n\nconst TEXTS = [\n \"url\",\n \"avatar\",\n \"header\",\n \"description\",\n \"email\",\n \"com.twitter\",\n \"com.farcaster\",\n \"com.github\",\n] as const satisfies string[];\n\nexport const DefaultRecordsSelection = {\n [ENSNamespaceIds.Mainnet]: {\n addresses: [ETH_COIN_TYPE, ...getENSIP19SupportedCoinTypes(ENSNamespaceIds.Mainnet)],\n texts: TEXTS,\n },\n [ENSNamespaceIds.Sepolia]: {\n addresses: [ETH_COIN_TYPE, ...getENSIP19SupportedCoinTypes(ENSNamespaceIds.Sepolia)],\n texts: TEXTS,\n },\n [ENSNamespaceIds.Holesky]: {\n addresses: [ETH_COIN_TYPE, ...getENSIP19SupportedCoinTypes(ENSNamespaceIds.Holesky)],\n texts: TEXTS,\n },\n [ENSNamespaceIds.EnsTestEnv]: {\n addresses: [ETH_COIN_TYPE, ...getENSIP19SupportedCoinTypes(ENSNamespaceIds.EnsTestEnv)],\n texts: TEXTS,\n },\n} as const satisfies Record<ENSNamespaceId, ResolverRecordsSelection>;\n"],"mappings":";AAAA,SAAS,gBAAgB;AAIlB,IAAM,YAAkB,SAAS,EAAE;AACnC,IAAM,WAAW,SAAS,KAAK;AAC/B,IAAM,iBAAiB,SAAS,UAAU;AAC1C,IAAM,kBAAkB,SAAS,WAAW;AAQ5C,IAAM,qBAAgC,oBAAI,IAAI,CAAC,SAAS,cAAc,CAAC,CAAC;;;ACf/E,SAAuB,QAAQ,WAAW,QAAQ,WAAW,aAAa;AAE1E,SAAS,iBAAiB;;;ACD1B;AAAA,EACE,wBAAwB;AAAA,EACxB,wBAAwB;AAAA,OACnB;AAYA,IAAM,gBAA0B;AAQhC,IAAM,uBAAgC;AAOtC,IAAM,wBAAwB;AAU9B,IAAM,uBAAuB,CAAC,aAAgC;AACnE,MAAI,aAAa,cAAe,QAAO;AACvC,SAAO,sBAAsB,QAAQ;AACvC;AAQO,IAAM,uBAAuB,CAAC,YAA+B;AAClE,MAAI,YAAY,EAAG,QAAO;AAC1B,SAAO,sBAAsB,OAAO;AACtC;AAUO,IAAM,mBAAmB,CAAC,UAA4B;AAC3D,MAAI,QAAQ,OAAO,OAAO,gBAAgB,GAAG;AAC3C,UAAM,IAAI,MAAM,IAAI,KAAK,kDAAkD;AAAA,EAC7E;AAEA,SAAO,OAAO,KAAK;AACrB;;;AC7DO,IAAM,mBAAmB,CAAC,YAA4B,QAAQ,MAAM,CAAC,EAAE,YAAY;AAOnF,IAAM,uBAAuB,CAAC,aAA8B,SAAS,SAAS,EAAE;AAmBhF,SAAS,YAAY,SAAkB,UAA0B;AACtE,QAAM,QAAQ,iBAAiB,OAAO;AAEtC,QAAM,UAAU,MAAM;AACpB,YAAQ,UAAU;AAAA,MAChB,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO,qBAAqB,QAAQ;AAAA,IACxC;AAAA,EACF,GAAG;AAEH,SAAO,GAAG,KAAK,IAAI,MAAM;AAC3B;;;AFxCO,IAAM,oBAAoB,CAAC,WAAsB,SACtD,UAAU,OAAO,CAAC,MAAM,SAAS,CAAC,CAAC;AAU9B,IAAM,iCAAiC,CAAC;AAAA,EAC7C;AAAA,EACA;AACF,MAMqB;AAEnB,MAAI,CAAC,UAAU,mBAAmB,GAAG;AACnC,UAAM,IAAI;AAAA,MACR,6BAA6B,mBAAmB;AAAA,IAClD;AAAA,EACF;AAEA,MAAI,CAAC,OAAO,SAAS,GAAG;AACtB,UAAM,IAAI;AAAA,MACR,uBAAuB,SAAS;AAAA,IAClC;AAAA,EACF;AAGA,QAAM,eAAe,iBAAiB,mBAAmB;AAGzD,MAAI,UAAU,YAAY,MAAM,UAAW,QAAO;AAIlD,SAAO;AACT;AAQO,IAAM,iBAAiB,CAAC,QAAqB,MAAM,KAAK,EAAE,MAAM,GAAG,CAAC;AAiC3E,IAAM,+BAA+B;AAAA,EACnC;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF;AAEA,IAAM,oCAAoC,IAAI;AAAA,EAC5C,6BAA6B,IAAI,CAAC,SAAS,KAAK,WAAW,CAAC,CAAC;AAC/D;AAaO,IAAM,mBAAmB,CAAC,UAAwC;AACvE,MAAI,CAAC,MAAO,QAAO;AAEnB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,QAAI,kCAAkC,IAAI,MAAM,WAAW,CAAC,CAAC,EAAG,QAAO;AAAA,EACzE;AAEA,SAAO;AACT;;;AGvHO,IAAM,mBAAmB,CAAC,SAC/B,KAAK,MAAM,GAAG,EAAE,IAAI,CAAC,GAAG,GAAG,WAAW,OAAO,MAAM,CAAC,EAAE,KAAK,GAAG,CAAC;;;ACHjE,SAAS,uBAAuB;;;ACJhC,SAAkB,YAAY,mBAAmB;AASjD,IAAM,qBAAqB;AAO3B,IAAM,oBAAoB,CAAC,iBAAiC,WAAW,KAAK,YAAY,EAAE;AAO1F,IAAM,qBAAqB,CAAC,kBAAmC;AAC7D,MAAI,kBAAkB,UAAW,QAAO;AACxC,MAAI,kBAAkB,OAAQ,QAAO;AAErC,SAAO,iBAAiB,YAAY,KAAK,aAAa,EAAE,CAAC;AAC3D;AAKO,SAAS,iBAAiB,MAA6D;AAC5F,QAAM,QAAQ,KAAK,MAAM,kBAAkB;AAC3C,MAAI,CAAC,MAAO,QAAO;AAEnB,MAAI;AACF,UAAM,CAAC,EAAE,cAAc,aAAa,IAAI;AACxC,QAAI,CAAC,aAAc,QAAO;AAC1B,QAAI,CAAC,cAAe,QAAO;AAE3B,WAAO;AAAA,MACL,SAAS,kBAAkB,YAAY;AAAA,MACvC,UAAU,mBAAmB,aAAa;AAAA,IAC5C;AAAA,EACF,QAAQ;AAEN,WAAO;AAAA,EACT;AACF;;;AClDA,SAAS,iBAAiB;AAUnB,SAAS,iBAAiB,MAAqB;AACpD,MAAI;AACF,WAAO,SAAS,UAAU,IAAI;AAAA,EAChC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAQO,SAAS,kBAAkB,OAAuB;AAEvD,MAAI,UAAU,GAAI,QAAO;AAGzB,MAAI,MAAM,SAAS,GAAG,EAAG,QAAO;AAEhC,MAAI;AACF,WAAO,UAAU,UAAU,KAAK;AAAA,EAClC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AC1BO,IAAM,kBAAkB,CAAC,cAC9B,IAAI,UAAU,MAAM,CAAC,CAAC;;;ACXxB,SAAS,iBAAAA,sBAAqB;;;ACQ9B,OAAOC,QAAO;;;ACmCP,IAAM,WAAN,MAAuF;AAAA,EAC3E,SAAS,oBAAI,IAAuB;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQV,YAAY,UAAkB;AACnC,QAAI,CAAC,OAAO,UAAU,QAAQ,GAAG;AAC/B,YAAM,IAAI;AAAA,QACR,iEAAiE,QAAQ;AAAA,MAC3E;AAAA,IACF;AAEA,QAAI,WAAW,GAAG;AAChB,YAAM,IAAI;AAAA,QACR,+DAA+D,QAAQ;AAAA,MACzE;AAAA,IACF;AAEA,SAAK,YAAY;AAAA,EACnB;AAAA,EAEO,IAAI,KAAa,OAAkB;AACxC,SAAK,OAAO,IAAI,KAAK,KAAK;AAE1B,QAAI,KAAK,OAAO,OAAO,KAAK,WAAW;AAErC,YAAM,YAAY,KAAK,OAAO,KAAK,EAAE,KAAK,EAAE;AAC5C,WAAK,OAAO,OAAO,SAAS;AAAA,IAC9B;AAAA,EACF;AAAA,EAEO,IAAI,KAAa;AACtB,UAAM,QAAQ,KAAK,OAAO,IAAI,GAAG;AACjC,QAAI,OAAO;AAET,WAAK,OAAO,OAAO,GAAG;AACtB,WAAK,OAAO,IAAI,KAAK,KAAK;AAAA,IAC5B;AACA,WAAO;AAAA,EACT;AAAA,EAEO,QAAQ;AACb,SAAK,OAAO,MAAM;AAAA,EACpB;AAAA,EAEA,IAAW,OAAO;AAChB,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAEA,IAAW,WAAW;AACpB,WAAO,KAAK;AAAA,EACd;AACF;;;ACjGO,IAAM,OAAO,CAAI,QAAkB,CAAC,GAAG,IAAI,IAAI,GAAG,CAAC;;;ACGnD,SAAS,iBAAiB,SAAiC;AAChE,SAAO,QAAQ,SAAS;AAC1B;AAKO,SAAS,kBAAkB,UAAqC;AACrE,SAAO,SAAS,YAAY;AAC9B;AAKO,SAAS,aAAa,KAAqB;AAChD,SAAO,IAAI,SAAS;AACtB;;;ACtBA,SAAS,qBAAqB;;;ACQ9B,OAAO,OAAO;AAyBP,IAAM,oBAAoB,CAAC,aAAqB,YACrD,EAAE,IAAI;AAAA,EACJ,OAAO,GAAG,UAAU;AACtB,CAAC;AAKI,IAAM,4BAA4B,CAAC,aAAqB,YAC7D,kBAAkB,UAAU,EAAE,SAAS;AAAA,EACrC,OAAO,GAAG,UAAU;AACtB,CAAC;AAKI,IAAM,+BAA+B,CAAC,aAAqB,YAChE,kBAAkB,UAAU,EAAE,YAAY;AAAA,EACxC,OAAO,GAAG,UAAU;AACtB,CAAC;AAKI,IAAM,qBAAqB,CAAC,aAAqB,YACtD,EAAE,OACC,OAAO;AAAA,EACN,OAAO,GAAG,UAAU;AACtB,CAAC,EACA,KAAK,6BAA6B,UAAU,CAAC;AAO3C,IAAM,oBAAoB,CAAC,aAAqB,eACrD,0BAA0B,UAAU;AAK/B,IAAM,0BAA0B,CAAC,aAAqB,sBAC3D,EACG,OAAO,EAAE,OAAO,GAAG,UAAU,6CAA6C,CAAC,EAC3E,KAAK,EAAE,OAAO,OAAO,EAAE,OAAO,GAAG,UAAU,2CAA2C,CAAC,CAAC,EACxF,KAAK,kBAAkB,oCAAoC,UAAU,EAAE,CAAC;AAKtE,IAAM,qBAAqB,CAAC,aAAqB,sBACtD,EAAE,IACC,SAAS,EAAE,OAAO,GAAG,UAAU,wCAAwC,CAAC,EACxE,UAAU,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC;AAK1B,IAAM,0BAA0B,CAAC,aAAqB,gBAC3D,kBAAkB,UAAU;AAKvB,IAAM,gBAAgB,CAAC,aAAqB,YACjD,EACG,IAAI;AAAA,EACH,OAAO,GAAG,UAAU;AACtB,CAAC,EACA,UAAU,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC;AAgBzB,IAAM,wBAAwB,CAAC,aAAqB,mBACzD,6BAA6B,UAAU;AAKlC,IAAM,uBAAuB,CAAC,aAAqB,YACxD,EACG;AAAA,EACC;AAAA,IACE,YAAY,sBAAsB,GAAG,UAAU,aAAa,EAAE,SAAS;AAAA,IACvE,UAAU,sBAAsB,GAAG,UAAU,WAAW,EAAE,SAAS;AAAA,EACrE;AAAA,EACA;AAAA,IACE,OAAO,GAAG,UAAU;AAAA,EACtB;AACF,EACC;AAAA,EACC,CAAC,MAAM;AACL,QAAI,EAAE,cAAc,EAAE,UAAU;AAC9B,aAAO,EAAE,cAAc,EAAE;AAAA,IAC3B;AAEA,WAAO;AAAA,EACT;AAAA,EACA,EAAE,OAAO,GAAG,UAAU,mDAAmD;AAC3E;AAKG,IAAM,qBAAqB,CAAC,aAAqB,YACtD,EAAE;AAAA,EACA;AAAA,IACE,WAAW,wBAAwB,GAAG,UAAU,YAAY;AAAA,IAC5D,QAAQ,sBAAsB,GAAG,UAAU,SAAS;AAAA,EACtD;AAAA,EACA;AAAA,IACE,OAAO,GAAG,UAAU;AAAA,EACtB;AACF;AAKK,IAAM,2BAA2B,CAAC,aAAqB,qBAC5D,EAAE,KAAK,iBAAiB;AAAA,EACtB,QAAQ;AACN,WAAO,WAAW,UAAU,sCAAsC,OAAO,KAAK,eAAe,EAAE,KAAK,IAAI,CAAC;AAAA,EAC3G;AACF,CAAC;;;AD3JI,SAAS,mBAAmB,cAA6B,YAA8B;AAC5F,QAAM,SAAS,wBAAwB,UAAU;AACjD,QAAM,SAAS,OAAO,UAAU,YAAY;AAE5C,MAAI,OAAO,OAAO;AAChB,UAAM,IAAI,MAAM;AAAA,EAAgC,cAAc,OAAO,KAAK,CAAC;AAAA,CAAI;AAAA,EACjF;AAEA,SAAO,OAAO;AAChB;AAEO,SAAS,oBAAoB,eAAuB,YAA+B;AACxF,QAAM,SAAS,mBAAmB,UAAU;AAC5C,QAAM,SAAS,OAAO,UAAU,aAAa;AAE7C,MAAI,OAAO,OAAO;AAChB,UAAM,IAAI,MAAM;AAAA,EAAiC,cAAc,OAAO,KAAK,CAAC;AAAA,CAAI;AAAA,EAClF;AAEA,SAAO,OAAO;AAChB;AAaO,SAAS,eAAe,UAAqB,YAA0B;AAC5E,QAAM,SAAS,cAAc,UAAU;AACvC,QAAM,SAAS,OAAO,UAAU,QAAQ;AAExC,MAAI,OAAO,OAAO;AAChB,UAAM,IAAI,MAAM;AAAA,EAA4B,cAAc,OAAO,KAAK,CAAC;AAAA,CAAI;AAAA,EAC7E;AAEA,SAAO,OAAO;AAChB;AAEO,SAAS,uBAAuB,kBAA0B,YAAkC;AACjG,QAAM,SAAS,sBAAsB,UAAU;AAC/C,QAAM,SAAS,OAAO,UAAU,gBAAgB;AAEhD,MAAI,OAAO,OAAO;AAChB,UAAM,IAAI,MAAM;AAAA,EAAoC,cAAc,OAAO,KAAK,CAAC;AAAA,CAAI;AAAA,EACrF;AAEA,SAAO,OAAO;AAChB;AAEO,SAAS,sBAAsB,iBAAsC,YAAqB;AAC/F,QAAM,SAAS,qBAAqB,UAAU;AAC9C,QAAM,SAAS,OAAO,UAAU,eAAe;AAE/C,MAAI,OAAO,OAAO;AAChB,UAAM,IAAI,MAAM;AAAA,EAAmC,cAAc,OAAO,KAAK,CAAC;AAAA,CAAI;AAAA,EACpF;AAEA,SAAO,OAAO;AAChB;AAEO,SAAS,oBACd,eACA,YACU;AACV,QAAM,SAAS,mBAAmB,UAAU;AAC5C,QAAM,SAAS,OAAO,UAAU,aAAa;AAE7C,MAAI,OAAO,OAAO;AAChB,UAAM,IAAI,MAAM;AAAA,EAAiC,cAAc,OAAO,KAAK,CAAC;AAAA,CAAI;AAAA,EAClF;AAEA,SAAO,OAAO;AAChB;AAEO,SAAS,oBAAoB,eAAuB,YAA+B;AACxF,QAAM,SAAS,mBAAmB,UAAU;AAC5C,QAAM,SAAS,OAAO,UAAU,aAAa;AAE7C,MAAI,OAAO,OAAO;AAChB,UAAM,IAAI,WAAW;AAAA,EAAiC,cAAc,OAAO,KAAK,CAAC;AAAA,CAAI;AAAA,EACvF;AAEA,SAAO,OAAO;AAChB;;;AEvGA,SAAS,sBAAsB;AAMxB,IAAM,iBAAiB,CAAC,GAAc,MAA0B;AACrE,SAAO,EAAE,YAAY,EAAE,WAAW,eAAe,EAAE,SAAS,EAAE,OAAO;AACvE;;;ACRA,SAAS,aAAAC,kBAAiB;AAoBnB,SAAS,sBAAsB,OAAwC;AAE5E,MAAI,kBAAkB,KAAK,EAAG,QAAO;AAGrC,SAAO,gBAAgBC,WAAU,KAAK,CAAC;AACzC;AAgBO,SAAS,qBAAqB,MAAkB;AAErD,MAAI,iBAAiB,IAAI,EAAG,QAAO;AAGnC,SAAO,KAAK,MAAM,GAAG,EAAE,IAAI,qBAAqB,EAAE,KAAK,GAAG;AAC5D;;;ACvCO,IAAK,aAAL,kBAAKC,gBAAL;AACL,EAAAA,YAAA,cAAW;AACX,EAAAA,YAAA,eAAY;AACZ,EAAAA,YAAA,gBAAa;AACb,EAAAA,YAAA,cAAW;AACX,EAAAA,YAAA,sBAAmB;AACnB,EAAAA,YAAA,eAAY;AACZ,EAAAA,YAAA,gBAAa;AAPH,SAAAA;AAAA,GAAA;;;ACFL,SAAS,qBACd,QAQS;AAET,QAAM,8BACJ,OAAO,QAAQ,WAAW,KAAK,OAAO,QAAQ,CAAC;AAKjD,QAAM,uCACJ,CAAC,OAAO,wBACR,CAAC,OAAO,kCACR,CAAC,OAAO;AAGV,QAAM,+BACJ,OAAO,SAAS,eAAe,cAAc,OAAO,SAAS,oBAAoB;AAEnF,SACE,+BACA,wCACA;AAEJ;;;ATbO,IAAM,4BAA4B,CAAC,aAAqB,wBAC7DC,GACG,MAAM,kBAAkB,UAAU,GAAG;AAAA,EACpC,OAAO,GAAG,UAAU;AACtB,CAAC,EACA,IAAI,GAAG,EAAE,OAAO,GAAG,UAAU,2CAA2C,CAAC,EACzE,UAAU,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC;AAOzB,IAAM,wBAAwB,CAAC,aAAqB,cACzDA,GACG;AAAA,EACCA,GAAE,KAAK,YAAY;AAAA,IACjB,OAAO,GAAG,UAAU,2EAA2E,OAAO;AAAA,MACpG;AAAA,IACF,EAAE,KAAK,IAAI,CAAC;AAAA,EACd,CAAC;AACH,EACC,IAAI,GAAG;AAAA,EACN,OAAO,GAAG,UAAU,2EAA2E,OAAO;AAAA,IACpG;AAAA,EACF,EAAE,KAAK,IAAI,CAAC;AACd,CAAC,EACA,OAAO,CAAC,QAAQ,IAAI,WAAW,KAAK,GAAG,EAAE,QAAQ;AAAA,EAChD,OAAO,GAAG,UAAU;AACtB,CAAC;AAOE,IAAM,+BAA+B,CAAC,aAAqB,2BAChEA,GACG,OAAO,EAAE,OAAO,GAAG,UAAU,oBAAoB,CAAC,EAClD,KAAK,EACL,SAAS;AAAA,EACR,OAAO,GAAG,UAAU;AACtB,CAAC;AAUE,IAAM,uBAAuB,CAAC,eAAuB;AAC1D,SAAOA,GACJ,OAAO,EAAE,OAAO,GAAG,UAAU,oBAAoB,CAAC,EAClD,IAAI,GAAG,EAAE,OAAO,GAAG,UAAU,gCAAgC,CAAC,EAC9D,IAAI,IAAI,EAAE,OAAO,GAAG,UAAU,gCAAgC,CAAC,EAC/D,MAAM,aAAa;AAAA,IAClB,OAAO,GAAG,UAAU;AAAA,EACtB,CAAC;AACL;AAUO,IAAM,4BAA4B,CAAC,eAAuB;AAC/D,SAAOA,GAAE,OACN,OAAO,EAAE,OAAO,GAAG,UAAU,uBAAuB,CAAC,EACrD,KAAK,6BAA6B,UAAU,CAAC;AAClD;AAOO,IAAM,gCAAgC,CAAC,aAAqB,gBAAgB;AACjF,MAAI,uBAAuB;AAC3B,MAAI,4BAA4B;AAChC,MAAI,cAAc,aAAa;AAC7B,2BAAuB;AACvB,gCAA4B;AAAA,EAC9B,OAAO;AACL,2BAAuB,aAAa;AACpC,gCAA4B,aAAa;AAAA,EAC3C;AACA,SAAOA,GAAE,OAAO;AAAA,IACd,YAAY,qBAAqB,oBAAoB;AAAA,IACrD,iBAAiB,0BAA0B,yBAAyB;AAAA,EACtE,CAAC;AACH;AAEA,IAAM,2BAA2B,CAAC,aAAqB,YACrDA,GAAE,OAAO,EAAE,SAAS,EAAE,OAAO,GAAG,UAAU,+BAA+B,CAAC;AAErE,IAAM,2BAA2B,CAAC,aAAqB,YAC5DA,GAAE;AAAA,EACA;AAAA,IACE,QAAQ,yBAAyB;AAAA,IACjC,QAAQ,yBAAyB;AAAA,IACjC,YAAY,yBAAyB;AAAA,IACrC,kBAAkB,0BAA0B;AAAA,EAC9C;AAAA,EACA;AAAA,IACE,OAAO,GAAG,UAAU;AAAA,EACtB;AACF;AAGK,SAAS,qDACd,KACA;AACA,QAAM,EAAE,OAAO,OAAO,IAAI;AAE1B,QAAM,+BAA+B,OAAO,QAAQ,mDAAoC;AAExF,MAAI,gCAAgC,CAAC,OAAO,gCAAgC;AAC1E,QAAI,OAAO,KAAK;AAAA,MACd,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS,kDAAmC;AAAA,IAC9C,CAAC;AAAA,EACH;AACF;AAGO,SAAS,2CACd,KAWA;AACA,QAAM,EAAE,OAAO,OAAO,IAAI;AAE1B,MAAI,OAAO,yBAAyB,qBAAqB,MAAM,GAAG;AAChE,UAAM,UAAU,OAAO,uBACnB,sEAAgE,yMAChE,qKAA+J;AAEnK,QAAI,OAAO,KAAK;AAAA,MACd,MAAM;AAAA,MACN,OAAO;AAAA,MACP;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAQO,IAAM,mCAAmC,CAAC,aAAqB,6BACpEA,GACG,OAAO;AAAA,EACN,aAAa,cAAc,GAAG,UAAU,cAAc;AAAA,EACtD,kBAAkB,cAAc,GAAG,UAAU,mBAAmB;AAAA,EAChE,UAAU,8BAA8B,GAAG,UAAU,WAAW;AAAA,EAChE,sBAAsBA,GAAE,QAAQ,EAAE,OAAO,GAAG,UAAU,wBAAwB,CAAC;AAAA,EAC/E,gCAAgCA,GAAE,QAAQ;AAAA,IACxC,OAAO,GAAG,UAAU;AAAA,EACtB,CAAC;AAAA,EACD,qBAAqBA,GAAE,QAAQ,EAAE,OAAO,GAAG,UAAU,uBAAuB,CAAC;AAAA,EAC7E,iBAAiB,0BAA0B,GAAG,UAAU,kBAAkB;AAAA,EAC1E,sBAAsBA,GAAE,QAAQ,EAAE,OAAO,GAAG,UAAU,wBAAwB,CAAC;AAAA,EAC/E,WAAW,yBAAyB,GAAG,UAAU,YAAY;AAAA,EAC7D,SAAS,sBAAsB,GAAG,UAAU,UAAU;AAAA,EACtD,oBAAoB,6BAA6B,GAAG,UAAU,qBAAqB;AAAA,EACnF,gBAAgB,yBAAyB,GAAG,UAAU,iBAAiB;AACzE,CAAC,EAMA,MAAM,oDAAoD,EAC1D,MAAM,0CAA0C;;;AD9M9C,SAAS,kCACd,aACA,YACwB;AACxB,QAAM,SAAS,iCAAiC,UAAU;AAC1D,QAAM,SAAS,OAAO,UAAU,WAAW;AAE3C,MAAI,OAAO,OAAO;AAChB,UAAM,IAAI,MAAM;AAAA,EAA+CC,eAAc,OAAO,KAAK,CAAC;AAAA,CAAI;AAAA,EAChG;AAEA,SAAO,OAAO;AAChB;;;AWZO,SAAS,yBAAyB,iBAA0D;AACjG,SAAO,MAAM,KAAK,eAAe;AACnC;AAIO,SAAS,gCACd,QACkC;AAClC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,sBAAAC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,SAAO;AAAA,IACL,aAAa,aAAa,WAAW;AAAA,IACrC,kBAAkB,aAAa,gBAAgB;AAAA,IAC/C;AAAA,IACA,iBAAiB,yBAAyB,eAAe;AAAA,IACzD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,sBAAAA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AChCO,SAAS,gBAAgB,iBAAqC;AACnE,SAAO,qBAAqB,YAAY,EAAE,MAAM,eAAe;AACjE;AAQO,SAAS,qBAAqB,sBAAwD;AAC3F,SAAO,0BAA0B,iBAAiB,EAAE,MAAM,oBAAoB;AAChF;AASO,SAAS,8BACd,YACA,iBAC0B;AAC1B,MAAI,oBAAoB,UAAa,eAAe,QAAW;AAC7D,UAAM,IAAI,MAAM,qEAAqE;AAAA,EACvF;AAEA,SAAO,EAAE,YAAY,gBAAgB;AACvC;AAQO,SAAS,oCACd,WACA,WACM;AACN,MAAI,UAAU,eAAe,QAAW;AAEtC;AAAA,EACF;AAEA,MAAI,UAAU,eAAe,UAAU,YAAY;AACjD,UAAM,IAAI;AAAA,MACR,wBAAwB,UAAU,UAAU,qDAAqD,UAAU,UAAU;AAAA,IACvH;AAAA,EACF;AAEA,MACE,UAAU,oBAAoB,UAC9B,UAAU,yBAAyB,UAAU,iBAC7C;AACA,UAAM,IAAI;AAAA,MACR,oCAAoC,UAAU,sBAAsB,4CAA4C,UAAU,eAAe,sBAAsB,UAAU,UAAU;AAAA,IACrL;AAAA,EACF;AACF;;;AC3EA,SAAoB,kBAAkB;AAS/B,SAAS,iBAAiB,WAAiC;AAChE,MAAI;AACF,QAAI,UAAU,WAAW,IAAI;AAC3B,YAAM,IAAI,MAAM,4BAA4B,UAAU,MAAM,2BAA2B;AAAA,IACzF;AACA,QAAI,cAAc,UAAU,YAAY,GAAG;AACzC,YAAM,IAAI,MAAM,gCAAgC;AAAA,IAClD;AACA,QAAI,CAAC,UAAU,WAAW,IAAI,GAAG;AAC/B,YAAM,IAAI,MAAM,+BAA+B;AAAA,IACjD;AACA,UAAM,QAAQ,WAAW,SAAS;AAClC,QAAI,MAAM,WAAW,IAAI;AAEvB,YAAM,IAAI,MAAM,4BAA4B,MAAM,MAAM,sBAAsB;AAAA,IAChF;AACA,WAAO;AAAA,EACT,SAAS,GAAG;AACV,QAAI,aAAa,OAAO;AACtB,YAAM;AAAA,IACR;AACA,UAAM,IAAI,MAAM,oBAAoB;AAAA,EACtC;AACF;;;AC1BO,SAAS,wBAAwB,aAA6B;AACnE,QAAM,UAAU,YAAY,KAAK;AAGjC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,uBAAuB;AAAA,EACzC;AAGA,MAAI,YAAY,MAAM;AACpB,UAAM,IAAI,MAAM,mDAAmD;AAAA,EACrE;AAEA,QAAM,MAAM,OAAO,WAAW;AAG9B,MAAI,OAAO,MAAM,GAAG,GAAG;AACrB,UAAM,IAAI,MAAM,IAAI,WAAW,yBAAyB;AAAA,EAC1D;AAGA,MAAI,CAAC,OAAO,SAAS,GAAG,GAAG;AACzB,UAAM,IAAI,MAAM,IAAI,WAAW,0BAA0B;AAAA,EAC3D;AAGA,MAAI,CAAC,OAAO,UAAU,GAAG,GAAG;AAC1B,UAAM,IAAI,MAAM,IAAI,WAAW,qBAAqB;AAAA,EACtD;AAGA,MAAI,MAAM,GAAG;AACX,UAAM,IAAI,MAAM,IAAI,WAAW,iCAAiC;AAAA,EAClE;AAEA,SAAO;AACT;;;AC1CA,SAAS,iBAAAC,sBAAqB;;;ACQ9B,OAAOC,QAAO;;;ACFP,SAAS,SAAS,QAAkB,QAAkB;AAC3D,SAAO,OAAO,SAAS,OAAO,UAAU,OAAO,YAAY,OAAO;AACpE;AAMO,SAAS,UAAU,QAAkB,QAAkB;AAC5D,SAAO,OAAO,WAAW,OAAO,UAAU,OAAO,cAAc,OAAO;AACxE;AAMO,SAAS,kBAAkB,QAAkB,QAAkB;AACpE,SAAO,SAAS,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM;AAC7D;;;ACtBO,IAAM,yBAAyB;AAAA,EACpC,WAAW;AAAA,EACX,UAAU;AAAA,EACV,WAAW;AAAA,EACX,WAAW;AACb;AAQO,IAAM,2BAA2B;AAAA,EACtC,WAAW;AAAA,EACX,UAAU;AAAA,EACV,WAAW;AAAA,EACX,WAAW;AAAA,EACX,cAAc;AAChB;AAQO,IAAM,2BAA2B;AAAA,EACtC,YAAY;AAAA,EACZ,UAAU;AACZ;;;ACNO,SAAS,yBACd,QACgF;AAChF,QAAM,gBAAgB,OAAO,IAAI,CAAC,UAAU,MAAM,MAAM;AAExD,MAAI;AAEJ,MAAI,cAAc,KAAK,CAAC,gBAAgB,gBAAgB,uBAAuB,SAAS,GAAG;AACzF,oBAAgB,yBAAyB;AAAA,EAC3C,WAAW,cAAc,KAAK,CAAC,gBAAgB,gBAAgB,uBAAuB,QAAQ,GAAG;AAC/F,oBAAgB,yBAAyB;AAAA,EAC3C,WACE,cAAc,KAAK,CAAC,gBAAgB,gBAAgB,uBAAuB,SAAS,GACpF;AACA,oBAAgB,yBAAyB;AAAA,EAC3C,OAAO;AACL,oBAAgB,yBAAyB;AAAA,EAC3C;AAEA,SAAO;AACT;AAOO,SAAS,iCAAiC,QAAyC;AACxF,QAAM,+BAA+B,OAClC,OAAO,CAAC,UAAU,MAAM,WAAW,uBAAuB,SAAS,EACnE,IAAI,CAAC,UAAU,MAAM,sBAAsB;AAE9C,MAAI,6BAA6B,WAAW,GAAG;AAC7C,UAAM,IAAI;AAAA,MACR,+FAA+F,yBAAyB,SAAS;AAAA,IACnI;AAAA,EACF;AAEA,QAAM,yBAAyB,KAAK,IAAI,GAAG,4BAA4B;AAEvE,SAAO;AACT;AAMO,SAAS,yCACd,QACe;AACf,QAAM,+BAAgD,OAAO;AAAA,IAC3D,CAAC,UAAU,MAAM,OAAO,WAAW;AAAA,EACrC;AAEA,SAAO,KAAK,IAAI,GAAG,4BAA4B;AACjD;AAMO,SAAS,0CACd,QACe;AACf,QAAM,6BAA8C,CAAC;AAErD,aAAW,SAAS,QAAQ;AAC1B,YAAQ,MAAM,QAAQ;AAAA,MACpB,KAAK,uBAAuB;AAC1B,YAAI,MAAM,OAAO,UAAU;AACzB,qCAA2B,KAAK,MAAM,OAAO,SAAS,SAAS;AAAA,QACjE;AACA;AAAA,MAEF,KAAK,uBAAuB;AAC1B,mCAA2B,KAAK,MAAM,iBAAiB,SAAS;AAEhE;AAAA,MAEF,KAAK,uBAAuB;AAC1B,mCAA2B,KAAK,MAAM,mBAAmB,SAAS;AAClE;AAAA,MAEF,KAAK,uBAAuB;AAC1B,mCAA2B,KAAK,MAAM,iBAAiB,SAAS;AAChE;AAAA,IACJ;AAAA,EACF;AAEA,SAAO,KAAK,IAAI,GAAG,0BAA0B;AAC/C;AAMO,SAAS,2BAA2B,QAAoD;AAC7F,SAAO,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,UAAU,MAAM,mBAAmB,SAAS,CAAC;AAC9E;AAKO,SAAS,gBAAgB,QAA4D;AAC1F,SAAO,OAAO;AAAA,IACZ,CAAC,UACC,MAAM,WAAW,uBAAuB,YACxC,MAAM,WAAW,uBAAuB;AAAA,EAC5C;AACF;AAKO,SAAS,iBAAiB,QAA6D;AAC5F,SAAO,OAAO;AAAA,IACZ,CAAC,UACC,MAAM,WAAW,uBAAuB,aACxC,MAAM,WAAW,uBAAuB;AAAA,EAC5C;AACF;AAQO,SAAS,qBACd,YACA,UACqB;AACrB,MAAI,UAAU;AACZ,WAAO;AAAA,MACL,UAAU,yBAAyB;AAAA,MACnC;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,UAAU,yBAAyB;AAAA,IACnC;AAAA,IACA,UAAU;AAAA,EACZ;AACF;AAUO,SAAS,oDACd,QAC0C;AAC1C,SAAO,OAAO,MAAM,CAAC,UAAU,MAAM,WAAW,uBAAuB,SAAS;AAClF;AAYO,SAAS,mDACd,QACyD;AACzD,QAAM,gCAAgC,OAAO;AAAA,IAC3C,CAAC,UAAU,MAAM,WAAW,uBAAuB;AAAA,EACrD;AACA,QAAM,+BAA+B,OAAO;AAAA,IAC1C,CAAC,UACC,MAAM,WAAW,uBAAuB,aACxC,MAAM,WAAW,uBAAuB,YACxC,MAAM,WAAW,uBAAuB;AAAA,EAC5C;AAEA,SAAO,iCAAiC;AAC1C;AAUO,SAAS,oDACd,QAC0C;AAC1C,QAAM,6BAA6B,OAAO;AAAA,IACxC,CAAC,UAAU,MAAM,WAAW,uBAAuB;AAAA,EACrD;AAEA,SAAO;AACT;AAQO,SAAS,oDACd,QACiC;AACjC,QAAM,6BAA6B,OAAO;AAAA,IACxC,CAAC,UAAU,MAAM,WAAW,uBAAuB;AAAA,EACrD;AAEA,SAAO;AACT;AAMO,SAAS,iCACd,QAC8B;AAE9B,SAAO;AAAA,IACL,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,EAAE,MAAM,MACpB,OAAO,OAAO,WAAW,YAAY,OAAO,OAAO,WAAW;AAAA,EAClE;AAEA,SAAO;AACT;;;AHtNA,IAAM,gCAAgC,CAAC,aAAqB,YAC1DC,GAAE,mBAAmB,YAAY;AAAA,EAC/BA,GAAE,aAAa;AAAA,IACb,UAAUA,GAAE,QAAQ,yBAAyB,UAAU;AAAA,IACvD,YAAY,mBAAmB,UAAU;AAAA,IACzC,UAAUA,GAAE,KAAK;AAAA,EACnB,CAAC;AAAA,EACDA,GAAE,aAAa;AAAA,IACb,UAAUA,GAAE,QAAQ,yBAAyB,QAAQ;AAAA,IACrD,YAAY,mBAAmB,UAAU;AAAA,IACzC,UAAU,mBAAmB,UAAU;AAAA,EACzC,CAAC;AACH,CAAC;AAKI,IAAM,yCAAyC,CAAC,aAAqB,YAC1EA,GACG,aAAa;AAAA,EACZ,QAAQA,GAAE,QAAQ,uBAAuB,SAAS;AAAA,EAClD,QAAQ,8BAA8B,UAAU;AAClD,CAAC,EACA;AAAA,EACC,CAAC,EAAE,OAAO,MACR,OAAO,aAAa,QAAiB,kBAAkB,OAAO,YAAY,OAAO,QAAQ;AAAA,EAC3F;AAAA,IACE,OAAO;AAAA,EACT;AACF;AAKG,IAAM,wCAAwC,CAAC,aAAqB,YACzEA,GACG,aAAa;AAAA,EACZ,QAAQA,GAAE,QAAQ,uBAAuB,QAAQ;AAAA,EACjD,QAAQ,8BAA8B,UAAU;AAAA,EAChD,oBAAoB,mBAAmB,UAAU;AAAA,EACjD,mBAAmB,mBAAmB,UAAU;AAAA,EAChD,kBAAkB,mBAAmB,UAAU;AACjD,CAAC,EACA;AAAA,EACC,CAAC,EAAE,QAAQ,mBAAmB,MACnB,kBAAkB,OAAO,YAAY,kBAAkB;AAAA,EAClE;AAAA,IACE,OAAO;AAAA,EACT;AACF,EACC;AAAA,EACC,CAAC,EAAE,oBAAoB,kBAAkB,MAC9B,kBAAkB,oBAAoB,iBAAiB;AAAA,EAClE;AAAA,IACE,OAAO;AAAA,EACT;AACF,EACC;AAAA,EACC,CAAC,EAAE,mBAAmB,iBAAiB,MAC5B,kBAAkB,mBAAmB,gBAAgB;AAAA,EAChE;AAAA,IACE,OAAO;AAAA,EACT;AACF,EACC;AAAA,EACC,CAAC,EAAE,QAAQ,iBAAiB,MAC1B,OAAO,aAAa,QAAiB,UAAU,kBAAkB,OAAO,QAAQ;AAAA,EAClF;AAAA,IACE,OAAO;AAAA,EACT;AACF;AAKG,IAAM,yCAAyC,CAAC,aAAqB,YAC1EA,GACG,aAAa;AAAA,EACZ,QAAQA,GAAE,QAAQ,uBAAuB,SAAS;AAAA,EAClD,QAAQA,GAAE,aAAa;AAAA,IACrB,UAAUA,GAAE,QAAQ,yBAAyB,UAAU;AAAA,IACvD,YAAY,mBAAmB,UAAU;AAAA,EAC3C,CAAC;AAAA,EACD,oBAAoB,mBAAmB,UAAU;AAAA,EACjD,kBAAkB,mBAAmB,UAAU;AAAA,EAC/C,wBAAwB,mBAAmB,UAAU;AACvD,CAAC,EACA;AAAA,EACC,CAAC,EAAE,QAAQ,mBAAmB,MACnB,kBAAkB,OAAO,YAAY,kBAAkB;AAAA,EAClE;AAAA,IACE,OAAO;AAAA,EACT;AACF,EACC;AAAA,EACC,CAAC,EAAE,oBAAoB,iBAAiB,MAC7B,kBAAkB,oBAAoB,gBAAgB;AAAA,EACjE;AAAA,IACE,OAAO;AAAA,EACT;AACF;AAKG,IAAM,yCAAyC,CAAC,aAAqB,YAC1EA,GACG,aAAa;AAAA,EACZ,QAAQA,GAAE,QAAQ,uBAAuB,SAAS;AAAA,EAClD,QAAQA,GAAE,aAAa;AAAA,IACrB,UAAUA,GAAE,QAAQ,yBAAyB,QAAQ;AAAA,IACrD,YAAY,mBAAmB,UAAU;AAAA,IACzC,UAAU,mBAAmB,UAAU;AAAA,EACzC,CAAC;AAAA,EACD,oBAAoB,mBAAmB,UAAU;AACnD,CAAC,EACA;AAAA,EACC,CAAC,EAAE,QAAQ,mBAAmB,MACnB,kBAAkB,OAAO,YAAY,kBAAkB;AAAA,EAClE;AAAA,IACE,OAAO;AAAA,EACT;AACF,EACC;AAAA,EACC,CAAC,EAAE,QAAQ,mBAAmB,MACnB,kBAAkB,oBAAoB,OAAO,QAAQ;AAAA,EAChE;AAAA,IACE,OAAO;AAAA,EACT;AACF;AAKG,IAAM,gCAAgC,CAAC,aAAqB,YACjEA,GAAE,mBAAmB,UAAU;AAAA,EAC7B,uCAAuC,UAAU;AAAA,EACjD,sCAAsC,UAAU;AAAA,EAChD,uCAAuC,UAAU;AAAA,EACjD,uCAAuC,UAAU;AACnD,CAAC;AAKI,IAAM,kCAAkC,CAAC,aAAqB,YACnEA,GACG,OAAO,wBAAwB,GAAG,8BAA8B,UAAU,GAAG;AAAA,EAC5E,OAAO;AACT,CAAC,EACA,UAAU,CAAC,mCAAmC;AAC7C,QAAM,uBAAuB,oBAAI,IAAkC;AAEnE,aAAW,CAAC,eAAe,WAAW,KAAK,OAAO,QAAQ,8BAA8B,GAAG;AACzF,yBAAqB,IAAI,mBAAmB,aAAa,GAAG,WAAW;AAAA,EACzE;AAEA,SAAO;AACT,CAAC;AAKL,IAAM,mCAAmC,CAAC,eACxCA,GACG,aAAa;AAAA,EACZ,eAAeA,GAAE,QAAQ,yBAAyB,SAAS;AAAA,EAC3D,QAAQ,gCAAgC,UAAU,EAC/C;AAAA,IACC,CAAC,WACC,oDAAoD,MAAM,KAAK,OAAO,OAAO,CAAC,CAAC;AAAA,IACjF;AAAA,MACE,OAAO,GAAG,UAAU;AAAA;AAAA,IAEtB;AAAA,EACF,EACC,UAAU,CAAC,WAAW,MAAoD;AAC/E,CAAC,EACA;AAAA,EACC,CAAC,mBAAmB;AAClB,UAAM,SAAS,MAAM,KAAK,eAAe,OAAO,OAAO,CAAC;AAExD,WAAO,yBAAyB,MAAM,MAAM,eAAe;AAAA,EAC7D;AAAA,EACA,EAAE,OAAO,GAAG,UAAU,gCAAgC;AACxD;AAKJ,IAAM,kCAAkC,CAAC,eACvCA,GACG,aAAa;AAAA,EACZ,eAAeA,GAAE,QAAQ,yBAAyB,QAAQ;AAAA,EAC1D,QAAQ,gCAAgC,UAAU,EAC/C;AAAA,IACC,CAAC,WACC,mDAAmD,MAAM,KAAK,OAAO,OAAO,CAAC,CAAC;AAAA,IAChF;AAAA,MACE,OAAO,GAAG,UAAU;AAAA;AAAA,IAEtB;AAAA,EACF,EACC,UAAU,CAAC,WAAW,MAAmE;AAAA,EAC5F,yBAAyB,wBAAwB,UAAU;AAC7D,CAAC,EACA;AAAA,EACC,CAAC,mBAAmB;AAClB,UAAM,SAAS,MAAM,KAAK,eAAe,OAAO,OAAO,CAAC;AAExD,WAAO,yBAAyB,MAAM,MAAM,eAAe;AAAA,EAC7D;AAAA,EACA,EAAE,OAAO,GAAG,UAAU,gCAAgC;AACxD,EACC;AAAA,EACC,CAAC,mBAAmB;AAClB,UAAM,SAAS,MAAM,KAAK,eAAe,OAAO,OAAO,CAAC;AAExD,UAAM,0BAA0B,iBAAiB,MAAM,EAAE;AAAA,MACvD,CAAC,UAAU,MAAM,OAAO,WAAW;AAAA,IACrC;AAEA,UAAM,kCAAkC,KAAK,IAAI,GAAG,uBAAuB;AAE3E,WAAO,eAAe,2BAA2B;AAAA,EACnD;AAAA,EACA;AAAA,IACE,OACE;AAAA,EACJ;AACF;AAKJ,IAAM,mCAAmC,CAAC,eACxCA,GACG,aAAa;AAAA,EACZ,eAAeA,GAAE,QAAQ,yBAAyB,SAAS;AAAA,EAC3D,QAAQ,gCAAgC,UAAU,EAC/C;AAAA,IACC,CAAC,WACC,oDAAoD,MAAM,KAAK,OAAO,OAAO,CAAC,CAAC;AAAA,IACjF;AAAA,MACE,OAAO,GAAG,UAAU;AAAA,IACtB;AAAA,EACF,EACC,UAAU,CAAC,WAAW,MAAoD;AAC/E,CAAC,EACA;AAAA,EACC,CAAC,mBAAmB;AAClB,UAAM,SAAS,MAAM,KAAK,eAAe,OAAO,OAAO,CAAC;AAExD,WAAO,yBAAyB,MAAM,MAAM,eAAe;AAAA,EAC7D;AAAA,EACA,EAAE,OAAO,GAAG,UAAU,gCAAgC;AACxD;AAKJ,IAAM,mCAAmC,CAAC,eACxCA,GACG,aAAa;AAAA,EACZ,eAAeA,GAAE,QAAQ,yBAAyB,SAAS;AAAA,EAC3D,QAAQ,gCAAgC,UAAU;AAAA,EAClD,+BAA+B,mBAAmB,UAAU;AAAA,EAC5D,yBAAyB,wBAAwB,UAAU;AAC7D,CAAC,EACA;AAAA,EACC,CAAC,mBAAmB;AAClB,UAAM,SAAS,MAAM,KAAK,eAAe,OAAO,OAAO,CAAC;AAExD,WAAO,yBAAyB,MAAM,MAAM,eAAe;AAAA,EAC7D;AAAA,EACA,EAAE,OAAO,GAAG,UAAU,gCAAgC;AACxD,EACC;AAAA,EACC,CAAC,mBACC;AAAA,IACE,MAAM,KAAK,eAAe,OAAO,OAAO,CAAC;AAAA,EAC3C;AAAA,EACF;AAAA,IACE,OAAO,GAAG,UAAU;AAAA,EACtB;AACF,EACC;AAAA,EACC,CAAC,mBAAmB;AAClB,UAAM,SAAS,MAAM,KAAK,eAAe,OAAO,OAAO,CAAC;AAExD,WACE,iCAAiC,MAAM,MAAM,eAAe;AAAA,EAEhE;AAAA,EACA,EAAE,OAAO,GAAG,UAAU,gDAAgD;AACxE,EACC;AAAA,EACC,CAAC,mBAAmB;AAClB,UAAM,SAAS,MAAM,KAAK,eAAe,OAAO,OAAO,CAAC;AAExD,UAAM,0BAA0B,iBAAiB,MAAM,EAAE;AAAA,MACvD,CAAC,UAAU,MAAM,OAAO,WAAW;AAAA,IACrC;AAEA,UAAM,kCAAkC,KAAK,IAAI,GAAG,uBAAuB;AAE3E,WAAO,eAAe,2BAA2B;AAAA,EACnD;AAAA,EACA;AAAA,IACE,OACE;AAAA,EACJ;AACF;AAKJ,IAAM,qCAAqC,CAAC,eAC1CA,GAAE,aAAa;AAAA,EACb,eAAeA,GAAE,QAAQ,yBAAyB,YAAY;AAChE,CAAC;AAQI,IAAM,qCAAqC,CAChD,aAAqB,+BAErBA,GAAE,mBAAmB,iBAAiB;AAAA,EACpC,iCAAiC,UAAU;AAAA,EAC3C,gCAAgC,UAAU;AAAA,EAC1C,iCAAiC,UAAU;AAAA,EAC3C,iCAAiC,UAAU;AAAA,EAC3C,mCAAmC,UAAU;AAC/C,CAAC;;;ADxXI,SAAS,oCACd,aACA,YACiC;AACjC,QAAM,SAAS,mCAAmC,UAAU;AAC5D,QAAM,SAAS,OAAO,UAAU,WAAW;AAE3C,MAAI,OAAO,OAAO;AAChB,UAAM,IAAI;AAAA,MACR;AAAA,EAAiDC,eAAc,OAAO,KAAK,CAAC;AAAA;AAAA,IAC9E;AAAA,EACF;AAEA,SAAO,OAAO;AAChB;;;AKJO,SAAS,+BACd,uBACgD;AAChD,QAAM,mCAAmF,CAAC;AAE1F,aAAW,CAAC,SAAS,mBAAmB,KAAK,sBAAsB,QAAQ,GAAG;AAC5E,qCAAiC,iBAAiB,OAAO,CAAC,IAAI;AAAA,EAChE;AAEA,SAAO;AACT;AAKO,SAAS,kCACd,gBAC2C;AAC3C,UAAQ,eAAe,eAAe;AAAA,IACpC,KAAK,yBAAyB;AAC5B,aAAO;AAAA,QACL,eAAe,yBAAyB;AAAA,MAC1C;AAAA,IAEF,KAAK,yBAAyB;AAC5B,aAAO;AAAA,QACL,eAAe,yBAAyB;AAAA,QACxC,QAAQ,+BAA+B,eAAe,MAAM;AAAA,MAC9D;AAAA,IAEF,KAAK,yBAAyB;AAC5B,aAAO;AAAA,QACL,eAAe,yBAAyB;AAAA,QACxC,QAAQ,+BAA+B,eAAe,MAAM;AAAA,QAC5D,yBAAyB,eAAe;AAAA,MAC1C;AAAA,IAEF,KAAK,yBAAyB,WAAW;AACvC,aAAO;AAAA,QACL,eAAe,yBAAyB;AAAA,QACxC,QAAQ,+BAA+B,eAAe,MAAM;AAAA,MAC9D;AAAA,IACF;AAAA,IAEA,KAAK,yBAAyB;AAC5B,aAAO;AAAA,QACL,eAAe,yBAAyB;AAAA,QACxC,QAAQ,+BAA+B,eAAe,MAAM;AAAA,QAC5D,+BAA+B,eAAe;AAAA,QAC9C,yBAAyB,eAAe;AAAA,MAC1C;AAAA,EACJ;AACF;;;ACnEO,IAAK,uBAAL,kBAAKC,0BAAL;AACL,EAAAA,sBAAA,uBAAoB;AACpB,EAAAA,sBAAA,uBAAoB;AAFV,SAAAA;AAAA,GAAA;AAQL,IAAK,gCAAL,kBAAKC,mCAAL;AACL,EAAAA,+BAAA,eAAY;AACZ,EAAAA,+BAAA,kBAAe;AACf,EAAAA,+BAAA,0BAAuB;AACvB,EAAAA,+BAAA,sCAAmC;AACnC,EAAAA,+BAAA,2CAAwC;AACxC,EAAAA,+BAAA,0CAAuC;AACvC,EAAAA,+BAAA,qBAAkB;AAClB,EAAAA,+BAAA,yBAAsB;AARZ,SAAAA;AAAA,GAAA;AAcL,IAAK,gCAAL,kBAAKC,mCAAL;AACL,EAAAA,+BAAA,eAAY;AACZ,EAAAA,+BAAA,wBAAqB;AACrB,EAAAA,+BAAA,sBAAmB;AACnB,EAAAA,+BAAA,iCAA8B;AAC9B,EAAAA,+BAAA,yCAAsC;AAL5B,SAAAA;AAAA,GAAA;AAQL,IAAM,4BAA4B;AAClC,IAAM,qBAAqB,GAAG,yBAAyB;AACvD,IAAM,qBAAqB,GAAG,yBAAyB;AACvD,IAAM,4BAA4B,GAAG,yBAAyB;;;ACpCrE,SAAS,iBAAAC,sBAAqB;;;ACA9B,OAAOC,QAAO;AAEP,IAAM,sBAAsBA,GAAE,OAAO;AAAA,EAC1C,SAASA,GAAE,OAAO;AAAA,EAClB,SAASA,GAAE,SAASA,GAAE,QAAQ,CAAC;AACjC,CAAC;;;ADDM,SAAS,yBAAyB,oBAA4C;AACnF,QAAM,SAAS,oBAAoB,UAAU,kBAAkB;AAE/D,MAAI,OAAO,OAAO;AAChB,UAAM,IAAI,MAAM;AAAA,EAAsCC,eAAc,OAAO,KAAK,CAAC;AAAA,CAAI;AAAA,EACvF;AAEA,SAAO,OAAO;AAChB;;;AEoGO,IAAM,8BAA8B;AAAA,EACzC,cAAc;AAAA,EACd,mCAAmC;AACrC;;;ACjHO,IAAM,cAAN,MAAM,qBAAoB,MAAM;AAAA,EACrC;AAAA,EAEA,YAAY,SAAiB,SAAmB;AAC9C,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,OAAO,kBAAkB,EAAE,SAAS,QAAQ,GAAkB;AAC5D,WAAO,IAAI,aAAY,SAAS,OAAO;AAAA,EACzC;AACF;;;ACYO,IAAM,0BAA0B;AAsChC,IAAM,gBAAN,MAAM,eAAc;AAAA,EACR;AAAA,EAEjB,OAAO,iBAAgC;AACrC,WAAO;AAAA,MACL,KAAK,IAAI,IAAI,uBAAuB;AAAA,IACtC;AAAA,EACF;AAAA,EAEA,YAAY,UAAkC,CAAC,GAAG;AAChD,SAAK,UAAU;AAAA,MACb,GAAG,eAAc,eAAe;AAAA,MAChC,GAAG;AAAA,IACL;AAAA,EACF;AAAA,EAEA,aAAsC;AACpC,WAAO,OAAO,OAAO;AAAA,MACnB,KAAK,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI;AAAA,IACpC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmCA,MAAM,eACJ,MACA,WACA,SAC4C;AAC5C,UAAM,MAAM,IAAI,IAAI,wBAAwB,mBAAmB,IAAI,CAAC,IAAI,KAAK,QAAQ,GAAG;AAGxF,QAAI,UAAU,MAAM;AAClB,UAAI,aAAa,IAAI,QAAQ,MAAM;AAAA,IACrC;AAEA,QAAI,UAAU,aAAa,UAAU,UAAU,SAAS,GAAG;AACzD,UAAI,aAAa,IAAI,aAAa,UAAU,UAAU,KAAK,GAAG,CAAC;AAAA,IACjE;AAEA,QAAI,UAAU,SAAS,UAAU,MAAM,SAAS,GAAG;AACjD,UAAI,aAAa,IAAI,SAAS,UAAU,MAAM,KAAK,GAAG,CAAC;AAAA,IACzD;AAEA,QAAI,SAAS,MAAO,KAAI,aAAa,IAAI,SAAS,MAAM;AACxD,QAAI,SAAS,WAAY,KAAI,aAAa,IAAI,cAAc,MAAM;AAElE,UAAM,WAAW,MAAM,MAAM,GAAG;AAEhC,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,QAAS,MAAM,SAAS,KAAK;AACnC,YAAM,YAAY,kBAAkB,KAAK;AAAA,IAC3C;AAEA,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmCA,MAAM,mBACJ,SACA,SACA,SACqC;AACrC,UAAM,MAAM,IAAI,IAAI,6BAA6B,OAAO,IAAI,OAAO,IAAI,KAAK,QAAQ,GAAG;AAEvF,QAAI,SAAS,MAAO,KAAI,aAAa,IAAI,SAAS,MAAM;AACxD,QAAI,SAAS,WAAY,KAAI,aAAa,IAAI,cAAc,MAAM;AAElE,UAAM,WAAW,MAAM,MAAM,GAAG;AAEhC,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,QAAS,MAAM,SAAS,KAAK;AACnC,YAAM,YAAY,kBAAkB,KAAK;AAAA,IAC3C;AAEA,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA+CA,MAAM,oBACJ,SACA,SACsC;AACtC,UAAM,MAAM,IAAI,IAAI,8BAA8B,OAAO,IAAI,KAAK,QAAQ,GAAG;AAE7E,QAAI,SAAS,SAAU,KAAI,aAAa,IAAI,YAAY,QAAQ,SAAS,KAAK,GAAG,CAAC;AAClF,QAAI,SAAS,MAAO,KAAI,aAAa,IAAI,SAAS,MAAM;AACxD,QAAI,SAAS,WAAY,KAAI,aAAa,IAAI,cAAc,MAAM;AAElE,UAAM,WAAW,MAAM,MAAM,GAAG;AAEhC,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,QAAS,MAAM,SAAS,KAAK;AACnC,YAAM,YAAY,kBAAkB,KAAK;AAAA,IAC3C;AAEA,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,SAAkC;AACtC,UAAM,MAAM,IAAI,IAAI,eAAe,KAAK,QAAQ,GAAG;AAEnD,UAAM,WAAW,MAAM,MAAM,GAAG;AAEhC,QAAI;AAIJ,QAAI;AACF,qBAAe,MAAM,SAAS,KAAK;AAAA,IACrC,QAAQ;AACN,YAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AAEA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,gBAAgB,yBAAyB,YAAY;AAC3D,YAAM,IAAI,MAAM,mCAAmC,cAAc,OAAO,EAAE;AAAA,IAC5E;AAEA,WAAO,kCAAkC,YAAgD;AAAA,EAC3F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,MAAM,eAAe,SAAkE;AACrF,UAAM,MAAM,IAAI,IAAI,wBAAwB,KAAK,QAAQ,GAAG;AAE5D,QAAI,OAAO,SAAS,wBAAwB,aAAa;AACvD,UAAI,aAAa,IAAI,uBAAuB,GAAG,QAAQ,mBAAmB,EAAE;AAAA,IAC9E;AAEA,UAAM,WAAW,MAAM,MAAM,GAAG;AAEhC,QAAI;AAIJ,QAAI;AACF,qBAAe,MAAM,SAAS,KAAK;AAAA,IACrC,QAAQ;AACN,YAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AAGA,QAAI,CAAC,SAAS,IAAI;AAChB,cAAQ,SAAS,QAAQ;AAAA,QACvB,KAAK,4BAA4B,cAAc;AAC7C,kBAAQ,MAAM,oCAAoC;AAClD,iBAAO;AAAA,YACL;AAAA,UACF;AAAA,QACF;AAAA,QAEA,KAAK,4BAA4B,mCAAmC;AAClE,kBAAQ;AAAA,YACN;AAAA,UACF;AACA,iBAAO;AAAA,YACL;AAAA,UACF;AAAA,QACF;AAAA,QAEA,SAAS;AACP,gBAAM,gBAAgB,yBAAyB,YAAY;AAC3D,gBAAM,IAAI,MAAM,4CAA4C,cAAc,OAAO,EAAE;AAAA,QACrF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,IACF;AAAA,EACF;AACF;;;AC7VO,IAAM,mBAAmB,CAAC,cAC/B,CAAC,UAAU,QAAQ,CAAC,UAAU,WAAW,UAAU,CAAC,UAAU,OAAO;;;AC5BvE;AAAA,EACE;AAAA,EAEA,mBAAAC;AAAA,EACA;AAAA,OACK;AAKP,IAAM,+BAA+B,CAAC,cACpC;AAAA,EACE;AAAA,IACE,mBAAmB,WAAW,gBAAgB,mBAAmB;AAAA,IACjE,mBAAmB,WAAW,gBAAgB,oBAAoB;AAAA,IAClE,mBAAmB,WAAW,gBAAgB,uBAAuB;AAAA,IACrE,mBAAmB,WAAW,gBAAgB,uBAAuB;AAAA,IACrE,mBAAmB,WAAW,gBAAgB,qBAAqB;AAAA,EACrE,EACG,OAAO,CAAC,OAAO,OAAO,MAAS,EAC/B,IAAI,CAAC,OAAO,GAAG,MAAM,EAAE;AAC5B,EAAE,IAAI,oBAAoB;AAE5B,IAAM,QAAQ;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,0BAA0B;AAAA,EACrC,CAACC,iBAAgB,OAAO,GAAG;AAAA,IACzB,WAAW,CAAC,eAAe,GAAG,6BAA6BA,iBAAgB,OAAO,CAAC;AAAA,IACnF,OAAO;AAAA,EACT;AAAA,EACA,CAACA,iBAAgB,OAAO,GAAG;AAAA,IACzB,WAAW,CAAC,eAAe,GAAG,6BAA6BA,iBAAgB,OAAO,CAAC;AAAA,IACnF,OAAO;AAAA,EACT;AAAA,EACA,CAACA,iBAAgB,OAAO,GAAG;AAAA,IACzB,WAAW,CAAC,eAAe,GAAG,6BAA6BA,iBAAgB,OAAO,CAAC;AAAA,IACnF,OAAO;AAAA,EACT;AAAA,EACA,CAACA,iBAAgB,UAAU,GAAG;AAAA,IAC5B,WAAW,CAAC,eAAe,GAAG,6BAA6BA,iBAAgB,UAAU,CAAC;AAAA,IACtF,OAAO;AAAA,EACT;AACF;","names":["prettifyError","z","labelhash","labelhash","PluginName","z","prettifyError","isSubgraphCompatible","prettifyError","z","z","prettifyError","TraceableENSProtocol","ForwardResolutionProtocolStep","ReverseResolutionProtocolStep","prettifyError","z","prettifyError","ENSNamespaceIds","ENSNamespaceIds"]}
1
+ {"version":3,"sources":["../src/ens/constants.ts","../src/ens/subname-helpers.ts","../src/ens/coin-type.ts","../src/ens/names.ts","../src/ens/is-normalized.ts","../src/ens/reverse-name.ts","../src/ens/types.ts","../src/ens/parse-reverse-name.ts","../src/shared/address.ts","../src/shared/cache.ts","../src/shared/collections.ts","../src/shared/serialize.ts","../src/shared/deserialize.ts","../src/shared/zod-schemas.ts","../src/shared/account-id.ts","../src/shared/labelhash.ts","../src/shared/interpretation.ts","../src/shared/url.ts","../src/ens/encode-labelhash.ts","../src/ens/dns-encoded-name.ts","../src/ens/index.ts","../src/ensindexer/config/deserialize.ts","../src/ensindexer/config/zod-schemas.ts","../src/ensindexer/config/helpers.ts","../src/ensindexer/config/types.ts","../src/ensindexer/config/validations.ts","../src/ensindexer/config/serialize.ts","../src/ensindexer/config/labelset-utils.ts","../src/ensindexer/config/label-utils.ts","../src/ensindexer/config/parsing.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/tracing/index.ts","../src/api/deserialize.ts","../src/api/zod-schemas.ts","../src/api/types.ts","../src/api/serialize.ts","../src/client-error.ts","../src/client.ts","../src/resolution/resolver-records-selection.ts","../src/resolution/types.ts","../src/resolution/default-records-selection.ts","../src/resolution/ensip19-chainid.ts","../src/resolution/identity.ts"],"sourcesContent":["import { namehash } 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","import { Hex, concat, 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 { CoinType, EvmCoinType } from \"@ensdomains/address-encoder\";\nimport {\n coinTypeToEvmChainId as _coinTypeToEvmChainId,\n evmChainIdToCoinType as _evmChainIdToCoinType,\n} from \"@ensdomains/address-encoder/utils\";\nimport { 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 { ens_beautify } from \"@adraffy/ens-normalize\";\nimport { isNormalizedLabel } from \"./is-normalized\";\nimport type { Label, Name, NormalizedName } from \"./types\";\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 * 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 { 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 { Address } from \"viem\";\n\nimport { 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 type { Hex } from \"viem\";\n\n// re-export ENSNamespaceIds and ENSNamespaceId from @ensnode/datasources\n// so consumers don't need it as a dependency\nexport { ENSNamespaceIds } from \"@ensnode/datasources\";\nexport type { ENSNamespaceId } 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 */\nexport type LabelHash = Hex;\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","import { Address, hexToBigInt, isAddress } from \"viem\";\nimport { asLowerCaseAddress } from \"../shared\";\nimport { CoinType, DEFAULT_EVM_COIN_TYPE, ETH_COIN_TYPE, bigintToCoinType } from \"./coin-type\";\nimport { 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, isAddress } 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","/**\n * Cache that maps from string -> ValueType.\n */\nexport interface Cache<KeyType extends string, ValueType> {\n /**\n * Store a value in the cache with the given key.\n *\n * @param key Cache key\n * @param value Value to store\n */\n set(key: KeyType, value: ValueType): void;\n\n /**\n * Retrieve a value from the cache with the given key.\n *\n * @param key Cache key\n * @returns The cached value if it exists, otherwise undefined\n */\n get(key: KeyType): ValueType | undefined;\n\n /**\n * Clear the cache.\n */\n clear(): void;\n\n /**\n * The current number of items in the cache. Always a non-negative integer.\n */\n get size(): number;\n\n /**\n * The maximum number of items in the cache. Always a non-negative integer that is >= size().\n */\n get capacity(): number;\n}\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","/**\n * Filter out duplicates.\n */\nexport const uniq = <T>(arr: T[]): T[] => [...new Set(arr)];\n","import type { ChainIdString, DatetimeISO8601, UrlString } from \"./serialized-types\";\nimport type { 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","import { prettifyError } from \"zod/v4\";\nimport type { ChainIdString, UrlString } from \"./serialized-types\";\nimport type { BlockNumber, BlockRef, Blockrange, ChainId, Datetime, Duration } from \"./types\";\nimport {\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: string, 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","import { type CoinType } from \"@ensdomains/address-encoder\";\nimport { type Address, isAddress } 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\";\nimport { ENSNamespaceIds } from \"../ens\";\nimport { asLowerCaseAddress } from \"./address\";\nimport type {\n BlockRef,\n ChainId,\n Datetime,\n DefaultableChainId,\n Duration,\n UnixTimestamp,\n} from \"./types\";\n\n/**\n * Zod `.check()` function input.\n */\nexport type ZodCheckFnInput<T> = z.core.ParsePayload<T>;\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 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 })\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\n/**\n * Parses a numeric value as a port number.\n */\nexport const makePortSchema = (valueLabel: string = \"Port\") =>\n makePositiveIntegerSchema(valueLabel).max(65535, {\n error: `${valueLabel} must be an integer between 1 and 65535.`,\n });\n","import { isAddressEqual } from \"viem\";\nimport { 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 { keccak256, stringToBytes } from \"viem\";\nimport { 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","import {\n type InterpretedLabel,\n InterpretedName,\n Label,\n type LiteralLabel,\n LiteralName,\n encodeLabelHash,\n isNormalizedLabel,\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","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 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","import { bytesToString, hexToBytes } from \"viem\";\n\nimport { 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","export * from \"./constants\";\nexport * from \"./subname-helpers\";\nexport * from \"./coin-type\";\nexport * from \"./names\";\nexport * from \"./reverse-name\";\nexport * from \"./types\";\nexport * from \"./parse-reverse-name\";\nexport * from \"./is-normalized\";\nexport * from \"./encode-labelhash\";\nexport * from \"./dns-encoded-name\";\nexport { getENSRootChainId } from \"@ensnode/datasources\";\n","import { prettifyError } from \"zod/v4\";\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","/**\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\";\nimport { uniq } from \"../../shared\";\nimport {\n ZodCheckFnInput,\n makeChainIdSchema,\n makeENSNamespaceIdSchema,\n makeNonNegativeIntegerSchema,\n makePositiveIntegerSchema,\n makeUrlSchema,\n} from \"../../shared/zod-schemas\";\nimport { isSubgraphCompatible } from \"./helpers\";\nimport { PluginName } from \"./types\";\nimport type { ENSIndexerPublicConfig } 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 { ENSNamespaceIds } from \"@ensnode/datasources\";\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 { ENSNamespaceId } from \"@ensnode/datasources\";\n\nimport type { EnsRainbowClientLabelSet } from \"../../ensrainbow\";\nimport { 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 Referrals = \"referrals\",\n TokenScope = \"tokenscope\",\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-schemas\";\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 { ChainId } from \"../../shared\";\nimport { SerializedENSIndexerPublicConfig, SerializedIndexedChainIds } from \"./serialized-types\";\nimport { 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 {\n type EnsRainbowClientLabelSet,\n type EnsRainbowServerLabelSet,\n type LabelSetId,\n type 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","import { ByteArray, hexToBytes } from \"viem\";\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","/**\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 { prettifyError } from \"zod/v4\";\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\";\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 ChainIndexingStatusSnapshot,\n ChainIndexingStatusSnapshotBackfill,\n ChainIndexingStatusSnapshotCompleted,\n ChainIndexingStatusSnapshotFollowing,\n ChainIndexingStatusSnapshotForOmnichainIndexingStatusSnapshotBackfill,\n 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 * A {@link BlockRef} to the block where indexing of the chain should end.\n */\n endBlock?: null;\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 { BlockRef, ChainId, UnixTimestamp } from \"../../shared\";\nimport {\n ChainIndexingConfig,\n ChainIndexingConfigDefinite,\n ChainIndexingConfigIndefinite,\n ChainIndexingConfigTypeIds,\n ChainIndexingStatusIds,\n ChainIndexingStatusSnapshot,\n ChainIndexingStatusSnapshotCompleted,\n ChainIndexingStatusSnapshotForOmnichainIndexingStatusSnapshotBackfill,\n ChainIndexingStatusSnapshotQueued,\n 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 (chain.config.endBlock) {\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","import type { ParsePayload } from \"zod/v4/core\";\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 ChainIndexingStatusSnapshot,\n ChainIndexingStatusSnapshotBackfill,\n ChainIndexingStatusSnapshotCompleted,\n ChainIndexingStatusSnapshotFollowing,\n ChainIndexingStatusSnapshotQueued,\n CrossChainIndexingStatusSnapshotOmnichain,\n type OmnichainIndexingStatusSnapshot,\n OmnichainIndexingStatusSnapshotFollowing,\n 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 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 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 .filter((chain) => chain.config.configType === ChainIndexingConfigTypeIds.Definite)\n .map((chain) => chain.config.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' 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 { ChainId, ChainIdString, serializeChainId } from \"../../shared\";\nimport {\n SerializedCrossChainIndexingStatusSnapshot,\n SerializedCurrentIndexingProjectionOmnichain,\n SerializedOmnichainIndexingStatusSnapshot,\n SerializedOmnichainIndexingStatusSnapshotBackfill,\n SerializedOmnichainIndexingStatusSnapshotCompleted,\n SerializedOmnichainIndexingStatusSnapshotFollowing,\n SerializedOmnichainIndexingStatusSnapshotUnstarted,\n SerializedRealtimeIndexingStatusProjection,\n} from \"./serialized-types\";\nimport {\n ChainIndexingStatusSnapshot,\n CrossChainIndexingStatusSnapshot,\n OmnichainIndexingStatusIds,\n OmnichainIndexingStatusSnapshot,\n 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","/**\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\nexport 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\ninterface SpanAttributes {\n [key: string]: unknown;\n}\n\ninterface SpanEvent {\n name: string;\n attributes: SpanAttributes;\n time: number;\n}\n\nexport interface ProtocolSpan {\n scope: string;\n id: string;\n traceId: string;\n parentSpanContext:\n | {\n traceId: string;\n spanId: string;\n }\n | undefined;\n name: string;\n timestamp: number;\n duration: number;\n attributes: SpanAttributes;\n status: { code: number; message?: string };\n events: SpanEvent[];\n}\n\nexport type ProtocolSpanTreeNode = ProtocolSpan & { children: ProtocolSpanTreeNode[] };\nexport type ProtocolTrace = ProtocolSpanTreeNode[];\n","import { prettifyError } from \"zod/v4\";\nimport { SerializedIndexingStatusResponse } from \"./serialized-types\";\nimport type { ErrorResponse, IndexingStatusResponse } from \"./types\";\nimport { ErrorResponseSchema, makeIndexingStatusResponseSchema } from \"./zod-schemas\";\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\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\";\nimport { makeRealtimeIndexingStatusProjectionSchema } from \"../ensindexer/indexing-status/zod-schemas\";\nimport {\n type IndexingStatusResponse,\n IndexingStatusResponseCodes,\n type IndexingStatusResponseError,\n type IndexingStatusResponseOk,\n} from \"./types\";\n\nexport const ErrorResponseSchema = z.object({\n message: z.string(),\n details: z.optional(z.unknown()),\n});\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 { ENSIndexerPublicConfig, RealtimeIndexingStatusProjection } from \"../ensindexer\";\nimport type {\n ForwardResolutionArgs,\n MultichainPrimaryNameResolutionArgs,\n MultichainPrimaryNameResolutionResult,\n ResolverRecordsResponse,\n ResolverRecordsSelection,\n ReverseResolutionArgs,\n ReverseResolutionResult,\n} from \"../resolution\";\nimport type { ProtocolTrace } from \"../tracing\";\n\n/**\n * API Error Response Type\n */\nexport interface ErrorResponse {\n message: string;\n details?: unknown; // subject to change\n}\n\nexport interface TraceableRequest {\n trace?: boolean;\n}\n\nexport interface TraceableResponse {\n trace?: ProtocolTrace;\n}\n\nexport interface AcceleratableRequest {\n accelerate?: boolean;\n}\n\nexport interface AcceleratableResponse {\n accelerationAttempted: boolean;\n}\n\n/**\n * Resolve Records Request Type\n */\nexport interface ResolveRecordsRequest<SELECTION extends ResolverRecordsSelection>\n extends ForwardResolutionArgs<SELECTION>,\n AcceleratableRequest,\n TraceableRequest {}\n\n/**\n * Resolve Records Response Type\n */\nexport interface ResolveRecordsResponse<SELECTION extends ResolverRecordsSelection>\n extends AcceleratableResponse,\n TraceableResponse {\n records: ResolverRecordsResponse<SELECTION>;\n}\n\n/**\n * Resolve Primary Name Request Type\n */\nexport interface ResolvePrimaryNameRequest\n extends ReverseResolutionArgs,\n AcceleratableRequest,\n TraceableRequest {}\n\n/**\n * Resolve Primary Name Response Type\n */\nexport interface ResolvePrimaryNameResponse extends AcceleratableResponse, TraceableResponse {\n name: ReverseResolutionResult;\n}\n\nexport interface ResolvePrimaryNamesRequest\n extends MultichainPrimaryNameResolutionArgs,\n AcceleratableRequest,\n TraceableRequest {}\n\nexport interface ResolvePrimaryNamesResponse extends AcceleratableResponse, TraceableResponse {\n names: MultichainPrimaryNameResolutionResult;\n}\n\n/**\n * ENSIndexer Public Config Response\n */\nexport type ConfigResponse = ENSIndexerPublicConfig;\n\n/**\n * Represents a request to Indexing Status API.\n */\nexport type IndexingStatusRequest = {};\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 {\n SerializedIndexingStatusResponse,\n SerializedIndexingStatusResponseOk,\n} from \"./serialized-types\";\nimport { type IndexingStatusResponse, IndexingStatusResponseCodes } from \"./types\";\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 { 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 {\n SerializedIndexingStatusResponse,\n deserializeErrorResponse,\n deserializeIndexingStatusResponse,\n} from \"./api\";\nimport {\n type ConfigResponse,\n type ErrorResponse,\n type IndexingStatusResponse,\n IndexingStatusResponseCodes,\n type ResolvePrimaryNameRequest,\n type ResolvePrimaryNameResponse,\n type ResolvePrimaryNamesRequest,\n type ResolvePrimaryNamesResponse,\n type ResolveRecordsRequest,\n type ResolveRecordsResponse,\n} from \"./api/types\";\nimport { ClientError } from \"./client-error\";\nimport {\n RealtimeIndexingStatusProjection,\n type SerializedENSIndexerPublicConfig,\n SerializedRealtimeIndexingStatusProjection,\n deserializeENSIndexerPublicConfig,\n deserializeRealtimeIndexingStatusProjection,\n} from \"./ensindexer\";\nimport { 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 * - 🚧 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 let responseData: unknown;\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 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 deserializeENSIndexerPublicConfig(responseData as SerializedENSIndexerPublicConfig);\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 let responseData: unknown;\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 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 let errorResponse: ErrorResponse | undefined;\n\n // check for a generic errorResponse\n try {\n errorResponse = deserializeErrorResponse(responseData);\n } catch {\n // if errorResponse is 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","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","import { Address } from \"viem\";\n\nimport type { Name } from \"../ens\";\nimport { ChainId, DefaultableChainId } from \"../shared\";\nimport { ResolverRecordsResponse } from \"./resolver-records-response\";\nimport type { ResolverRecordsSelection } from \"./resolver-records-selection\";\n\n/**\n * Arguments required to perform Forward Resolution\n */\nexport interface ForwardResolutionArgs<SELECTION extends ResolverRecordsSelection> {\n name: Name;\n selection: SELECTION;\n}\n\n/**\n * The result of performing ForwardResolution\n */\nexport type ForwardResolutionResult<SELECTION extends ResolverRecordsSelection> =\n ResolverRecordsResponse<SELECTION>;\n\n/**\n * Arguments required to perform Reverse Resolution\n */\nexport interface ReverseResolutionArgs {\n address: Address;\n chainId: ChainId;\n}\n\n/**\n * The result of performing ReverseResolution\n */\nexport type ReverseResolutionResult = Name | null;\n\n/**\n * Arguments required to perform Multichain Primary Name Resolution\n */\nexport interface MultichainPrimaryNameResolutionArgs {\n address: Address;\n chainIds?: ChainId[];\n}\n\n/**\n * The result of performing MultichainPrimaryNameResolution\n */\nexport type MultichainPrimaryNameResolutionResult = Record<ChainId, Name | null>;\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 {\n DatasourceNames,\n ENSNamespaceId,\n ENSNamespaceIds,\n maybeGetDatasource,\n} from \"@ensnode/datasources\";\nimport { CoinType, ETH_COIN_TYPE, evmChainIdToCoinType } from \"../ens\";\nimport { uniq } from \"../shared\";\nimport type { ResolverRecordsSelection } from \"./resolver-records-selection\";\n\nconst getENSIP19SupportedCoinTypes = (namespace: ENSNamespaceId) =>\n uniq(\n [\n maybeGetDatasource(namespace, DatasourceNames.ReverseResolverBase),\n maybeGetDatasource(namespace, DatasourceNames.ReverseResolverLinea),\n maybeGetDatasource(namespace, DatasourceNames.ReverseResolverOptimism),\n maybeGetDatasource(namespace, DatasourceNames.ReverseResolverArbitrum),\n maybeGetDatasource(namespace, DatasourceNames.ReverseResolverScroll),\n ]\n .filter((ds) => ds !== undefined)\n .map((ds) => ds.chain.id),\n ).map(evmChainIdToCoinType);\n\nexport const getCommonCoinTypes = (namespace: ENSNamespaceId): CoinType[] => {\n return [ETH_COIN_TYPE, ...getENSIP19SupportedCoinTypes(namespace)];\n};\n\nconst TEXTS = [\n \"url\",\n \"avatar\",\n \"header\",\n \"description\",\n \"email\",\n \"com.twitter\",\n \"com.farcaster\",\n \"com.github\",\n] as const satisfies string[];\n\n// TODO: Phase out this concept. All apps should define their own selection of records.\n// Additionally, we should update `useRecords` so that it can return not only all the\n// (texts / addresses) records that are explicitly requested, but also any other (texts / addresses)\n// records that ENSNode has found onchain.\n// see: https://github.com/namehash/ensnode/issues/1084\nexport const DefaultRecordsSelection = {\n [ENSNamespaceIds.Mainnet]: {\n addresses: getCommonCoinTypes(ENSNamespaceIds.Mainnet),\n texts: TEXTS,\n },\n [ENSNamespaceIds.Sepolia]: {\n addresses: getCommonCoinTypes(ENSNamespaceIds.Sepolia),\n texts: TEXTS,\n },\n [ENSNamespaceIds.Holesky]: {\n addresses: getCommonCoinTypes(ENSNamespaceIds.Holesky),\n texts: TEXTS,\n },\n [ENSNamespaceIds.EnsTestEnv]: {\n addresses: getCommonCoinTypes(ENSNamespaceIds.EnsTestEnv),\n texts: TEXTS,\n },\n} as const satisfies Record<ENSNamespaceId, ResolverRecordsSelection>;\n","import { ENSNamespaceId, getENSRootChainId } from \"@ensnode/datasources\";\nimport { mainnet } from \"viem/chains\";\nimport { DEFAULT_EVM_CHAIN_ID } from \"../ens\";\nimport { 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 { ENSNamespaceId, getENSRootChainId } from \"@ensnode/datasources\";\nimport { Address } from \"viem\";\nimport { DefaultableChainId } from \"../shared\";\nimport { Identity, ResolutionStatusIds, ResolvedIdentity, UnresolvedIdentity } 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"],"mappings":"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","names":["isAddress","keccak256","isAddress","prettifyError","z","ENSNamespaceIds","PluginName","ENSNamespaceIds","z","prettifyError","isSubgraphCompatible","hexToBytes","prettifyError","z","z","prettifyError","TraceableENSProtocol","ForwardResolutionProtocolStep","ReverseResolutionProtocolStep","prettifyError","z","z","prettifyError","ENSNamespaceIds","ENSNamespaceIds","getENSRootChainId","getENSRootChainId","getENSRootChainId","getENSRootChainId"]}