@ensnode/ensnode-sdk 0.31.0 → 0.32.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/README.md +150 -3
- package/dist/index.d.ts +1261 -46
- package/dist/index.js +1077 -48
- package/dist/index.js.map +1 -1
- package/package.json +7 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/constants.ts","../src/utils/types.ts","../src/utils/cache.ts","../src/utils/subname-helpers.ts"],"sourcesContent":["import { namehash } from \"viem\";\nimport { Node } from \"./types\";\n\nexport const ROOT_NODE: Node = namehash(\"\");\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\n/**\n * The ETH coinType.\n *\n * @see https://docs.ens.domains/ensip/9\n */\nexport const ETH_COIN_TYPE = 60n;\n","import type { Hex } from \"viem\";\n\n/**\n * A PluginName is a unique id for a 'plugin': we use the notion of 'plugins' to describe bundles\n * of indexing logic.\n */\nexport enum PluginName {\n Subgraph = \"subgraph\",\n Basenames = \"basenames\",\n Lineanames = \"lineanames\",\n ThreeDNS = \"threedns\",\n}\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 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\n/**\n * A Name represents a human-readable ENS name.\n *\n * ex: vitalik.eth\n */\nexport type Name = string;\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","import { Address, concat, isAddress, isHash, keccak256, toHex } from \"viem\";\n\nimport { labelhash } from \"viem/ens\";\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 * Gets the Label used for subnames of \"addr.reverse\" used for reverse lookups of `address` as per\n * https://docs.ens.domains/resolution/names#reverse-nodes\n */\nconst addrReverseLabel = (address: Address): Label => address.slice(2).toLowerCase();\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) => 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"],"mappings":";AAAA,SAAS,gBAAgB;AAGlB,IAAM,YAAkB,SAAS,EAAE;AAQnC,IAAM,qBAAgC,oBAAI,IAAI,CAAC,SAAS,cAAc,CAAC,CAAC;AAOxE,IAAM,gBAAgB;;;ACZtB,IAAK,aAAL,kBAAKA,gBAAL;AACL,EAAAA,YAAA,cAAW;AACX,EAAAA,YAAA,eAAY;AACZ,EAAAA,YAAA,gBAAa;AACb,EAAAA,YAAA,cAAW;AAJD,SAAAA;AAAA,GAAA;;;ACqCL,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;;;ACpGA,SAAkB,QAAQ,WAAW,QAAQ,WAAW,aAAa;AAErE,SAAS,iBAAiB;AAQnB,IAAM,oBAAoB,CAAC,WAAsB,SACtD,UAAU,OAAO,CAAC,MAAM,SAAS,CAAC,CAAC;AAMrC,IAAM,mBAAmB,CAAC,YAA4B,QAAQ,MAAM,CAAC,EAAE,YAAY;AAU5E,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,QAAgB,MAAM,KAAK,EAAE,MAAM,GAAG,CAAC;AAiCtE,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;","names":["PluginName"]}
|
|
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/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/is-normalized.ts","../src/ensindexer/config/types.ts","../src/ensindexer/config/helpers.ts","../src/ensindexer/config/serialize.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/client.ts","../src/resolution/resolver-records-selection.ts"],"sourcesContent":["import { namehash } from \"viem\";\n\nimport type { Node } from \"./types\";\n\nexport const ROOT_NODE: Node = namehash(\"\");\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, 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) => 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 { 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 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\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: experimentalResolution requires ReverseResolvers plugin\nexport function invariant_experimentalResolutionNeedsReverseResolversPlugin(\n ctx: ZodCheckFnInput<Pick<ENSIndexerPublicConfig, \"plugins\" | \"experimentalResolution\">>,\n) {\n const { value: config } = ctx;\n\n const reverseResolversPluginActive = config.plugins.includes(PluginName.ReverseResolvers);\n\n if (config.experimentalResolution && !reverseResolversPluginActive) {\n ctx.issues.push({\n code: \"custom\",\n input: config,\n message: `'reverseResolversPluginActive' requires the ${PluginName.ReverseResolvers} plugin to be active.`,\n });\n }\n}\n\n// Invariant: isSubgraphCompatible requires Subgraph plugin only, and no extra indexing features\nexport function invariant_isSubgraphCompatibleRequirements(\n ctx: ZodCheckFnInput<\n Pick<\n ENSIndexerPublicConfig,\n \"plugins\" | \"isSubgraphCompatible\" | \"healReverseAddresses\" | \"indexAdditionalResolverRecords\"\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. Also, both 'indexAdditionalResolverRecords' and 'healReverseAddresses' must be set to 'false'`\n : `Both 'indexAdditionalResolverRecords' and 'healReverseAddresses' were set to 'false', and the only active plugin was the '${PluginName.Subgraph}' plugin. 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 experimentalResolution: z.boolean({ error: `${valueLabel}.experimentalResolution` }),\n healReverseAddresses: z.boolean({ error: `${valueLabel}.healReverseAddresses` }),\n indexAdditionalResolverRecords: z.boolean({\n error: `${valueLabel}.indexAdditionalResolverRecords`,\n }),\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_experimentalResolutionNeedsReverseResolversPlugin)\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, ChainId, 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 { normalize } from \"viem/ens\";\n\nimport type { Name } from \"../ens\";\n\nexport function isNormalized(name: Name) {\n try {\n return name === normalize(name);\n } catch {\n return false;\n }\n}\n","import type { ENSNamespaceId } from \"../../ens\";\nimport type { ChainId } from \"../../shared\";\n\n/**\n * A PluginName is a unique id for a 'plugin': we use the notion of\n * 'plugins' to describe bundles of indexing logic.\n */\nexport enum PluginName {\n Subgraph = \"subgraph\",\n Basenames = \"basenames\",\n Lineanames = \"lineanames\",\n ThreeDNS = \"threedns\",\n ReverseResolvers = \"reverse-resolvers\",\n Referrals = \"referrals\",\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 * 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\n * indexed data becoming a _superset_ of the Subgraph. For exact data-level\n * backwards compatibility with the ENS Subgraph,\n * {@link indexAdditionalResolverRecords} should be `false`.\n */\n indexAdditionalResolverRecords: boolean;\n\n /**\n * Experiment to enable forward/reverse resolution APIs.\n */\n experimentalResolution: 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 * Subgraph compatibility\n *\n * Tells if indexer config guarantees data to be indexed while\n * maintaining full subgraph-compatibility.\n */\nexport function isSubgraphCompatible(\n config: Pick<\n ENSIndexerPublicConfig,\n \"plugins\" | \"healReverseAddresses\" | \"indexAdditionalResolverRecords\"\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 const indexingBehaviorIsSubgraphCompatible =\n !config.healReverseAddresses && !config.indexAdditionalResolverRecords;\n\n return onlySubgraphPluginActivated && indexingBehaviorIsSubgraphCompatible;\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 indexedChainIds,\n databaseSchemaName,\n experimentalResolution,\n healReverseAddresses,\n indexAdditionalResolverRecords,\n isSubgraphCompatible,\n namespace,\n plugins,\n dependencyInfo,\n } = config;\n\n return {\n ensAdminUrl: serializeUrl(ensAdminUrl),\n ensNodePublicUrl: serializeUrl(ensNodePublicUrl),\n indexedChainIds: serializeIndexedChainIds(indexedChainIds),\n databaseSchemaName,\n experimentalResolution,\n healReverseAddresses,\n indexAdditionalResolverRecords,\n isSubgraphCompatible,\n namespace,\n plugins,\n dependencyInfo,\n } satisfies SerializedENSIndexerPublicConfig;\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 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, backfillEndBlock }) =>\n blockRef.isBeforeOrEqualTo(latestIndexedBlock, backfillEndBlock),\n {\n error: `latestIndexedBlock 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 }) => blockRef.isEqualTo(latestIndexedBlock, config.endBlock),\n {\n error: `latestIndexedBlock must be the 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 `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 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, 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 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","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 = \"operation\",\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 = \"operation\",\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\nconst PROTOCOL_ATTRIBUTE_PREFIX = \"ens\";\n\nexport const ATTR_PROTOCOL_NAME = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol`;\nexport const ATTR_PROTOCOL_STEP = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol.step`;\nexport const ATTR_PROTOCOL_STEP_RESULT = `${PROTOCOL_ATTRIBUTE_PREFIX}.protocol.step.result`;\n\n/**\n * Re-implements hrTimeToMicroseconds to avoid a dependency on @opentelemetry/core.\n *\n * @see https://github.com/open-telemetry/opentelemetry-js/blob/41ba7f57cbf5ae22290168188b467e0c60cd4765/packages/opentelemetry-core/src/common/time.ts#L135\n */\nexport function hrTimeToMicroseconds(time: [number, number] /* api.HrTime */): number {\n return time[0] * 1e6 + time[1] / 1e3;\n}\n\n/**\n * Encodes a ReadableSpan as a consumer-friendly and externally-visible JSON-representable object.\n *\n * NOTE: to avoid a dependency on @opentelemetry/sdk-trace-base and an obscure typing issue related\n * to the patched version necessary for it to run in ENSIndexer, we type the span as `any`, but note\n * that it is ReadableSpan.\n */\nexport const readableSpanToProtocolSpan = (span: any /* ReadableSpan */) => ({\n id: span.spanContext().spanId,\n traceId: span.spanContext().traceId,\n parentSpanContext: span.parentSpanContext,\n name: span.name,\n timestamp: hrTimeToMicroseconds(span.startTime),\n duration: hrTimeToMicroseconds(span.duration),\n // only export `ens.*` attributes to avoid leaking internal details\n attributes: Object.fromEntries(\n Object.entries(span.attributes).filter(([key]) =>\n key.startsWith(`${PROTOCOL_ATTRIBUTE_PREFIX}.`),\n ),\n ),\n status: span.status,\n events: span.events,\n});\n\nexport type ProtocolSpan = ReturnType<typeof readableSpanToProtocolSpan>;\nexport type ProtocolTrace = ProtocolSpan[];\n","import {\n ErrorResponse,\n ResolvePrimaryNameRequest,\n ResolvePrimaryNameResponse,\n ResolvePrimaryNamesRequest,\n ResolvePrimaryNamesResponse,\n ResolveRecordsRequest,\n ResolveRecordsResponse,\n} from \"./api/types\";\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 * @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 true)\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 === false) url.searchParams.set(\"accelerate\", \"false\");\n\n const response = await fetch(url);\n\n if (!response.ok) {\n const error = (await response.json()) as ErrorResponse;\n throw new Error(`Records Resolution Failed: ${error.message}`);\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 * @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 true)\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 === false) url.searchParams.set(\"accelerate\", \"false\");\n\n const response = await fetch(url);\n\n if (!response.ok) {\n const error = (await response.json()) as ErrorResponse;\n throw new Error(`Primary Name Resolution Failed: ${error.message}`);\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 * @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 === false) url.searchParams.set(\"accelerate\", \"false\");\n\n const response = await fetch(url);\n\n if (!response.ok) {\n const error = (await response.json()) as ErrorResponse;\n throw new Error(`Primary Names Resolution Failed: ${error.message}`);\n }\n\n const data = await response.json();\n return data as ResolvePrimaryNamesResponse;\n }\n}\n","import { CoinType, ETH_COIN_TYPE } 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 DEFAULT_RECORDS_SELECTION = {\n addresses: [ETH_COIN_TYPE],\n texts: [\n \"url\",\n \"avatar\",\n \"header\",\n \"description\",\n \"email\",\n \"com.twitter\",\n \"com.farcaster\",\n \"com.github\",\n ],\n} as const satisfies ResolverRecordsSelection;\n\nexport const isSelectionEmpty = (selection: ResolverRecordsSelection) =>\n !selection.name && !selection.addresses?.length && !selection.texts?.length;\n"],"mappings":"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","names":["prettifyError","z","PluginName","z","prettifyError","isSubgraphCompatible","prettifyError","z","z","prettifyError","TraceableENSProtocol","ForwardResolutionProtocolStep","ReverseResolutionProtocolStep"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ensnode/ensnode-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.32.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A utility library for interacting with ENSNode and ENS data",
|
|
6
6
|
"license": "MIT",
|
|
@@ -36,7 +36,12 @@
|
|
|
36
36
|
"typescript": "^5.7.3",
|
|
37
37
|
"viem": "^2.22.13",
|
|
38
38
|
"vitest": "^3.1.1",
|
|
39
|
-
"@ensnode/shared-configs": "0.
|
|
39
|
+
"@ensnode/shared-configs": "0.32.0"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@ensdomains/address-encoder": "^1.1.2",
|
|
43
|
+
"zod": "^3.25.7",
|
|
44
|
+
"@ensnode/datasources": "0.32.0"
|
|
40
45
|
},
|
|
41
46
|
"scripts": {
|
|
42
47
|
"prepublish": "tsup",
|