@liberfi.io/utils 0.2.6 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/chain.ts","../src/errors.ts","../src/dateTime.ts","../src/fetch.ts","../src/number.ts","../src/string.ts","../src/symbol.ts","../src/tokenProtocols.ts","../src/tokens.ts","../src/urls.ts","../src/timing.ts","../src/collection.ts"],"sourcesContent":["import { Chain, ChainNamespace } from \"@liberfi.io/types\";\n\n// ---------------------------------------------------------------------------\n// Namespace classification\n// ---------------------------------------------------------------------------\n\nconst solanaChains: ReadonlySet<Chain> = new Set([\n Chain.SOLANA,\n Chain.SOLANA_TESTNET,\n Chain.SOLANA_DEVNET,\n]);\n\nconst ethereumChains: ReadonlySet<Chain> = new Set([Chain.ETHEREUM]);\n\nconst binanceChains: ReadonlySet<Chain> = new Set([\n Chain.BINANCE,\n Chain.BINANCE_TESTNET,\n]);\n\n/** Returns the chain namespace (EVM or SOLANA) for a given chain. */\nexport function chainToNamespace(chain: Chain): ChainNamespace {\n return solanaChains.has(chain) ? ChainNamespace.SOLANA : ChainNamespace.EVM;\n}\n\nexport function isSolanaChain(chain: Chain): boolean {\n return solanaChains.has(chain);\n}\n\nexport function isEthereumChain(chain: Chain): boolean {\n return ethereumChains.has(chain);\n}\n\nexport function isBinanceChain(chain: Chain): boolean {\n return binanceChains.has(chain);\n}\n\n// ---------------------------------------------------------------------------\n// Single chain metadata registry\n// ---------------------------------------------------------------------------\n\n/** All per-chain metadata stored in one record. */\nexport interface ChainMetadata {\n /** Canonical lowercase slug (used in URLs and icon CDN). */\n slug: string;\n /** Optional short abbreviation (e.g. \"eth\" for Ethereum). Takes precedence over `slug` in display. */\n abbr?: string;\n /** Optional brand colour (hex). */\n color?: string;\n}\n\n/** Single source of truth for chain metadata. */\nexport const CHAIN_REGISTRY: Partial<Record<Chain, ChainMetadata>> = {\n [Chain.ETHEREUM]: {\n slug: \"ethereum\",\n abbr: \"eth\",\n color: \"#627EEA\",\n },\n [Chain.UBIQ]: { slug: \"ubiq\" },\n [Chain.OPTIMISM]: { slug: \"optimism\", abbr: \"opt\", color: \"#FF0420\" },\n [Chain.FLARE]: { slug: \"flare\" },\n [Chain.SONGBIRD]: { slug: \"songbird\" },\n [Chain.ELASTOS]: { slug: \"elastos\" },\n [Chain.KARDIA]: { slug: \"kardia\" },\n [Chain.CRONOS]: { slug: \"cronos\", color: \"#002D74\" },\n [Chain.RSK]: { slug: \"rsk\" },\n [Chain.TELOS]: { slug: \"telos\" },\n [Chain.LUKSO]: { slug: \"lukso\" },\n [Chain.CRAB]: { slug: \"crab\" },\n [Chain.DARWINIA]: { slug: \"darwinia\" },\n [Chain.XDC]: { slug: \"xdc\" },\n [Chain.CSC]: { slug: \"csc\" },\n [Chain.ZYX]: { slug: \"zyx\" },\n [Chain.BINANCE]: { slug: \"binance\", abbr: \"bsc\", color: \"#F0B90B\" },\n [Chain.SYSCOIN]: { slug: \"syscoin\" },\n [Chain.GOCHAIN]: { slug: \"gochain\" },\n [Chain.ETHEREUMCLASSIC]: { slug: \"ethereumclassic\" },\n [Chain.OKEXCHAIN]: { slug: \"okexchain\" },\n [Chain.HOO]: { slug: \"hoo\" },\n [Chain.METER]: { slug: \"meter\" },\n [Chain.NOVA_NETWORK]: { slug: \"nova network\" },\n [Chain.TOMOCHAIN]: { slug: \"tomochain\" },\n [Chain.BITKUB]: { slug: \"bitkub\" },\n [Chain.XDAI]: { slug: \"xdai\" },\n [Chain.SOLANA]: { slug: \"solana\", abbr: \"sol\", color: \"#9945FF\" },\n [Chain.VELAS]: { slug: \"velas\" },\n [Chain.THUNDERCORE]: { slug: \"thundercore\" },\n [Chain.ENULS]: { slug: \"enuls\" },\n [Chain.FUSE]: { slug: \"fuse\" },\n [Chain.HECO]: { slug: \"heco\" },\n [Chain.UNICHAIN]: { slug: \"unichain\" },\n [Chain.POLYGON]: { slug: \"polygon\", color: \"#8247E5\" },\n [Chain.SONIC]: { slug: \"sonic\", color: \"#5B6EF5\" },\n [Chain.SHIMMER_EVM]: { slug: \"shimmer_evm\" },\n [Chain.RBN]: { slug: \"rbn\" },\n [Chain.OMNI]: { slug: \"omni\" },\n [Chain.MANTA]: { slug: \"manta\" },\n [Chain.HSK]: { slug: \"hsk\" },\n [Chain.WATER]: { slug: \"water\" },\n [Chain.XLAYER]: { slug: \"xlayer\" },\n [Chain.XDAIARB]: { slug: \"xdaiarb\" },\n [Chain.OP_BNB]: { slug: \"op_bnb\" },\n [Chain.VINUCHAIN]: { slug: \"vinuchain\" },\n [Chain.ENERGYWEB]: { slug: \"energyweb\" },\n [Chain.OASYS]: { slug: \"oasys\" },\n [Chain.FANTOM]: { slug: \"fantom\" },\n [Chain.FRAXTAL]: { slug: \"fraxtal\" },\n [Chain.HPB]: { slug: \"hpb\" },\n [Chain.BOBA]: { slug: \"boba\" },\n [Chain.OMAX]: { slug: \"omax\" },\n [Chain.FILECOIN]: { slug: \"filecoin\" },\n [Chain.KUCOIN]: { slug: \"kucoin\" },\n [Chain.ZKSYNC_ERA]: { slug: \"zksync era\" },\n [Chain.SHIDEN]: { slug: \"shiden\" },\n [Chain.THETA]: { slug: \"theta\" },\n [Chain.PULSE]: { slug: \"pulse\" },\n [Chain.CRONOS_ZKEVM]: { slug: \"cronos zkevm\" },\n [Chain.SX]: { slug: \"sx\" },\n [Chain.AREON]: { slug: \"areon\" },\n [Chain.WC]: { slug: \"wc\" },\n [Chain.CANDLE]: { slug: \"candle\" },\n [Chain.ROLLUX]: { slug: \"rollux\" },\n [Chain.ASTAR]: { slug: \"astar\" },\n [Chain.REDSTONE]: { slug: \"redstone\" },\n [Chain.MATCHAIN]: { slug: \"matchain\" },\n [Chain.CALLISTO]: { slug: \"callisto\" },\n [Chain.TARA]: { slug: \"tara\" },\n [Chain.WANCHAIN]: { slug: \"wanchain\" },\n [Chain.LYRA_CHAIN]: { slug: \"lyra chain\" },\n [Chain.BIFROST]: { slug: \"bifrost\" },\n [Chain.CONFLUX]: { slug: \"conflux\" },\n [Chain.METIS]: { slug: \"metis\" },\n [Chain.DYMENSION]: { slug: \"dymension\" },\n [Chain.POLYGON_ZKEVM]: { slug: \"polygon zkevm\" },\n [Chain.CORE]: { slug: \"core\" },\n [Chain.LISK]: { slug: \"lisk\" },\n [Chain.ULTRON]: { slug: \"ultron\" },\n [Chain.STEP]: { slug: \"step\" },\n [Chain.MOONBEAM]: { slug: \"moonbeam\" },\n [Chain.MOONRIVER]: { slug: \"moonriver\" },\n [Chain.SEI]: { slug: \"sei\" },\n [Chain.LIVING_ASSETS_MAINNET]: { slug: \"living assets mainnet\" },\n [Chain.STY]: { slug: \"sty\" },\n [Chain.TENET]: { slug: \"tenet\" },\n [Chain.GRAVITY]: { slug: \"gravity\" },\n [Chain.REYA_NETWORK]: { slug: \"reya network\" },\n [Chain.SONEIUM]: { slug: \"soneium\" },\n [Chain.SWELLCHAIN]: { slug: \"swellchain\" },\n [Chain.ONUS]: { slug: \"onus\" },\n [Chain.HUBBLENET]: { slug: \"hubblenet\" },\n [Chain.SANKO]: { slug: \"sanko\" },\n [Chain.DOGECHAIN]: { slug: \"dogechain\" },\n [Chain.MILKOMEDA]: { slug: \"milkomeda\" },\n [Chain.MILKOMEDA_A1]: { slug: \"milkomeda_a1\" },\n [Chain.KAVA]: { slug: \"kava\" },\n [Chain.SOMA]: { slug: \"soma\" },\n [Chain.KARAK]: { slug: \"karak\" },\n [Chain.ABSTRACT]: { slug: \"abstract\" },\n [Chain.MORPH]: { slug: \"morph\" },\n [Chain.CROSSFI]: { slug: \"crossfi\" },\n [Chain.BEAM]: { slug: \"beam\" },\n [Chain.IOTEX]: { slug: \"iotex\" },\n [Chain.MANTLE]: { slug: \"mantle\" },\n [Chain.XLC]: { slug: \"xlc\" },\n [Chain.NAHMII]: { slug: \"nahmii\" },\n [Chain.BOUNCEBIT]: { slug: \"bouncebit\" },\n [Chain.TOMBCHAIN]: { slug: \"tombchain\" },\n [Chain.ZETACHAIN]: { slug: \"zetachain\" },\n [Chain.PLANQ]: { slug: \"planq\" },\n [Chain.BITROCK]: { slug: \"bitrock\" },\n [Chain.XSAT]: { slug: \"xsat\" },\n [Chain.CYETH]: { slug: \"cyeth\" },\n [Chain.CANTO]: { slug: \"canto\" },\n [Chain.KLAYTN]: { slug: \"klaytn\" },\n [Chain.THAT]: { slug: \"that\" },\n [Chain.BASE]: { slug: \"base\", color: \"#0052FF\" },\n [Chain.HELA]: { slug: \"hela\" },\n [Chain.IOTAEVM]: { slug: \"iotaevm\" },\n [Chain.JBC]: { slug: \"jbc\" },\n [Chain.EVMOS]: { slug: \"evmos\" },\n [Chain.CARBON]: { slug: \"carbon\" },\n [Chain.SMARTBCH]: { slug: \"smartbch\" },\n [Chain.ARTELA]: { slug: \"artela\" },\n [Chain.IMMUTABLE_ZKEVM]: { slug: \"immutable zkevm\" },\n [Chain.LOOP]: { slug: \"loop\" },\n [Chain.GENESYS]: { slug: \"genesys\" },\n [Chain.EOS_EVM]: { slug: \"eos evm\" },\n [Chain.MAP_PROTOCOL]: { slug: \"map protocol\" },\n [Chain.SAPPHIRE]: { slug: \"sapphire\" },\n [Chain.BITGERT]: { slug: \"bitgert\" },\n [Chain.FUSION]: { slug: \"fusion\" },\n [Chain.ZILLIQA]: { slug: \"zilliqa\" },\n [Chain.APECHAIN]: { slug: \"apechain\" },\n [Chain.EDU_CHAIN]: { slug: \"edu chain\" },\n [Chain.ARBITRUM]: { slug: \"arbitrum\", abbr: \"arb\", color: \"#28A0F0\" },\n [Chain.ARBITRUM_NOVA]: { slug: \"arbitrum nova\" },\n [Chain.CELO]: { slug: \"celo\" },\n [Chain.OASIS]: { slug: \"oasis\" },\n [Chain.ASSETCHAIN]: { slug: \"assetchain\" },\n [Chain.ETHERLINK]: { slug: \"etherlink\" },\n [Chain.AVALANCHE]: { slug: \"avalanche\", abbr: \"avax\", color: \"#E84142\" },\n [Chain.REI]: { slug: \"rei\" },\n [Chain.ZIRCUIT]: { slug: \"zircuit\" },\n [Chain.SOPHON]: { slug: \"sophon\" },\n [Chain.ETN]: { slug: \"etn\" },\n [Chain.SUPERPOSITION]: { slug: \"superposition\" },\n [Chain.REICHAIN]: { slug: \"reichain\" },\n [Chain.BOBA_BNB]: { slug: \"boba_bnb\" },\n [Chain.INK]: { slug: \"ink\" },\n [Chain.LINEA]: { slug: \"linea\", color: \"#61DFFF\" },\n [Chain.BOB]: { slug: \"bob\" },\n [Chain.GODWOKEN]: { slug: \"godwoken\" },\n [Chain.BERACHAIN]: { slug: \"berachain\", color: \"#964B00\" },\n [Chain.BLAST]: { slug: \"blast\", color: \"#FCFC03\" },\n [Chain.CHILIZ]: { slug: \"chiliz\" },\n [Chain.STRATIS]: { slug: \"stratis\" },\n [Chain.REAL]: { slug: \"real\" },\n [Chain.ODYSSEY]: { slug: \"odyssey\" },\n [Chain.TAIKO]: { slug: \"taiko\" },\n [Chain.BITLAYER]: { slug: \"bitlayer\" },\n [Chain.HYDRATION]: { slug: \"hydration\" },\n [Chain.PAREX]: { slug: \"parex\" },\n [Chain.POLIS]: { slug: \"polis\" },\n [Chain.KEKCHAIN]: { slug: \"kekchain\" },\n [Chain.SCROLL]: { slug: \"scroll\", color: \"#FFEEDA\" },\n [Chain.ZERO_NETWORK]: { slug: \"zero_network\" },\n [Chain.ZKLINK_NOVA]: { slug: \"zklink nova\" },\n [Chain.VISION]: { slug: \"vision\" },\n [Chain.SAAKURU]: { slug: \"saakuru\" },\n [Chain.ZORA]: { slug: \"zora\" },\n [Chain.CORN]: { slug: \"corn\" },\n [Chain.NEON]: { slug: \"neon\" },\n [Chain.LUMIA]: { slug: \"lumia\" },\n [Chain.AURORA]: { slug: \"aurora\" },\n [Chain.HARMONY]: { slug: \"harmony\" },\n [Chain.PALM]: { slug: \"palm\" },\n [Chain.ZENIQ]: { slug: \"zeniq\" },\n [Chain.CURIO]: { slug: \"curio\" },\n [Chain.MODE]: { slug: \"mode\" },\n};\n\n// ---------------------------------------------------------------------------\n// Derived lookups + accessors\n// ---------------------------------------------------------------------------\n\n/** Returns the brand colour for the chain, when defined. */\nexport function chainColor(chainId: Chain): string | undefined {\n return CHAIN_REGISTRY[chainId]?.color;\n}\n\n/** Returns the canonical slug for the chain, when defined. */\nexport function chainSlug(chainId: Chain): string | undefined {\n return CHAIN_REGISTRY[chainId]?.slug;\n}\n\n/**\n * Returns a CDN icon URL for the chain.\n * Accepts either a `Chain` enum value or a slug / abbreviation string.\n */\nexport function chainIcon(chain: Chain | string): string | undefined {\n const chainId = chainIdBySlug(chain) ?? chain;\n const slug = CHAIN_REGISTRY[chainId as Chain]?.slug;\n return slug\n ? `https://icons.llamao.fi/icons/chains/rsz_${encodeURIComponent(slug)}.jpg`\n : undefined;\n}\n\n/**\n * Returns a user-facing display name for the chain.\n * Prefers the uppercased abbreviation when defined, otherwise title-cases the slug.\n */\nexport function chainDisplayName(chainId: Chain): string {\n const meta = CHAIN_REGISTRY[chainId];\n if (!meta) return chainId;\n if (meta.abbr) return meta.abbr.toUpperCase();\n return meta.slug.replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n\n/**\n * Reverse lookup: slug or abbreviation → chain id.\n * Abbreviations take precedence over slugs when both are registered with the\n * same key.\n */\nconst slugToChainId: Map<string, Chain> = (() => {\n const map = new Map<string, Chain>();\n for (const [chainId, meta] of Object.entries(CHAIN_REGISTRY)) {\n if (meta?.abbr) map.set(meta.abbr.toLowerCase(), chainId as Chain);\n }\n for (const [chainId, meta] of Object.entries(CHAIN_REGISTRY)) {\n const key = meta?.slug.toLowerCase();\n if (key && !map.has(key)) map.set(key, chainId as Chain);\n }\n return map;\n})();\n\nexport function chainIdBySlug(slug: string): Chain | undefined {\n return slugToChainId.get(slug.toLowerCase());\n}\n\n// ---------------------------------------------------------------------------\n// Wallet address validation\n// ---------------------------------------------------------------------------\n\nexport function isValidWalletAddress(chain: Chain | string, addr: string) {\n const chainId = (chainIdBySlug(chain) ?? chain) as Chain;\n const namespace = chainToNamespace(chainId);\n switch (namespace) {\n case ChainNamespace.SOLANA:\n return isValidSolanaAddress(addr);\n case ChainNamespace.EVM:\n return isValidEvmAddress(addr);\n default:\n throw new Error(`Unsupported chain: ${chain}`);\n }\n}\n\nconst EVM_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;\n\nexport function isValidEvmAddress(value: string) {\n return EVM_ADDRESS_RE.test(value);\n}\n\nconst SOLANA_BASE58_RE = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;\n\nexport function isValidSolanaAddress(value: string): boolean {\n return SOLANA_BASE58_RE.test(value);\n}\n","/**\n * Error subclass raised by {@link httpRequest} when the server returns a\n * structured 400-class response with a `message` / `code` payload.\n */\nexport class ApiError extends Error {\n constructor(\n message: string,\n /** Application-level error code parsed from the response body. */\n public readonly code: number,\n /** HTTP status code returned by the server, when known. */\n public readonly status?: number,\n /** Raw parsed response body, when JSON. Useful for surfacing validation errors. */\n public readonly data?: unknown,\n ) {\n super(message);\n this.name = \"ApiError\";\n }\n}\n","const MINUTE = 60;\nconst HOUR = 60 * MINUTE;\nconst DAY = 24 * HOUR;\nconst YEAR = 365 * DAY;\n\nexport interface FormatAgeOptions {\n justNow?: string;\n secondsAgo?: string;\n minutesAgo?: string;\n hoursAgo?: string;\n daysAgo?: string;\n yearsAgo?: string;\n}\n\nconst defaultLabels: Required<FormatAgeOptions> = {\n justNow: \"just now\",\n secondsAgo: \"{n}s\",\n minutesAgo: \"{n}m\",\n hoursAgo: \"{n}h\",\n daysAgo: \"{n}d\",\n yearsAgo: \"{n}y\",\n};\n\n/**\n * Formats an age (elapsed time) given in **seconds** into a compact\n * human-readable string like \"3m\", \"2h\", or \"just now\".\n *\n * Use this when you already have the elapsed time in seconds (e.g. from\n * a server-provided `age` field). If you have milliseconds instead, use\n * {@link formatAge}.\n *\n * @example\n * formatAgeInSeconds(5) // \"just now\" (< 10s)\n * formatAgeInSeconds(45) // \"45s\"\n * formatAgeInSeconds(120) // \"2m\"\n * formatAgeInSeconds(7200) // \"2h\"\n * formatAgeInSeconds(172800) // \"2d\"\n * formatAgeInSeconds(63072000) // \"2y\"\n *\n * @example Custom labels (e.g. for i18n)\n * formatAgeInSeconds(120, { minutesAgo: \"{n} minutes ago\" }) // \"2 minutes ago\"\n */\nexport function formatAgeInSeconds(\n age: number,\n options: FormatAgeOptions = {},\n): string {\n const labels = { ...defaultLabels, ...options };\n\n if (age < 10) return labels.justNow;\n if (age < MINUTE) return labels.secondsAgo.replace(\"{n}\", String(age));\n\n if (age < HOUR) {\n return labels.minutesAgo.replace(\"{n}\", String(Math.floor(age / MINUTE)));\n }\n if (age < DAY) {\n return labels.hoursAgo.replace(\"{n}\", String(Math.floor(age / HOUR)));\n }\n if (age < YEAR) {\n return labels.daysAgo.replace(\"{n}\", String(Math.floor(age / DAY)));\n }\n return labels.yearsAgo.replace(\"{n}\", String(Math.floor(age / YEAR)));\n}\n\n/**\n * Formats an age (elapsed time) given in **milliseconds** into a compact\n * human-readable string. Internally converts to seconds and delegates to\n * {@link formatAgeInSeconds}.\n *\n * This is the primary function used across UI components to display how\n * long ago something happened (e.g. a trade, a tweet, a channel update).\n *\n * @example\n * formatAge(3000) // \"just now\" (3 s < 10 s threshold)\n * formatAge(45000) // \"45s\"\n * formatAge(120000) // \"2m\"\n * formatAge(7200000) // \"2h\"\n *\n * @example Custom labels (e.g. for i18n)\n * formatAge(120000, { minutesAgo: \"{n} 分钟前\" }) // \"2 分钟前\"\n */\nexport function formatAge(age: number, options: FormatAgeOptions = {}): string {\n return formatAgeInSeconds(Math.floor(age / 1000), options);\n}\n","import { ApiError } from \"./errors\";\n\ninterface ParsedErrorBody {\n message?: string;\n code?: number;\n [key: string]: unknown;\n}\n\n/**\n * Parse the response body as JSON when possible; otherwise return `undefined`.\n * Never throws — non-JSON bodies are tolerated.\n */\nasync function parseErrorBody(\n response: Response,\n): Promise<ParsedErrorBody | undefined> {\n const text = await response.text().catch(() => \"\");\n if (!text) return undefined;\n try {\n return JSON.parse(text) as ParsedErrorBody;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Generic HTTP request helper.\n *\n * On success returns the parsed JSON body typed as `R` (defaults to `unknown`).\n * On HTTP 400 responses throws {@link ApiError} populated with the response\n * `message`, `code`, HTTP status, and raw parsed body. On any other non-OK\n * response throws a plain `Error` with a best-effort message.\n */\nexport async function httpRequest<R = unknown>(\n url: string,\n options: RequestInit,\n): Promise<R> {\n if (!url.startsWith(\"http\")) {\n throw new Error(\"url must start with http(s)\");\n }\n const response = await fetch(url, {\n ...options,\n headers: _createHeaders(options.headers, options.method),\n });\n\n if (response.ok) {\n return (await response.json()) as R;\n }\n\n const body = await parseErrorBody(response);\n const message =\n body?.message ??\n (body?.code !== undefined ? String(body.code) : undefined) ??\n response.statusText;\n\n if (response.status === 400) {\n throw new ApiError(\n message,\n body?.code ?? response.status,\n response.status,\n body,\n );\n }\n throw new Error(message);\n}\n\nfunction _createHeaders(\n headers: HeadersInit = {},\n method?: string,\n): HeadersInit {\n const _headers = new Headers(headers);\n\n if (!_headers.has(\"Content-Type\")) {\n if (method !== \"DELETE\") {\n _headers.append(\"Content-Type\", \"application/json;charset=utf-8\");\n } else {\n _headers.append(\"Content-Type\", \"application/x-www-form-urlencoded\");\n }\n }\n\n return _headers;\n}\n\nexport async function httpGet<R = unknown>(\n url: string,\n options?: RequestInit,\n): Promise<R> {\n return await httpRequest<R>(url, {\n method: \"GET\",\n ...options,\n });\n}\n\nexport async function httpPost<R = unknown, P = unknown>(\n url: string,\n data: P,\n options?: Omit<RequestInit, \"method\">,\n): Promise<R> {\n return await httpRequest<R>(url, {\n method: \"POST\",\n body: JSON.stringify(data),\n ...options,\n });\n}\n\nexport async function httpPut<R = unknown, P = unknown>(\n url: string,\n data: P,\n options?: Omit<RequestInit, \"method\">,\n): Promise<R> {\n return await httpRequest<R>(url, {\n method: \"PUT\",\n body: JSON.stringify(data),\n ...options,\n });\n}\n\nexport async function httpDelete<R = unknown>(\n url: string,\n options?: Omit<RequestInit, \"method\">,\n): Promise<R> {\n return await httpRequest<R>(url, {\n method: \"DELETE\",\n ...options,\n });\n}\n\nexport async function httpMutate<R = unknown>(\n url: string,\n init: RequestInit,\n): Promise<R> {\n return await httpRequest<R>(url, init);\n}\n","import BigNumber from \"bignumber.js\";\n\n// ---------------------------------------------------------------------------\n// SafeBigNumber\n// ---------------------------------------------------------------------------\n\n/**\n * A `BigNumber` subclass that never throws on construction.\n *\n * - `undefined` / `null` → falls back to `0`.\n * - Strings that `BigNumber` can't parse (e.g. `\"not-a-number\"`) → falls back to `0`.\n * - Strings with extra trailing characters (e.g. `\"123abc\"`) → falls back to `0`\n * (because `BigNumber` itself returns NaN for these).\n * - Any unexpected throw inside `BigNumber`'s constructor is caught and treated as `0`.\n */\nexport class SafeBigNumber extends BigNumber {\n constructor(num?: BigNumber.Value, base?: number) {\n try {\n super(num ?? 0, base);\n if (this.isNaN()) {\n return new BigNumber(0, base) as SafeBigNumber;\n }\n } catch (e) {\n console.error(\"SafeBigNumber constructor error\", e);\n super(0, base);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\n/** Decimal number literal: optional sign, digits, optional `.frac`, optional `eN` exponent. */\nconst NUMERIC_STRING_RE = /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:e[+-]?\\d+)?$/i;\n\n/**\n * Returns `true` when the value can be unambiguously parsed as a finite number.\n *\n * Strings must be fully numeric decimal literals (after trimming). Permissive\n * partial parses such as `\"123abc\"`, hex prefixes like `\"0x10\"`, the literal\n * `\"Infinity\"`, or empty strings are rejected. Finite numbers and `BigNumber`\n * / `SafeBigNumber` instances are accepted.\n */\nexport const isValidNumber = (num: unknown): boolean => {\n if (typeof num === \"number\") return Number.isFinite(num);\n if (num instanceof SafeBigNumber || num instanceof BigNumber) {\n return !num.isNaN() && num.isFinite();\n }\n if (typeof num !== \"string\") return false;\n const trimmed = num.trim();\n if (trimmed === \"\") return false;\n if (!NUMERIC_STRING_RE.test(trimmed)) return false;\n return Number.isFinite(Number(trimmed));\n};\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nconst subscriptDigits = [\n \"₀\",\n \"₁\",\n \"₂\",\n \"₃\",\n \"₄\",\n \"₅\",\n \"₆\",\n \"₇\",\n \"₈\",\n \"₉\",\n \"₁₀\",\n \"₁₁\",\n \"₁₂\",\n \"₁₃\",\n \"₁₄\",\n \"₁₅\",\n \"₁₆\",\n \"₁₇\",\n \"₁₈\",\n \"₁₉\",\n \"₂₀\",\n \"₂₁\",\n \"₂₂\",\n \"₂₃\",\n \"₂₄\",\n \"₂₅\",\n \"₂₆\",\n \"₂₇\",\n \"₂₈\",\n \"₂₉\",\n \"₃₀\",\n \"₃₁\",\n \"₃₂\",\n \"₃₃\",\n \"₃₄\",\n \"₃₅\",\n \"₃₆\",\n \"₃₇\",\n \"₃₈\",\n \"₃₉\",\n \"₄₀\",\n];\n\nconst MAX_SUBSCRIPT_INDEX = subscriptDigits.length - 1;\n\n/**\n * Add thousand-separators (commas) and truncate to `precision` decimals.\n *\n * stringifyNumberWithGroupingSeparator(12345.6789, 2) → \"12,345.67\"\n */\nconst stringifyNumberWithGroupingSeparator = (\n num: BigNumber.Value,\n precision: number = 0,\n rounding: BigNumber.RoundingMode = BigNumber.ROUND_DOWN,\n) => {\n const bn = new SafeBigNumber(num);\n const parts = bn.decimalPlaces(precision, rounding).toString().split(\".\");\n parts[0] = parts[0].replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\n return parts.join(\".\");\n};\n\n/**\n * Abbreviate large numbers with K / M / B / T suffixes.\n *\n * stringifyNumberWithAbbreviation(1234) → \"1.2K\"\n * stringifyNumberWithAbbreviation(5_600_000) → \"5.6M\"\n */\nconst stringifyNumberWithAbbreviation = (\n num: BigNumber.Value,\n precision: number = 1,\n): string => {\n const bn = new SafeBigNumber(num);\n if (bn.lt(1e3)) return bn.toString();\n if (bn.lt(1e6))\n return `${stringifyNumberWithGroupingSeparator(bn.div(1e3), precision)}K`;\n if (bn.lt(1e9))\n return `${stringifyNumberWithGroupingSeparator(bn.div(1e6), precision)}M`;\n if (bn.lt(1e12))\n return `${stringifyNumberWithGroupingSeparator(bn.dividedBy(1e9), precision)}B`;\n return `${stringifyNumberWithGroupingSeparator(bn.dividedBy(1e12), precision)}T`;\n};\n\n/**\n * Display tiny decimals with Unicode subscript zero-count notation.\n * E.g. `0.00000382` → `\"0.0₅382\"` (5 leading zeros after the decimal).\n *\n * For extreme values where the leading-zero count exceeds the available\n * subscript glyph table, falls back to `\"0\"` rather than producing\n * `\"undefined\"` in the output.\n */\nconst stringifyNumberWithLeadingZeroSubscripts = (\n num: BigNumber.Value,\n precision: number = 5,\n) => {\n const bn = new SafeBigNumber(num);\n if (bn.eq(0)) return \"0\";\n const [integerPart, decimalPart] = bn.toFixed().split(\".\");\n const digits = decimalPart.split(\"\");\n const firstNonZeroIndex = digits.findIndex((num) => \"0\" !== num);\n if (firstNonZeroIndex < 0 || firstNonZeroIndex > MAX_SUBSCRIPT_INDEX) {\n return \"0\";\n }\n const precisionDigitsCount = Math.min(\n digits.length - firstNonZeroIndex,\n precision,\n );\n return `${stringifyNumberWithGroupingSeparator(integerPart)}.0`\n .concat(subscriptDigits[firstNonZeroIndex])\n .concat(\n digits\n .slice(firstNonZeroIndex, firstNonZeroIndex + precisionDigitsCount)\n .join(\"\")\n .replace(/\\.?0+$/, \"\"),\n );\n};\n\n/**\n * Round to `precision` *significant* decimal digits (skipping leading zeros).\n * E.g. `0.00456` with precision 2 → keeps 5 decimal places → `\"0.00456\"`.\n */\nconst stringifyNumberWithSignificantPrecision = (\n num: BigNumber,\n precision: number,\n) => {\n const matched = num.toString().match(/\\.0*/);\n const significantPrecision =\n (matched ? matched[0].length - 1 : 0) + precision;\n return stringifyNumberWithGroupingSeparator(num, significantPrecision);\n};\n\nconst stringifyPercent = (bn: BigNumber, precision: number) => {\n const scaled = bn\n .times(100)\n .decimalPlaces(precision, BigNumber.ROUND_HALF_UP);\n return `${stringifyNumberWithGroupingSeparator(scaled, precision)}%`;\n};\n\n// ---------------------------------------------------------------------------\n// Sign / validation wrapper shared by every amount formatter\n// ---------------------------------------------------------------------------\n\ntype FormatTier = (abs: SafeBigNumber) => string;\n\ninterface FormatWithSignOptions {\n showPlusGtThanZero?: boolean;\n /** String returned when the input is not a valid number. */\n invalidPlaceholder?: string;\n /** Returned as-is when the formatted absolute value collapses to zero. */\n zeroToken?: string;\n}\n\n/**\n * Shared validation / sign-handling wrapper for amount formatters.\n *\n * - Returns `invalidPlaceholder` when `isValidNumber(num)` is false.\n * - Computes the absolute value and passes it through `tier` for tier-specific formatting.\n * - Returns the formatted string as-is when it equals `zeroToken` (used to avoid `-$0`).\n * - Prefixes `\"-\"` for negatives, `\"+\"` for positives when `showPlusGtThanZero` is set.\n */\nconst formatWithSign = (\n num: BigNumber.Value,\n tier: FormatTier,\n options: FormatWithSignOptions,\n): string => {\n const { showPlusGtThanZero, invalidPlaceholder = \"--\", zeroToken } = options;\n if (!isValidNumber(num)) return invalidPlaceholder;\n\n const bn = new SafeBigNumber(num);\n const negative = bn.lt(0);\n const abs = bn.abs();\n const formatted = tier(abs);\n\n if (zeroToken !== undefined && formatted === zeroToken) return formatted;\n if (formatted === \"0\" || Number(formatted) === 0) return formatted;\n if (negative) return `-${formatted}`;\n if (showPlusGtThanZero) return `+${formatted}`;\n return formatted;\n};\n\n// ---------------------------------------------------------------------------\n// Public formatting functions\n// ---------------------------------------------------------------------------\n\nexport type FormatAmountOptions = {\n showPlusGtThanZero: boolean;\n};\n\nconst tierAmount: FormatTier = (abs) =>\n abs.lt(0.001)\n ? abs.decimalPlaces(5, BigNumber.ROUND_DOWN).toString()\n : abs.lt(1)\n ? abs.decimalPlaces(3, BigNumber.ROUND_DOWN).toString()\n : abs.lt(100)\n ? abs.decimalPlaces(2, BigNumber.ROUND_DOWN).toString()\n : abs.lt(1e5)\n ? stringifyNumberWithGroupingSeparator(abs, 2)\n : stringifyNumberWithAbbreviation(abs);\n\n/**\n * Format a raw token / asset amount (no currency symbol).\n *\n * Precision tiers (ROUND_DOWN):\n * | Range | Format | Example input → output |\n * |---------------|-------------------------|------------------------------|\n * | < 0.001 | 5 decimal places | 0.0001234 → \"0.00012\" |\n * | < 1 | 3 decimal places | 0.56789 → \"0.567\" |\n * | < 100 | 2 decimal places | 42.678 → \"42.67\" |\n * | < 100 000 | grouped, 2 dp | 12345.6 → \"12,345.60\" |\n * | ≥ 100 000 | abbreviated (K/M/B/T) | 1_500_000 → \"1.5M\" |\n *\n * @param num - The numeric value.\n * @param options.showPlusGtThanZero - Prefix positive values with \"+\".\n */\nexport const formatAmount = (\n num: BigNumber.Value = \"\",\n options: FormatAmountOptions = { showPlusGtThanZero: false },\n) =>\n formatWithSign(num, tierAmount, {\n showPlusGtThanZero: options?.showPlusGtThanZero,\n });\n\nconst tierAmountUSD: FormatTier = (abs) =>\n abs.lt(0.001)\n ? \"$0\"\n : abs.lt(1)\n ? `$${abs.decimalPlaces(3, BigNumber.ROUND_DOWN)}`\n : abs.lt(100)\n ? `$${abs.decimalPlaces(2, BigNumber.ROUND_DOWN)}`\n : abs.lt(1e4)\n ? `$${stringifyNumberWithGroupingSeparator(abs, 2)}`\n : `$${stringifyNumberWithAbbreviation(abs)}`;\n\n/**\n * Format a USD dollar amount with \"$\" prefix (standard precision).\n *\n * Precision tiers (ROUND_DOWN):\n * | Range | Format | Example input → output |\n * |---------------|-------------------------|------------------------------|\n * | < 0.001 | \"$0\" | 0.00001 → \"$0\" |\n * | < 1 | 3 decimal places | 0.56789 → \"$0.567\" |\n * | < 100 | 2 decimal places | 42.678 → \"$42.67\" |\n * | < 10 000 | grouped, 2 dp | 1234.5 → \"$1,234.50\" |\n * | ≥ 10 000 | abbreviated (K/M/B/T) | 1_500_000 → \"$1.5M\" |\n *\n * Use this for standard financial displays (volume, market cap, liquidity).\n *\n * @param num - The numeric value.\n * @param options.showPlusGtThanZero - Prefix positive values with \"+\".\n */\nexport const formatAmountUSD = (\n num: BigNumber.Value = \"\",\n options: FormatAmountOptions = { showPlusGtThanZero: false },\n) =>\n formatWithSign(num, tierAmountUSD, {\n showPlusGtThanZero: options?.showPlusGtThanZero,\n zeroToken: \"$0\",\n });\n\nconst tierAmountUSDCompact: FormatTier = (abs) => {\n if (abs.lt(0.001)) return \"$0\";\n if (abs.lt(1)) return `$${abs.decimalPlaces(3, BigNumber.ROUND_DOWN)}`;\n if (abs.lt(100)) return `$${abs.decimalPlaces(2, BigNumber.ROUND_DOWN)}`;\n if (abs.lt(1e3)) return `$${abs.decimalPlaces(0, BigNumber.ROUND_DOWN)}`;\n const roundedAbs = abs.div(100).integerValue(BigNumber.ROUND_DOWN).times(100);\n return `$${stringifyNumberWithAbbreviation(roundedAbs, 0)}`;\n};\n\n/**\n * Format a USD dollar amount with \"$\" prefix — **compact** variant.\n *\n * Compared to {@link formatAmountUSD}, this variant is more aggressively\n * rounded and suited for space-constrained UIs (cards, badges, list items):\n *\n * | Range | Format | Example input → output |\n * |---------------|-------------------------|------------------------------|\n * | < 0.001 | \"$0\" | 0.00001 → \"$0\" |\n * | < 1 | 3 decimal places | 0.56789 → \"$0.567\" |\n * | < 100 | 2 decimal places | 42.678 → \"$42.67\" |\n * | < 1 000 | 0 decimal places | 567.89 → \"$567\" |\n * | ≥ 1 000 | abbreviated, 0 dp, | 15 678 → \"$15.6K\" |\n * | | rounded to nearest 100 | 1 234 567 → \"$1.2M\" |\n *\n * Key differences from `formatAmountUSD`:\n * - 100–1 000: shows 0 dp instead of 2 dp\n * - ≥ 1 000: abbreviates earlier (1K vs 10K) with 0 precision, rounded to 100s\n *\n * @param num - The numeric value.\n * @param options.showPlusGtThanZero - Prefix positive values with \"+\".\n */\nexport const formatAmountUSDCompact = (\n num: BigNumber.Value = \"\",\n options: FormatAmountOptions = { showPlusGtThanZero: false },\n) =>\n formatWithSign(num, tierAmountUSDCompact, {\n showPlusGtThanZero: options?.showPlusGtThanZero,\n zeroToken: \"$0\",\n });\n\nexport type FormatPriceOptions = {\n isHighPrecise: boolean;\n};\n\n/**\n * Shared tier for {@link formatPrice} and {@link formatPriceUSD}: identical\n * precision ladder, with only the leading `\"$\"` differing between the two.\n */\nconst tierPrice = (isHighPrecise: boolean): FormatTier => {\n return (abs) =>\n abs.lt(1e-4)\n ? stringifyNumberWithLeadingZeroSubscripts(abs, isHighPrecise ? 4 : 2)\n : abs.lt(1)\n ? isHighPrecise\n ? stringifyNumberWithGroupingSeparator(abs, 4)\n : stringifyNumberWithSignificantPrecision(abs, 2)\n : abs.lt(100) || abs.lt(1e4)\n ? stringifyNumberWithGroupingSeparator(abs, isHighPrecise ? 4 : 2)\n : abs.lt(1e5)\n ? stringifyNumberWithGroupingSeparator(abs, 2)\n : stringifyNumberWithAbbreviation(abs);\n};\n\n/**\n * Format a token price (no currency symbol). Negative inputs render as `\"--\"`.\n *\n * Same precision tiers as {@link formatPriceUSD} but without the \"$\" prefix.\n *\n * @param num - The price value.\n * @param options.isHighPrecise - Use high-precision mode (default: true).\n */\nexport const formatPrice = (\n num: BigNumber.Value = \"\",\n options: FormatPriceOptions = { isHighPrecise: true },\n) => {\n if (!isValidNumber(num)) return \"--\";\n const bn = new SafeBigNumber(num);\n if (bn.lt(0)) return \"--\";\n return tierPrice(options.isHighPrecise)(bn.abs());\n};\n\n/**\n * Format a token price with \"$\" prefix. Negative inputs render as `\"--\"`.\n *\n * Two precision modes controlled by `isHighPrecise` (default: `true`):\n *\n * | Range | High precision (default) | Low precision |\n * |---------------|-------------------------------|------------------------------|\n * | < 0.0001 | subscript notation, 4 sig | subscript notation, 2 sig |\n * | | 0.0000382 → \"$0.0₄382\" | 0.0000382 → \"$0.0₄38\" |\n * | < 1 | 4 dp, grouped | 2 significant dp |\n * | | 0.12345 → \"$0.1234\" | 0.12345 → \"$0.12\" |\n * | < 10 000 | 4 dp, grouped | 2 dp, grouped |\n * | | 1234.567 → \"$1,234.5670\" | 1234.567 → \"$1,234.56\" |\n * | < 100 000 | 2 dp, grouped | 2 dp, grouped |\n * | ≥ 100 000 | abbreviated (K/M/B/T) | abbreviated (K/M/B/T) |\n *\n * @param num - The price value.\n * @param options.isHighPrecise - Use high-precision mode (default: true).\n */\nexport const formatPriceUSD = (\n num: BigNumber.Value = \"\",\n options: FormatPriceOptions = { isHighPrecise: true },\n) => {\n if (!isValidNumber(num)) return \"--\";\n const bn = new SafeBigNumber(num);\n if (bn.lt(0)) return \"--\";\n return `$${tierPrice(options.isHighPrecise)(bn.abs())}`;\n};\n\nexport type FormatPercentOptions = {\n showPlusGtThanZero?: boolean;\n precision?: number;\n};\n\n/**\n * Format a ratio as a percentage string.\n *\n * The input is a **ratio** (0.3 = 30%, 1.5 = 150%).\n *\n * | Input range | Output example |\n * |---------------|-----------------------------------------|\n * | < 0.0001 | \"0%\" |\n * | < 100 | \"56.79%\" (2 dp by default) |\n * | < 1000 | \"15,000.5%\" (1 dp by default) |\n * | ≥ 1000 | \"> 99,999%\" |\n *\n * Large values use thousand-grouping separators (e.g. `\"15,000%\"`).\n *\n * @param num - The ratio value (0.3 means 30%).\n * @param options.showPlusGtThanZero - Prefix positive values with \"+\".\n * @param options.precision - Decimal precision override.\n */\nexport const formatPercent = (\n num: BigNumber.Value = \"\",\n options: FormatPercentOptions = {},\n) => {\n if (!isValidNumber(num)) return \"-- %\";\n\n const bn = new SafeBigNumber(num);\n const negative = bn.lt(0);\n const abs = bn.abs();\n const sign = negative ? \"-\" : options?.showPlusGtThanZero ? \"+\" : \"\";\n\n if (abs.lt(1e-4)) return \"0%\";\n if (abs.lt(100))\n return `${sign}${stringifyPercent(abs, options?.precision ?? 2)}`;\n if (abs.lt(1e3))\n return `${sign}${stringifyPercent(abs, options?.precision ?? 1)}`;\n return `${sign}> 99,999%`;\n};\n","/**\n * Capitalize the first letter of a string, lowercasing the rest.\n *\n * @example\n * capitalize(\"hello\") // \"Hello\"\n * capitalize(\"hELLO\") // \"Hello\"\n * capitalize(\"solana\") // \"Solana\"\n */\nexport function capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();\n}\n\n/**\n * Truncate an address (or any string) to show the first `start` and last `end`\n * characters with \"...\" in between.\n *\n * @param address - The full address string.\n * @param start - Number of characters to keep from the beginning (default 6).\n * @param end - Number of characters to keep from the end (default 4).\n *\n * @example\n * truncateAddress(\"0x1234567890abcdef1234567890abcdef12345678\")\n * // \"0x1234...5678\"\n *\n * truncateAddress(\"0x1234567890abcdef1234567890abcdef12345678\", 4, 4)\n * // \"0x12...5678\"\n */\nexport function truncateAddress(\n address: string,\n start: number = 6,\n end: number = 4,\n): string {\n return address.slice(0, start) + \"...\" + address.slice(-end);\n}\n","/** Single regex used to replace every placeholder occurrence in one pass. */\nconst SYMBOL_PLACEHOLDER_RE = /\\{?\\b(type|base|quote)\\b\\}?/g;\n\n/**\n * Format trading pair symbol.\n *\n * Splits a symbol like `\"PERP_BTC_USDT\"` into `type`/`base`/`quote` parts and\n * substitutes them into the format template. Placeholders may be written either\n * as bare words (`type`, `base`, `quote`) or with curly braces (`{type}`,\n * `{base}`, `{quote}`). All placeholder occurrences are replaced in a single\n * pass, so substitutions cannot interfere with each other even if the\n * substituted value happens to contain another placeholder substring.\n *\n * @param symbol - Original trading pair symbol in format `\"type_base_quote\"` (e.g. `\"PERP_BTC_USDT\"`).\n * @param formatString - Format string template; defaults to `\"base-type\"`.\n *\n * @returns Formatted string, or `\"\"` if `symbol` is empty.\n *\n * @example\n * ```typescript\n * formatSymbol(\"PERP_BTC_USDT\") // \"BTC-PERP\" (default \"base-type\")\n * formatSymbol(\"PERP_BTC_USDT\", \"base\") // \"BTC\"\n * formatSymbol(\"PERP_BTC_USDT\", \"base-type\") // \"BTC-PERP\"\n * formatSymbol(\"SPOT_ETH_USDC\", \"base-quote\") // \"ETH-USDC\"\n * formatSymbol(\"SPOT_ETH_USDC\", \"{base}/{quote}\") // \"ETH/USDC\"\n * ```\n */\nexport function formatSymbol(\n symbol: string,\n formatString: string = \"base-type\",\n): string {\n if (!symbol) return \"\";\n\n const [type = \"\", base = \"\", quote = \"\"] = symbol.split(\"_\");\n\n return formatString.replace(SYMBOL_PLACEHOLDER_RE, (_, key) => {\n if (key === \"type\") return type;\n if (key === \"base\") return base;\n return quote;\n });\n}\n","import {\n Chain,\n SOLANA_TOKEN_PROTOCOLS,\n TokenProtocol,\n} from \"@liberfi.io/types\";\n\nconst SOLANA_PROTOCOL_SET = new Set<string>(SOLANA_TOKEN_PROTOCOLS);\n\n/** Sorted by length descending so \"pump-amm\" is tested before \"pump\". */\nconst SOLANA_PROTOCOLS_BY_SPECIFICITY = [...SOLANA_TOKEN_PROTOCOLS].sort(\n (a, b) => b.length - a.length,\n);\n\nexport const parseTokenProtocolFamily = (\n chain: Chain,\n protocolFamily: string,\n): TokenProtocol | undefined => {\n if (chain !== Chain.SOLANA) return undefined;\n\n const normalized = protocolFamily.toLowerCase();\n\n if (SOLANA_PROTOCOL_SET.has(normalized)) {\n return normalized as TokenProtocol;\n }\n\n return SOLANA_PROTOCOLS_BY_SPECIFICITY.find((p) => normalized.includes(p));\n};\n\nexport const formatTokenProtocolName = (protocol: TokenProtocol): string => {\n return protocol\n .split(\"-\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \");\n};\n","import { Chain } from \"@liberfi.io/types\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface PredefinedToken {\n address: string;\n symbol: string;\n decimals: number;\n}\n\nexport interface ChainPredefinedTokens {\n native: PredefinedToken;\n wrapped: PredefinedToken;\n stablecoins: Record<string, PredefinedToken>;\n}\n\n// ---------------------------------------------------------------------------\n// EVM common\n// ---------------------------------------------------------------------------\n\nconst EVM_NATIVE_ADDRESS = \"0x0000000000000000000000000000000000000000\";\n\n// ---------------------------------------------------------------------------\n// Solana\n// ---------------------------------------------------------------------------\n\nexport const SOLANA_TOKENS: ChainPredefinedTokens = {\n native: {\n address: \"11111111111111111111111111111111\",\n symbol: \"SOL\",\n decimals: 9,\n },\n wrapped: {\n address: \"So11111111111111111111111111111111111111112\",\n symbol: \"SOL\",\n decimals: 9,\n },\n stablecoins: {\n USDC: {\n address: \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\",\n symbol: \"USDC\",\n decimals: 6,\n },\n USDT: {\n address: \"Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB\",\n symbol: \"USDT\",\n decimals: 6,\n },\n USD1: {\n address: \"USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB\",\n symbol: \"USD1\",\n decimals: 6,\n },\n },\n};\n\n// ---------------------------------------------------------------------------\n// Ethereum\n// ---------------------------------------------------------------------------\n\nexport const ETHEREUM_TOKENS: ChainPredefinedTokens = {\n native: {\n address: EVM_NATIVE_ADDRESS,\n symbol: \"ETH\",\n decimals: 18,\n },\n wrapped: {\n address: \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\",\n symbol: \"WETH\",\n decimals: 18,\n },\n stablecoins: {\n USDC: {\n address: \"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\",\n symbol: \"USDC\",\n decimals: 6,\n },\n USDT: {\n address: \"0xdAC17F958D2ee523a2206206994597C13D831ec7\",\n symbol: \"USDT\",\n decimals: 6,\n },\n },\n};\n\n// ---------------------------------------------------------------------------\n// BSC (Binance Smart Chain)\n// ---------------------------------------------------------------------------\n\nexport const BSC_TOKENS: ChainPredefinedTokens = {\n native: {\n address: EVM_NATIVE_ADDRESS,\n symbol: \"BNB\",\n decimals: 18,\n },\n wrapped: {\n address: \"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c\",\n symbol: \"WBNB\",\n decimals: 18,\n },\n stablecoins: {\n USDC: {\n address: \"0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d\",\n symbol: \"USDC\",\n decimals: 18,\n },\n USDT: {\n address: \"0x55d398326f99059fF775485246999027B3197955\",\n symbol: \"USDT\",\n decimals: 18,\n },\n },\n};\n\n// ---------------------------------------------------------------------------\n// Arbitrum\n// ---------------------------------------------------------------------------\n\nexport const ARBITRUM_TOKENS: ChainPredefinedTokens = {\n native: {\n address: EVM_NATIVE_ADDRESS,\n symbol: \"ETH\",\n decimals: 18,\n },\n wrapped: {\n address: \"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1\",\n symbol: \"WETH\",\n decimals: 18,\n },\n stablecoins: {\n USDC: {\n address: \"0xaf88d065e77c8cC2239327C5EDb3A432268e5831\",\n symbol: \"USDC\",\n decimals: 6,\n },\n USDT: {\n address: \"0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9\",\n symbol: \"USDT\",\n decimals: 6,\n },\n },\n};\n\n// ---------------------------------------------------------------------------\n// Optimism\n// ---------------------------------------------------------------------------\n\nexport const OPTIMISM_TOKENS: ChainPredefinedTokens = {\n native: {\n address: EVM_NATIVE_ADDRESS,\n symbol: \"ETH\",\n decimals: 18,\n },\n wrapped: {\n address: \"0x4200000000000000000000000000000000000006\",\n symbol: \"WETH\",\n decimals: 18,\n },\n stablecoins: {\n USDC: {\n address: \"0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85\",\n symbol: \"USDC\",\n decimals: 6,\n },\n USDT: {\n address: \"0x94b008aA00579c1307B0EF2c499aD98a8ce58e58\",\n symbol: \"USDT\",\n decimals: 6,\n },\n },\n};\n\n// ---------------------------------------------------------------------------\n// Avalanche\n// ---------------------------------------------------------------------------\n\nexport const AVALANCHE_TOKENS: ChainPredefinedTokens = {\n native: {\n address: EVM_NATIVE_ADDRESS,\n symbol: \"AVAX\",\n decimals: 18,\n },\n wrapped: {\n address: \"0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7\",\n symbol: \"WAVAX\",\n decimals: 18,\n },\n stablecoins: {\n USDC: {\n address: \"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E\",\n symbol: \"USDC\",\n decimals: 6,\n },\n USDT: {\n address: \"0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7\",\n symbol: \"USDT\",\n decimals: 6,\n },\n },\n};\n\n// ---------------------------------------------------------------------------\n// Chain -> Tokens index\n// ---------------------------------------------------------------------------\n\nexport const CHAIN_TOKENS: Partial<Record<Chain, ChainPredefinedTokens>> = {\n [Chain.SOLANA]: SOLANA_TOKENS,\n [Chain.ETHEREUM]: ETHEREUM_TOKENS,\n [Chain.BINANCE]: BSC_TOKENS,\n [Chain.ARBITRUM]: ARBITRUM_TOKENS,\n [Chain.OPTIMISM]: OPTIMISM_TOKENS,\n [Chain.AVALANCHE]: AVALANCHE_TOKENS,\n};\n\n// ---------------------------------------------------------------------------\n// Helper functions\n// ---------------------------------------------------------------------------\n\nexport function getNativeToken(chain: Chain): PredefinedToken | undefined {\n return CHAIN_TOKENS[chain]?.native;\n}\n\nexport function getWrappedToken(chain: Chain): PredefinedToken | undefined {\n return CHAIN_TOKENS[chain]?.wrapped;\n}\n\nexport function getStablecoins(\n chain: Chain,\n): Record<string, PredefinedToken> | undefined {\n return CHAIN_TOKENS[chain]?.stablecoins;\n}\n\n/** Returns all predefined token addresses for the given chain (native + wrapped + stablecoins). */\nexport function getCommonTokenAddresses(chain: Chain): string[] {\n const tokens = CHAIN_TOKENS[chain];\n if (!tokens) return [];\n return [\n tokens.native.address,\n tokens.wrapped.address,\n ...Object.values(tokens.stablecoins).map((t) => t.address),\n ];\n}\n\n/** Returns an address -> symbol map for all predefined tokens on the given chain. */\nexport function getCommonTokenSymbolsMap(chain: Chain): Record<string, string> {\n const tokens = CHAIN_TOKENS[chain];\n if (!tokens) return {};\n const map: Record<string, string> = {\n [tokens.native.address]: tokens.native.symbol,\n [tokens.wrapped.address]: tokens.wrapped.symbol,\n };\n for (const t of Object.values(tokens.stablecoins)) {\n map[t.address] = t.symbol;\n }\n return map;\n}\n","import { Chain } from \"@liberfi.io/types\";\n\nconst TX_EXPLORER_URLS: Partial<Record<Chain, string>> = {\n [Chain.SOLANA]: \"https://solscan.io/tx/\",\n [Chain.ETHEREUM]: \"https://etherscan.io/tx/\",\n [Chain.POLYGON]: \"https://polygonscan.com/tx/\",\n [Chain.BINANCE]: \"https://bscscan.com/tx/\",\n [Chain.BINANCE_TESTNET]: \"https://testnet.bscscan.com/tx/\",\n [Chain.AVALANCHE]: \"https://snowtrace.io/tx/\",\n [Chain.BASE]: \"https://basescan.org/tx/\",\n [Chain.BLAST]: \"https://blastracker.xyz/tx/\",\n [Chain.ARBITRUM]: \"https://arbiscan.io/tx/\",\n [Chain.ARBITRUM_NOVA]: \"https://nova.arbiscan.io/tx/\",\n [Chain.ARBITRUM_TESTNET_GOERLI]: \"https://goerli.arbiscan.io/tx/\",\n [Chain.ARBITRUM_TESTNET_SEPOLIA]: \"https://sepolia.arbiscan.io/tx/\",\n};\n\nconst ACCOUNT_EXPLORER_URLS: Partial<Record<Chain, string>> = {\n [Chain.SOLANA]: \"https://solscan.io/account/\",\n [Chain.ETHEREUM]: \"https://etherscan.io/address/\",\n [Chain.POLYGON]: \"https://polygonscan.com/address/\",\n [Chain.BINANCE]: \"https://bscscan.com/address/\",\n [Chain.BINANCE_TESTNET]: \"https://testnet.bscscan.com/address/\",\n [Chain.AVALANCHE]: \"https://snowtrace.io/address/\",\n [Chain.BASE]: \"https://basescan.org/address/\",\n [Chain.BLAST]: \"https://blastracker.xyz/address/\",\n [Chain.ARBITRUM]: \"https://arbiscan.io/address/\",\n [Chain.ARBITRUM_NOVA]: \"https://nova.arbiscan.io/address/\",\n [Chain.ARBITRUM_TESTNET_GOERLI]: \"https://goerli.arbiscan.io/address/\",\n [Chain.ARBITRUM_TESTNET_SEPOLIA]: \"https://sepolia.arbiscan.io/address/\",\n};\n\nfunction explorerUrl(\n urls: Partial<Record<Chain, string>>,\n chainId: Chain,\n value: string,\n): string | undefined {\n const base = urls[chainId];\n return base ? `${base}${value}` : undefined;\n}\n\nexport function txExplorerUrl(\n chainId: Chain,\n txHash: string,\n): string | undefined {\n return explorerUrl(TX_EXPLORER_URLS, chainId, txHash);\n}\n\nexport function accountExplorerUrl(\n chainId: Chain,\n account: string,\n): string | undefined {\n return explorerUrl(ACCOUNT_EXPLORER_URLS, chainId, account);\n}\n\nexport function searchImageUrl(image: string): string {\n return `https://lens.google.com/uploadbyurl?url=${encodeURIComponent(image)}`;\n}\n\nexport function searchTwitterUrl(q: string): string {\n return `https://x.com/search?q=${encodeURIComponent(q)}`;\n}\n\nexport function twitterUserUrl(username: string): string {\n return `https://x.com/${username}`;\n}\n\nexport function twitterTweetUrl(id: string): string {\n return `https://x.com/i/status/${id}`;\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\nexport function throttle<T extends (...args: any[]) => void>(\n fn: T,\n wait: number,\n): T {\n let lastCallTime = 0;\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let lastArgs: Parameters<T> | null = null;\n\n const throttled = (...args: Parameters<T>) => {\n const now = Date.now();\n const remaining = wait - (now - lastCallTime);\n\n if (remaining <= 0) {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n lastCallTime = now;\n fn(...args);\n } else {\n lastArgs = args;\n if (timeoutId === null) {\n timeoutId = setTimeout(() => {\n lastCallTime = Date.now();\n timeoutId = null;\n if (lastArgs) {\n fn(...lastArgs);\n lastArgs = null;\n }\n }, remaining);\n }\n }\n };\n\n return throttled as T;\n}\n\nexport type DebouncedFunction<T extends (...args: any[]) => void> = T & {\n cancel: () => void;\n};\n\nexport function debounce<T extends (...args: any[]) => void>(\n fn: T,\n wait: number,\n): DebouncedFunction<T> {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const debounced = (...args: Parameters<T>) => {\n if (timeoutId !== null) clearTimeout(timeoutId);\n timeoutId = setTimeout(() => {\n timeoutId = null;\n fn(...args);\n }, wait);\n };\n\n debounced.cancel = () => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n };\n\n return debounced as DebouncedFunction<T>;\n}\n","/** Accepts either a key-extractor function or a property name. */\ntype Iteratee<T, R> = ((item: T) => R) | keyof T;\n\n/**\n * Normalize an `Iteratee` into a plain getter function.\n *\n * @param iteratee - Function or property key.\n * @param stringify - If `true`, the value extracted via a property key is wrapped\n * in `String(...)` (used by `keyBy` / `groupBy`).\n */\nfunction asGetter<T, R>(\n iteratee: Iteratee<T, R>,\n stringify = false,\n): (item: T) => R {\n if (typeof iteratee === \"function\") return iteratee;\n return stringify\n ? (item: T) => String(item[iteratee]) as R\n : (item: T) => item[iteratee] as R;\n}\n\nexport function uniqBy<T>(array: T[], iteratee: Iteratee<T, unknown>): T[] {\n const getter = asGetter(iteratee);\n const seen = new Set<unknown>();\n return array.filter((item) => {\n const key = getter(item);\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\nexport function intersectionBy<T>(\n a: T[],\n b: T[],\n iteratee: Iteratee<T, unknown>,\n): T[] {\n const getter = asGetter(iteratee);\n const bKeys = new Set(b.map(getter));\n return a.filter((item) => bKeys.has(getter(item)));\n}\n\nexport function keyBy<T>(\n array: T[],\n iteratee: Iteratee<T, string>,\n): Record<string, T> {\n const getter = asGetter(iteratee, true);\n const result: Record<string, T> = {};\n for (const item of array) {\n result[getter(item)] = item;\n }\n return result;\n}\n\nexport function groupBy<T>(\n array: T[],\n iteratee: Iteratee<T, string>,\n): Record<string, T[]> {\n const getter = asGetter(iteratee, true);\n const result: Record<string, T[]> = {};\n for (const item of array) {\n const key = getter(item);\n (result[key] ??= []).push(item);\n }\n return result;\n}\n\nexport function mapKeys<T>(\n obj: Record<string, T>,\n iteratee: (value: T, key: string) => string,\n): Record<string, T> {\n const result: Record<string, T> = {};\n for (const key of Object.keys(obj)) {\n result[iteratee(obj[key], key)] = obj[key];\n }\n return result;\n}\n\nexport function mapValues<T, R>(\n obj: Record<string, T>,\n iteratee: (value: T, key: string) => R,\n): Record<string, R> {\n const result: Record<string, R> = {};\n for (const key of Object.keys(obj)) {\n result[key] = iteratee(obj[key], key);\n }\n return result;\n}\n"],"mappings":"AAAA,OAAS,SAAAA,EAAO,kBAAAC,MAAsB,oBAMtC,IAAMC,EAAmC,IAAI,IAAI,CAC/CF,EAAM,OACNA,EAAM,eACNA,EAAM,aACR,CAAC,EAEKG,EAAqC,IAAI,IAAI,CAACH,EAAM,QAAQ,CAAC,EAE7DI,EAAoC,IAAI,IAAI,CAChDJ,EAAM,QACNA,EAAM,eACR,CAAC,EAGM,SAASK,EAAiBC,EAA8B,CAC7D,OAAOJ,EAAa,IAAII,CAAK,EAAIL,EAAe,OAASA,EAAe,GAC1E,CAEO,SAASM,GAAcD,EAAuB,CACnD,OAAOJ,EAAa,IAAII,CAAK,CAC/B,CAEO,SAASE,GAAgBF,EAAuB,CACrD,OAAOH,EAAe,IAAIG,CAAK,CACjC,CAEO,SAASG,GAAeH,EAAuB,CACpD,OAAOF,EAAc,IAAIE,CAAK,CAChC,CAiBO,IAAMI,EAAwD,CACnE,CAACV,EAAM,QAAQ,EAAG,CAChB,KAAM,WACN,KAAM,MACN,MAAO,SACT,EACA,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,QAAQ,EAAG,CAAE,KAAM,WAAY,KAAM,MAAO,MAAO,SAAU,EACpE,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,QAAQ,EAAG,CAAE,KAAM,UAAW,EACrC,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,QAAS,EACjC,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,SAAU,MAAO,SAAU,EACnD,CAACA,EAAM,GAAG,EAAG,CAAE,KAAM,KAAM,EAC3B,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,QAAQ,EAAG,CAAE,KAAM,UAAW,EACrC,CAACA,EAAM,GAAG,EAAG,CAAE,KAAM,KAAM,EAC3B,CAACA,EAAM,GAAG,EAAG,CAAE,KAAM,KAAM,EAC3B,CAACA,EAAM,GAAG,EAAG,CAAE,KAAM,KAAM,EAC3B,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,UAAW,KAAM,MAAO,MAAO,SAAU,EAClE,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,eAAe,EAAG,CAAE,KAAM,iBAAkB,EACnD,CAACA,EAAM,SAAS,EAAG,CAAE,KAAM,WAAY,EACvC,CAACA,EAAM,GAAG,EAAG,CAAE,KAAM,KAAM,EAC3B,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,YAAY,EAAG,CAAE,KAAM,cAAe,EAC7C,CAACA,EAAM,SAAS,EAAG,CAAE,KAAM,WAAY,EACvC,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,QAAS,EACjC,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,SAAU,KAAM,MAAO,MAAO,SAAU,EAChE,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,WAAW,EAAG,CAAE,KAAM,aAAc,EAC3C,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,QAAQ,EAAG,CAAE,KAAM,UAAW,EACrC,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,UAAW,MAAO,SAAU,EACrD,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,QAAS,MAAO,SAAU,EACjD,CAACA,EAAM,WAAW,EAAG,CAAE,KAAM,aAAc,EAC3C,CAACA,EAAM,GAAG,EAAG,CAAE,KAAM,KAAM,EAC3B,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,GAAG,EAAG,CAAE,KAAM,KAAM,EAC3B,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,QAAS,EACjC,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,QAAS,EACjC,CAACA,EAAM,SAAS,EAAG,CAAE,KAAM,WAAY,EACvC,CAACA,EAAM,SAAS,EAAG,CAAE,KAAM,WAAY,EACvC,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,QAAS,EACjC,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,GAAG,EAAG,CAAE,KAAM,KAAM,EAC3B,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,QAAQ,EAAG,CAAE,KAAM,UAAW,EACrC,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,QAAS,EACjC,CAACA,EAAM,UAAU,EAAG,CAAE,KAAM,YAAa,EACzC,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,QAAS,EACjC,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,YAAY,EAAG,CAAE,KAAM,cAAe,EAC7C,CAACA,EAAM,EAAE,EAAG,CAAE,KAAM,IAAK,EACzB,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,EAAE,EAAG,CAAE,KAAM,IAAK,EACzB,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,QAAS,EACjC,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,QAAS,EACjC,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,QAAQ,EAAG,CAAE,KAAM,UAAW,EACrC,CAACA,EAAM,QAAQ,EAAG,CAAE,KAAM,UAAW,EACrC,CAACA,EAAM,QAAQ,EAAG,CAAE,KAAM,UAAW,EACrC,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,QAAQ,EAAG,CAAE,KAAM,UAAW,EACrC,CAACA,EAAM,UAAU,EAAG,CAAE,KAAM,YAAa,EACzC,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,SAAS,EAAG,CAAE,KAAM,WAAY,EACvC,CAACA,EAAM,aAAa,EAAG,CAAE,KAAM,eAAgB,EAC/C,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,QAAS,EACjC,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,QAAQ,EAAG,CAAE,KAAM,UAAW,EACrC,CAACA,EAAM,SAAS,EAAG,CAAE,KAAM,WAAY,EACvC,CAACA,EAAM,GAAG,EAAG,CAAE,KAAM,KAAM,EAC3B,CAACA,EAAM,qBAAqB,EAAG,CAAE,KAAM,uBAAwB,EAC/D,CAACA,EAAM,GAAG,EAAG,CAAE,KAAM,KAAM,EAC3B,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,YAAY,EAAG,CAAE,KAAM,cAAe,EAC7C,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,UAAU,EAAG,CAAE,KAAM,YAAa,EACzC,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,SAAS,EAAG,CAAE,KAAM,WAAY,EACvC,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,SAAS,EAAG,CAAE,KAAM,WAAY,EACvC,CAACA,EAAM,SAAS,EAAG,CAAE,KAAM,WAAY,EACvC,CAACA,EAAM,YAAY,EAAG,CAAE,KAAM,cAAe,EAC7C,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,QAAQ,EAAG,CAAE,KAAM,UAAW,EACrC,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,QAAS,EACjC,CAACA,EAAM,GAAG,EAAG,CAAE,KAAM,KAAM,EAC3B,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,QAAS,EACjC,CAACA,EAAM,SAAS,EAAG,CAAE,KAAM,WAAY,EACvC,CAACA,EAAM,SAAS,EAAG,CAAE,KAAM,WAAY,EACvC,CAACA,EAAM,SAAS,EAAG,CAAE,KAAM,WAAY,EACvC,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,QAAS,EACjC,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,OAAQ,MAAO,SAAU,EAC/C,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,GAAG,EAAG,CAAE,KAAM,KAAM,EAC3B,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,QAAS,EACjC,CAACA,EAAM,QAAQ,EAAG,CAAE,KAAM,UAAW,EACrC,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,QAAS,EACjC,CAACA,EAAM,eAAe,EAAG,CAAE,KAAM,iBAAkB,EACnD,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,YAAY,EAAG,CAAE,KAAM,cAAe,EAC7C,CAACA,EAAM,QAAQ,EAAG,CAAE,KAAM,UAAW,EACrC,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,QAAS,EACjC,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,QAAQ,EAAG,CAAE,KAAM,UAAW,EACrC,CAACA,EAAM,SAAS,EAAG,CAAE,KAAM,WAAY,EACvC,CAACA,EAAM,QAAQ,EAAG,CAAE,KAAM,WAAY,KAAM,MAAO,MAAO,SAAU,EACpE,CAACA,EAAM,aAAa,EAAG,CAAE,KAAM,eAAgB,EAC/C,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,UAAU,EAAG,CAAE,KAAM,YAAa,EACzC,CAACA,EAAM,SAAS,EAAG,CAAE,KAAM,WAAY,EACvC,CAACA,EAAM,SAAS,EAAG,CAAE,KAAM,YAAa,KAAM,OAAQ,MAAO,SAAU,EACvE,CAACA,EAAM,GAAG,EAAG,CAAE,KAAM,KAAM,EAC3B,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,QAAS,EACjC,CAACA,EAAM,GAAG,EAAG,CAAE,KAAM,KAAM,EAC3B,CAACA,EAAM,aAAa,EAAG,CAAE,KAAM,eAAgB,EAC/C,CAACA,EAAM,QAAQ,EAAG,CAAE,KAAM,UAAW,EACrC,CAACA,EAAM,QAAQ,EAAG,CAAE,KAAM,UAAW,EACrC,CAACA,EAAM,GAAG,EAAG,CAAE,KAAM,KAAM,EAC3B,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,QAAS,MAAO,SAAU,EACjD,CAACA,EAAM,GAAG,EAAG,CAAE,KAAM,KAAM,EAC3B,CAACA,EAAM,QAAQ,EAAG,CAAE,KAAM,UAAW,EACrC,CAACA,EAAM,SAAS,EAAG,CAAE,KAAM,YAAa,MAAO,SAAU,EACzD,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,QAAS,MAAO,SAAU,EACjD,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,QAAS,EACjC,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,QAAQ,EAAG,CAAE,KAAM,UAAW,EACrC,CAACA,EAAM,SAAS,EAAG,CAAE,KAAM,WAAY,EACvC,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,QAAQ,EAAG,CAAE,KAAM,UAAW,EACrC,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,SAAU,MAAO,SAAU,EACnD,CAACA,EAAM,YAAY,EAAG,CAAE,KAAM,cAAe,EAC7C,CAACA,EAAM,WAAW,EAAG,CAAE,KAAM,aAAc,EAC3C,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,QAAS,EACjC,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,MAAM,EAAG,CAAE,KAAM,QAAS,EACjC,CAACA,EAAM,OAAO,EAAG,CAAE,KAAM,SAAU,EACnC,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,EAC7B,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,KAAK,EAAG,CAAE,KAAM,OAAQ,EAC/B,CAACA,EAAM,IAAI,EAAG,CAAE,KAAM,MAAO,CAC/B,EAOO,SAASW,GAAWC,EAAoC,CAC7D,OAAOF,EAAeE,CAAO,GAAG,KAClC,CAGO,SAASC,GAAUD,EAAoC,CAC5D,OAAOF,EAAeE,CAAO,GAAG,IAClC,CAMO,SAASE,GAAUR,EAA2C,CACnE,IAAMM,EAAUG,EAAcT,CAAK,GAAKA,EAClCU,EAAON,EAAeE,CAAgB,GAAG,KAC/C,OAAOI,EACH,4CAA4C,mBAAmBA,CAAI,CAAC,OACpE,MACN,CAMO,SAASC,GAAiBL,EAAwB,CACvD,IAAMM,EAAOR,EAAeE,CAAO,EACnC,OAAKM,EACDA,EAAK,KAAaA,EAAK,KAAK,YAAY,EACrCA,EAAK,KAAK,QAAQ,QAAUC,GAAMA,EAAE,YAAY,CAAC,EAFtCP,CAGpB,CAOA,IAAMQ,GAAqC,IAAM,CAC/C,IAAMC,EAAM,IAAI,IAChB,OAAW,CAACT,EAASM,CAAI,IAAK,OAAO,QAAQR,CAAc,EACrDQ,GAAM,MAAMG,EAAI,IAAIH,EAAK,KAAK,YAAY,EAAGN,CAAgB,EAEnE,OAAW,CAACA,EAASM,CAAI,IAAK,OAAO,QAAQR,CAAc,EAAG,CAC5D,IAAMY,EAAMJ,GAAM,KAAK,YAAY,EAC/BI,GAAO,CAACD,EAAI,IAAIC,CAAG,GAAGD,EAAI,IAAIC,EAAKV,CAAgB,CACzD,CACA,OAAOS,CACT,GAAG,EAEI,SAASN,EAAcC,EAAiC,CAC7D,OAAOI,EAAc,IAAIJ,EAAK,YAAY,CAAC,CAC7C,CAMO,SAASO,GAAqBjB,EAAuBkB,EAAc,CACxE,IAAMZ,EAAWG,EAAcT,CAAK,GAAKA,EAEzC,OADkBD,EAAiBO,CAAO,EACvB,CACjB,KAAKX,EAAe,OAClB,OAAOwB,EAAqBD,CAAI,EAClC,KAAKvB,EAAe,IAClB,OAAOyB,EAAkBF,CAAI,EAC/B,QACE,MAAM,IAAI,MAAM,sBAAsBlB,CAAK,EAAE,CACjD,CACF,CAEA,IAAMqB,EAAiB,sBAEhB,SAASD,EAAkBE,EAAe,CAC/C,OAAOD,EAAe,KAAKC,CAAK,CAClC,CAEA,IAAMC,EAAmB,gCAElB,SAASJ,EAAqBG,EAAwB,CAC3D,OAAOC,EAAiB,KAAKD,CAAK,CACpC,CCjUO,IAAME,EAAN,cAAuB,KAAM,CAClC,YACEC,EAEgBC,EAEAC,EAEAC,EAChB,CACA,MAAMH,CAAO,EANG,UAAAC,EAEA,YAAAC,EAEA,UAAAC,EAGhB,KAAK,KAAO,UACd,CACF,ECHA,IAAMC,EAA4C,CAChD,QAAS,WACT,WAAY,OACZ,WAAY,OACZ,SAAU,OACV,QAAS,OACT,SAAU,MACZ,EAqBO,SAASC,EACdC,EACAC,EAA4B,CAAC,EACrB,CACR,IAAMC,EAAS,CAAE,GAAGJ,EAAe,GAAGG,CAAQ,EAE9C,OAAID,EAAM,GAAWE,EAAO,QACxBF,EAAM,GAAeE,EAAO,WAAW,QAAQ,MAAO,OAAOF,CAAG,CAAC,EAEjEA,EAAM,KACDE,EAAO,WAAW,QAAQ,MAAO,OAAO,KAAK,MAAMF,EAAM,EAAM,CAAC,CAAC,EAEtEA,EAAM,MACDE,EAAO,SAAS,QAAQ,MAAO,OAAO,KAAK,MAAMF,EAAM,IAAI,CAAC,CAAC,EAElEA,EAAM,QACDE,EAAO,QAAQ,QAAQ,MAAO,OAAO,KAAK,MAAMF,EAAM,KAAG,CAAC,CAAC,EAE7DE,EAAO,SAAS,QAAQ,MAAO,OAAO,KAAK,MAAMF,EAAM,OAAI,CAAC,CAAC,CACtE,CAmBO,SAASG,GAAUH,EAAaC,EAA4B,CAAC,EAAW,CAC7E,OAAOF,EAAmB,KAAK,MAAMC,EAAM,GAAI,EAAGC,CAAO,CAC3D,CCtEA,eAAeG,EACbC,EACsC,CACtC,IAAMC,EAAO,MAAMD,EAAS,KAAK,EAAE,MAAM,IAAM,EAAE,EACjD,GAAKC,EACL,GAAI,CACF,OAAO,KAAK,MAAMA,CAAI,CACxB,MAAQ,CACN,MACF,CACF,CAUA,eAAsBC,EACpBC,EACAC,EACY,CACZ,GAAI,CAACD,EAAI,WAAW,MAAM,EACxB,MAAM,IAAI,MAAM,6BAA6B,EAE/C,IAAMH,EAAW,MAAM,MAAMG,EAAK,CAChC,GAAGC,EACH,QAASC,EAAeD,EAAQ,QAASA,EAAQ,MAAM,CACzD,CAAC,EAED,GAAIJ,EAAS,GACX,OAAQ,MAAMA,EAAS,KAAK,EAG9B,IAAMM,EAAO,MAAMP,EAAeC,CAAQ,EACpCO,EACJD,GAAM,UACLA,GAAM,OAAS,OAAY,OAAOA,EAAK,IAAI,EAAI,SAChDN,EAAS,WAEX,MAAIA,EAAS,SAAW,IAChB,IAAIQ,EACRD,EACAD,GAAM,MAAQN,EAAS,OACvBA,EAAS,OACTM,CACF,EAEI,IAAI,MAAMC,CAAO,CACzB,CAEA,SAASF,EACPI,EAAuB,CAAC,EACxBC,EACa,CACb,IAAMC,EAAW,IAAI,QAAQF,CAAO,EAEpC,OAAKE,EAAS,IAAI,cAAc,IAC1BD,IAAW,SACbC,EAAS,OAAO,eAAgB,gCAAgC,EAEhEA,EAAS,OAAO,eAAgB,mCAAmC,GAIhEA,CACT,CAEA,eAAsBC,GACpBT,EACAC,EACY,CACZ,OAAO,MAAMF,EAAeC,EAAK,CAC/B,OAAQ,MACR,GAAGC,CACL,CAAC,CACH,CAEA,eAAsBS,GACpBV,EACAW,EACAV,EACY,CACZ,OAAO,MAAMF,EAAeC,EAAK,CAC/B,OAAQ,OACR,KAAM,KAAK,UAAUW,CAAI,EACzB,GAAGV,CACL,CAAC,CACH,CAEA,eAAsBW,GACpBZ,EACAW,EACAV,EACY,CACZ,OAAO,MAAMF,EAAeC,EAAK,CAC/B,OAAQ,MACR,KAAM,KAAK,UAAUW,CAAI,EACzB,GAAGV,CACL,CAAC,CACH,CAEA,eAAsBY,GACpBb,EACAC,EACY,CACZ,OAAO,MAAMF,EAAeC,EAAK,CAC/B,OAAQ,SACR,GAAGC,CACL,CAAC,CACH,CAEA,eAAsBa,GACpBd,EACAe,EACY,CACZ,OAAO,MAAMhB,EAAeC,EAAKe,CAAI,CACvC,CCnIA,OAAOC,MAAe,eAef,IAAMC,EAAN,cAA4BD,CAAU,CAC3C,YAAYE,EAAuBC,EAAe,CAChD,GAAI,CAEF,GADA,MAAMD,GAAO,EAAGC,CAAI,EAChB,KAAK,MAAM,EACb,OAAO,IAAIH,EAAU,EAAGG,CAAI,CAEhC,OAASC,EAAG,CACV,QAAQ,MAAM,kCAAmCA,CAAC,EAClD,MAAM,EAAGD,CAAI,CACf,CACF,CACF,EAOME,EAAoB,4CAUbC,EAAiBJ,GAA0B,CACtD,GAAI,OAAOA,GAAQ,SAAU,OAAO,OAAO,SAASA,CAAG,EACvD,GAAIA,aAAeD,GAAiBC,aAAeF,EACjD,MAAO,CAACE,EAAI,MAAM,GAAKA,EAAI,SAAS,EAEtC,GAAI,OAAOA,GAAQ,SAAU,MAAO,GACpC,IAAMK,EAAUL,EAAI,KAAK,EAEzB,OADIK,IAAY,IACZ,CAACF,EAAkB,KAAKE,CAAO,EAAU,GACtC,OAAO,SAAS,OAAOA,CAAO,CAAC,CACxC,EAMMC,EAAkB,CACtB,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,cACF,EAEMC,EAAsBD,EAAgB,OAAS,EAO/CE,EAAuC,CAC3CR,EACAS,EAAoB,EACpBC,EAAmCZ,EAAU,aAC1C,CAEH,IAAMa,EADK,IAAIZ,EAAcC,CAAG,EACf,cAAcS,EAAWC,CAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,EACxE,OAAAC,EAAM,CAAC,EAAIA,EAAM,CAAC,EAAE,QAAQ,wBAAyB,GAAG,EACjDA,EAAM,KAAK,GAAG,CACvB,EAQMC,EAAkC,CACtCZ,EACAS,EAAoB,IACT,CACX,IAAMI,EAAK,IAAId,EAAcC,CAAG,EAChC,OAAIa,EAAG,GAAG,GAAG,EAAUA,EAAG,SAAS,EAC/BA,EAAG,GAAG,GAAG,EACJ,GAAGL,EAAqCK,EAAG,IAAI,GAAG,EAAGJ,CAAS,CAAC,IACpEI,EAAG,GAAG,GAAG,EACJ,GAAGL,EAAqCK,EAAG,IAAI,GAAG,EAAGJ,CAAS,CAAC,IACpEI,EAAG,GAAG,IAAI,EACL,GAAGL,EAAqCK,EAAG,UAAU,GAAG,EAAGJ,CAAS,CAAC,IACvE,GAAGD,EAAqCK,EAAG,UAAU,IAAI,EAAGJ,CAAS,CAAC,GAC/E,EAUMK,EAA2C,CAC/Cd,EACAS,EAAoB,IACjB,CACH,IAAMI,EAAK,IAAId,EAAcC,CAAG,EAChC,GAAIa,EAAG,GAAG,CAAC,EAAG,MAAO,IACrB,GAAM,CAACE,EAAaC,CAAW,EAAIH,EAAG,QAAQ,EAAE,MAAM,GAAG,EACnDI,EAASD,EAAY,MAAM,EAAE,EAC7BE,EAAoBD,EAAO,UAAWjB,GAAgBA,IAAR,GAAW,EAC/D,GAAIkB,EAAoB,GAAKA,EAAoBX,EAC/C,MAAO,IAET,IAAMY,EAAuB,KAAK,IAChCF,EAAO,OAASC,EAChBT,CACF,EACA,MAAO,GAAGD,EAAqCO,CAAW,CAAC,KACxD,OAAOT,EAAgBY,CAAiB,CAAC,EACzC,OACCD,EACG,MAAMC,EAAmBA,EAAoBC,CAAoB,EACjE,KAAK,EAAE,EACP,QAAQ,SAAU,EAAE,CACzB,CACJ,EAMMC,EAA0C,CAC9CpB,EACAS,IACG,CACH,IAAMY,EAAUrB,EAAI,SAAS,EAAE,MAAM,MAAM,EACrCsB,GACHD,EAAUA,EAAQ,CAAC,EAAE,OAAS,EAAI,GAAKZ,EAC1C,OAAOD,EAAqCR,EAAKsB,CAAoB,CACvE,EAEMC,EAAmB,CAACV,EAAeJ,IAAsB,CAC7D,IAAMe,EAASX,EACZ,MAAM,GAAG,EACT,cAAcJ,EAAWX,EAAU,aAAa,EACnD,MAAO,GAAGU,EAAqCgB,EAAQf,CAAS,CAAC,GACnE,EAwBMgB,EAAiB,CACrBzB,EACA0B,EACAC,IACW,CACX,GAAM,CAAE,mBAAAC,EAAoB,mBAAAC,EAAqB,KAAM,UAAAC,CAAU,EAAIH,EACrE,GAAI,CAACvB,EAAcJ,CAAG,EAAG,OAAO6B,EAEhC,IAAMhB,EAAK,IAAId,EAAcC,CAAG,EAC1B+B,EAAWlB,EAAG,GAAG,CAAC,EAClBmB,EAAMnB,EAAG,IAAI,EACboB,EAAYP,EAAKM,CAAG,EAG1B,OADIF,IAAc,QAAaG,IAAcH,GACzCG,IAAc,KAAO,OAAOA,CAAS,IAAM,EAAUA,EACrDF,EAAiB,IAAIE,CAAS,GAC9BL,EAA2B,IAAIK,CAAS,GACrCA,CACT,EAUMC,EAA0BF,GAC9BA,EAAI,GAAG,IAAK,EACRA,EAAI,cAAc,EAAGlC,EAAU,UAAU,EAAE,SAAS,EACpDkC,EAAI,GAAG,CAAC,EACNA,EAAI,cAAc,EAAGlC,EAAU,UAAU,EAAE,SAAS,EACpDkC,EAAI,GAAG,GAAG,EACRA,EAAI,cAAc,EAAGlC,EAAU,UAAU,EAAE,SAAS,EACpDkC,EAAI,GAAG,GAAG,EACRxB,EAAqCwB,EAAK,CAAC,EAC3CpB,EAAgCoB,CAAG,EAiBlCG,GAAe,CAC1BnC,EAAuB,GACvB2B,EAA+B,CAAE,mBAAoB,EAAM,IAE3DF,EAAezB,EAAKkC,EAAY,CAC9B,mBAAoBP,GAAS,kBAC/B,CAAC,EAEGS,EAA6BJ,GACjCA,EAAI,GAAG,IAAK,EACR,KACAA,EAAI,GAAG,CAAC,EACN,IAAIA,EAAI,cAAc,EAAGlC,EAAU,UAAU,CAAC,GAC9CkC,EAAI,GAAG,GAAG,EACR,IAAIA,EAAI,cAAc,EAAGlC,EAAU,UAAU,CAAC,GAC9CkC,EAAI,GAAG,GAAG,EACR,IAAIxB,EAAqCwB,EAAK,CAAC,CAAC,GAChD,IAAIpB,EAAgCoB,CAAG,CAAC,GAmBvCK,GAAkB,CAC7BrC,EAAuB,GACvB2B,EAA+B,CAAE,mBAAoB,EAAM,IAE3DF,EAAezB,EAAKoC,EAAe,CACjC,mBAAoBT,GAAS,mBAC7B,UAAW,IACb,CAAC,EAEGW,EAAoCN,GAAQ,CAChD,GAAIA,EAAI,GAAG,IAAK,EAAG,MAAO,KAC1B,GAAIA,EAAI,GAAG,CAAC,EAAG,MAAO,IAAIA,EAAI,cAAc,EAAGlC,EAAU,UAAU,CAAC,GACpE,GAAIkC,EAAI,GAAG,GAAG,EAAG,MAAO,IAAIA,EAAI,cAAc,EAAGlC,EAAU,UAAU,CAAC,GACtE,GAAIkC,EAAI,GAAG,GAAG,EAAG,MAAO,IAAIA,EAAI,cAAc,EAAGlC,EAAU,UAAU,CAAC,GACtE,IAAMyC,EAAaP,EAAI,IAAI,GAAG,EAAE,aAAalC,EAAU,UAAU,EAAE,MAAM,GAAG,EAC5E,MAAO,IAAIc,EAAgC2B,EAAY,CAAC,CAAC,EAC3D,EAwBaC,GAAyB,CACpCxC,EAAuB,GACvB2B,EAA+B,CAAE,mBAAoB,EAAM,IAE3DF,EAAezB,EAAKsC,EAAsB,CACxC,mBAAoBX,GAAS,mBAC7B,UAAW,IACb,CAAC,EAUGc,EAAaC,GACTV,GACNA,EAAI,GAAG,IAAI,EACPlB,EAAyCkB,EAAKU,EAAgB,EAAI,CAAC,EACnEV,EAAI,GAAG,CAAC,EACNU,EACElC,EAAqCwB,EAAK,CAAC,EAC3CZ,EAAwCY,EAAK,CAAC,EAChDA,EAAI,GAAG,GAAG,GAAKA,EAAI,GAAG,GAAG,EACvBxB,EAAqCwB,EAAKU,EAAgB,EAAI,CAAC,EAC/DV,EAAI,GAAG,GAAG,EACRxB,EAAqCwB,EAAK,CAAC,EAC3CpB,EAAgCoB,CAAG,EAWpCW,GAAc,CACzB3C,EAAuB,GACvB2B,EAA8B,CAAE,cAAe,EAAK,IACjD,CACH,GAAI,CAACvB,EAAcJ,CAAG,EAAG,MAAO,KAChC,IAAMa,EAAK,IAAId,EAAcC,CAAG,EAChC,OAAIa,EAAG,GAAG,CAAC,EAAU,KACd4B,EAAUd,EAAQ,aAAa,EAAEd,EAAG,IAAI,CAAC,CAClD,EAqBa+B,GAAiB,CAC5B5C,EAAuB,GACvB2B,EAA8B,CAAE,cAAe,EAAK,IACjD,CACH,GAAI,CAACvB,EAAcJ,CAAG,EAAG,MAAO,KAChC,IAAMa,EAAK,IAAId,EAAcC,CAAG,EAChC,OAAIa,EAAG,GAAG,CAAC,EAAU,KACd,IAAI4B,EAAUd,EAAQ,aAAa,EAAEd,EAAG,IAAI,CAAC,CAAC,EACvD,EAyBagC,GAAgB,CAC3B7C,EAAuB,GACvB2B,EAAgC,CAAC,IAC9B,CACH,GAAI,CAACvB,EAAcJ,CAAG,EAAG,MAAO,OAEhC,IAAMa,EAAK,IAAId,EAAcC,CAAG,EAC1B+B,EAAWlB,EAAG,GAAG,CAAC,EAClBmB,EAAMnB,EAAG,IAAI,EACbiC,EAAOf,EAAW,IAAMJ,GAAS,mBAAqB,IAAM,GAElE,OAAIK,EAAI,GAAG,IAAI,EAAU,KACrBA,EAAI,GAAG,GAAG,EACL,GAAGc,CAAI,GAAGvB,EAAiBS,EAAKL,GAAS,WAAa,CAAC,CAAC,GAC7DK,EAAI,GAAG,GAAG,EACL,GAAGc,CAAI,GAAGvB,EAAiBS,EAAKL,GAAS,WAAa,CAAC,CAAC,GAC1D,GAAGmB,CAAI,WAChB,EC7cO,SAASC,GAAWC,EAAqB,CAC9C,OAAOA,EAAI,OAAO,CAAC,EAAE,YAAY,EAAIA,EAAI,MAAM,CAAC,EAAE,YAAY,CAChE,CAiBO,SAASC,GACdC,EACAC,EAAgB,EAChBC,EAAc,EACN,CACR,OAAOF,EAAQ,MAAM,EAAGC,CAAK,EAAI,MAAQD,EAAQ,MAAM,CAACE,CAAG,CAC7D,CChCA,IAAMC,EAAwB,+BA0BvB,SAASC,GACdC,EACAC,EAAuB,YACf,CACR,GAAI,CAACD,EAAQ,MAAO,GAEpB,GAAM,CAACE,EAAO,GAAIC,EAAO,GAAIC,EAAQ,EAAE,EAAIJ,EAAO,MAAM,GAAG,EAE3D,OAAOC,EAAa,QAAQH,EAAuB,CAACO,EAAGC,IACjDA,IAAQ,OAAeJ,EACvBI,IAAQ,OAAeH,EACpBC,CACR,CACH,CCxCA,OACE,SAAAG,EACA,0BAAAC,MAEK,oBAEP,IAAMC,GAAsB,IAAI,IAAYD,CAAsB,EAG5DE,GAAkC,CAAC,GAAGF,CAAsB,EAAE,KAClE,CAACG,EAAGC,IAAMA,EAAE,OAASD,EAAE,MACzB,EAEaE,GAA2B,CACtCC,EACAC,IAC8B,CAC9B,GAAID,IAAUP,EAAM,OAAQ,OAE5B,IAAMS,EAAaD,EAAe,YAAY,EAE9C,OAAIN,GAAoB,IAAIO,CAAU,EAC7BA,EAGFN,GAAgC,KAAMO,GAAMD,EAAW,SAASC,CAAC,CAAC,CAC3E,EAEaC,GAA2BC,GAC/BA,EACJ,MAAM,GAAG,EACT,IAAKC,GAASA,EAAK,OAAO,CAAC,EAAE,YAAY,EAAIA,EAAK,MAAM,CAAC,CAAC,EAC1D,KAAK,GAAG,EChCb,OAAS,SAAAC,MAAa,oBAsBtB,IAAMC,EAAqB,6CAMdC,GAAuC,CAClD,OAAQ,CACN,QAAS,mCACT,OAAQ,MACR,SAAU,CACZ,EACA,QAAS,CACP,QAAS,8CACT,OAAQ,MACR,SAAU,CACZ,EACA,YAAa,CACX,KAAM,CACJ,QAAS,+CACT,OAAQ,OACR,SAAU,CACZ,EACA,KAAM,CACJ,QAAS,+CACT,OAAQ,OACR,SAAU,CACZ,EACA,KAAM,CACJ,QAAS,8CACT,OAAQ,OACR,SAAU,CACZ,CACF,CACF,EAMaC,GAAyC,CACpD,OAAQ,CACN,QAASF,EACT,OAAQ,MACR,SAAU,EACZ,EACA,QAAS,CACP,QAAS,6CACT,OAAQ,OACR,SAAU,EACZ,EACA,YAAa,CACX,KAAM,CACJ,QAAS,6CACT,OAAQ,OACR,SAAU,CACZ,EACA,KAAM,CACJ,QAAS,6CACT,OAAQ,OACR,SAAU,CACZ,CACF,CACF,EAMaG,GAAoC,CAC/C,OAAQ,CACN,QAASH,EACT,OAAQ,MACR,SAAU,EACZ,EACA,QAAS,CACP,QAAS,6CACT,OAAQ,OACR,SAAU,EACZ,EACA,YAAa,CACX,KAAM,CACJ,QAAS,6CACT,OAAQ,OACR,SAAU,EACZ,EACA,KAAM,CACJ,QAAS,6CACT,OAAQ,OACR,SAAU,EACZ,CACF,CACF,EAMaI,GAAyC,CACpD,OAAQ,CACN,QAASJ,EACT,OAAQ,MACR,SAAU,EACZ,EACA,QAAS,CACP,QAAS,6CACT,OAAQ,OACR,SAAU,EACZ,EACA,YAAa,CACX,KAAM,CACJ,QAAS,6CACT,OAAQ,OACR,SAAU,CACZ,EACA,KAAM,CACJ,QAAS,6CACT,OAAQ,OACR,SAAU,CACZ,CACF,CACF,EAMaK,GAAyC,CACpD,OAAQ,CACN,QAASL,EACT,OAAQ,MACR,SAAU,EACZ,EACA,QAAS,CACP,QAAS,6CACT,OAAQ,OACR,SAAU,EACZ,EACA,YAAa,CACX,KAAM,CACJ,QAAS,6CACT,OAAQ,OACR,SAAU,CACZ,EACA,KAAM,CACJ,QAAS,6CACT,OAAQ,OACR,SAAU,CACZ,CACF,CACF,EAMaM,GAA0C,CACrD,OAAQ,CACN,QAASN,EACT,OAAQ,OACR,SAAU,EACZ,EACA,QAAS,CACP,QAAS,6CACT,OAAQ,QACR,SAAU,EACZ,EACA,YAAa,CACX,KAAM,CACJ,QAAS,6CACT,OAAQ,OACR,SAAU,CACZ,EACA,KAAM,CACJ,QAAS,6CACT,OAAQ,OACR,SAAU,CACZ,CACF,CACF,EAMaO,EAA8D,CACzE,CAACR,EAAM,MAAM,EAAGE,GAChB,CAACF,EAAM,QAAQ,EAAGG,GAClB,CAACH,EAAM,OAAO,EAAGI,GACjB,CAACJ,EAAM,QAAQ,EAAGK,GAClB,CAACL,EAAM,QAAQ,EAAGM,GAClB,CAACN,EAAM,SAAS,EAAGO,EACrB,EAMO,SAASE,GAAeC,EAA2C,CACxE,OAAOF,EAAaE,CAAK,GAAG,MAC9B,CAEO,SAASC,GAAgBD,EAA2C,CACzE,OAAOF,EAAaE,CAAK,GAAG,OAC9B,CAEO,SAASE,GACdF,EAC6C,CAC7C,OAAOF,EAAaE,CAAK,GAAG,WAC9B,CAGO,SAASG,GAAwBH,EAAwB,CAC9D,IAAMI,EAASN,EAAaE,CAAK,EACjC,OAAKI,EACE,CACLA,EAAO,OAAO,QACdA,EAAO,QAAQ,QACf,GAAG,OAAO,OAAOA,EAAO,WAAW,EAAE,IAAKC,GAAMA,EAAE,OAAO,CAC3D,EALoB,CAAC,CAMvB,CAGO,SAASC,GAAyBN,EAAsC,CAC7E,IAAMI,EAASN,EAAaE,CAAK,EACjC,GAAI,CAACI,EAAQ,MAAO,CAAC,EACrB,IAAMG,EAA8B,CAClC,CAACH,EAAO,OAAO,OAAO,EAAGA,EAAO,OAAO,OACvC,CAACA,EAAO,QAAQ,OAAO,EAAGA,EAAO,QAAQ,MAC3C,EACA,QAAWC,KAAK,OAAO,OAAOD,EAAO,WAAW,EAC9CG,EAAIF,EAAE,OAAO,EAAIA,EAAE,OAErB,OAAOE,CACT,CCjQA,OAAS,SAAAC,MAAa,oBAEtB,IAAMC,GAAmD,CACvD,CAACD,EAAM,MAAM,EAAG,yBAChB,CAACA,EAAM,QAAQ,EAAG,2BAClB,CAACA,EAAM,OAAO,EAAG,8BACjB,CAACA,EAAM,OAAO,EAAG,0BACjB,CAACA,EAAM,eAAe,EAAG,kCACzB,CAACA,EAAM,SAAS,EAAG,2BACnB,CAACA,EAAM,IAAI,EAAG,2BACd,CAACA,EAAM,KAAK,EAAG,8BACf,CAACA,EAAM,QAAQ,EAAG,0BAClB,CAACA,EAAM,aAAa,EAAG,+BACvB,CAACA,EAAM,uBAAuB,EAAG,iCACjC,CAACA,EAAM,wBAAwB,EAAG,iCACpC,EAEME,GAAwD,CAC5D,CAACF,EAAM,MAAM,EAAG,8BAChB,CAACA,EAAM,QAAQ,EAAG,gCAClB,CAACA,EAAM,OAAO,EAAG,mCACjB,CAACA,EAAM,OAAO,EAAG,+BACjB,CAACA,EAAM,eAAe,EAAG,uCACzB,CAACA,EAAM,SAAS,EAAG,gCACnB,CAACA,EAAM,IAAI,EAAG,gCACd,CAACA,EAAM,KAAK,EAAG,mCACf,CAACA,EAAM,QAAQ,EAAG,+BAClB,CAACA,EAAM,aAAa,EAAG,oCACvB,CAACA,EAAM,uBAAuB,EAAG,sCACjC,CAACA,EAAM,wBAAwB,EAAG,sCACpC,EAEA,SAASG,EACPC,EACAC,EACAC,EACoB,CACpB,IAAMC,EAAOH,EAAKC,CAAO,EACzB,OAAOE,EAAO,GAAGA,CAAI,GAAGD,CAAK,GAAK,MACpC,CAEO,SAASE,GACdH,EACAI,EACoB,CACpB,OAAON,EAAYF,GAAkBI,EAASI,CAAM,CACtD,CAEO,SAASC,GACdL,EACAM,EACoB,CACpB,OAAOR,EAAYD,GAAuBG,EAASM,CAAO,CAC5D,CAEO,SAASC,GAAeC,EAAuB,CACpD,MAAO,2CAA2C,mBAAmBA,CAAK,CAAC,EAC7E,CAEO,SAASC,GAAiBC,EAAmB,CAClD,MAAO,0BAA0B,mBAAmBA,CAAC,CAAC,EACxD,CAEO,SAASC,GAAeC,EAA0B,CACvD,MAAO,iBAAiBA,CAAQ,EAClC,CAEO,SAASC,GAAgBC,EAAoB,CAClD,MAAO,0BAA0BA,CAAE,EACrC,CCnEO,SAASC,GACdC,EACAC,EACG,CACH,IAAIC,EAAe,EACfC,EAAkD,KAClDC,EAAiC,KA4BrC,MA1BkB,IAAIC,IAAwB,CAC5C,IAAMC,EAAM,KAAK,IAAI,EACfC,EAAYN,GAAQK,EAAMJ,GAE5BK,GAAa,GACXJ,IAAc,OAChB,aAAaA,CAAS,EACtBA,EAAY,MAEdD,EAAeI,EACfN,EAAG,GAAGK,CAAI,IAEVD,EAAWC,EACPF,IAAc,OAChBA,EAAY,WAAW,IAAM,CAC3BD,EAAe,KAAK,IAAI,EACxBC,EAAY,KACRC,IACFJ,EAAG,GAAGI,CAAQ,EACdA,EAAW,KAEf,EAAGG,CAAS,GAGlB,CAGF,CAMO,SAASC,GACdR,EACAC,EACsB,CACtB,IAAIE,EAAkD,KAEhDM,EAAY,IAAIJ,IAAwB,CACxCF,IAAc,MAAM,aAAaA,CAAS,EAC9CA,EAAY,WAAW,IAAM,CAC3BA,EAAY,KACZH,EAAG,GAAGK,CAAI,CACZ,EAAGJ,CAAI,CACT,EAEA,OAAAQ,EAAU,OAAS,IAAM,CACnBN,IAAc,OAChB,aAAaA,CAAS,EACtBA,EAAY,KAEhB,EAEOM,CACT,CCvDA,SAASC,EACPC,EACAC,EAAY,GACI,CAChB,OAAI,OAAOD,GAAa,WAAmBA,EACpCC,EACFC,GAAY,OAAOA,EAAKF,CAAQ,CAAC,EACjCE,GAAYA,EAAKF,CAAQ,CAChC,CAEO,SAASG,GAAUC,EAAYJ,EAAqC,CACzE,IAAMK,EAASN,EAASC,CAAQ,EAC1BM,EAAO,IAAI,IACjB,OAAOF,EAAM,OAAQF,GAAS,CAC5B,IAAMK,EAAMF,EAAOH,CAAI,EACvB,OAAII,EAAK,IAAIC,CAAG,EAAU,IAC1BD,EAAK,IAAIC,CAAG,EACL,GACT,CAAC,CACH,CAEO,SAASC,GACdC,EACAC,EACAV,EACK,CACL,IAAMK,EAASN,EAASC,CAAQ,EAC1BW,EAAQ,IAAI,IAAID,EAAE,IAAIL,CAAM,CAAC,EACnC,OAAOI,EAAE,OAAQP,GAASS,EAAM,IAAIN,EAAOH,CAAI,CAAC,CAAC,CACnD,CAEO,SAASU,GACdR,EACAJ,EACmB,CACnB,IAAMK,EAASN,EAASC,EAAU,EAAI,EAChCa,EAA4B,CAAC,EACnC,QAAWX,KAAQE,EACjBS,EAAOR,EAAOH,CAAI,CAAC,EAAIA,EAEzB,OAAOW,CACT,CAEO,SAASC,GACdV,EACAJ,EACqB,CACrB,IAAMK,EAASN,EAASC,EAAU,EAAI,EAChCa,EAA8B,CAAC,EACrC,QAAWX,KAAQE,EAAO,CACxB,IAAMG,EAAMF,EAAOH,CAAI,GACtBW,EAAON,CAAG,IAAM,CAAC,GAAG,KAAKL,CAAI,CAChC,CACA,OAAOW,CACT,CAEO,SAASE,GACdC,EACAhB,EACmB,CACnB,IAAMa,EAA4B,CAAC,EACnC,QAAWN,KAAO,OAAO,KAAKS,CAAG,EAC/BH,EAAOb,EAASgB,EAAIT,CAAG,EAAGA,CAAG,CAAC,EAAIS,EAAIT,CAAG,EAE3C,OAAOM,CACT,CAEO,SAASI,GACdD,EACAhB,EACmB,CACnB,IAAMa,EAA4B,CAAC,EACnC,QAAWN,KAAO,OAAO,KAAKS,CAAG,EAC/BH,EAAON,CAAG,EAAIP,EAASgB,EAAIT,CAAG,EAAGA,CAAG,EAEtC,OAAOM,CACT","names":["Chain","ChainNamespace","solanaChains","ethereumChains","binanceChains","chainToNamespace","chain","isSolanaChain","isEthereumChain","isBinanceChain","CHAIN_REGISTRY","chainColor","chainId","chainSlug","chainIcon","chainIdBySlug","slug","chainDisplayName","meta","c","slugToChainId","map","key","isValidWalletAddress","addr","isValidSolanaAddress","isValidEvmAddress","EVM_ADDRESS_RE","value","SOLANA_BASE58_RE","ApiError","message","code","status","data","defaultLabels","formatAgeInSeconds","age","options","labels","formatAge","parseErrorBody","response","text","httpRequest","url","options","_createHeaders","body","message","ApiError","headers","method","_headers","httpGet","httpPost","data","httpPut","httpDelete","httpMutate","init","BigNumber","SafeBigNumber","num","base","e","NUMERIC_STRING_RE","isValidNumber","trimmed","subscriptDigits","MAX_SUBSCRIPT_INDEX","stringifyNumberWithGroupingSeparator","precision","rounding","parts","stringifyNumberWithAbbreviation","bn","stringifyNumberWithLeadingZeroSubscripts","integerPart","decimalPart","digits","firstNonZeroIndex","precisionDigitsCount","stringifyNumberWithSignificantPrecision","matched","significantPrecision","stringifyPercent","scaled","formatWithSign","tier","options","showPlusGtThanZero","invalidPlaceholder","zeroToken","negative","abs","formatted","tierAmount","formatAmount","tierAmountUSD","formatAmountUSD","tierAmountUSDCompact","roundedAbs","formatAmountUSDCompact","tierPrice","isHighPrecise","formatPrice","formatPriceUSD","formatPercent","sign","capitalize","str","truncateAddress","address","start","end","SYMBOL_PLACEHOLDER_RE","formatSymbol","symbol","formatString","type","base","quote","_","key","Chain","SOLANA_TOKEN_PROTOCOLS","SOLANA_PROTOCOL_SET","SOLANA_PROTOCOLS_BY_SPECIFICITY","a","b","parseTokenProtocolFamily","chain","protocolFamily","normalized","p","formatTokenProtocolName","protocol","word","Chain","EVM_NATIVE_ADDRESS","SOLANA_TOKENS","ETHEREUM_TOKENS","BSC_TOKENS","ARBITRUM_TOKENS","OPTIMISM_TOKENS","AVALANCHE_TOKENS","CHAIN_TOKENS","getNativeToken","chain","getWrappedToken","getStablecoins","getCommonTokenAddresses","tokens","t","getCommonTokenSymbolsMap","map","Chain","TX_EXPLORER_URLS","ACCOUNT_EXPLORER_URLS","explorerUrl","urls","chainId","value","base","txExplorerUrl","txHash","accountExplorerUrl","account","searchImageUrl","image","searchTwitterUrl","q","twitterUserUrl","username","twitterTweetUrl","id","throttle","fn","wait","lastCallTime","timeoutId","lastArgs","args","now","remaining","debounce","debounced","asGetter","iteratee","stringify","item","uniqBy","array","getter","seen","key","intersectionBy","a","b","bKeys","keyBy","result","groupBy","mapKeys","obj","mapValues"]}
1
+ {"version":3,"sources":["../src/chain.ts","../src/errors.ts","../src/dateTime.ts","../src/fetch.ts","../src/number.ts","../src/string.ts","../src/symbol.ts","../src/tokenProtocols.ts","../src/tokens.ts","../src/urls.ts","../src/timing.ts","../src/collection.ts"],"sourcesContent":["import { Chain, ChainNamespace } from \"@liberfi.io/types\";\n\n// ---------------------------------------------------------------------------\n// Namespace classification\n// ---------------------------------------------------------------------------\n\nconst solanaChains: ReadonlySet<Chain> = new Set([\n Chain.SOLANA,\n Chain.SOLANA_TESTNET,\n Chain.SOLANA_DEVNET,\n]);\n\nconst ethereumChains: ReadonlySet<Chain> = new Set([Chain.ETHEREUM]);\n\nconst binanceChains: ReadonlySet<Chain> = new Set([\n Chain.BINANCE,\n Chain.BINANCE_TESTNET,\n]);\n\n/** Returns the chain namespace (EVM or SOLANA) for a given chain. */\nexport function chainToNamespace(chain: Chain): ChainNamespace {\n return solanaChains.has(chain) ? ChainNamespace.SOLANA : ChainNamespace.EVM;\n}\n\nexport function isSolanaChain(chain: Chain): boolean {\n return solanaChains.has(chain);\n}\n\nexport function isEthereumChain(chain: Chain): boolean {\n return ethereumChains.has(chain);\n}\n\nexport function isBinanceChain(chain: Chain): boolean {\n return binanceChains.has(chain);\n}\n\n// ---------------------------------------------------------------------------\n// Single chain metadata registry\n// ---------------------------------------------------------------------------\n\n/** All per-chain metadata stored in one record. */\nexport interface ChainMetadata {\n /** Canonical lowercase slug (used in URLs and icon CDN). */\n slug: string;\n /** Optional short abbreviation (e.g. \"eth\" for Ethereum). Takes precedence over `slug` in display. */\n abbr?: string;\n /** Optional brand colour (hex). */\n color?: string;\n}\n\n/** Single source of truth for chain metadata. */\nexport const CHAIN_REGISTRY: Partial<Record<Chain, ChainMetadata>> = {\n [Chain.ETHEREUM]: {\n slug: \"ethereum\",\n abbr: \"eth\",\n color: \"#627EEA\",\n },\n [Chain.UBIQ]: { slug: \"ubiq\" },\n [Chain.OPTIMISM]: { slug: \"optimism\", abbr: \"opt\", color: \"#FF0420\" },\n [Chain.FLARE]: { slug: \"flare\" },\n [Chain.SONGBIRD]: { slug: \"songbird\" },\n [Chain.ELASTOS]: { slug: \"elastos\" },\n [Chain.KARDIA]: { slug: \"kardia\" },\n [Chain.CRONOS]: { slug: \"cronos\", color: \"#002D74\" },\n [Chain.RSK]: { slug: \"rsk\" },\n [Chain.TELOS]: { slug: \"telos\" },\n [Chain.LUKSO]: { slug: \"lukso\" },\n [Chain.CRAB]: { slug: \"crab\" },\n [Chain.DARWINIA]: { slug: \"darwinia\" },\n [Chain.XDC]: { slug: \"xdc\" },\n [Chain.CSC]: { slug: \"csc\" },\n [Chain.ZYX]: { slug: \"zyx\" },\n [Chain.BINANCE]: { slug: \"binance\", abbr: \"bsc\", color: \"#F0B90B\" },\n [Chain.SYSCOIN]: { slug: \"syscoin\" },\n [Chain.GOCHAIN]: { slug: \"gochain\" },\n [Chain.ETHEREUMCLASSIC]: { slug: \"ethereumclassic\" },\n [Chain.OKEXCHAIN]: { slug: \"okexchain\" },\n [Chain.HOO]: { slug: \"hoo\" },\n [Chain.METER]: { slug: \"meter\" },\n [Chain.NOVA_NETWORK]: { slug: \"nova network\" },\n [Chain.TOMOCHAIN]: { slug: \"tomochain\" },\n [Chain.BITKUB]: { slug: \"bitkub\" },\n [Chain.XDAI]: { slug: \"xdai\" },\n [Chain.SOLANA]: { slug: \"solana\", abbr: \"sol\", color: \"#9945FF\" },\n [Chain.VELAS]: { slug: \"velas\" },\n [Chain.THUNDERCORE]: { slug: \"thundercore\" },\n [Chain.ENULS]: { slug: \"enuls\" },\n [Chain.FUSE]: { slug: \"fuse\" },\n [Chain.HECO]: { slug: \"heco\" },\n [Chain.UNICHAIN]: { slug: \"unichain\" },\n [Chain.POLYGON]: { slug: \"polygon\", color: \"#8247E5\" },\n [Chain.SONIC]: { slug: \"sonic\", color: \"#5B6EF5\" },\n [Chain.SHIMMER_EVM]: { slug: \"shimmer_evm\" },\n [Chain.RBN]: { slug: \"rbn\" },\n [Chain.OMNI]: { slug: \"omni\" },\n [Chain.MANTA]: { slug: \"manta\" },\n [Chain.HSK]: { slug: \"hsk\" },\n [Chain.WATER]: { slug: \"water\" },\n [Chain.XLAYER]: { slug: \"xlayer\" },\n [Chain.XDAIARB]: { slug: \"xdaiarb\" },\n [Chain.OP_BNB]: { slug: \"op_bnb\" },\n [Chain.VINUCHAIN]: { slug: \"vinuchain\" },\n [Chain.ENERGYWEB]: { slug: \"energyweb\" },\n [Chain.OASYS]: { slug: \"oasys\" },\n [Chain.FANTOM]: { slug: \"fantom\" },\n [Chain.FRAXTAL]: { slug: \"fraxtal\" },\n [Chain.HPB]: { slug: \"hpb\" },\n [Chain.BOBA]: { slug: \"boba\" },\n [Chain.OMAX]: { slug: \"omax\" },\n [Chain.FILECOIN]: { slug: \"filecoin\" },\n [Chain.KUCOIN]: { slug: \"kucoin\" },\n [Chain.ZKSYNC_ERA]: { slug: \"zksync era\" },\n [Chain.SHIDEN]: { slug: \"shiden\" },\n [Chain.THETA]: { slug: \"theta\" },\n [Chain.PULSE]: { slug: \"pulse\" },\n [Chain.CRONOS_ZKEVM]: { slug: \"cronos zkevm\" },\n [Chain.SX]: { slug: \"sx\" },\n [Chain.AREON]: { slug: \"areon\" },\n [Chain.WC]: { slug: \"wc\" },\n [Chain.CANDLE]: { slug: \"candle\" },\n [Chain.ROLLUX]: { slug: \"rollux\" },\n [Chain.ASTAR]: { slug: \"astar\" },\n [Chain.REDSTONE]: { slug: \"redstone\" },\n [Chain.MATCHAIN]: { slug: \"matchain\" },\n [Chain.CALLISTO]: { slug: \"callisto\" },\n [Chain.TARA]: { slug: \"tara\" },\n [Chain.WANCHAIN]: { slug: \"wanchain\" },\n [Chain.LYRA_CHAIN]: { slug: \"lyra chain\" },\n [Chain.BIFROST]: { slug: \"bifrost\" },\n [Chain.CONFLUX]: { slug: \"conflux\" },\n [Chain.METIS]: { slug: \"metis\" },\n [Chain.DYMENSION]: { slug: \"dymension\" },\n [Chain.POLYGON_ZKEVM]: { slug: \"polygon zkevm\" },\n [Chain.CORE]: { slug: \"core\" },\n [Chain.LISK]: { slug: \"lisk\" },\n [Chain.ULTRON]: { slug: \"ultron\" },\n [Chain.STEP]: { slug: \"step\" },\n [Chain.MOONBEAM]: { slug: \"moonbeam\" },\n [Chain.MOONRIVER]: { slug: \"moonriver\" },\n [Chain.SEI]: { slug: \"sei\" },\n [Chain.LIVING_ASSETS_MAINNET]: { slug: \"living assets mainnet\" },\n [Chain.STY]: { slug: \"sty\" },\n [Chain.TENET]: { slug: \"tenet\" },\n [Chain.GRAVITY]: { slug: \"gravity\" },\n [Chain.REYA_NETWORK]: { slug: \"reya network\" },\n [Chain.SONEIUM]: { slug: \"soneium\" },\n [Chain.SWELLCHAIN]: { slug: \"swellchain\" },\n [Chain.ONUS]: { slug: \"onus\" },\n [Chain.HUBBLENET]: { slug: \"hubblenet\" },\n [Chain.SANKO]: { slug: \"sanko\" },\n [Chain.DOGECHAIN]: { slug: \"dogechain\" },\n [Chain.MILKOMEDA]: { slug: \"milkomeda\" },\n [Chain.MILKOMEDA_A1]: { slug: \"milkomeda_a1\" },\n [Chain.KAVA]: { slug: \"kava\" },\n [Chain.SOMA]: { slug: \"soma\" },\n [Chain.KARAK]: { slug: \"karak\" },\n [Chain.ABSTRACT]: { slug: \"abstract\" },\n [Chain.MORPH]: { slug: \"morph\" },\n [Chain.CROSSFI]: { slug: \"crossfi\" },\n [Chain.BEAM]: { slug: \"beam\" },\n [Chain.IOTEX]: { slug: \"iotex\" },\n [Chain.MANTLE]: { slug: \"mantle\" },\n [Chain.XLC]: { slug: \"xlc\" },\n [Chain.NAHMII]: { slug: \"nahmii\" },\n [Chain.BOUNCEBIT]: { slug: \"bouncebit\" },\n [Chain.TOMBCHAIN]: { slug: \"tombchain\" },\n [Chain.ZETACHAIN]: { slug: \"zetachain\" },\n [Chain.PLANQ]: { slug: \"planq\" },\n [Chain.BITROCK]: { slug: \"bitrock\" },\n [Chain.XSAT]: { slug: \"xsat\" },\n [Chain.CYETH]: { slug: \"cyeth\" },\n [Chain.CANTO]: { slug: \"canto\" },\n [Chain.KLAYTN]: { slug: \"klaytn\" },\n [Chain.THAT]: { slug: \"that\" },\n [Chain.BASE]: { slug: \"base\", color: \"#0052FF\" },\n [Chain.HELA]: { slug: \"hela\" },\n [Chain.IOTAEVM]: { slug: \"iotaevm\" },\n [Chain.JBC]: { slug: \"jbc\" },\n [Chain.EVMOS]: { slug: \"evmos\" },\n [Chain.CARBON]: { slug: \"carbon\" },\n [Chain.SMARTBCH]: { slug: \"smartbch\" },\n [Chain.ARTELA]: { slug: \"artela\" },\n [Chain.IMMUTABLE_ZKEVM]: { slug: \"immutable zkevm\" },\n [Chain.LOOP]: { slug: \"loop\" },\n [Chain.GENESYS]: { slug: \"genesys\" },\n [Chain.EOS_EVM]: { slug: \"eos evm\" },\n [Chain.MAP_PROTOCOL]: { slug: \"map protocol\" },\n [Chain.SAPPHIRE]: { slug: \"sapphire\" },\n [Chain.BITGERT]: { slug: \"bitgert\" },\n [Chain.FUSION]: { slug: \"fusion\" },\n [Chain.ZILLIQA]: { slug: \"zilliqa\" },\n [Chain.APECHAIN]: { slug: \"apechain\" },\n [Chain.EDU_CHAIN]: { slug: \"edu chain\" },\n [Chain.ARBITRUM]: { slug: \"arbitrum\", abbr: \"arb\", color: \"#28A0F0\" },\n [Chain.ARBITRUM_NOVA]: { slug: \"arbitrum nova\" },\n [Chain.CELO]: { slug: \"celo\" },\n [Chain.OASIS]: { slug: \"oasis\" },\n [Chain.ASSETCHAIN]: { slug: \"assetchain\" },\n [Chain.ETHERLINK]: { slug: \"etherlink\" },\n [Chain.AVALANCHE]: { slug: \"avalanche\", abbr: \"avax\", color: \"#E84142\" },\n [Chain.REI]: { slug: \"rei\" },\n [Chain.ZIRCUIT]: { slug: \"zircuit\" },\n [Chain.SOPHON]: { slug: \"sophon\" },\n [Chain.ETN]: { slug: \"etn\" },\n [Chain.SUPERPOSITION]: { slug: \"superposition\" },\n [Chain.REICHAIN]: { slug: \"reichain\" },\n [Chain.BOBA_BNB]: { slug: \"boba_bnb\" },\n [Chain.INK]: { slug: \"ink\" },\n [Chain.LINEA]: { slug: \"linea\", color: \"#61DFFF\" },\n [Chain.BOB]: { slug: \"bob\" },\n [Chain.GODWOKEN]: { slug: \"godwoken\" },\n [Chain.BERACHAIN]: { slug: \"berachain\", color: \"#964B00\" },\n [Chain.BLAST]: { slug: \"blast\", color: \"#FCFC03\" },\n [Chain.CHILIZ]: { slug: \"chiliz\" },\n [Chain.STRATIS]: { slug: \"stratis\" },\n [Chain.REAL]: { slug: \"real\" },\n [Chain.ODYSSEY]: { slug: \"odyssey\" },\n [Chain.TAIKO]: { slug: \"taiko\" },\n [Chain.BITLAYER]: { slug: \"bitlayer\" },\n [Chain.HYDRATION]: { slug: \"hydration\" },\n [Chain.PAREX]: { slug: \"parex\" },\n [Chain.POLIS]: { slug: \"polis\" },\n [Chain.KEKCHAIN]: { slug: \"kekchain\" },\n [Chain.SCROLL]: { slug: \"scroll\", color: \"#FFEEDA\" },\n [Chain.ZERO_NETWORK]: { slug: \"zero_network\" },\n [Chain.ZKLINK_NOVA]: { slug: \"zklink nova\" },\n [Chain.VISION]: { slug: \"vision\" },\n [Chain.SAAKURU]: { slug: \"saakuru\" },\n [Chain.ZORA]: { slug: \"zora\" },\n [Chain.CORN]: { slug: \"corn\" },\n [Chain.NEON]: { slug: \"neon\" },\n [Chain.LUMIA]: { slug: \"lumia\" },\n [Chain.AURORA]: { slug: \"aurora\" },\n [Chain.HARMONY]: { slug: \"harmony\" },\n [Chain.PALM]: { slug: \"palm\" },\n [Chain.ZENIQ]: { slug: \"zeniq\" },\n [Chain.CURIO]: { slug: \"curio\" },\n [Chain.MODE]: { slug: \"mode\" },\n};\n\n// ---------------------------------------------------------------------------\n// Derived lookups + accessors\n// ---------------------------------------------------------------------------\n\n/** Returns the brand colour for the chain, when defined. */\nexport function chainColor(chainId: Chain): string | undefined {\n return CHAIN_REGISTRY[chainId]?.color;\n}\n\n/** Returns the canonical slug for the chain, when defined. */\nexport function chainSlug(chainId: Chain): string | undefined {\n return CHAIN_REGISTRY[chainId]?.slug;\n}\n\n/**\n * Returns a CDN icon URL for the chain.\n * Accepts either a `Chain` enum value or a slug / abbreviation string.\n */\nexport function chainIcon(chain: Chain | string): string | undefined {\n const chainId = chainIdBySlug(chain) ?? chain;\n const slug = CHAIN_REGISTRY[chainId as Chain]?.slug;\n return slug\n ? `https://icons.llamao.fi/icons/chains/rsz_${encodeURIComponent(slug)}.jpg`\n : undefined;\n}\n\n/**\n * Returns a user-facing display name for the chain.\n * Prefers the uppercased abbreviation when defined, otherwise title-cases the slug.\n */\nexport function chainDisplayName(chainId: Chain): string {\n const meta = CHAIN_REGISTRY[chainId];\n if (!meta) return chainId;\n if (meta.abbr) return meta.abbr.toUpperCase();\n return meta.slug.replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n\n/**\n * Reverse lookup: slug or abbreviation → chain id.\n * Abbreviations take precedence over slugs when both are registered with the\n * same key.\n */\nconst slugToChainId: Map<string, Chain> = (() => {\n const map = new Map<string, Chain>();\n for (const [chainId, meta] of Object.entries(CHAIN_REGISTRY)) {\n if (meta?.abbr) map.set(meta.abbr.toLowerCase(), chainId as Chain);\n }\n for (const [chainId, meta] of Object.entries(CHAIN_REGISTRY)) {\n const key = meta?.slug.toLowerCase();\n if (key && !map.has(key)) map.set(key, chainId as Chain);\n }\n return map;\n})();\n\nexport function chainIdBySlug(slug: string): Chain | undefined {\n return slugToChainId.get(slug.toLowerCase());\n}\n\n// ---------------------------------------------------------------------------\n// Wallet address validation\n// ---------------------------------------------------------------------------\n\nexport function isValidWalletAddress(chain: Chain | string, addr: string) {\n const chainId = (chainIdBySlug(chain) ?? chain) as Chain;\n const namespace = chainToNamespace(chainId);\n switch (namespace) {\n case ChainNamespace.SOLANA:\n return isValidSolanaAddress(addr);\n case ChainNamespace.EVM:\n return isValidEvmAddress(addr);\n default:\n throw new Error(`Unsupported chain: ${chain}`);\n }\n}\n\nconst EVM_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;\n\nexport function isValidEvmAddress(value: string) {\n return EVM_ADDRESS_RE.test(value);\n}\n\nconst SOLANA_BASE58_RE = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;\n\nexport function isValidSolanaAddress(value: string): boolean {\n return SOLANA_BASE58_RE.test(value);\n}\n","/**\n * Error subclass raised by {@link httpRequest} when the server returns a\n * structured 400-class response with a `message` / `code` payload.\n */\nexport class ApiError extends Error {\n constructor(\n message: string,\n /** Application-level error code parsed from the response body. */\n public readonly code: number,\n /** HTTP status code returned by the server, when known. */\n public readonly status?: number,\n /** Raw parsed response body, when JSON. Useful for surfacing validation errors. */\n public readonly data?: unknown,\n ) {\n super(message);\n this.name = \"ApiError\";\n }\n}\n","const MINUTE = 60;\nconst HOUR = 60 * MINUTE;\nconst DAY = 24 * HOUR;\nconst YEAR = 365 * DAY;\n\nexport interface FormatAgeOptions {\n justNow?: string;\n secondsAgo?: string;\n minutesAgo?: string;\n hoursAgo?: string;\n daysAgo?: string;\n yearsAgo?: string;\n}\n\nconst defaultLabels: Required<FormatAgeOptions> = {\n justNow: \"just now\",\n secondsAgo: \"{n}s\",\n minutesAgo: \"{n}m\",\n hoursAgo: \"{n}h\",\n daysAgo: \"{n}d\",\n yearsAgo: \"{n}y\",\n};\n\n/**\n * Formats an age (elapsed time) given in **seconds** into a compact\n * human-readable string like \"3m\", \"2h\", or \"just now\".\n *\n * Use this when you already have the elapsed time in seconds (e.g. from\n * a server-provided `age` field). If you have milliseconds instead, use\n * {@link formatAge}.\n *\n * @example\n * formatAgeInSeconds(5) // \"just now\" (< 10s)\n * formatAgeInSeconds(45) // \"45s\"\n * formatAgeInSeconds(120) // \"2m\"\n * formatAgeInSeconds(7200) // \"2h\"\n * formatAgeInSeconds(172800) // \"2d\"\n * formatAgeInSeconds(63072000) // \"2y\"\n *\n * @example Custom labels (e.g. for i18n)\n * formatAgeInSeconds(120, { minutesAgo: \"{n} minutes ago\" }) // \"2 minutes ago\"\n */\nexport function formatAgeInSeconds(\n age: number,\n options: FormatAgeOptions = {},\n): string {\n const labels = { ...defaultLabels, ...options };\n\n if (age < 10) return labels.justNow;\n if (age < MINUTE) return labels.secondsAgo.replace(\"{n}\", String(age));\n\n if (age < HOUR) {\n return labels.minutesAgo.replace(\"{n}\", String(Math.floor(age / MINUTE)));\n }\n if (age < DAY) {\n return labels.hoursAgo.replace(\"{n}\", String(Math.floor(age / HOUR)));\n }\n if (age < YEAR) {\n return labels.daysAgo.replace(\"{n}\", String(Math.floor(age / DAY)));\n }\n return labels.yearsAgo.replace(\"{n}\", String(Math.floor(age / YEAR)));\n}\n\n/**\n * Formats an age (elapsed time) given in **milliseconds** into a compact\n * human-readable string. Internally converts to seconds and delegates to\n * {@link formatAgeInSeconds}.\n *\n * This is the primary function used across UI components to display how\n * long ago something happened (e.g. a trade, a tweet, a channel update).\n *\n * @example\n * formatAge(3000) // \"just now\" (3 s < 10 s threshold)\n * formatAge(45000) // \"45s\"\n * formatAge(120000) // \"2m\"\n * formatAge(7200000) // \"2h\"\n *\n * @example Custom labels (e.g. for i18n)\n * formatAge(120000, { minutesAgo: \"{n} 分钟前\" }) // \"2 分钟前\"\n */\nexport function formatAge(age: number, options: FormatAgeOptions = {}): string {\n return formatAgeInSeconds(Math.floor(age / 1000), options);\n}\n","import { ApiError } from \"./errors\";\n\ninterface ParsedErrorBody {\n message?: string;\n code?: number;\n [key: string]: unknown;\n}\n\n/**\n * Parse the response body as JSON when possible; otherwise return `undefined`.\n * Never throws — non-JSON bodies are tolerated.\n */\nasync function parseErrorBody(\n response: Response,\n): Promise<ParsedErrorBody | undefined> {\n const text = await response.text().catch(() => \"\");\n if (!text) return undefined;\n try {\n return JSON.parse(text) as ParsedErrorBody;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Generic HTTP request helper.\n *\n * On success returns the parsed JSON body typed as `R` (defaults to `unknown`).\n * On HTTP 400 responses throws {@link ApiError} populated with the response\n * `message`, `code`, HTTP status, and raw parsed body. On any other non-OK\n * response throws a plain `Error` with a best-effort message.\n */\nexport async function httpRequest<R = unknown>(\n url: string,\n options: RequestInit,\n): Promise<R> {\n if (!url.startsWith(\"http\")) {\n throw new Error(\"url must start with http(s)\");\n }\n const response = await fetch(url, {\n ...options,\n headers: _createHeaders(options.headers, options.method),\n });\n\n if (response.ok) {\n return (await response.json()) as R;\n }\n\n const body = await parseErrorBody(response);\n const message =\n body?.message ??\n (body?.code !== undefined ? String(body.code) : undefined) ??\n response.statusText;\n\n if (response.status === 400) {\n throw new ApiError(\n message,\n body?.code ?? response.status,\n response.status,\n body,\n );\n }\n throw new Error(message);\n}\n\nfunction _createHeaders(\n headers: HeadersInit = {},\n method?: string,\n): HeadersInit {\n const _headers = new Headers(headers);\n\n if (!_headers.has(\"Content-Type\")) {\n if (method !== \"DELETE\") {\n _headers.append(\"Content-Type\", \"application/json;charset=utf-8\");\n } else {\n _headers.append(\"Content-Type\", \"application/x-www-form-urlencoded\");\n }\n }\n\n return _headers;\n}\n\nexport async function httpGet<R = unknown>(\n url: string,\n options?: RequestInit,\n): Promise<R> {\n return await httpRequest<R>(url, {\n method: \"GET\",\n ...options,\n });\n}\n\nexport async function httpPost<R = unknown, P = unknown>(\n url: string,\n data: P,\n options?: Omit<RequestInit, \"method\">,\n): Promise<R> {\n return await httpRequest<R>(url, {\n method: \"POST\",\n body: JSON.stringify(data),\n ...options,\n });\n}\n\nexport async function httpPut<R = unknown, P = unknown>(\n url: string,\n data: P,\n options?: Omit<RequestInit, \"method\">,\n): Promise<R> {\n return await httpRequest<R>(url, {\n method: \"PUT\",\n body: JSON.stringify(data),\n ...options,\n });\n}\n\nexport async function httpDelete<R = unknown>(\n url: string,\n options?: Omit<RequestInit, \"method\">,\n): Promise<R> {\n return await httpRequest<R>(url, {\n method: \"DELETE\",\n ...options,\n });\n}\n\nexport async function httpMutate<R = unknown>(\n url: string,\n init: RequestInit,\n): Promise<R> {\n return await httpRequest<R>(url, init);\n}\n","import BigNumber from \"bignumber.js\";\n\n// ---------------------------------------------------------------------------\n// SafeBigNumber\n// ---------------------------------------------------------------------------\n\n/**\n * A `BigNumber` subclass that never throws on construction.\n *\n * - `undefined` / `null` → falls back to `0`.\n * - Strings that `BigNumber` can't parse (e.g. `\"not-a-number\"`) → falls back to `0`.\n * - Strings with extra trailing characters (e.g. `\"123abc\"`) → falls back to `0`\n * (because `BigNumber` itself returns NaN for these).\n * - Any unexpected throw inside `BigNumber`'s constructor is caught and treated as `0`.\n */\nexport class SafeBigNumber extends BigNumber {\n constructor(num?: BigNumber.Value, base?: number) {\n try {\n super(num ?? 0, base);\n if (this.isNaN()) {\n return new BigNumber(0, base) as SafeBigNumber;\n }\n } catch (e) {\n console.error(\"SafeBigNumber constructor error\", e);\n super(0, base);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\n/** Decimal number literal: optional sign, digits, optional `.frac`, optional `eN` exponent. */\nconst NUMERIC_STRING_RE = /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:e[+-]?\\d+)?$/i;\n\n/**\n * Returns `true` when the value can be unambiguously parsed as a finite number.\n *\n * Strings must be fully numeric decimal literals (after trimming). Permissive\n * partial parses such as `\"123abc\"`, hex prefixes like `\"0x10\"`, the literal\n * `\"Infinity\"`, or empty strings are rejected. Finite numbers and `BigNumber`\n * / `SafeBigNumber` instances are accepted.\n */\nexport const isValidNumber = (num: unknown): boolean => {\n if (typeof num === \"number\") return Number.isFinite(num);\n if (num instanceof SafeBigNumber || num instanceof BigNumber) {\n return !num.isNaN() && num.isFinite();\n }\n if (typeof num !== \"string\") return false;\n const trimmed = num.trim();\n if (trimmed === \"\") return false;\n if (!NUMERIC_STRING_RE.test(trimmed)) return false;\n return Number.isFinite(Number(trimmed));\n};\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nconst subscriptDigits = [\n \"₀\",\n \"₁\",\n \"₂\",\n \"₃\",\n \"₄\",\n \"₅\",\n \"₆\",\n \"₇\",\n \"₈\",\n \"₉\",\n \"₁₀\",\n \"₁₁\",\n \"₁₂\",\n \"₁₃\",\n \"₁₄\",\n \"₁₅\",\n \"₁₆\",\n \"₁₇\",\n \"₁₈\",\n \"₁₉\",\n \"₂₀\",\n \"₂₁\",\n \"₂₂\",\n \"₂₃\",\n \"₂₄\",\n \"₂₅\",\n \"₂₆\",\n \"₂₇\",\n \"₂₈\",\n \"₂₉\",\n \"₃₀\",\n \"₃₁\",\n \"₃₂\",\n \"₃₃\",\n \"₃₄\",\n \"₃₅\",\n \"₃₆\",\n \"₃₇\",\n \"₃₈\",\n \"₃₉\",\n \"₄₀\",\n];\n\nconst MAX_SUBSCRIPT_INDEX = subscriptDigits.length - 1;\n\n/**\n * Add thousand-separators (commas) and truncate to `precision` decimals.\n *\n * stringifyNumberWithGroupingSeparator(12345.6789, 2) → \"12,345.67\"\n */\nconst stringifyNumberWithGroupingSeparator = (\n num: BigNumber.Value,\n precision: number = 0,\n rounding: BigNumber.RoundingMode = BigNumber.ROUND_DOWN,\n) => {\n const bn = new SafeBigNumber(num);\n const parts = bn.decimalPlaces(precision, rounding).toString().split(\".\");\n parts[0] = parts[0].replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\n return parts.join(\".\");\n};\n\n/**\n * Abbreviate large numbers with K / M / B / T suffixes.\n *\n * stringifyNumberWithAbbreviation(1234) → \"1.2K\"\n * stringifyNumberWithAbbreviation(5_600_000) → \"5.6M\"\n */\nconst stringifyNumberWithAbbreviation = (\n num: BigNumber.Value,\n precision: number = 1,\n): string => {\n const bn = new SafeBigNumber(num);\n if (bn.lt(1e3)) return bn.toString();\n if (bn.lt(1e6))\n return `${stringifyNumberWithGroupingSeparator(bn.div(1e3), precision)}K`;\n if (bn.lt(1e9))\n return `${stringifyNumberWithGroupingSeparator(bn.div(1e6), precision)}M`;\n if (bn.lt(1e12))\n return `${stringifyNumberWithGroupingSeparator(bn.dividedBy(1e9), precision)}B`;\n return `${stringifyNumberWithGroupingSeparator(bn.dividedBy(1e12), precision)}T`;\n};\n\n/**\n * Display tiny decimals with Unicode subscript zero-count notation.\n * E.g. `0.00000382` → `\"0.0₅382\"` (5 leading zeros after the decimal).\n *\n * For extreme values where the leading-zero count exceeds the available\n * subscript glyph table, falls back to `\"0\"` rather than producing\n * `\"undefined\"` in the output.\n */\nconst stringifyNumberWithLeadingZeroSubscripts = (\n num: BigNumber.Value,\n precision: number = 5,\n) => {\n const bn = new SafeBigNumber(num);\n if (bn.eq(0)) return \"0\";\n const [integerPart, decimalPart] = bn.toFixed().split(\".\");\n const digits = decimalPart.split(\"\");\n const firstNonZeroIndex = digits.findIndex((num) => \"0\" !== num);\n if (firstNonZeroIndex < 0 || firstNonZeroIndex > MAX_SUBSCRIPT_INDEX) {\n return \"0\";\n }\n const precisionDigitsCount = Math.min(\n digits.length - firstNonZeroIndex,\n precision,\n );\n return `${stringifyNumberWithGroupingSeparator(integerPart)}.0`\n .concat(subscriptDigits[firstNonZeroIndex])\n .concat(\n digits\n .slice(firstNonZeroIndex, firstNonZeroIndex + precisionDigitsCount)\n .join(\"\")\n .replace(/\\.?0+$/, \"\"),\n );\n};\n\n/**\n * Round to `precision` *significant* decimal digits (skipping leading zeros).\n * E.g. `0.00456` with precision 2 → keeps 5 decimal places → `\"0.00456\"`.\n */\nconst stringifyNumberWithSignificantPrecision = (\n num: BigNumber,\n precision: number,\n) => {\n const matched = num.toString().match(/\\.0*/);\n const significantPrecision =\n (matched ? matched[0].length - 1 : 0) + precision;\n return stringifyNumberWithGroupingSeparator(num, significantPrecision);\n};\n\nconst stringifyPercent = (bn: BigNumber, precision: number) => {\n const scaled = bn\n .times(100)\n .decimalPlaces(precision, BigNumber.ROUND_HALF_UP);\n return `${stringifyNumberWithGroupingSeparator(scaled, precision)}%`;\n};\n\n// ---------------------------------------------------------------------------\n// Sign / validation wrapper shared by every amount formatter\n// ---------------------------------------------------------------------------\n\ntype FormatTier = (abs: SafeBigNumber) => string;\n\ninterface FormatWithSignOptions {\n showPlusGtThanZero?: boolean;\n /** String returned when the input is not a valid number. */\n invalidPlaceholder?: string;\n /** Returned as-is when the formatted absolute value collapses to zero. */\n zeroToken?: string;\n}\n\n/**\n * Shared validation / sign-handling wrapper for amount formatters.\n *\n * - Returns `invalidPlaceholder` when `isValidNumber(num)` is false.\n * - Computes the absolute value and passes it through `tier` for tier-specific formatting.\n * - Returns the formatted string as-is when it equals `zeroToken` (used to avoid `-$0`).\n * - Prefixes `\"-\"` for negatives, `\"+\"` for positives when `showPlusGtThanZero` is set.\n */\nconst formatWithSign = (\n num: BigNumber.Value,\n tier: FormatTier,\n options: FormatWithSignOptions,\n): string => {\n const { showPlusGtThanZero, invalidPlaceholder = \"--\", zeroToken } = options;\n if (!isValidNumber(num)) return invalidPlaceholder;\n\n const bn = new SafeBigNumber(num);\n const negative = bn.lt(0);\n const abs = bn.abs();\n const formatted = tier(abs);\n\n if (zeroToken !== undefined && formatted === zeroToken) return formatted;\n if (formatted === \"0\" || Number(formatted) === 0) return formatted;\n if (negative) return `-${formatted}`;\n if (showPlusGtThanZero) return `+${formatted}`;\n return formatted;\n};\n\n// ---------------------------------------------------------------------------\n// Public formatting functions\n// ---------------------------------------------------------------------------\n\nexport type FormatAmountOptions = {\n showPlusGtThanZero: boolean;\n};\n\nconst tierAmount: FormatTier = (abs) =>\n abs.lt(0.001)\n ? abs.decimalPlaces(5, BigNumber.ROUND_DOWN).toString()\n : abs.lt(1)\n ? abs.decimalPlaces(3, BigNumber.ROUND_DOWN).toString()\n : abs.lt(100)\n ? abs.decimalPlaces(2, BigNumber.ROUND_DOWN).toString()\n : abs.lt(1e5)\n ? stringifyNumberWithGroupingSeparator(abs, 2)\n : stringifyNumberWithAbbreviation(abs);\n\n/**\n * Format a raw token / asset amount (no currency symbol).\n *\n * Precision tiers (ROUND_DOWN):\n * | Range | Format | Example input → output |\n * |---------------|-------------------------|------------------------------|\n * | < 0.001 | 5 decimal places | 0.0001234 → \"0.00012\" |\n * | < 1 | 3 decimal places | 0.56789 → \"0.567\" |\n * | < 100 | 2 decimal places | 42.678 → \"42.67\" |\n * | < 100 000 | grouped, 2 dp | 12345.6 → \"12,345.60\" |\n * | ≥ 100 000 | abbreviated (K/M/B/T) | 1_500_000 → \"1.5M\" |\n *\n * @param num - The numeric value.\n * @param options.showPlusGtThanZero - Prefix positive values with \"+\".\n */\nexport const formatAmount = (\n num: BigNumber.Value = \"\",\n options: FormatAmountOptions = { showPlusGtThanZero: false },\n) =>\n formatWithSign(num, tierAmount, {\n showPlusGtThanZero: options?.showPlusGtThanZero,\n });\n\nconst tierAmountUSD: FormatTier = (abs) =>\n abs.lt(0.001)\n ? \"$0\"\n : abs.lt(1)\n ? `$${abs.decimalPlaces(3, BigNumber.ROUND_DOWN)}`\n : abs.lt(100)\n ? `$${abs.decimalPlaces(2, BigNumber.ROUND_DOWN)}`\n : abs.lt(1e4)\n ? `$${stringifyNumberWithGroupingSeparator(abs, 2)}`\n : `$${stringifyNumberWithAbbreviation(abs)}`;\n\n/**\n * Format a USD dollar amount with \"$\" prefix (standard precision).\n *\n * Precision tiers (ROUND_DOWN):\n * | Range | Format | Example input → output |\n * |---------------|-------------------------|------------------------------|\n * | < 0.001 | \"$0\" | 0.00001 → \"$0\" |\n * | < 1 | 3 decimal places | 0.56789 → \"$0.567\" |\n * | < 100 | 2 decimal places | 42.678 → \"$42.67\" |\n * | < 10 000 | grouped, 2 dp | 1234.5 → \"$1,234.50\" |\n * | ≥ 10 000 | abbreviated (K/M/B/T) | 1_500_000 → \"$1.5M\" |\n *\n * Use this for standard financial displays (volume, market cap, liquidity).\n *\n * @param num - The numeric value.\n * @param options.showPlusGtThanZero - Prefix positive values with \"+\".\n */\nexport const formatAmountUSD = (\n num: BigNumber.Value = \"\",\n options: FormatAmountOptions = { showPlusGtThanZero: false },\n) =>\n formatWithSign(num, tierAmountUSD, {\n showPlusGtThanZero: options?.showPlusGtThanZero,\n zeroToken: \"$0\",\n });\n\nconst tierAmountCompact: FormatTier = (abs) => {\n if (abs.lt(0.001)) return \"0\";\n if (abs.lt(1)) return abs.decimalPlaces(3, BigNumber.ROUND_DOWN).toString();\n if (abs.lt(100)) return abs.decimalPlaces(2, BigNumber.ROUND_DOWN).toString();\n if (abs.lt(1e3)) return abs.decimalPlaces(0, BigNumber.ROUND_DOWN).toString();\n const roundedAbs = abs.div(100).integerValue(BigNumber.ROUND_DOWN).times(100);\n return stringifyNumberWithAbbreviation(roundedAbs, 0);\n};\n\n/**\n * Format a raw token / asset amount (no currency symbol) — **compact** variant.\n *\n * Same tier ladder as {@link formatAmountUSDCompact} but without the `\"$\"`\n * prefix. Suited for space-constrained UIs that need to render an amount\n * alongside a token symbol (e.g. `\"15K SOL\"`) inside narrow buttons or\n * badges.\n *\n * | Range | Format | Example input → output |\n * |---------------|-------------------------|------------------------------|\n * | < 0.001 | \"0\" | 0.00001 → \"0\" |\n * | < 1 | 3 decimal places | 0.56789 → \"0.567\" |\n * | < 100 | 2 decimal places | 42.678 → \"42.67\" |\n * | < 1 000 | 0 decimal places | 567.89 → \"567\" |\n * | ≥ 1 000 | abbreviated, 0 dp, | 15 678 → \"15K\" |\n * | | rounded to nearest 100 | 1 234 567 → \"1M\" |\n *\n * @param num - The numeric value.\n * @param options.showPlusGtThanZero - Prefix positive values with \"+\".\n */\nexport const formatAmountCompact = (\n num: BigNumber.Value = \"\",\n options: FormatAmountOptions = { showPlusGtThanZero: false },\n) =>\n formatWithSign(num, tierAmountCompact, {\n showPlusGtThanZero: options?.showPlusGtThanZero,\n zeroToken: \"0\",\n });\n\nconst tierAmountUSDCompact: FormatTier = (abs) => {\n if (abs.lt(0.001)) return \"$0\";\n if (abs.lt(1)) return `$${abs.decimalPlaces(3, BigNumber.ROUND_DOWN)}`;\n if (abs.lt(100)) return `$${abs.decimalPlaces(2, BigNumber.ROUND_DOWN)}`;\n if (abs.lt(1e3)) return `$${abs.decimalPlaces(0, BigNumber.ROUND_DOWN)}`;\n const roundedAbs = abs.div(100).integerValue(BigNumber.ROUND_DOWN).times(100);\n return `$${stringifyNumberWithAbbreviation(roundedAbs, 0)}`;\n};\n\n/**\n * Format a USD dollar amount with \"$\" prefix — **compact** variant.\n *\n * Compared to {@link formatAmountUSD}, this variant is more aggressively\n * rounded and suited for space-constrained UIs (cards, badges, list items):\n *\n * | Range | Format | Example input → output |\n * |---------------|-------------------------|------------------------------|\n * | < 0.001 | \"$0\" | 0.00001 → \"$0\" |\n * | < 1 | 3 decimal places | 0.56789 → \"$0.567\" |\n * | < 100 | 2 decimal places | 42.678 → \"$42.67\" |\n * | < 1 000 | 0 decimal places | 567.89 → \"$567\" |\n * | ≥ 1 000 | abbreviated, 0 dp, | 15 678 → \"$15.6K\" |\n * | | rounded to nearest 100 | 1 234 567 → \"$1.2M\" |\n *\n * Key differences from `formatAmountUSD`:\n * - 100–1 000: shows 0 dp instead of 2 dp\n * - ≥ 1 000: abbreviates earlier (1K vs 10K) with 0 precision, rounded to 100s\n *\n * @param num - The numeric value.\n * @param options.showPlusGtThanZero - Prefix positive values with \"+\".\n */\nexport const formatAmountUSDCompact = (\n num: BigNumber.Value = \"\",\n options: FormatAmountOptions = { showPlusGtThanZero: false },\n) =>\n formatWithSign(num, tierAmountUSDCompact, {\n showPlusGtThanZero: options?.showPlusGtThanZero,\n zeroToken: \"$0\",\n });\n\nexport type FormatPriceOptions = {\n isHighPrecise: boolean;\n};\n\n/**\n * Shared tier for {@link formatPrice} and {@link formatPriceUSD}: identical\n * precision ladder, with only the leading `\"$\"` differing between the two.\n */\nconst tierPrice = (isHighPrecise: boolean): FormatTier => {\n return (abs) =>\n abs.lt(1e-4)\n ? stringifyNumberWithLeadingZeroSubscripts(abs, isHighPrecise ? 4 : 2)\n : abs.lt(1)\n ? isHighPrecise\n ? stringifyNumberWithGroupingSeparator(abs, 4)\n : stringifyNumberWithSignificantPrecision(abs, 2)\n : abs.lt(100) || abs.lt(1e4)\n ? stringifyNumberWithGroupingSeparator(abs, isHighPrecise ? 4 : 2)\n : abs.lt(1e5)\n ? stringifyNumberWithGroupingSeparator(abs, 2)\n : stringifyNumberWithAbbreviation(abs);\n};\n\n/**\n * Format a token price (no currency symbol). Negative inputs render as `\"--\"`.\n *\n * Same precision tiers as {@link formatPriceUSD} but without the \"$\" prefix.\n *\n * @param num - The price value.\n * @param options.isHighPrecise - Use high-precision mode (default: true).\n */\nexport const formatPrice = (\n num: BigNumber.Value = \"\",\n options: FormatPriceOptions = { isHighPrecise: true },\n) => {\n if (!isValidNumber(num)) return \"--\";\n const bn = new SafeBigNumber(num);\n if (bn.lt(0)) return \"--\";\n return tierPrice(options.isHighPrecise)(bn.abs());\n};\n\n/**\n * Format a token price with \"$\" prefix. Negative inputs render as `\"--\"`.\n *\n * Two precision modes controlled by `isHighPrecise` (default: `true`):\n *\n * | Range | High precision (default) | Low precision |\n * |---------------|-------------------------------|------------------------------|\n * | < 0.0001 | subscript notation, 4 sig | subscript notation, 2 sig |\n * | | 0.0000382 → \"$0.0₄382\" | 0.0000382 → \"$0.0₄38\" |\n * | < 1 | 4 dp, grouped | 2 significant dp |\n * | | 0.12345 → \"$0.1234\" | 0.12345 → \"$0.12\" |\n * | < 10 000 | 4 dp, grouped | 2 dp, grouped |\n * | | 1234.567 → \"$1,234.5670\" | 1234.567 → \"$1,234.56\" |\n * | < 100 000 | 2 dp, grouped | 2 dp, grouped |\n * | ≥ 100 000 | abbreviated (K/M/B/T) | abbreviated (K/M/B/T) |\n *\n * @param num - The price value.\n * @param options.isHighPrecise - Use high-precision mode (default: true).\n */\nexport const formatPriceUSD = (\n num: BigNumber.Value = \"\",\n options: FormatPriceOptions = { isHighPrecise: true },\n) => {\n if (!isValidNumber(num)) return \"--\";\n const bn = new SafeBigNumber(num);\n if (bn.lt(0)) return \"--\";\n return `$${tierPrice(options.isHighPrecise)(bn.abs())}`;\n};\n\nexport type FormatPercentOptions = {\n showPlusGtThanZero?: boolean;\n precision?: number;\n};\n\n/**\n * Format a ratio as a percentage string.\n *\n * The input is a **ratio** (0.3 = 30%, 1.5 = 150%).\n *\n * | Input range | Output example |\n * |---------------|-----------------------------------------|\n * | < 0.0001 | \"0%\" |\n * | < 100 | \"56.79%\" (2 dp by default) |\n * | < 1000 | \"15,000.5%\" (1 dp by default) |\n * | ≥ 1000 | \"> 99,999%\" |\n *\n * Large values use thousand-grouping separators (e.g. `\"15,000%\"`).\n *\n * @param num - The ratio value (0.3 means 30%).\n * @param options.showPlusGtThanZero - Prefix positive values with \"+\".\n * @param options.precision - Decimal precision override.\n */\nexport const formatPercent = (\n num: BigNumber.Value = \"\",\n options: FormatPercentOptions = {},\n) => {\n if (!isValidNumber(num)) return \"-- %\";\n\n const bn = new SafeBigNumber(num);\n const negative = bn.lt(0);\n const abs = bn.abs();\n const sign = negative ? \"-\" : options?.showPlusGtThanZero ? \"+\" : \"\";\n\n if (abs.lt(1e-4)) return \"0%\";\n if (abs.lt(100))\n return `${sign}${stringifyPercent(abs, options?.precision ?? 2)}`;\n if (abs.lt(1e3))\n return `${sign}${stringifyPercent(abs, options?.precision ?? 1)}`;\n return `${sign}> 99,999%`;\n};\n","/**\n * Capitalize the first letter of a string, lowercasing the rest.\n *\n * @example\n * capitalize(\"hello\") // \"Hello\"\n * capitalize(\"hELLO\") // \"Hello\"\n * capitalize(\"solana\") // \"Solana\"\n */\nexport function capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();\n}\n\n/**\n * Truncate an address (or any string) to show the first `start` and last `end`\n * characters with \"...\" in between.\n *\n * @param address - The full address string.\n * @param start - Number of characters to keep from the beginning (default 6).\n * @param end - Number of characters to keep from the end (default 4).\n *\n * @example\n * truncateAddress(\"0x1234567890abcdef1234567890abcdef12345678\")\n * // \"0x1234...5678\"\n *\n * truncateAddress(\"0x1234567890abcdef1234567890abcdef12345678\", 4, 4)\n * // \"0x12...5678\"\n */\nexport function truncateAddress(\n address: string,\n start: number = 6,\n end: number = 4,\n): string {\n return address.slice(0, start) + \"...\" + address.slice(-end);\n}\n","/** Single regex used to replace every placeholder occurrence in one pass. */\nconst SYMBOL_PLACEHOLDER_RE = /\\{?\\b(type|base|quote)\\b\\}?/g;\n\n/**\n * Format trading pair symbol.\n *\n * Splits a symbol like `\"PERP_BTC_USDT\"` into `type`/`base`/`quote` parts and\n * substitutes them into the format template. Placeholders may be written either\n * as bare words (`type`, `base`, `quote`) or with curly braces (`{type}`,\n * `{base}`, `{quote}`). All placeholder occurrences are replaced in a single\n * pass, so substitutions cannot interfere with each other even if the\n * substituted value happens to contain another placeholder substring.\n *\n * @param symbol - Original trading pair symbol in format `\"type_base_quote\"` (e.g. `\"PERP_BTC_USDT\"`).\n * @param formatString - Format string template; defaults to `\"base-type\"`.\n *\n * @returns Formatted string, or `\"\"` if `symbol` is empty.\n *\n * @example\n * ```typescript\n * formatSymbol(\"PERP_BTC_USDT\") // \"BTC-PERP\" (default \"base-type\")\n * formatSymbol(\"PERP_BTC_USDT\", \"base\") // \"BTC\"\n * formatSymbol(\"PERP_BTC_USDT\", \"base-type\") // \"BTC-PERP\"\n * formatSymbol(\"SPOT_ETH_USDC\", \"base-quote\") // \"ETH-USDC\"\n * formatSymbol(\"SPOT_ETH_USDC\", \"{base}/{quote}\") // \"ETH/USDC\"\n * ```\n */\nexport function formatSymbol(\n symbol: string,\n formatString: string = \"base-type\",\n): string {\n if (!symbol) return \"\";\n\n const [type = \"\", base = \"\", quote = \"\"] = symbol.split(\"_\");\n\n return formatString.replace(SYMBOL_PLACEHOLDER_RE, (_, key) => {\n if (key === \"type\") return type;\n if (key === \"base\") return base;\n return quote;\n });\n}\n","import {\n Chain,\n SOLANA_TOKEN_PROTOCOLS,\n TokenProtocol,\n} from \"@liberfi.io/types\";\n\nconst SOLANA_PROTOCOL_SET = new Set<string>(SOLANA_TOKEN_PROTOCOLS);\n\n/** Sorted by length descending so \"pump-amm\" is tested before \"pump\". */\nconst SOLANA_PROTOCOLS_BY_SPECIFICITY = [...SOLANA_TOKEN_PROTOCOLS].sort(\n (a, b) => b.length - a.length,\n);\n\nexport const parseTokenProtocolFamily = (\n chain: Chain,\n protocolFamily: string,\n): TokenProtocol | undefined => {\n if (chain !== Chain.SOLANA) return undefined;\n\n const normalized = protocolFamily.toLowerCase();\n\n if (SOLANA_PROTOCOL_SET.has(normalized)) {\n return normalized as TokenProtocol;\n }\n\n return SOLANA_PROTOCOLS_BY_SPECIFICITY.find((p) => normalized.includes(p));\n};\n\nexport const formatTokenProtocolName = (protocol: TokenProtocol): string => {\n return protocol\n .split(\"-\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \");\n};\n","import { Chain } from \"@liberfi.io/types\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface PredefinedToken {\n address: string;\n symbol: string;\n decimals: number;\n}\n\nexport interface ChainPredefinedTokens {\n native: PredefinedToken;\n wrapped: PredefinedToken;\n stablecoins: Record<string, PredefinedToken>;\n}\n\n// ---------------------------------------------------------------------------\n// EVM common\n// ---------------------------------------------------------------------------\n\nconst EVM_NATIVE_ADDRESS = \"0x0000000000000000000000000000000000000000\";\n\n// ---------------------------------------------------------------------------\n// Solana\n// ---------------------------------------------------------------------------\n\nexport const SOLANA_TOKENS: ChainPredefinedTokens = {\n native: {\n address: \"11111111111111111111111111111111\",\n symbol: \"SOL\",\n decimals: 9,\n },\n wrapped: {\n address: \"So11111111111111111111111111111111111111112\",\n symbol: \"SOL\",\n decimals: 9,\n },\n stablecoins: {\n USDC: {\n address: \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\",\n symbol: \"USDC\",\n decimals: 6,\n },\n USDT: {\n address: \"Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB\",\n symbol: \"USDT\",\n decimals: 6,\n },\n USD1: {\n address: \"USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB\",\n symbol: \"USD1\",\n decimals: 6,\n },\n },\n};\n\n// ---------------------------------------------------------------------------\n// Ethereum\n// ---------------------------------------------------------------------------\n\nexport const ETHEREUM_TOKENS: ChainPredefinedTokens = {\n native: {\n address: EVM_NATIVE_ADDRESS,\n symbol: \"ETH\",\n decimals: 18,\n },\n wrapped: {\n address: \"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\",\n symbol: \"WETH\",\n decimals: 18,\n },\n stablecoins: {\n USDC: {\n address: \"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\",\n symbol: \"USDC\",\n decimals: 6,\n },\n USDT: {\n address: \"0xdAC17F958D2ee523a2206206994597C13D831ec7\",\n symbol: \"USDT\",\n decimals: 6,\n },\n },\n};\n\n// ---------------------------------------------------------------------------\n// BSC (Binance Smart Chain)\n// ---------------------------------------------------------------------------\n\nexport const BSC_TOKENS: ChainPredefinedTokens = {\n native: {\n address: EVM_NATIVE_ADDRESS,\n symbol: \"BNB\",\n decimals: 18,\n },\n wrapped: {\n address: \"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c\",\n symbol: \"WBNB\",\n decimals: 18,\n },\n stablecoins: {\n USDC: {\n address: \"0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d\",\n symbol: \"USDC\",\n decimals: 18,\n },\n USDT: {\n address: \"0x55d398326f99059fF775485246999027B3197955\",\n symbol: \"USDT\",\n decimals: 18,\n },\n },\n};\n\n// ---------------------------------------------------------------------------\n// Arbitrum\n// ---------------------------------------------------------------------------\n\nexport const ARBITRUM_TOKENS: ChainPredefinedTokens = {\n native: {\n address: EVM_NATIVE_ADDRESS,\n symbol: \"ETH\",\n decimals: 18,\n },\n wrapped: {\n address: \"0x82aF49447D8a07e3bd95BD0d56f35241523fBab1\",\n symbol: \"WETH\",\n decimals: 18,\n },\n stablecoins: {\n USDC: {\n address: \"0xaf88d065e77c8cC2239327C5EDb3A432268e5831\",\n symbol: \"USDC\",\n decimals: 6,\n },\n USDT: {\n address: \"0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9\",\n symbol: \"USDT\",\n decimals: 6,\n },\n },\n};\n\n// ---------------------------------------------------------------------------\n// Optimism\n// ---------------------------------------------------------------------------\n\nexport const OPTIMISM_TOKENS: ChainPredefinedTokens = {\n native: {\n address: EVM_NATIVE_ADDRESS,\n symbol: \"ETH\",\n decimals: 18,\n },\n wrapped: {\n address: \"0x4200000000000000000000000000000000000006\",\n symbol: \"WETH\",\n decimals: 18,\n },\n stablecoins: {\n USDC: {\n address: \"0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85\",\n symbol: \"USDC\",\n decimals: 6,\n },\n USDT: {\n address: \"0x94b008aA00579c1307B0EF2c499aD98a8ce58e58\",\n symbol: \"USDT\",\n decimals: 6,\n },\n },\n};\n\n// ---------------------------------------------------------------------------\n// Avalanche\n// ---------------------------------------------------------------------------\n\nexport const AVALANCHE_TOKENS: ChainPredefinedTokens = {\n native: {\n address: EVM_NATIVE_ADDRESS,\n symbol: \"AVAX\",\n decimals: 18,\n },\n wrapped: {\n address: \"0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7\",\n symbol: \"WAVAX\",\n decimals: 18,\n },\n stablecoins: {\n USDC: {\n address: \"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E\",\n symbol: \"USDC\",\n decimals: 6,\n },\n USDT: {\n address: \"0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7\",\n symbol: \"USDT\",\n decimals: 6,\n },\n },\n};\n\n// ---------------------------------------------------------------------------\n// Chain -> Tokens index\n// ---------------------------------------------------------------------------\n\nexport const CHAIN_TOKENS: Partial<Record<Chain, ChainPredefinedTokens>> = {\n [Chain.SOLANA]: SOLANA_TOKENS,\n [Chain.ETHEREUM]: ETHEREUM_TOKENS,\n [Chain.BINANCE]: BSC_TOKENS,\n [Chain.ARBITRUM]: ARBITRUM_TOKENS,\n [Chain.OPTIMISM]: OPTIMISM_TOKENS,\n [Chain.AVALANCHE]: AVALANCHE_TOKENS,\n};\n\n// ---------------------------------------------------------------------------\n// Helper functions\n// ---------------------------------------------------------------------------\n\nexport function getNativeToken(chain: Chain): PredefinedToken | undefined {\n return CHAIN_TOKENS[chain]?.native;\n}\n\nexport function getWrappedToken(chain: Chain): PredefinedToken | undefined {\n return CHAIN_TOKENS[chain]?.wrapped;\n}\n\nexport function getStablecoins(\n chain: Chain,\n): Record<string, PredefinedToken> | undefined {\n return CHAIN_TOKENS[chain]?.stablecoins;\n}\n\n/** Returns all predefined token addresses for the given chain (native + wrapped + stablecoins). */\nexport function getCommonTokenAddresses(chain: Chain): string[] {\n const tokens = CHAIN_TOKENS[chain];\n if (!tokens) return [];\n return [\n tokens.native.address,\n tokens.wrapped.address,\n ...Object.values(tokens.stablecoins).map((t) => t.address),\n ];\n}\n\n/** Returns an address -> symbol map for all predefined tokens on the given chain. */\nexport function getCommonTokenSymbolsMap(chain: Chain): Record<string, string> {\n const tokens = CHAIN_TOKENS[chain];\n if (!tokens) return {};\n const map: Record<string, string> = {\n [tokens.native.address]: tokens.native.symbol,\n [tokens.wrapped.address]: tokens.wrapped.symbol,\n };\n for (const t of Object.values(tokens.stablecoins)) {\n map[t.address] = t.symbol;\n }\n return map;\n}\n","import { Chain } from \"@liberfi.io/types\";\n\nconst TX_EXPLORER_URLS: Partial<Record<Chain, string>> = {\n [Chain.SOLANA]: \"https://solscan.io/tx/\",\n [Chain.ETHEREUM]: \"https://etherscan.io/tx/\",\n [Chain.POLYGON]: \"https://polygonscan.com/tx/\",\n [Chain.BINANCE]: \"https://bscscan.com/tx/\",\n [Chain.BINANCE_TESTNET]: \"https://testnet.bscscan.com/tx/\",\n [Chain.AVALANCHE]: \"https://snowtrace.io/tx/\",\n [Chain.BASE]: \"https://basescan.org/tx/\",\n [Chain.BLAST]: \"https://blastracker.xyz/tx/\",\n [Chain.ARBITRUM]: \"https://arbiscan.io/tx/\",\n [Chain.ARBITRUM_NOVA]: \"https://nova.arbiscan.io/tx/\",\n [Chain.ARBITRUM_TESTNET_GOERLI]: \"https://goerli.arbiscan.io/tx/\",\n [Chain.ARBITRUM_TESTNET_SEPOLIA]: \"https://sepolia.arbiscan.io/tx/\",\n};\n\nconst ACCOUNT_EXPLORER_URLS: Partial<Record<Chain, string>> = {\n [Chain.SOLANA]: \"https://solscan.io/account/\",\n [Chain.ETHEREUM]: \"https://etherscan.io/address/\",\n [Chain.POLYGON]: \"https://polygonscan.com/address/\",\n [Chain.BINANCE]: \"https://bscscan.com/address/\",\n [Chain.BINANCE_TESTNET]: \"https://testnet.bscscan.com/address/\",\n [Chain.AVALANCHE]: \"https://snowtrace.io/address/\",\n [Chain.BASE]: \"https://basescan.org/address/\",\n [Chain.BLAST]: \"https://blastracker.xyz/address/\",\n [Chain.ARBITRUM]: \"https://arbiscan.io/address/\",\n [Chain.ARBITRUM_NOVA]: \"https://nova.arbiscan.io/address/\",\n [Chain.ARBITRUM_TESTNET_GOERLI]: \"https://goerli.arbiscan.io/address/\",\n [Chain.ARBITRUM_TESTNET_SEPOLIA]: \"https://sepolia.arbiscan.io/address/\",\n};\n\nfunction explorerUrl(\n urls: Partial<Record<Chain, string>>,\n chainId: Chain,\n value: string,\n): string | undefined {\n const base = urls[chainId];\n return base ? `${base}${value}` : undefined;\n}\n\nexport function txExplorerUrl(\n chainId: Chain,\n txHash: string,\n): string | undefined {\n return explorerUrl(TX_EXPLORER_URLS, chainId, txHash);\n}\n\nexport function accountExplorerUrl(\n chainId: Chain,\n account: string,\n): string | undefined {\n return explorerUrl(ACCOUNT_EXPLORER_URLS, chainId, account);\n}\n\nexport function searchImageUrl(image: string): string {\n return `https://lens.google.com/uploadbyurl?url=${encodeURIComponent(image)}`;\n}\n\nexport function searchTwitterUrl(q: string): string {\n return `https://x.com/search?q=${encodeURIComponent(q)}`;\n}\n\nexport function twitterUserUrl(username: string): string {\n return `https://x.com/${username}`;\n}\n\nexport function twitterTweetUrl(id: string): string {\n return `https://x.com/i/status/${id}`;\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\nexport function throttle<T extends (...args: any[]) => void>(\n fn: T,\n wait: number,\n): T {\n let lastCallTime = 0;\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let lastArgs: Parameters<T> | null = null;\n\n const throttled = (...args: Parameters<T>) => {\n const now = Date.now();\n const remaining = wait - (now - lastCallTime);\n\n if (remaining <= 0) {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n lastCallTime = now;\n fn(...args);\n } else {\n lastArgs = args;\n if (timeoutId === null) {\n timeoutId = setTimeout(() => {\n lastCallTime = Date.now();\n timeoutId = null;\n if (lastArgs) {\n fn(...lastArgs);\n lastArgs = null;\n }\n }, remaining);\n }\n }\n };\n\n return throttled as T;\n}\n\nexport type DebouncedFunction<T extends (...args: any[]) => void> = T & {\n cancel: () => void;\n};\n\nexport function debounce<T extends (...args: any[]) => void>(\n fn: T,\n wait: number,\n): DebouncedFunction<T> {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const debounced = (...args: Parameters<T>) => {\n if (timeoutId !== null) clearTimeout(timeoutId);\n timeoutId = setTimeout(() => {\n timeoutId = null;\n fn(...args);\n }, wait);\n };\n\n debounced.cancel = () => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n };\n\n return debounced as DebouncedFunction<T>;\n}\n","/** Accepts either a key-extractor function or a property name. */\ntype Iteratee<T, R> = ((item: T) => R) | keyof T;\n\n/**\n * Normalize an `Iteratee` into a plain getter function.\n *\n * @param iteratee - Function or property key.\n * @param stringify - If `true`, the value extracted via a property key is wrapped\n * in `String(...)` (used by `keyBy` / `groupBy`).\n */\nfunction asGetter<T, R>(\n iteratee: Iteratee<T, R>,\n stringify = false,\n): (item: T) => R {\n if (typeof iteratee === \"function\") return iteratee;\n return stringify\n ? (item: T) => String(item[iteratee]) as R\n : (item: T) => item[iteratee] as R;\n}\n\nexport function uniqBy<T>(array: T[], iteratee: Iteratee<T, unknown>): T[] {\n const getter = asGetter(iteratee);\n const seen = new Set<unknown>();\n return array.filter((item) => {\n const key = getter(item);\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\nexport function intersectionBy<T>(\n a: T[],\n b: T[],\n iteratee: Iteratee<T, unknown>,\n): T[] {\n const getter = asGetter(iteratee);\n const bKeys = new Set(b.map(getter));\n return a.filter((item) => bKeys.has(getter(item)));\n}\n\nexport function keyBy<T>(\n array: T[],\n iteratee: Iteratee<T, string>,\n): Record<string, T> {\n const getter = asGetter(iteratee, true);\n const result: Record<string, T> = {};\n for (const item of array) {\n result[getter(item)] = item;\n }\n return result;\n}\n\nexport function groupBy<T>(\n array: T[],\n iteratee: Iteratee<T, string>,\n): Record<string, T[]> {\n const getter = asGetter(iteratee, true);\n const result: Record<string, T[]> = {};\n for (const item of array) {\n const key = getter(item);\n (result[key] ??= []).push(item);\n }\n return result;\n}\n\nexport function mapKeys<T>(\n obj: Record<string, T>,\n iteratee: (value: T, key: string) => string,\n): Record<string, T> {\n const result: Record<string, T> = {};\n for (const key of Object.keys(obj)) {\n result[iteratee(obj[key], key)] = obj[key];\n }\n return result;\n}\n\nexport function mapValues<T, R>(\n obj: Record<string, T>,\n iteratee: (value: T, key: string) => R,\n): Record<string, R> {\n const result: Record<string, R> = {};\n for (const key of Object.keys(obj)) {\n result[key] = iteratee(obj[key], key);\n }\n return result;\n}\n"],"mappings":"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","names":["Chain","ChainNamespace","solanaChains","ethereumChains","binanceChains","chainToNamespace","chain","isSolanaChain","isEthereumChain","isBinanceChain","CHAIN_REGISTRY","chainColor","chainId","chainSlug","chainIcon","chainIdBySlug","slug","chainDisplayName","meta","c","slugToChainId","map","key","isValidWalletAddress","addr","isValidSolanaAddress","isValidEvmAddress","EVM_ADDRESS_RE","value","SOLANA_BASE58_RE","ApiError","message","code","status","data","defaultLabels","formatAgeInSeconds","age","options","labels","formatAge","parseErrorBody","response","text","httpRequest","url","options","_createHeaders","body","message","ApiError","headers","method","_headers","httpGet","httpPost","data","httpPut","httpDelete","httpMutate","init","BigNumber","SafeBigNumber","num","base","e","NUMERIC_STRING_RE","isValidNumber","trimmed","subscriptDigits","MAX_SUBSCRIPT_INDEX","stringifyNumberWithGroupingSeparator","precision","rounding","parts","stringifyNumberWithAbbreviation","bn","stringifyNumberWithLeadingZeroSubscripts","integerPart","decimalPart","digits","firstNonZeroIndex","precisionDigitsCount","stringifyNumberWithSignificantPrecision","matched","significantPrecision","stringifyPercent","scaled","formatWithSign","tier","options","showPlusGtThanZero","invalidPlaceholder","zeroToken","negative","abs","formatted","tierAmount","formatAmount","tierAmountUSD","formatAmountUSD","tierAmountCompact","roundedAbs","formatAmountCompact","tierAmountUSDCompact","formatAmountUSDCompact","tierPrice","isHighPrecise","formatPrice","formatPriceUSD","formatPercent","sign","capitalize","str","truncateAddress","address","start","end","SYMBOL_PLACEHOLDER_RE","formatSymbol","symbol","formatString","type","base","quote","_","key","Chain","SOLANA_TOKEN_PROTOCOLS","SOLANA_PROTOCOL_SET","SOLANA_PROTOCOLS_BY_SPECIFICITY","a","b","parseTokenProtocolFamily","chain","protocolFamily","normalized","p","formatTokenProtocolName","protocol","word","Chain","EVM_NATIVE_ADDRESS","SOLANA_TOKENS","ETHEREUM_TOKENS","BSC_TOKENS","ARBITRUM_TOKENS","OPTIMISM_TOKENS","AVALANCHE_TOKENS","CHAIN_TOKENS","getNativeToken","chain","getWrappedToken","getStablecoins","getCommonTokenAddresses","tokens","t","getCommonTokenSymbolsMap","map","Chain","TX_EXPLORER_URLS","ACCOUNT_EXPLORER_URLS","explorerUrl","urls","chainId","value","base","txExplorerUrl","txHash","accountExplorerUrl","account","searchImageUrl","image","searchTwitterUrl","q","twitterUserUrl","username","twitterTweetUrl","id","throttle","fn","wait","lastCallTime","timeoutId","lastArgs","args","now","remaining","debounce","debounced","asGetter","iteratee","stringify","item","uniqBy","array","getter","seen","key","intersectionBy","a","b","bKeys","keyBy","result","groupBy","mapKeys","obj","mapValues"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liberfi.io/utils",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "Liberfi React SDK utils",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -15,11 +15,11 @@
15
15
  "ts-jest": "^29.4.0",
16
16
  "tsup": "^8.5.0",
17
17
  "typescript": "^5.9.2",
18
- "tsconfig": "0.1.190"
18
+ "tsconfig": "0.1.192"
19
19
  },
20
20
  "dependencies": {
21
21
  "bignumber.js": "^9.3.1",
22
- "@liberfi.io/types": "0.4.7"
22
+ "@liberfi.io/types": "0.4.9"
23
23
  },
24
24
  "publishConfig": {
25
25
  "access": "public"