@dfinity/utils
Version:
A collection of utilities and constants for NNS/SNS projects.
5 lines • 62.7 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../src/enums/token.enums.ts", "../src/constants/constants.ts", "../src/parser/token.ts", "../src/services/canister.ts", "../src/utils/nullish.utils.ts", "../src/services/query.ts", "../src/utils/actor.utils.ts", "../src/utils/agent.utils.ts", "../src/utils/asserts.utils.ts", "../src/utils/arrays.utils.ts", "../src/utils/base32.utils.ts", "../src/utils/base64.utils.ts", "../src/utils/crc.utils.ts", "../src/utils/json.utils.ts", "../src/utils/crypto.utils.ts", "../src/utils/date.utils.ts", "../src/utils/debounce.utils.ts", "../src/utils/did.utils.ts", "../src/utils/principal.utils.ts", "../src/utils/version.utils.ts"],
"sourcesContent": ["export enum FromStringToTokenError {\n FractionalMoreThan8Decimals,\n InvalidFormat,\n FractionalTooManyDecimals,\n}\n", "export const E8S_PER_TOKEN = BigInt(100000000);\n", "import { E8S_PER_TOKEN } from \"../constants/constants\";\nimport { FromStringToTokenError } from \"../enums/token.enums\";\n\nconst DECIMALS_CONVERSION_SUPPORTED = 8;\n\n/**\n * Receives a string representing a number and returns the big int or error.\n *\n * @param amount - in string format\n * @returns bigint | FromStringToTokenError\n */\nexport const convertStringToE8s = (\n value: string,\n): bigint | FromStringToTokenError => {\n // replace exponential format (1e-4) with plain (0.0001)\n // doesn't support decimals for values >= ~1e16\n let amount = value.includes(\"e\")\n ? Number(value).toLocaleString(\"en\", {\n useGrouping: false,\n maximumFractionDigits: 20,\n })\n : value;\n\n // Remove all instances of \",\" and \"'\".\n amount = amount.trim().replace(/[,']/g, \"\");\n\n // Verify that the string is of the format 1234.5678\n const regexMatch = amount.match(/\\d*(\\.\\d*)?/);\n if (!regexMatch || regexMatch[0] !== amount) {\n return FromStringToTokenError.InvalidFormat;\n }\n\n const [integral, fractional] = amount.split(\".\");\n\n let e8s = BigInt(0);\n\n if (integral) {\n try {\n e8s += BigInt(integral) * E8S_PER_TOKEN;\n } catch {\n return FromStringToTokenError.InvalidFormat;\n }\n }\n\n if (fractional) {\n if (fractional.length > 8) {\n return FromStringToTokenError.FractionalMoreThan8Decimals;\n }\n try {\n e8s += BigInt(fractional.padEnd(8, \"0\"));\n } catch {\n return FromStringToTokenError.InvalidFormat;\n }\n }\n\n return e8s;\n};\n\n/**\n * Receives a string representing a number and returns the big int or error.\n *\n * @param amount - in string format\n * @returns bigint | FromStringToTokenError\n */\nconst convertStringToUlps = ({\n amount,\n decimals,\n}: {\n amount: string;\n decimals: number;\n}): bigint | FromStringToTokenError => {\n // Remove all instances of \",\" and \"'\".\n amount = amount.trim().replace(/[,']/g, \"\");\n\n // Verify that the string is of the format 1234.5678\n const regexMatch = amount.match(/\\d*(\\.\\d*)?/);\n if (!regexMatch || regexMatch[0] !== amount) {\n return FromStringToTokenError.InvalidFormat;\n }\n\n const [integral, fractional] = amount.split(\".\");\n\n let ulps = 0n;\n const ulpsPerToken = 10n ** BigInt(decimals);\n\n if (integral) {\n try {\n ulps += BigInt(integral) * ulpsPerToken;\n } catch {\n return FromStringToTokenError.InvalidFormat;\n }\n }\n\n if (fractional) {\n if (fractional.length > decimals) {\n return FromStringToTokenError.FractionalTooManyDecimals;\n }\n try {\n ulps += BigInt(fractional.padEnd(decimals, \"0\"));\n } catch {\n return FromStringToTokenError.InvalidFormat;\n }\n }\n\n return ulps;\n};\n\nexport interface Token {\n symbol: string;\n name: string;\n decimals: number;\n logo?: string;\n}\n\n// TODO: Remove this token and use the value from ICP ledger\nexport const ICPToken: Token = {\n symbol: \"ICP\",\n name: \"Internet Computer\",\n decimals: 8,\n};\n\n/**\n * Deprecated. Use TokenAmountV2 instead which supports decimals !== 8.\n *\n * Represents an amount of tokens.\n *\n * @param e8s - The amount of tokens in bigint.\n * @param token - The token type.\n */\nexport class TokenAmount {\n private constructor(\n protected e8s: bigint,\n public token: Token,\n ) {\n if (token.decimals !== 8) {\n throw new Error(\"Use TokenAmountV2 for number of decimals other than 8\");\n }\n }\n\n /**\n * Initialize from a bigint. Bigint are considered e8s.\n *\n * @param {amount: bigint; token?: Token;} params\n * @param {bigint} params.amount The amount in bigint format.\n * @param {Token} params.token The token type.\n */\n public static fromE8s({\n amount,\n token,\n }: {\n amount: bigint;\n token: Token;\n }): TokenAmount {\n return new TokenAmount(amount, token);\n }\n\n /**\n * Initialize from a string. Accepted formats:\n *\n * 1234567.8901\n * 1'234'567.8901\n * 1,234,567.8901\n *\n * @param {amount: string; token?: Token;} params\n * @param {string} params.amount The amount in string format.\n * @param {Token} params.token The token type.\n */\n public static fromString({\n amount,\n token,\n }: {\n amount: string;\n token: Token;\n }): TokenAmount | FromStringToTokenError {\n // If parsing the number fails because of the number of decimals, we still\n // want the error to be about the number of decimals and not about the\n // parsing.\n if (token.decimals !== 8) {\n throw new Error(\"Use TokenAmountV2 for number of decimals other than 8\");\n }\n const e8s = convertStringToE8s(amount);\n\n if (typeof e8s === \"bigint\") {\n return new TokenAmount(e8s, token);\n }\n return e8s;\n }\n\n /**\n * Initialize from a number.\n *\n * 1 integer is considered E8S_PER_TOKEN\n *\n * @param {amount: number; token?: Token;} params\n * @param {string} params.amount The amount in number format.\n * @param {Token} params.token The token type.\n */\n public static fromNumber({\n amount,\n token,\n }: {\n amount: number;\n token: Token;\n }): TokenAmount {\n const tokenAmount = TokenAmount.fromString({\n amount: amount.toString(),\n token,\n });\n if (tokenAmount instanceof TokenAmount) {\n return tokenAmount;\n }\n if (tokenAmount === FromStringToTokenError.FractionalMoreThan8Decimals) {\n throw new Error(`Number ${amount} has more than 8 decimals`);\n }\n\n // This should never happen\n throw new Error(`Invalid number ${amount}`);\n }\n\n /**\n *\n * @returns The amount of e8s.\n */\n public toE8s(): bigint {\n return this.e8s;\n }\n}\n\n/**\n * Represents an amount of tokens.\n *\n * @param upls - The amount of tokens in units in the last place. If the token\n * supports N decimals, 10^N ulp = 1 token.\n * @param token - The token type.\n */\nexport class TokenAmountV2 {\n private constructor(\n protected ulps: bigint,\n public token: Token,\n ) {}\n\n /**\n * Initialize from a bigint. Bigint are considered ulps.\n *\n * @param {amount: bigint; token?: Token;} params\n * @param {bigint} params.amount The amount in bigint format.\n * @param {Token} params.token The token type.\n */\n public static fromUlps({\n amount,\n token,\n }: {\n amount: bigint;\n token: Token;\n }): TokenAmountV2 {\n return new TokenAmountV2(amount, token);\n }\n\n /**\n * Initialize from a string. Accepted formats:\n *\n * 1234567.8901\n * 1'234'567.8901\n * 1,234,567.8901\n *\n * @param {amount: string; token?: Token;} params\n * @param {string} params.amount The amount in string format.\n * @param {Token} params.token The token type.\n */\n public static fromString({\n amount,\n token,\n }: {\n amount: string;\n token: Token;\n }): TokenAmountV2 | FromStringToTokenError {\n const ulps = convertStringToUlps({ amount, decimals: token.decimals });\n\n if (typeof ulps === \"bigint\") {\n return new TokenAmountV2(ulps, token);\n }\n return ulps;\n }\n\n /**\n * Initialize from a number.\n *\n * 1 integer is considered 10^{token.decimals} ulps\n *\n * @param {amount: number; token?: Token;} params\n * @param {string} params.amount The amount in number format.\n * @param {Token} params.token The token type.\n */\n public static fromNumber({\n amount,\n token,\n }: {\n amount: number;\n token: Token;\n }): TokenAmountV2 {\n const tokenAmount = TokenAmountV2.fromString({\n amount: amount.toFixed(\n Math.min(DECIMALS_CONVERSION_SUPPORTED, token.decimals),\n ),\n token,\n });\n if (tokenAmount instanceof TokenAmountV2) {\n return tokenAmount;\n }\n if (tokenAmount === FromStringToTokenError.FractionalTooManyDecimals) {\n throw new Error(\n `Number ${amount} has more than ${token.decimals} decimals`,\n );\n }\n\n // This should never happen\n throw new Error(`Invalid number ${amount}`);\n }\n\n /**\n *\n * @returns The amount of ulps.\n */\n public toUlps(): bigint {\n return this.ulps;\n }\n\n /**\n *\n * @returns The amount of ulps in e8s precision\n */\n public toE8s(): bigint {\n if (this.token.decimals < 8) {\n return this.ulps * 10n ** BigInt(8 - this.token.decimals);\n }\n if (this.token.decimals === 8) {\n return this.ulps;\n }\n return this.ulps / 10n ** BigInt(this.token.decimals - 8);\n }\n}\n", "import type { Principal } from \"@icp-sdk/core/principal\";\nimport type { QueryParams } from \"../types/query.params\";\n\nexport abstract class Canister<T> {\n protected constructor(\n private readonly id: Principal,\n protected readonly service: T,\n protected readonly certifiedService: T,\n ) {}\n\n get canisterId(): Principal {\n return this.id;\n }\n\n protected caller = ({ certified = true }: QueryParams): T =>\n certified ? this.certifiedService : this.service;\n}\n", "/**\n * Checks if a given argument is null or undefined.\n *\n * @template T - The type of the argument.\n * @param {T | undefined | null} argument - The argument to check.\n * @returns {argument is undefined | null} `true` if the argument is null or undefined; otherwise, `false`.\n */\nexport const isNullish = <T>(\n argument: T | undefined | null,\n): argument is undefined | null => argument === null || argument === undefined;\n\n/**\n * Checks if a given argument is neither null nor undefined.\n *\n * @template T - The type of the argument.\n * @param {T | undefined | null} argument - The argument to check.\n * @returns {argument is NonNullable<T>} `true` if the argument is not null or undefined; otherwise, `false`.\n */\nexport const nonNullish = <T>(\n argument: T | undefined | null,\n): argument is NonNullable<T> => !isNullish(argument);\n\n/**\n * Checks if a given value is not null, not undefined, and not an empty string.\n *\n * @param {string | undefined | null} value - The value to check.\n * @returns {boolean} `true` if the value is not null, not undefined, and not an empty string; otherwise, `false`.\n */\nexport const notEmptyString = (\n value: string | undefined | null,\n): value is string => nonNullish(value) && value !== \"\";\n\n/**\n * Checks if a given value is null, undefined, or an empty string.\n *\n * @param {string | undefined | null} value - The value to check.\n * @returns {value is undefined | null | \"\"} Type predicate indicating if the value is null, undefined, or an empty string.\n */\nexport const isEmptyString = (\n value: string | undefined | null,\n): value is undefined | null | \"\" => !notEmptyString(value);\n", "import type { QueryAndUpdateParams } from \"../types/query-and-update.params\";\nimport { isNullish } from \"../utils/nullish.utils\";\n\n/**\n * This service performs a query (not-certified) call and/or an update (certified) call, and handles the results.\n *\n * It is useful because it can do both type of calls for security reasons.\n * For example, malicious nodes can forge transactions and balance when calling an Index canister, if no update is performed to certify the results.\n *\n * Furthermore, it can handle the results of the calls in different ways:\n * - `query` only performs a query call.\n * - `update` only performs an update call.\n * - `query_and_update` performs both calls.\n *\n * The resolution can be:\n * - `all_settled` waits for all calls to settle.\n * - `race` waits for the first call to settle (typically, `query` is the fastest one).\n *\n * Once the call(s) are done, the response is handled by the `onLoad` callback.\n * However, if an error occurs, it is handled by the error callbacks, if provided: one for the query call and one for the update call.\n *\n * @param {QueryAndUpdateParams<R, E>} params The parameters to perform the request.\n * @param {QueryAndUpdateRequest<R>} params.request The request to perform.\n * @param {QueryAndUpdateOnResponse<R>} params.onLoad The callback to handle the response of the request.\n * @param {QueryAndUpdateOnQueryError<E>} [params.onQueryError] The callback to handle the error of the `query` request.\n * @param {QueryAndUpdateOnUpdateError<E>} [params.onUpdateError] The callback to handle the error of the `update` request.\n * @param {QueryAndUpdateStrategy} [params.strategy=\"query_and_update\"] The strategy to use. Default is `query_and_update`.\n * @param {QueryAndUpdateIdentity} params.identity The identity to use for the request.\n * @param {QueryAndUpdatePromiseResolution} [params.resolution=\"race\"] The resolution to use. Default is `race`.\n *\n * @template R The type of the response.\n * @template E The type of the error.\n *\n * @returns A promise that resolves when the request is done.\n */\nexport const queryAndUpdate = async <R, E = unknown>({\n request,\n onLoad,\n onQueryError,\n onUpdateError,\n strategy = \"query_and_update\",\n identity,\n resolution = \"race\",\n}: QueryAndUpdateParams<R, E>): Promise<void> => {\n let certifiedDone = false;\n\n const queryOrUpdate = (certified: boolean) =>\n request({ certified, identity })\n .then((response) => {\n if (certifiedDone) {\n return;\n }\n\n onLoad({ certified, response });\n })\n .catch((error: E) => {\n if (!certified) {\n onQueryError?.({ error, identity });\n }\n\n if (certifiedDone) {\n return;\n }\n\n if (isNullish(onUpdateError)) {\n return;\n }\n\n console.error(error);\n\n if (!certified) {\n return;\n }\n\n onUpdateError({ error, identity });\n })\n .finally(() => (certifiedDone = certifiedDone || certified));\n\n const requests: Array<Promise<void>> =\n strategy === \"query\"\n ? [queryOrUpdate(false)]\n : strategy === \"update\"\n ? [queryOrUpdate(true)]\n : [queryOrUpdate(false), queryOrUpdate(true)];\n\n await (resolution === \"all_settled\"\n ? Promise.allSettled(requests)\n : Promise.race(requests));\n};\n", "import {\n Actor,\n type ActorConfig,\n type ActorSubclass,\n type Agent,\n} from \"@icp-sdk/core/agent\";\nimport type { IDL } from \"@icp-sdk/core/candid\";\nimport type { Principal } from \"@icp-sdk/core/principal\";\nimport type { CanisterOptions } from \"../types/canister.options\";\nimport { defaultAgent } from \"./agent.utils\";\n\ntype RequiredCanisterOptions<T> = Required<\n Pick<CanisterOptions<T>, \"canisterId\">\n> &\n Omit<CanisterOptions<T>, \"canisterId\">;\n\nexport const createServices = <T>({\n options: {\n canisterId,\n serviceOverride,\n certifiedServiceOverride,\n agent: agentOption,\n callTransform,\n queryTransform,\n },\n idlFactory,\n certifiedIdlFactory,\n}: {\n options: RequiredCanisterOptions<T> &\n Pick<ActorConfig, \"queryTransform\" | \"callTransform\">;\n idlFactory: IDL.InterfaceFactory;\n certifiedIdlFactory: IDL.InterfaceFactory;\n}): {\n service: ActorSubclass<T>;\n certifiedService: ActorSubclass<T>;\n agent: Agent;\n canisterId: Principal;\n} => {\n const agent: Agent = agentOption ?? defaultAgent();\n\n const service: ActorSubclass<T> =\n serviceOverride ??\n Actor.createActor<T>(idlFactory, {\n agent,\n canisterId,\n callTransform,\n queryTransform,\n });\n\n const certifiedService: ActorSubclass<T> =\n certifiedServiceOverride ??\n Actor.createActor<T>(certifiedIdlFactory, {\n agent,\n canisterId,\n callTransform,\n queryTransform,\n });\n\n return { service, certifiedService, agent, canisterId };\n};\n", "import {\n AnonymousIdentity,\n HttpAgent,\n type Agent,\n type Identity,\n} from \"@icp-sdk/core/agent\";\nimport type { CreateAgentParams } from \"../types/agent.utils\";\nimport { isNullish, nonNullish } from \"./nullish.utils\";\n\n/**\n * Get a default agent that connects to mainnet with the anonymous identity.\n * @returns The default agent to use\n */\nexport const defaultAgent = (): Agent =>\n HttpAgent.createSync({\n host: \"https://icp-api.io\",\n identity: new AnonymousIdentity(),\n });\n\n/**\n * Create an agent for a given identity\n *\n * @param {CreateAgentParams} params The parameters to create a new HTTP agent\n * @param {Identity} params.identity A mandatory identity to use for the agent\n * @param {string} params.host An optional host to connect to, particularly useful for local development\n * @param {boolean} params.fetchRootKey Fetch root key for certificate validation during local development or on testnet\n * @param {boolean} params.verifyQuerySignatures Check for signatures in the state tree signed by the node that replies to queries - i.e. certify responses.\n * @param {number} params.retryTimes Set the number of retries the agent should perform before error.\n */\nexport const createAgent = async ({\n identity,\n host,\n fetchRootKey = false,\n verifyQuerySignatures = false,\n retryTimes,\n}: CreateAgentParams): Promise<HttpAgent> =>\n await HttpAgent.create({\n identity,\n ...(nonNullish(host) && { host }),\n verifyQuerySignatures,\n ...(nonNullish(retryTimes) && { retryTimes }),\n shouldFetchRootKey: fetchRootKey,\n });\n\nexport type AgentManagerConfig = Pick<\n CreateAgentParams,\n \"fetchRootKey\" | \"host\"\n>;\n\n/**\n * AgentManager class manages HttpAgent instances for different identities.\n *\n * It caches agents by identity to optimise resource usage and avoid unnecessary agent creation.\n * Provides functionality to create new agents, retrieve cached agents, and clear the cache when needed.\n */\nexport class AgentManager {\n private agents: Record<string, HttpAgent> | undefined | null = undefined;\n\n private constructor(private readonly config: AgentManagerConfig) {}\n\n /**\n * Static factory method to create a new AgentManager instance.\n *\n * This method serves as an alternative to directly using the private constructor,\n * making it more convenient to create instances of `AgentManager` using a simple and clear method.\n *\n * @param {AgentManagerConfig} config - Configuration options for the AgentManager instance.\n * @param {boolean} config.fetchRootKey - Whether to fetch the root key for certificate validation.\n * @param {string} config.host - The host to connect to.\n * @returns {AgentManager} A new instance of `AgentManager`.\n */\n public static create(config: AgentManagerConfig): AgentManager {\n return new AgentManager(config);\n }\n\n /**\n * Get or create an HTTP agent for a given identity.\n *\n * If the agent for the specified identity has been created and cached, it is retrieved from the cache.\n * If no agent exists for the identity, a new one is created, cached, and then returned.\n *\n * @param {Identity} identity - The identity to be used to create the agent.\n * @returns {Promise<HttpAgent>} The HttpAgent associated with the given identity.\n */\n public getAgent = async ({\n identity,\n }: {\n identity: Identity;\n }): Promise<HttpAgent> => {\n const key = identity.getPrincipal().toText();\n\n if (isNullish(this.agents) || isNullish(this.agents[key])) {\n const agent = await createAgent({\n identity,\n fetchRootKey: this.config.fetchRootKey,\n host: this.config.host,\n verifyQuerySignatures: true,\n });\n\n this.agents = {\n ...(this.agents ?? {}),\n [key]: agent,\n };\n\n return agent;\n }\n\n return this.agents[key];\n };\n\n /**\n * Clear the cache of HTTP agents.\n *\n * This method removes all cached agents, forcing new agent creation on the next request for any identity.\n * Useful when identities have changed or if you want to reset all active connections.\n */\n public clearAgents = (): void => {\n this.agents = null;\n };\n}\n", "export class InvalidPercentageError extends Error {}\nexport class NullishError extends Error {}\n\nexport const assertNonNullish: <T>(\n value: T,\n message?: string,\n // eslint-disable-next-line local-rules/prefer-object-params\n) => asserts value is NonNullable<T> = <T>(\n value: T,\n message?: string,\n): void => {\n if (value === null || value === undefined) {\n throw new NullishError(message);\n }\n};\n\n// eslint-disable-next-line local-rules/prefer-object-params\nexport const asNonNullish = <T>(value: T, message?: string): NonNullable<T> => {\n assertNonNullish(value, message);\n return value;\n};\n\nexport const assertPercentageNumber = (percentage: number) => {\n if (percentage < 0 || percentage > 100) {\n throw new InvalidPercentageError(\n `${percentage} is not a valid percentage number.`,\n );\n }\n};\n\n/**\n * Utility to enforce exhaustiveness checks in TypeScript.\n *\n * This function should only be called in branches of a `switch` or conditional\n * that should be unreachable if the union type has been fully handled.\n *\n * By typing the parameter as `never`, the compiler will emit an error if\n * a new variant is added to the union but not covered in the logic.\n *\n * @param _ - A value that should be of type `never`. If this is not the case,\n * the TypeScript compiler will flag a type error.\n * @param message - Optional custom error message to include in the thrown error.\n * @throws {Error} Always throws when invoked at runtime.\n *\n */\n// eslint-disable-next-line local-rules/prefer-object-params\nexport const assertNever = (_: never, message?: string): never => {\n throw new Error(message);\n};\n", "import { assertNonNullish } from \"./asserts.utils\";\n\nexport const uint8ArrayToBigInt = (array: Uint8Array): bigint => {\n const view = new DataView(array.buffer, array.byteOffset, array.byteLength);\n if (typeof view.getBigUint64 === \"function\") {\n return view.getBigUint64(0);\n }\n const high = BigInt(view.getUint32(0));\n const low = BigInt(view.getUint32(4));\n\n return (high << BigInt(32)) + low;\n};\n\nexport const bigIntToUint8Array = (value: bigint): Uint8Array => {\n const buffer = new ArrayBuffer(8);\n const view = new DataView(buffer);\n if (typeof view.setBigUint64 === \"function\") {\n view.setBigUint64(0, value);\n } else {\n const high = Number(value >> BigInt(32));\n const low = Number(value & BigInt(0xffffffff));\n\n view.setUint32(0, high);\n view.setUint32(4, low);\n }\n\n return new Uint8Array(buffer);\n};\n\nexport const numberToUint8Array = (value: number): Uint8Array => {\n const view = new DataView(new ArrayBuffer(8));\n for (let index = 7; index >= 0; --index) {\n view.setUint8(index, value % 256);\n value = value >> 8;\n }\n return new Uint8Array(view.buffer);\n};\n\nexport const arrayBufferToUint8Array = (buffer: ArrayBuffer): Uint8Array =>\n new Uint8Array(buffer);\n\nexport const uint8ArrayToArrayOfNumber = (array: Uint8Array): Array<number> =>\n Array.from(array);\n\nexport const arrayOfNumberToUint8Array = (numbers: Array<number>): Uint8Array =>\n new Uint8Array(numbers);\n\nexport const asciiStringToByteArray = (text: string): Array<number> =>\n Array.from(text).map((c) => c.charCodeAt(0));\n\nexport const hexStringToUint8Array = (hexString: string): Uint8Array => {\n const matches = hexString.match(/.{1,2}/g);\n\n assertNonNullish(matches, \"Invalid hex string.\");\n\n return Uint8Array.from(matches.map((byte) => parseInt(byte, 16)));\n};\n\n/**\n * Compare two Uint8Arrays for byte-level equality.\n *\n * @param {Object} params\n * @param {Uint8Array} params.a - First Uint8Array to compare.\n * @param {Uint8Array} params.b - Second Uint8Array to compare.\n * @returns {boolean} True if both arrays have the same length and identical contents.\n */\nexport const uint8ArraysEqual = ({ a, b }: { a: Uint8Array; b: Uint8Array }) =>\n a.length === b.length && a.every((byte, i) => byte === b[i]);\n\nexport const uint8ArrayToHexString = (bytes: Uint8Array | number[]) => {\n if (!(bytes instanceof Uint8Array)) {\n bytes = Uint8Array.from(bytes);\n }\n return bytes.reduce(\n (str, byte) => str + byte.toString(16).padStart(2, \"0\"),\n \"\",\n );\n};\n\nexport const candidNumberArrayToBigInt = (array: number[]): bigint => {\n let result = 0n;\n for (let i = array.length - 1; i >= 0; i--) {\n result = (result << 32n) + BigInt(array[i]);\n }\n return result;\n};\n", "import { assertNonNullish } from \"./asserts.utils\";\n\nconst ALPHABET = \"abcdefghijklmnopqrstuvwxyz234567\";\n\n// Build a lookup table for decoding.\nconst LOOKUP_TABLE: Record<string, number> = Object.create(null);\nfor (let i = 0; i < ALPHABET.length; i++) {\n LOOKUP_TABLE[ALPHABET[i]] = i;\n}\n\n// Add aliases for rfc4648.\nLOOKUP_TABLE[\"0\"] = LOOKUP_TABLE.o;\nLOOKUP_TABLE[\"1\"] = LOOKUP_TABLE.i;\n\n/**\n * Encode an Uint8Array to a base32 string.\n *\n * @param input The input array to encode.\n * @returns A Base32 string encoding the input.\n */\nexport const encodeBase32 = (input: Uint8Array): string => {\n // How many bits will we skip from the first byte.\n let skip = 0;\n // 5 high bits, carry from one byte to the next.\n let bits = 0;\n\n // The output string in base32.\n let output = \"\";\n\n const encodeByte = (byte: number): number => {\n if (skip < 0) {\n // we have a carry from the previous byte\n bits |= byte >> -skip;\n } else {\n // no carry\n bits = (byte << skip) & 248;\n }\n\n if (skip > 3) {\n // Not enough data to produce a character, get us another one\n skip -= 8;\n return 1;\n }\n\n if (skip < 4) {\n // produce a character\n output += ALPHABET[bits >> 3];\n skip += 5;\n }\n\n return 0;\n };\n\n for (let i = 0; i < input.length; ) {\n i += encodeByte(input[i]);\n }\n\n return output + (skip < 0 ? ALPHABET[bits >> 3] : \"\");\n};\n\n/**\n * Decode a base32 string to Uint8Array.\n *\n * @param input The input string to decode.\n * @param input The base32 encoded string to decode.\n */\nexport const decodeBase32 = (input: string): Uint8Array => {\n // how many bits we have from the previous character.\n let skip = 0;\n // current byte we're producing.\n let byte = 0;\n\n const output = new Uint8Array(((input.length * 4) / 3) | 0);\n let o = 0;\n\n const decodeChar = (char: string) => {\n // Consume a character from the stream, store\n // the output in this.output. As before, better\n // to use update().\n let val = LOOKUP_TABLE[char.toLowerCase()];\n assertNonNullish(val, `Invalid character: ${JSON.stringify(char)}`);\n\n // move to the high bits\n val <<= 3;\n byte |= val >>> skip;\n skip += 5;\n\n if (skip >= 8) {\n // We have enough bytes to produce an output\n output[o++] = byte;\n skip -= 8;\n\n if (skip > 0) {\n byte = (val << (5 - skip)) & 255;\n } else {\n byte = 0;\n }\n }\n };\n\n for (const c of input) {\n decodeChar(c);\n }\n\n return output.slice(0, o);\n};\n", "/**\n * Converts a Uint8Array (binary data) to a base64 encoded string.\n *\n * @param {Uint8Array} uint8Array - The Uint8Array containing binary data to be encoded.\n * @returns {string} - The base64 encoded string representation of the binary data.\n */\nexport const uint8ArrayToBase64 = (uint8Array: Uint8Array): string =>\n btoa(String.fromCharCode(...new Uint8Array(uint8Array)));\n\n/**\n * Converts a base64 encoded string to a Uint8Array (binary data).\n *\n * @param {string} base64String - The base64 encoded string to be decoded.\n * @returns {Uint8Array} - The Uint8Array representation of the decoded binary data.\n */\nexport const base64ToUint8Array = (base64String: string): Uint8Array =>\n Uint8Array.from(atob(base64String), (c) => c.charCodeAt(0));\n", "// This file is translated to JavaScript from\n// https://lxp32.github.io/docs/a-simple-example-crc32-calculation/\nconst lookUpTable: Uint32Array = new Uint32Array([\n 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,\n 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,\n 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,\n 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,\n 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,\n 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,\n 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,\n 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,\n 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,\n 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,\n 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,\n 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,\n 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,\n 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,\n 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,\n 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,\n 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,\n 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,\n 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,\n 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,\n 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,\n 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,\n 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,\n 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,\n 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,\n 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,\n 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,\n 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,\n 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,\n 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,\n 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,\n 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,\n 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,\n 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,\n 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,\n 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,\n 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,\n 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,\n 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,\n 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,\n 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,\n 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,\n 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,\n]);\n\nconst crc32 = (bytes: Uint8Array): number => {\n let crc = -1;\n\n for (let i = 0; i < bytes.length; i++) {\n const byte = bytes[i];\n const t = (byte ^ crc) & 0xff;\n crc = lookUpTable[t] ^ (crc >>> 8);\n }\n\n return (crc ^ -1) >>> 0;\n};\n\nexport const bigEndianCrc32 = (bytes: Uint8Array): Uint8Array => {\n const checksumArrayBuf = new ArrayBuffer(4);\n const view = new DataView(checksumArrayBuf);\n view.setUint32(0, crc32(bytes), false);\n return new Uint8Array(checksumArrayBuf);\n};\n", "import { Principal } from \"@icp-sdk/core/principal\";\nimport { nonNullish } from \"./nullish.utils\";\n\nconst JSON_KEY_BIGINT = \"__bigint__\";\nconst JSON_KEY_PRINCIPAL = \"__principal__\";\nconst JSON_KEY_UINT8ARRAY = \"__uint8array__\";\n\n/**\n * A custom replacer for `JSON.stringify` that converts specific types not natively supported\n * by the API into JSON-compatible formats.\n *\n * Supported conversions:\n * - `BigInt` \u2192 `{ \"__bigint__\": string }`\n * - `Principal` \u2192 `{ \"__principal__\": string }`\n * - `Uint8Array` \u2192 `{ \"__uint8array__\": number[] }`\n *\n * @param {string} _key - Ignored. Only provided for API compatibility.\n * @param {unknown} value - The value to transform before stringification.\n * @returns {unknown} The transformed value if it matches a known type, otherwise the original value.\n */\n// eslint-disable-next-line local-rules/prefer-object-params\nexport const jsonReplacer = (_key: string, value: unknown): unknown => {\n if (typeof value === \"bigint\") {\n return { [JSON_KEY_BIGINT]: `${value}` };\n }\n\n if (nonNullish(value) && Principal.isPrincipal(value)) {\n // isPrincipal asserts if a value is a Principal, but does not assert if the object\n // contains functions such as toText(). That's why we construct a new object.\n return { [JSON_KEY_PRINCIPAL]: Principal.from(value).toText() };\n }\n\n if (nonNullish(value) && value instanceof Uint8Array) {\n return { [JSON_KEY_UINT8ARRAY]: Array.from(value) };\n }\n\n return value;\n};\n\n/**\n * A custom reviver for `JSON.parse` that reconstructs specific types from their JSON-encoded representations.\n *\n * This reverses the transformations applied by `jsonReplacer`, restoring the original types.\n *\n * Supported conversions:\n * - `{ \"__bigint__\": string }` \u2192 `BigInt`\n * - `{ \"__principal__\": string }` \u2192 `Principal`\n * - `{ \"__uint8array__\": number[] }` \u2192 `Uint8Array`\n *\n * @param {string} _key - Ignored but provided for API compatibility.\n * @param {unknown} value - The parsed value to transform.\n * @returns {unknown} The reconstructed value if it matches a known type, otherwise the original value.\n */\n// eslint-disable-next-line local-rules/prefer-object-params\nexport const jsonReviver = (_key: string, value: unknown): unknown => {\n const mapValue = <T>(key: string): T => (value as Record<string, T>)[key];\n\n if (\n nonNullish(value) &&\n typeof value === \"object\" &&\n JSON_KEY_BIGINT in value\n ) {\n return BigInt(mapValue(JSON_KEY_BIGINT));\n }\n\n if (\n nonNullish(value) &&\n typeof value === \"object\" &&\n JSON_KEY_PRINCIPAL in value\n ) {\n return Principal.fromText(mapValue(JSON_KEY_PRINCIPAL));\n }\n\n if (\n nonNullish(value) &&\n typeof value === \"object\" &&\n JSON_KEY_UINT8ARRAY in value\n ) {\n return Uint8Array.from(mapValue(JSON_KEY_UINT8ARRAY));\n }\n\n return value;\n};\n", "import { uint8ArrayToHexString } from \"./arrays.utils\";\nimport { jsonReplacer } from \"./json.utils\";\n\n/**\n * Generates a SHA-256 hash from the given object.\n *\n * The object is first stringified using a custom `jsonReplacer`, then\n * hashed using the SubtleCrypto API. The resulting hash is returned as a hex string.\n *\n * @template T - The type of the input object.\n * @param {T} params - The object to hash.\n * @returns {Promise<string>} A promise that resolves to the hex string of the SHA-256 hash.\n */\nexport const hashObject = async <T extends object>(\n params: T,\n): Promise<string> => {\n const jsonString = JSON.stringify(params, jsonReplacer);\n\n return await hashText(jsonString);\n};\n\n/**\n * Generates a SHA-256 hash from a plain text string.\n *\n * The string is UTF-8 encoded and hashed using the SubtleCrypto API.\n * The resulting hash is returned as a hexadecimal string.\n *\n * @param {string} text - The text to hash.\n * @returns {Promise<string>} A promise that resolves to the hex string of the SHA-256 hash.\n */\nexport const hashText = async (text: string): Promise<string> => {\n const dataBuffer = new TextEncoder().encode(text);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", dataBuffer);\n\n return uint8ArrayToHexString(new Uint8Array(hashBuffer));\n};\n", "const SECONDS_IN_MINUTE = 60;\nconst MINUTES_IN_HOUR = 60;\nconst HOURS_IN_DAY = 24;\nconst DAYS_IN_NON_LEAP_YEAR = 365;\n\nexport interface I18nSecondsToDuration {\n year: string;\n year_plural: string;\n month: string;\n month_plural: string;\n day: string;\n day_plural: string;\n hour: string;\n hour_plural: string;\n minute: string;\n minute_plural: string;\n second: string;\n second_plural: string;\n}\n\nconst EN_TIME: I18nSecondsToDuration = {\n year: \"year\",\n year_plural: \"years\",\n month: \"month\",\n month_plural: \"months\",\n day: \"day\",\n day_plural: \"days\",\n hour: \"hour\",\n hour_plural: \"hours\",\n minute: \"minute\",\n minute_plural: \"minutes\",\n second: \"second\",\n second_plural: \"seconds\",\n};\n\n/**\n * Convert seconds to a human-readable duration, such as \"6 days, 10 hours.\"\n * @param {Object} options - The options object.\n * @param {bigint} options.seconds - The number of seconds to convert.\n * @param {I18nSecondsToDuration} [options.i18n] - The i18n object for customizing language and units. Defaults to English.\n * @returns {string} The human-readable duration string.\n */\nexport const secondsToDuration = ({\n seconds,\n i18n = EN_TIME,\n}: {\n seconds: bigint;\n i18n?: I18nSecondsToDuration;\n}): string => {\n let minutes = seconds / BigInt(SECONDS_IN_MINUTE);\n\n let hours = minutes / BigInt(MINUTES_IN_HOUR);\n minutes -= hours * BigInt(MINUTES_IN_HOUR);\n\n let days = hours / BigInt(HOURS_IN_DAY);\n hours -= days * BigInt(HOURS_IN_DAY);\n\n const years = fullYearsInDays(days);\n days -= daysInYears(years);\n\n const periods = [\n createLabel({ labelKey: \"year\", amount: years }),\n createLabel({ labelKey: \"day\", amount: days }),\n createLabel({ labelKey: \"hour\", amount: hours }),\n createLabel({ labelKey: \"minute\", amount: minutes }),\n ...(seconds > BigInt(0) && seconds < BigInt(60)\n ? [createLabel({ labelKey: \"second\", amount: seconds })]\n : []),\n ];\n\n return periods\n .filter(({ amount }) => amount > 0)\n .slice(0, 2)\n .map(\n (labelInfo) =>\n `${labelInfo.amount} ${\n labelInfo.amount === 1\n ? i18n[labelInfo.labelKey]\n : i18n[`${labelInfo.labelKey}_plural`]\n }`,\n )\n .join(\", \");\n};\n\nconst fullYearsInDays = (days: bigint): bigint => {\n // Use integer division.\n let years = days / BigInt(DAYS_IN_NON_LEAP_YEAR);\n while (daysInYears(years) > days) {\n years--;\n }\n return years;\n};\n\nconst daysInYears = (years: bigint): bigint => {\n // Use integer division.\n const leapDays = years / BigInt(4);\n return years * BigInt(DAYS_IN_NON_LEAP_YEAR) + leapDays;\n};\n\ntype LabelKey = \"year\" | \"month\" | \"day\" | \"hour\" | \"minute\" | \"second\";\ninterface LabelInfo {\n labelKey: LabelKey;\n amount: number;\n}\nconst createLabel = ({\n labelKey,\n amount,\n}: {\n labelKey: LabelKey;\n amount: bigint;\n}): LabelInfo => ({\n labelKey,\n amount: Number(amount),\n});\n\nconst NANOSECONDS_PER_MILLISECOND = 1_000_000n;\n\n/**\n * Returns the current timestamp in nanoseconds as a `bigint`.\n *\n * @returns {bigint} The current timestamp in nanoseconds.\n */\nexport const nowInBigIntNanoSeconds = (): bigint =>\n BigInt(Date.now()) * NANOSECONDS_PER_MILLISECOND;\n\n/**\n * Converts a given `Date` object to a timestamp in nanoseconds as a `bigint`.\n *\n * @param {Date} date - The `Date` object to convert.\n * @returns {bigint} The timestamp in nanoseconds.\n */\nexport const toBigIntNanoSeconds = (date: Date): bigint =>\n BigInt(date.getTime()) * NANOSECONDS_PER_MILLISECOND;\n", "/**\n * Creates a debounced version of the provided function.\n *\n * The debounced function postpones its execution until after a certain amount of time\n * has elapsed since the last time it was invoked. This is useful for limiting the rate\n * at which a function is called (e.g. in response to user input or events).\n *\n * @param {Function} func - The function to debounce. It will only be called after no new calls happen within the specified timeout.\n * @param {number} [timeout=300] - The debounce delay in milliseconds. Defaults to 300ms if not provided or invalid.\n * @returns {(args: unknown[]) => void} A debounced version of the original function.\n */\n// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type, local-rules/prefer-object-params\nexport const debounce = (func: Function, timeout?: number) => {\n let timer: NodeJS.Timer | undefined;\n\n return (...args: unknown[]) => {\n const next = () => func(...args);\n\n if (timer) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore TypeScript global and window confusion even if we are using @types/node\n clearTimeout(timer);\n }\n\n timer = setTimeout(\n next,\n timeout !== undefined && timeout > 0 ? timeout : 300,\n );\n };\n};\n", "import type { Nullable, NullishNullable } from \"../types/did.utils\";\nimport { assertNonNullish } from \"./asserts.utils\";\nimport { nonNullish } from \"./nullish.utils\";\n\n/**\n * Converts a value into a Candid-style variant representation of an optional value.\n *\n * @template T The type of the value.\n * @param {T | null | undefined} value - The value to convert into a Candid-style variant.\n * @returns {Nullable<T>} A Candid-style variant representation: an empty array for `null` and `undefined` or an array with the value.\n */\nexport const toNullable = <T>(value?: T | null): Nullable<T> =>\n nonNullish(value) ? [value] : [];\n\n/**\n * Extracts the value from a Candid-style variant representation of an optional value.\n *\n * @template T The type of the value.\n * @param {Nullable<T>} value - A Candid-style variant representing an optional value.\n * @returns {T | undefined} The extracted value, or `undefined` if the array is empty.\n */\nexport const fromNullable = <T>(value: Nullable<T>): T | undefined =>\n value?.[0];\n\n/**\n * Extracts the value from a Candid-style variant representation of an optional value,\n * ensuring the value is defined. Throws an error if the array is empty or the value is nullish.\n *\n * @template T The type of the value.\n * @param {Nullable<T>} value - A Candid-style variant representing an optional value.\n * @returns {T} The extracted value.\n * @throws {Error} If the array is empty or the value is nullish.\n */\nexport const fromDefinedNullable = <T>(value: Nullable<T>): T => {\n const result = fromNullable(value);\n\n assertNonNullish(result);\n\n return result;\n};\n\n/**\n * Extracts the value from a nullish Candid-style variant representation.\n *\n * @template T The type of the value.\n * @param {NullishNullable<T>} value - A Candid-style variant or `undefined`.\n * @returns {T | undefined} The extracted value, or `undefined` if the input is nullish or the array is empty.\n */\nexport const fromNullishNullable = <T>(\n value: NullishNullable<T>,\n): T | undefined => fromNullable(value ?? []);\n", "import type { Principal } from \"@icp-sdk/core/principal\";\n\n/**\n * Convert a principal to a Uint8Array 32 length.\n * e.g. Useful to convert a canister ID when topping up cycles with the Cmc canister\n * @param principal The principal that needs to be converted to Subaccount\n */\nexport const principalToSubAccount = (principal: Principal): Uint8Array => {\n const bytes: Uint8Array = principal.toUint8Array();\n const subAccount: Uint8Array = new Uint8Array(32);\n subAccount[0] = bytes.length;\n subAccount.set(bytes, 1);\n return subAccount;\n};\n", "const AMOUNT_VERSION_PARTS = 3;\nconst addZeros = ({\n nums,\n amountZeros,\n}: {\n nums: number[];\n amountZeros: number;\n}): number[] =>\n amountZeros > nums.length\n ? [...nums, ...[...Array(amountZeros - nums.length).keys()].map(() => 0)]\n : nums;\n\nconst convertToNumber = (versionStringPart: string): number => {\n if (!Number.isNaN(Number(versionStringPart))) {\n return Number(versionStringPart);\n }\n const strippedVersion = versionStringPart.split(\"\").reduce((acc, char) => {\n if (Number.isNaN(Number(char))) {\n return acc;\n }\n return acc + char;\n }, \"\");\n return Number(strippedVersion);\n};\n/**\n * Returns true if the current version is smaller than the minVersion, false if equal or bigger.\n * Tags after patch version are ignored, e.g. 1.0.0-beta.1 is considered equal to 1.0.0.\n *\n * @param {Object} params\n * @param {string} params.minVersion Ex: \"1.0.0\"\n * @param {string} params.currentVersion Ex: \"2.0.0\"\n * @returns boolean\n */\nexport const smallerVersion = ({\n minVersion,\n currentVersion,\n}: {\n minVersion: string;\n currentVersion: string;\n}): boolean => {\n const minVersionStandarized = addZeros({\n nums: minVersion.split(\".\").map(convertToNumber),\n amountZeros: AMOUNT_VERSION_PARTS,\n }).join(\".\");\n const currentVersionStandarized = addZeros({\n nums: currentVersion.split(\".\").map(convertToNumber),\n amountZeros: AMOUNT_VERSION_PARTS,\n }).join(\".\");\n // Versions need to have the same number of parts to be comparable\n // Source: https://stackoverflow.com/a/65687141\n return (\n currentVersionStandarized.localeCompare(minVersionStandarized, undefined, {\n numeric: true,\n sensitivity: \"base\",\n }) < 0\n );\n};\n"],
"mappings": "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