@anywalletkit/protocol-swap2-thorchain 0.1.8 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/activity.ts","../src/provider.ts","../src/protocol.ts"],"sourcesContent":["export * from \"./config.js\";\nexport * from \"./provider.js\";\nexport {ThorchainSwap2Protocol} from \"./protocol.js\";\nexport {ThorchainSwap2Protocol as default} from \"./protocol.js\";\nexport * from \"./activity.js\";\n","import {evmRef, isEvm, namespace} from \"@anywalletkit/protocol-swap2-core/util\";\n\n// ── THORChain — native L1 assets: BTC/ETH/BSC/BASE/Cosmos/Tron/Solana, and\n// (2026-08, pools live) XRP/LTC/DOGE/BCH + GAIA.ATOM ──────────────────────\n// Only EVM source executors actually implemented by provider.ts.\nconst THOR_EVM = new Set([1, 8453, 56, 43114]); // ETH, BASE, BSC, AVAX (2026-09-16)\nconst THOR_NS = new Set([\"bitcoin\", \"cosmos\", \"solana\", \"tron\", \"xrp\", \"litecoin\", \"doge\", \"bch\"]);\nexport const thorchain = {\n enabled: () => true,\n affiliate: () => \"\",\n affiliateBps: () => \"\",\n supportsChain(chain: string): boolean {\n if (THOR_NS.has(namespace(chain))) return true;\n return isEvm(chain) && THOR_EVM.has(evmRef(chain));\n },\n supports(from: string, to: string): boolean {\n return this.supportsChain(from) && this.supportsChain(to);\n },\n};\n","/**\n * Activity recognition for THORChain on its EVM source chains.\n *\n * Routers and Asgard vaults rotate, so nothing is matched by address: the\n * THORChain router ABI is unique enough. `depositWithExpiry` is our source leg\n * (`bridge`, \"Bridged A\"; `swap` when the swap settled back on the same chain\n * and both legs netted). `transferOut` / `transferOutAndCall` are the router\n * paying a destination leg — recognized only when the owner actually received\n * something (\"Received A via THORChain\"). Native sends to an inbound vault with\n * a memo (Tron, BTC) carry no router call and are not recognizable offline.\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {callSelector, describeSwapLike, ownerAssets} from \"@anywalletkit/protocol-swap2-core/activity\";\nimport {thorchain as thorchainCfg} from \"./config.js\";\n\nexport const THORCHAIN_MODULE = \"@anywalletkit/protocol-swap2-thorchain\";\n\n/** depositWithExpiry(address,address,uint256,string,uint256) */\nexport const THORCHAIN_DEPOSIT_WITH_EXPIRY = \"0x44bc937b\";\n/** transferOut(address,address,uint256,string) */\nexport const THORCHAIN_TRANSFER_OUT = \"0x574da717\";\n/** transferOutAndCall(address,address,uint256,address,address,string) */\nexport const THORCHAIN_TRANSFER_OUT_AND_CALL = \"0xec341444\";\n\nexport function describeThorchainActivity(tx: ChainTx, ctx: DescribeActivityContext): ActivityItem | null {\n if (!tx.chain.startsWith(\"eip155:\") || !thorchainCfg.supportsChain(tx.chain)) return null;\n const selector = callSelector(tx);\n if (selector === THORCHAIN_DEPOSIT_WITH_EXPIRY) {\n // The owner must be the depositor: a stranger's deposit that paid us is a transferOut, not ours.\n const isOwn = (a: string) => ctx.own.has(a) || ctx.own.has(a.toLowerCase());\n if (!isOwn(tx.from)) return null;\n return describeSwapLike(tx, ctx, {protocol: THORCHAIN_MODULE, subtitle: \"THORChain\", kind: \"auto\"});\n }\n if (selector === THORCHAIN_TRANSFER_OUT || selector === THORCHAIN_TRANSFER_OUT_AND_CALL) {\n const {assetsIn} = ownerAssets(tx, ctx);\n if (assetsIn.length === 0) return null;\n return describeSwapLike(tx, ctx, {protocol: THORCHAIN_MODULE, subtitle: \"THORChain\", kind: \"bridge\", inSuffix: \"via THORChain\"});\n }\n return null;\n}\n","import {thorchain as thorCfg} from \"./config.js\";\nimport {describeThorchainActivity} from \"./activity.js\";\nimport {decodeFunctionData, encodeFunctionData} from \"viem\";\nimport {timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {ccAsset, ccAssetByToken} from \"@anywalletkit/swap2-assets\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\nimport {bigintToNumber} from \"@anywalletkit/core\";\n\n/**\n * THORChain — native L1 swaps via asgard vaults (no wrapping). Ported from\n * a production THORChain integration. Scope here is **EVM sources first**: the user\n * deposits on an EVM chain (Ethereum/Base/BSC/Avalanche) into the THORChain router with\n * `depositWithExpiry(vault, asset, amount, memo, expiry)`; THORChain settles the\n * swap and delivers ETH/stables to our mainnet vault. **Tron** (opt-in,\n * `tronSource`) executes as a native TRX send / TRC-20 transfer to the inbound\n * vault with the memo in `raw_data.data` — bifrost reads that field for both\n * TransferContract and TriggerSmartContract. BTC/Cosmos/Solana sources are not\n * routed yet (no memo-capable send surface).\n *\n * Safety: the MEMO and inbound vault come verbatim from the quote — we never\n * hand-build them (a wrong memo makes funds unrecoverable). The quote\n * embeds an on-chain LIM, so a bad-price swap refunds instead of filling:\n * `liquidity_tolerance_bps` when the caller passes a slippage (LIM = expected\n * output after fees × (1 − slippage)), `tolerance_bps` otherwise.\n *\n * Hosts (re-verified 2026-09-16): ninerealms retired, the Liquify vanity\n * hostnames went stale; dev.thorchain.org now lists exactly two THORNode\n * entries — Liquify's public GATEWAY (50k req/day per IP; x-client-id\n * identifies us for a bump) and thornode.thorchain.network (no DNS today, kept\n * as the documented fallback in case it returns). Hosts are tried in order and\n * a quote is only ever bound to an inbound snapshot from the SAME host, so a\n * lagging secondary can never be compared against a primary's vault. The\n * list is an explicit constructor option (`nodeUrl`, one or many); this\n * package never reads deployment environment values.\n */\n\nconst HOSTS = [\n \"https://gateway.liquify.com/chain/thorchain_api\",\n \"https://thornode.thorchain.network\",\n];\n\nconst DEFAULT_CLIENT_ID = \"anywalletkit\";\n\nconst NATIVE = \"0x0000000000000000000000000000000000000000\";\nconst TOLERANCE_BPS = \"300\"; // 3% max slippage, embedded as an on-chain LIM\n// Two ways to ask THORNode for the LIM:\n// - `liquidity_tolerance_bps` — measured from the expected output AFTER\n// THORChain's fees (liquidity, outbound, affiliate): LIM = expected × (1 −\n// slippage), the floor every other provider quotes and validQuote enforces.\n// Used whenever the caller passes a slippage, in one request.\n// - `tolerance_bps` — measured from the FEELESS spot: LIM = spot × (1 −\n// tolerance), so the room left is (tolerance − fees) and the node rejects\n// the quote outright when fees exceed it (\"emit asset X less than price\n// limit Y\"; 500 USDC Base → BTC at 1% paid ≈1.7%). Kept only for legacy\n// quotes without a slippage, which widen it to what the pool needs.\n// Both are hard-capped: a route whose THORChain fees alone exceed the cap\n// stays hidden, with a named reason.\nconst MAX_TOLERANCE_BPS = 500n;\n/** How long a quote stays executable (bounded by the memo's own expiry). */\nconst QUOTE_VALIDITY_MS = 5 * 60_000;\n\n// CAIP-2 → THORChain chain prefix. EVM chains execute via the router; TRON\n// executes via a native send to the inbound vault + memo (no router).\nconst THOR_CHAIN: Record<string, string> = {\n \"eip155:1\": \"ETH\",\n \"eip155:8453\": \"BASE\",\n \"eip155:56\": \"BSC\",\n // 2026-09-16: AVAX.AVAX/USDC/USDT pools Available (≈$2.5M/$0.3M/$0.2M),\n // router 0x00dc61…f1d4 live in inbound_addresses; same depositWithExpiry ABI.\n // Polygon has no THORChain pool any more — deliberately absent.\n \"eip155:43114\": \"AVAX\",\n \"tron:728126428\": \"TRON\",\n \"bitcoin:mainnet\": \"BTC\",\n // 2026-08 (pools verified live via the Liquify gateway): THORChain added\n // SOL/XRP, and our catalog now carries LTC/DOGE/BCH/ATOM — destination legs\n // for the step-2 off-ramp (source stays EVM/Tron, see supportsRoute).\n \"solana:mainnet\": \"SOL\",\n \"xrp:mainnet\": \"XRP\",\n \"litecoin:mainnet\": \"LTC\",\n \"doge:mainnet\": \"DOGE\",\n \"bch:mainnet\": \"BCH\",\n \"cosmos:cosmoshub-4\": \"GAIA\",\n};\nconst CHAIN_ID: Record<string, number> = {\"eip155:1\": 1, \"eip155:8453\": 8453, \"eip155:56\": 56, \"eip155:43114\": 43114};\nconst TRON_CAIP2 = \"tron:728126428\";\n// Sources executed as a plain send to the inbound vault + memo (no router).\n// Only chains whose account can attach the memo ON-CHAIN belong here; an\n// unsent memo strands the deposit in the vault.\nconst DEPOSIT_SOURCES = new Set([TRON_CAIP2]);\nconst NATIVE_ASSET: Record<string, string> = {\n ETH: \"ETH.ETH\",\n BASE: \"BASE.ETH\",\n BSC: \"BSC.BNB\",\n AVAX: \"AVAX.AVAX\",\n TRON: \"TRON.TRX\",\n BTC: \"BTC.BTC\",\n SOL: \"SOL.SOL\",\n XRP: \"XRP.XRP\",\n LTC: \"LTC.LTC\",\n DOGE: \"DOGE.DOGE\",\n BCH: \"BCH.BCH\",\n GAIA: \"GAIA.ATOM\",\n};\n\n// Curated token asset notation (UPPERCASE contract, as THORChain expects).\n// Pools come and go (all eight verified Available via the Liquify gateway,\n// 2026-09-16); a retired pool's quote just 404s to null, so entries stay harmless.\nconst TOKEN_ASSET: Record<string, string> = {\n \"ETH:USDC\": \"ETH.USDC-0XA0B86991C6218B36C1D19D4A2E9EB0CE3606EB48\",\n \"ETH:USDT\": \"ETH.USDT-0XDAC17F958D2EE523A2206206994597C13D831EC7\",\n \"BASE:USDC\": \"BASE.USDC-0X833589FCD6EDB6E08F4C7C32D4F71B54BDA02913\",\n \"BSC:USDC\": \"BSC.USDC-0X8AC76A51CC950D9822D68B83FE1AD97B32CD580D\",\n \"BSC:USDT\": \"BSC.USDT-0X55D398326F99059FF775485246999027B3197955\",\n \"AVAX:USDC\": \"AVAX.USDC-0XB97EF9EF8734C71904D8002F8B6BC66DD9C48A6E\",\n \"AVAX:USDT\": \"AVAX.USDT-0X9702230A8EA53601F5CD2DC00FDBC13D4DF4A8C7\",\n \"TRON:USDT\": \"TRON.USDT-TR7NHQJEKQXGTCI8Q8ZY4PL8OTSZGJLJ6T\",\n};\n\nconst ROUTER_ABI = [\n {\n type: \"function\",\n name: \"depositWithExpiry\",\n stateMutability: \"payable\",\n inputs: [\n {name: \"vault\", type: \"address\"},\n {name: \"asset\", type: \"address\"},\n {name: \"amount\", type: \"uint256\"},\n {name: \"memo\", type: \"string\"},\n {name: \"expiration\", type: \"uint256\"},\n ],\n outputs: [],\n },\n] as const;\n\nfunction isEvm(caip2: string): boolean {\n return caip2.startsWith(\"eip155:\");\n}\n\n/** THOR asset notation for a (chain, symbol) on either leg, or undefined. */\nfunction thorAsset(caip2: string, symbol: string): string | undefined {\n const chain = THOR_CHAIN[caip2];\n if (!chain) return undefined;\n const sym = symbol.toUpperCase();\n const token = TOKEN_ASSET[`${chain}:${sym}`];\n if (token) return token;\n const native = NATIVE_ASSET[chain];\n return native && native.split(\".\")[1] === sym ? native : undefined;\n}\n\n/**\n * Destination asset for either direction: inbound → the vault on Ethereum, or\n * the step-2 off-ramp → any THOR-supported chain (BTC/BASE/BSC/TRON). Resolved\n * from the catalog so we get the right symbol + decimals for the target chain.\n */\nfunction destAsset(destChain: string, destToken: string): {asset: string; decimals: number} | undefined {\n const a = ccAssetByToken(destChain, destToken);\n if (!a) return undefined;\n const asset = thorAsset(destChain, a.symbol);\n return asset ? {asset, decimals: a.decimals} : undefined;\n}\n\ninterface ThorQuoteResponse {\n expected_amount_out?: string;\n inbound_address?: string;\n router?: string;\n memo?: string;\n expiry?: number;\n total_swap_seconds?: number;\n /** 1e8 source units; below this the swap is refunded minus fees. */\n recommended_min_amount_in?: string;\n error?: string;\n /** thornode simulation rejections arrive as {code, message}. */\n message?: string;\n /** THORChain's fees on this quote; `total_bps` includes liquidity, outbound and affiliate. */\n fees?: {total_bps?: number};\n}\n\n/**\n * A host-level failure (unreachable, gateway error, rate-limited, blocked):\n * the next host may answer. Anything else the node says — including a 4xx\n * business rejection such as \"no pool\" — is an answer, not a reason to shop\n * the same question to another node.\n */\nclass HostUnavailable extends Error {\n constructor(host: string, reason: string) {\n super(`thorchain: ${host} unavailable (${reason})`);\n }\n}\n\ninterface HostResponse {\n ok: boolean;\n status: number;\n body: Record<string, unknown> | unknown[] | null;\n}\n\nasync function hostGet(host: string, path: string, clientId: string, signal?: AbortSignal): Promise<HostResponse> {\n let res: Response;\n try {\n res = await fetch(`${host}${path}`, {\n headers: {accept: \"application/json\", \"x-client-id\": clientId},\n cache: \"no-store\",\n signal: signal ?? timeoutSignal(8000),\n });\n } catch (error) {\n if (signal?.aborted) throw error; // the caller gave up — not the host's fault\n throw new HostUnavailable(host, error instanceof Error ? error.message : \"fetch failed\");\n }\n if (res.status >= 500 || res.status === 429 || res.status === 403) {\n throw new HostUnavailable(host, `HTTP ${res.status}`);\n }\n const body = (await res.json().catch(() => null)) as HostResponse[\"body\"];\n return {ok: res.ok, status: res.status, body};\n}\n\n/** Per-request failover for reads whose answer is host-independent (tx status). */\nasync function thornodeGet(\n path: string,\n signal: AbortSignal | undefined,\n hosts: string[],\n clientId: string,\n): Promise<Record<string, unknown> | null> {\n for (const host of hosts) {\n try {\n const res = await hostGet(host, path, clientId, signal);\n if (!res.ok) continue;\n return Array.isArray(res.body) ? null : res.body;\n } catch (error) {\n if (error instanceof HostUnavailable) continue;\n throw error;\n }\n }\n return null;\n}\n\ninterface InboundAddress {\n chain?: string;\n address?: string;\n router?: string;\n halted?: boolean;\n global_trading_paused?: boolean;\n chain_trading_paused?: boolean;\n /** 1e8 source units; inbounds at or below it are IGNORED by THORChain. */\n dust_threshold?: string;\n}\n\n/** Fail closed on amounts THORChain would ignore (dust) or refund (below the\n * recommended minimum). Both are quoted in 1e8 source units. */\nfunction belowThorMinimums(amount1e8: bigint, inbound: InboundAddress | undefined, quote: ThorQuoteResponse | null): string | null {\n const dust = inbound?.dust_threshold;\n if (dust !== undefined && (!/^\\d+$/.test(String(dust)) || amount1e8 <= BigInt(dust))) return \"amount at or below THORChain dust threshold\";\n const min = quote?.recommended_min_amount_in;\n if (min !== undefined && (!/^\\d+$/.test(String(min)) || amount1e8 < BigInt(min))) return \"amount below THORChain recommended minimum\";\n return null;\n}\n\n/** Inbound snapshot from ONE host. Throws HostUnavailable so the caller can\n * re-run the whole quote on the next host rather than mixing nodes. */\nasync function inboundAddressesOn(host: string, clientId: string): Promise<InboundAddress[]> {\n const res = await hostGet(host, \"/thorchain/inbound_addresses\", clientId);\n if (!res.ok || !Array.isArray(res.body)) throw new HostUnavailable(host, `inbound_addresses HTTP ${res.status}`);\n return res.body as InboundAddress[];\n}\n\n/** Pre-broadcast re-check: any live host is an acceptable authority — a\n * disagreeing secondary fails closed, which is the safe direction. */\nasync function inboundAddresses(hosts: string[], clientId: string): Promise<InboundAddress[] | null> {\n for (const host of hosts) {\n try {\n return await inboundAddressesOn(host, clientId);\n } catch (error) {\n if (error instanceof HostUnavailable) continue;\n throw error;\n }\n }\n return null;\n}\n\nfunction paused(entry: InboundAddress | undefined): boolean {\n return !entry || entry.halted === true || entry.global_trading_paused === true || entry.chain_trading_paused === true;\n}\n\nfunction sameTarget(a: string | undefined, b: string | undefined): boolean {\n if (!a || !b) return false;\n return a.startsWith(\"0x\") || b.startsWith(\"0x\") ? a.toLowerCase() === b.toLowerCase() : a === b;\n}\n\nfunction verifiedMemo(\n memo: string,\n expectedAsset: string,\n expectedDestination: string,\n expectedRefund: string,\n expectedAffiliate: string,\n expectedAffiliateBps: string,\n): {limit: bigint; canonical: string} | null {\n if (memo.includes(\"|\")) return null; // DEX-aggregator tail is a separate, unbound execution program.\n const parts = memo.split(\":\");\n if (parts.length !== 4 && parts.length !== 6) return null;\n const [op, asset, destination, limit, affiliate, bps] = parts;\n // Quote responses legitimately use THORChain fuzzy asset notation (`b` for\n // BTC.BTC). We never execute that untrusted spelling: after checking the\n // shape, destination/refund, limit and affiliate we rebuild a canonical memo\n // from our own route facts below.\n if (op !== \"=\" || !asset || !/^[A-Za-z0-9._~\\-]+$/.test(asset)) return null;\n const expectedTarget = expectedRefund ? `${expectedDestination}/${expectedRefund}` : expectedDestination;\n if (!sameTarget(destination, expectedTarget)) return null;\n if (parts.length === 6) {\n if (!expectedAffiliate || affiliate !== expectedAffiliate || bps !== expectedAffiliateBps) return null;\n } else if (expectedAffiliate || expectedAffiliateBps) {\n return null;\n }\n const stream = (limit ?? \"\").split(\"/\");\n // We never request streaming swaps. A provider-supplied LIM/INTERVAL/QTY\n // memo changes the floor to a per-sub-swap condition, so reject it instead\n // of presenting LIM as an atomic total guarantee.\n if (stream.length !== 1 || stream.some((v) => !/^\\d+$/.test(v))) return null;\n const floor = BigInt(stream[0] ?? \"0\");\n if (floor <= 0n) return null;\n const canonical = `=:${expectedAsset}:${expectedTarget}:${stream.join(\"/\")}${\n expectedAffiliate ? `:${expectedAffiliate}:${expectedAffiliateBps}` : \"\"\n }`;\n return {limit: floor, canonical};\n}\n\nfunction toThorUnitsCeil(amount: bigint, decimals: number): bigint {\n const scale = 10n ** BigInt(decimals);\n return (amount * 100_000_000n + scale - 1n) / scale;\n}\n\n/** Explicit constructor configuration; no deployment environment is read. */\nexport interface ThorchainProviderConfig {\n enabled?: boolean;\n affiliate?: string;\n affiliateBps?: string;\n /**\n * THORNode base URL(s), tried in order; a comma-separated string is\n * accepted for env-style configuration. Defaults to the documented public\n * hosts. Quote + inbound snapshot always come from the same host.\n */\n nodeUrl?: string | string[];\n /** Optional gateway identification; defaults to a neutral module name. */\n clientId?: string;\n /**\n * Opt-in Tron SOURCE execution: a native TRX send / TRC-20 transfer to the\n * inbound vault carrying the swap memo in `raw_data.data`. Ships dark: the\n * bound account MUST attach the memo on-chain (`raw_data.data`); a\n * memo-less send is unsettleable.\n */\n tronSource?: boolean;\n}\n\nexport function thorchainProvider(config: ThorchainProviderConfig = {}): CrossChainProvider {\n config = Object.freeze({...config});\n const configuredHosts = (Array.isArray(config.nodeUrl) ? config.nodeUrl : (config.nodeUrl ?? \"\").split(\",\"))\n .map((h) => h.trim())\n .filter(Boolean);\n const hosts = [...new Set((configuredHosts.length ? configuredHosts : HOSTS).map((h) => {\n let url: URL;\n try {\n url = new URL(h);\n } catch {\n throw new Error(\"thorchain: nodeUrl must be an absolute http(s) URL\");\n }\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") throw new Error(\"thorchain: nodeUrl must use http or https\");\n return url.toString().replace(/\\/$/, \"\");\n }))];\n const configuredAffiliate = config.affiliate ?? \"\";\n const configuredAffiliateBps = config.affiliateBps ?? \"\";\n if (!!configuredAffiliate !== !!configuredAffiliateBps) {\n throw new Error(\"thorchain: affiliate and affiliateBps must be configured together\");\n }\n if (configuredAffiliate && !/^[A-Za-z0-9._~-]+$/.test(configuredAffiliate)) {\n throw new Error(\"thorchain: affiliate contains unsupported memo characters\");\n }\n if (configuredAffiliateBps && (!/^\\d+$/.test(configuredAffiliateBps) || BigInt(configuredAffiliateBps) > 10_000n)) {\n throw new Error(\"thorchain: affiliateBps must be an integer between 0 and 10000\");\n }\n const clientId = config.clientId?.trim() || DEFAULT_CLIENT_ID;\n if (!/^[\\x21-\\x7e]{1,128}$/.test(clientId)) throw new Error(\"thorchain: clientId must contain 1-128 visible ASCII characters\");\n const tronSource = config.tronSource === true;\n const isDepositSource = (caip2: string): boolean => tronSource && DEPOSIT_SOURCES.has(caip2);\n return {\n name: \"thorchain\",\n describeActivity: describeThorchainActivity,\n enabled: () => config.enabled ?? true,\n\n // Capability discovery comes from the provider itself, so it can run alone\n // or inside the optional aggregator without a central capability table.\n supportsChain: (chain: string) => thorCfg.supportsChain(chain),\n supportsChainPair: (fromChain: string, toChain: string) => thorCfg.supports(fromChain, toChain),\n // Inbound: EVM/Tron source → the mainnet vault. Outbound (step-2 off-ramp):\n // EVM source (Ethereum) → any THOR-supported chain. The SOURCE must be EVM\n // (router calldata) or, when opted in, Tron (send + memo); both legs must\n // be THOR chains and differ.\n supportsRoute(from: Asset, to: Asset): boolean {\n const srcExec = isEvm(from.chain) || isDepositSource(from.chain);\n if (!(srcExec && !!THOR_CHAIN[from.chain] && !!THOR_CHAIN[to.chain] && from.chain !== to.chain)) return false;\n // Asset level too: claiming a chain pair whose assets THORChain has no\n // pool for (e.g. USDC on Solana) put the provider in every route list\n // and then answered a silent null.\n const fromAsset = thorAsset(from.chain, from.token) ?? thorAsset(from.chain, ccAssetByToken(from.chain, from.token)?.symbol ?? \"\");\n const toAsset = destAsset(to.chain, to.token) ?? (thorAsset(to.chain, to.token) ? {asset: thorAsset(to.chain, to.token)!} : undefined);\n return !!fromAsset && !!toAsset && fromAsset !== toAsset.asset;\n },\n\n async getQuote(params: QuoteParams, signal?: AbortSignal): Promise<Quote | null> {\n if (!(config.enabled ?? true)) return null;\n if (params.flex) return null; // memo/LIM embed the exact amount\n const chainId = CHAIN_ID[params.sourceChain];\n // EVM sources execute via the router; opted-in deposit sources (Tron)\n // via send + memo. Anything else has no safe executor.\n if (!chainId && !isDepositSource(params.sourceChain)) return null;\n if (params.sourceChain === params.destChain) return null; // same-chain: not a swap\n\n const src = ccAsset(params.sourceChain, params.sourceToken);\n const fromAsset = thorAsset(params.sourceChain, params.sourceToken);\n const dst = destAsset(params.destChain, params.destToken);\n if (!src || !fromAsset || !dst || fromAsset === dst.asset) {\n params.onRefusal?.(`thorchain: no pool for ${params.sourceToken} on ${params.sourceChain} → ${params.destToken} on ${params.destChain}`);\n return null;\n }\n\n // THORChain amounts are universally 1e8-scaled.\n const amountIn = BigInt(params.amountIn);\n const amount1e8 = (amountIn * 100000000n) / 10n ** BigInt(src.decimals);\n if (amount1e8 <= 0n) return null;\n // THOR quotes only 1e8 units. Never send a larger high-precision source\n // amount than the amount priced by the quote (the remainder is dust the\n // memo cannot account for and may be donated to the vault).\n if (amount1e8 * 10n ** BigInt(src.decimals) !== amountIn * 100_000_000n) {\n params.onRefusal?.(`thorchain: amount has more precision than THORChain's 8 decimals — round it to 8 decimals`);\n return null;\n }\n\n const requestedTolerance = params.slippageBps ?? Number(TOLERANCE_BPS);\n if (!Number.isInteger(requestedTolerance) || requestedTolerance < 0 || requestedTolerance > bigintToNumber(MAX_TOLERANCE_BPS)) {\n params.onRefusal?.(`thorchain: slippage ${String(params.slippageBps)} bps is outside 0–${MAX_TOLERANCE_BPS} bps`);\n return null;\n }\n // An explicit slippage → `liquidity_tolerance_bps`. The node floors LIM in\n // 1e8 units; for a destination with more than 8 decimals that floor lands\n // a hair below expected × (1 − slippage) in base units, so ask 1 bp\n // tighter there (never looser). 0 bp cannot carry a LIM that way: such a\n // request goes out as `tolerance_bps` and the node's answer stands.\n const explicitSlippage = params.slippageBps !== undefined;\n const liquidityBps = explicitSlippage ? (dst.decimals > 8 ? requestedTolerance - 1 : requestedTolerance) : 0;\n const limitMode = liquidityBps > 0 ? \"liquidity_tolerance_bps\" : \"tolerance_bps\";\n // `tolerance_bps` → LIM from the feeless spot output; `liquidity_tolerance_bps`\n // → LIM from the expected output after fees (the node accepts only one).\n const quoteOn = async (\n host: string,\n bps: string,\n limitMode: \"tolerance_bps\" | \"liquidity_tolerance_bps\" = \"tolerance_bps\",\n ): Promise<ThorQuoteResponse | null> => {\n const qs = new URLSearchParams({\n from_asset: fromAsset,\n to_asset: dst.asset,\n amount: amount1e8.toString(),\n destination: params.destAddress,\n [limitMode]: bps,\n // Pin a single (non-streaming) swap. Left to itself the node picks\n // streaming for thin pools (max_streaming_quantity > 1) and then\n // simulates the LIM per sub-swap — the adaptive retry could never\n // pass on BASE.ETH / BSC stables (verified 2026-09-16). We reject\n // streaming memos anyway, so the quote must be simulated atomically.\n streaming_quantity: \"1\",\n });\n if (configuredAffiliate && configuredAffiliateBps) {\n qs.set(\"affiliate\", configuredAffiliate);\n qs.set(\"affiliate_bps\", configuredAffiliateBps);\n }\n if (params.refundAddress) qs.set(\"refund_address\", params.refundAddress);\n const res = await hostGet(host, `/thorchain/quote/swap?${qs.toString()}`, clientId, signal);\n if (Array.isArray(res.body)) return null;\n // A 4xx carries the node's rejection body (used by the adaptive retry).\n return (res.body ?? (res.ok ? null : {error: `HTTP ${res.status}`})) as ThorQuoteResponse | null;\n };\n\n // Host failover: the quote AND the inbound snapshot it is bound to must\n // come from one node. If either call fails at the host level, the whole\n // pair is re-run on the next host; a node's business rejection is final.\n let q: ThorQuoteResponse | null = null;\n let checkedMemo: ReturnType<typeof verifiedMemo> = null;\n let inbounds: InboundAddress[] | null = null;\n for (const host of hosts) {\n try {\n if (limitMode === \"liquidity_tolerance_bps\") {\n q = await quoteOn(host, String(liquidityBps), \"liquidity_tolerance_bps\");\n const feeBps = Number(q?.fees?.total_bps);\n if (Number.isFinite(feeBps) && feeBps > bigintToNumber(MAX_TOLERANCE_BPS)) {\n // Dust amounts: a fixed outbound fee eats the swap.\n params.onRefusal?.(`thorchain: THORChain fees ${(feeBps / 100).toFixed(2)}% — too expensive at this amount (cap ${bigintToNumber(MAX_TOLERANCE_BPS) / 100}%)`);\n return null;\n }\n } else {\n q = await quoteOn(host, String(requestedTolerance));\n // Legacy quotes without a slippage: fees > tolerance makes the node\n // reject the quote; the rejection carries the actual emit vs the\n // limit the tolerance implied. ONE retry, on the same host, widens\n // the tolerance to what the pool needs (+buffer), capped. An\n // explicit 0 bp slippage is never widened — the rejection stands.\n const rejected = (q?.error ?? q?.message)?.match(/emit asset (\\d+) less than price limit (\\d+)/);\n if (rejected && !explicitSlippage) {\n const emit = BigInt(rejected[1] ?? \"0\");\n const limit = BigInt(rejected[2] ?? \"0\");\n if (emit > 0n && limit > emit) {\n // limit = spot × (1 − tolerance/10000) → spot; needed = 1 − emit/spot.\n const spot = (limit * 10000n) / (10000n - BigInt(requestedTolerance));\n const needed = 10000n - (emit * 10000n) / spot + 50n; // +0.5% buffer\n if (needed <= MAX_TOLERANCE_BPS) q = await quoteOn(host, needed.toString());\n }\n }\n }\n // Validate the node's answer BEFORE touching the network again: a\n // rejection, a malformed quote or an unbound memo is final.\n if (q?.error || q?.message) {\n // The node's own rejection (no pool, price limit, halted…) is the\n // caller's answer — surface it instead of an anonymous null.\n params.onRefusal?.(`thorchain: ${String(q.error ?? q.message).slice(0, 200)}`);\n return null;\n }\n if (!q || !q.expected_amount_out || !q.inbound_address || !q.memo || !q.expiry) {\n params.onRefusal?.(`thorchain: incomplete quote from ${host} (expected_amount_out / inbound_address / memo / expiry missing)`);\n return null;\n }\n // A router is required for EVM and must be ABSENT for a deposit\n // source: a router on a Tron quote means the venue changed its\n // execution model and a plain send would no longer settle.\n if (chainId ? !q.router : !!q.router) {\n params.onRefusal?.(chainId ? \"thorchain: quote has no router for an EVM source\" : \"thorchain: quote names a router for a deposit source — execution model changed\");\n return null;\n }\n checkedMemo = verifiedMemo(q.memo, dst.asset, params.destAddress, params.refundAddress ?? \"\", configuredAffiliate, configuredAffiliateBps);\n if (!checkedMemo) {\n params.onRefusal?.(`thorchain: memo failed verification (${String(q.memo).slice(0, 80)})`);\n return null;\n }\n const floor1e8 = params.minAmountOut !== undefined ? toThorUnitsCeil(BigInt(params.minAmountOut), dst.decimals) : undefined;\n if (floor1e8 !== undefined && checkedMemo.limit < floor1e8) {\n params.onRefusal?.(`thorchain: floor breach (limit=${checkedMemo.limit} < floor=${floor1e8}, 1e8 units)`);\n return null;\n }\n // A quote gateway is not an authority for rotating vault/router\n // state. Bind it against a separately fetched no-store inbound\n // snapshot from the SAME host now, then repeat the check before broadcast.\n inbounds = await inboundAddressesOn(host, clientId);\n break;\n } catch (error) {\n if (error instanceof HostUnavailable) {\n q = null;\n checkedMemo = null;\n inbounds = null;\n continue;\n }\n throw error;\n }\n }\n if (!q?.expected_amount_out || !q.inbound_address || !q.expiry || !checkedMemo || !inbounds) {\n params.onRefusal?.(!inbounds ? \"thorchain: inbound addresses unavailable from every node\" : \"thorchain: no quote from any node\");\n return null;\n }\n const limit1e8 = checkedMemo.limit;\n const srcInbound = inbounds.find((entry) => entry.chain === THOR_CHAIN[params.sourceChain]);\n const dstInbound = inbounds.find((entry) => entry.chain === THOR_CHAIN[params.destChain]);\n if (paused(srcInbound) || paused(dstInbound)) {\n params.onRefusal?.(`thorchain: ${paused(srcInbound) ? THOR_CHAIN[params.sourceChain] : THOR_CHAIN[params.destChain]} chain is halted / paused on THORChain`);\n return null;\n }\n if (!sameTarget(srcInbound?.address, q.inbound_address)) {\n params.onRefusal?.(\"thorchain: quote inbound address differs from the node's current inbound (vault rotated) — retry\");\n return null;\n }\n if (chainId && !sameTarget(srcInbound?.router, q.router)) {\n params.onRefusal?.(\"thorchain: quote router differs from the node's current router — retry\");\n return null;\n }\n const tooSmall = belowThorMinimums(amount1e8, srcInbound, q);\n if (tooSmall) {\n params.onRefusal?.(`thorchain: ${tooSmall}`);\n return null;\n }\n\n // expected_amount_out is 1e8 of the DEST asset → base units.\n const outUnits = (BigInt(q.expected_amount_out) * 10n ** BigInt(dst.decimals)) / 100000000n;\n if (outUnits <= 0n) {\n params.onRefusal?.(\"thorchain: expected output rounds to zero\");\n return null;\n }\n const memoMinUnits = (limit1e8 * 10n ** BigInt(dst.decimals)) / 100_000_000n;\n const minUnits = memoMinUnits;\n if (minUnits <= 0n || minUnits > outUnits) {\n params.onRefusal?.(`thorchain: memo limit ${limit1e8} inconsistent with expected output ${q.expected_amount_out}`);\n return null;\n }\n // The caller's slippage is measured from the quoted output, as validQuote\n // does for every provider. A memo LIM below that floor would only be\n // dropped later as an anonymous validation failure — name it here.\n if (params.slippageBps !== undefined) {\n const slippageFloor = (outUnits * BigInt(10_000 - params.slippageBps)) / 10_000n;\n if (minUnits < slippageFloor) {\n params.onRefusal?.(`thorchain: memo limit ${limit1e8} is below expected ${q.expected_amount_out} minus ${params.slippageBps} bps slippage (1e8 units)`);\n return null;\n }\n }\n\n const nowSeconds = Math.floor(Date.now() / 1000);\n const executionExpiry = Math.min(q.expiry, nowSeconds + 15 * 60);\n if (!Number.isInteger(executionExpiry) || executionExpiry <= nowSeconds + 30) {\n params.onRefusal?.(`thorchain: quote expires in ${Number.isInteger(executionExpiry) ? executionExpiry - nowSeconds : \"?\"} s — too soon to execute`);\n return null;\n }\n const assetAddr = (src.contract ? src.contract : NATIVE) as `0x${string}`;\n const common = {\n provider: \"thorchain\",\n intentId: `thorchain:${chainId ?? THOR_CHAIN[params.sourceChain]}`,\n sourceAmount: params.amountIn,\n destAmount: outUnits.toString(),\n minDestAmount: minUnits.toString(),\n feeUsd: 0, // destAmount is already net of THORChain fees\n etaSeconds: q.total_swap_seconds ?? 120,\n reliability: 0.9,\n // Validity must outlive the ERC-20 approval leg: for USDT that is\n // approve(0) + approve(n), each awaited to inclusion (≈2 blocks), so a\n // 60 s window expired before the deposit and only the revoke went out\n // (2026-09-16). The on-chain LIM bounds price movement and preflight\n // re-checks vault/router/halts right before broadcast, so a longer\n // window costs nothing in safety.\n validUntilMs: Math.min(Date.now() + QUOTE_VALIDITY_MS, executionExpiry * 1000),\n providerData: {\n sourceChain: params.sourceChain,\n destChain: params.destChain,\n inboundAddress: q.inbound_address,\n router: q.router ?? \"\",\n assetAddress: assetAddr,\n expiry: String(executionExpiry),\n memo: checkedMemo.canonical,\n },\n };\n\n // Deposit source (Tron): the engine sends `sourceAmount` of the source\n // asset to the inbound vault with the canonical memo attached on-chain.\n if (!chainId) {\n return {...common, depositAddress: q.inbound_address, depositMemo: checkedMemo.canonical};\n }\n\n // EVM: router calldata depositWithExpiry(asgardVault, asset, amount, memo, expiry).\n const data = encodeFunctionData({\n abi: ROUTER_ABI,\n functionName: \"depositWithExpiry\",\n args: [q.inbound_address as `0x${string}`, assetAddr, amountIn, checkedMemo.canonical, BigInt(executionExpiry)],\n });\n return {\n ...common,\n depositAddress: \"\",\n depositMemo: null,\n txRequest: {\n to: q.router!,\n data,\n value: src.contract ? \"0\" : params.amountIn,\n chainId: chainId!,\n ...(src.contract ? {approvalAddress: q.router!} : {}),\n },\n };\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n if (!quote.txRequest) {\n const sourceChain = quote.providerData?.sourceChain ?? \"\";\n if (!isDepositSource(sourceChain) || !quote.depositAddress || !quote.depositMemo) {\n throw new Error(\"thorchain: deposit-address execution is only supported for an opted-in Tron source\");\n }\n // Plain send to the inbound vault (the engine turns a TRC-20 source\n // into transfer()); the memo MUST ride on-chain in raw_data.data.\n return {chain: sourceChain, to: quote.depositAddress, value: quote.sourceAmount, memo: quote.depositMemo};\n }\n return {\n chain: \"\",\n to: quote.txRequest?.to ?? \"\",\n value: quote.txRequest?.value ?? \"0\",\n ...(quote.txRequest?.data ? {data: quote.txRequest.data} : {}),\n ...(quote.txRequest?.chainId !== undefined ? {chainId: quote.txRequest.chainId} : {}),\n ...(quote.txRequest?.gasLimit ? {gasLimit: quote.txRequest.gasLimit} : {}),\n ...(quote.txRequest?.approvalAddress ? {approvalAddress: quote.txRequest.approvalAddress} : {}),\n };\n },\n\n async preflightDeposit(quote: Quote, tx: UnsignedTx): Promise<void> {\n const data = quote.providerData;\n if (!data?.sourceChain || !data.destChain || !data.inboundAddress || !data.assetAddress || !data.expiry || !data.memo) {\n throw new Error(\"thorchain: quote is missing execution-bound metadata\");\n }\n const evmSource = CHAIN_ID[data.sourceChain] !== undefined;\n if (evmSource && !data.router) throw new Error(\"thorchain: quote is missing execution-bound metadata\");\n if (!evmSource && !isDepositSource(data.sourceChain)) throw new Error(\"thorchain: source chain has no executor\");\n if (!/^\\d+$/.test(data.expiry) || BigInt(data.expiry) <= BigInt(Math.floor(Date.now() / 1000))) {\n throw new Error(\"thorchain: quote expired before broadcast\");\n }\n const inbounds = await inboundAddresses(hosts, clientId);\n if (!inbounds) throw new Error(\"thorchain: cannot refresh inbound addresses before broadcast\");\n const src = inbounds.find((entry) => entry.chain === THOR_CHAIN[data.sourceChain!]);\n const dst = inbounds.find((entry) => entry.chain === THOR_CHAIN[data.destChain!]);\n if (paused(src) || paused(dst)) throw new Error(\"thorchain: source or destination chain trading is paused\");\n if (!sameTarget(src?.address, data.inboundAddress)) throw new Error(\"thorchain: inbound vault rotated after quote\");\n if (!evmSource) {\n // Deposit source: exactly a plain send of the validated amount to the\n // validated vault carrying the validated memo — nothing else.\n if (tx.data !== undefined || tx.approvalAddress !== undefined || tx.bodyBoc !== undefined || tx.typedData !== undefined || tx.serializedTx !== undefined || tx.stateInitBoc !== undefined) {\n throw new Error(\"thorchain: deposit-address execution must be a plain send with memo\");\n }\n if (!sameTarget(tx.to, data.inboundAddress) || tx.memo !== data.memo || tx.value !== quote.sourceAmount || (tx.chain && tx.chain !== data.sourceChain)) {\n throw new Error(\"thorchain: deposit does not match the validated quote\");\n }\n const srcAsset = ccAssetByToken(data.sourceChain, sameTarget(data.assetAddress, NATIVE) ? \"\" : data.assetAddress);\n if (!srcAsset) throw new Error(\"thorchain: unknown source asset\");\n const amount1e8 = (BigInt(quote.sourceAmount) * 100_000_000n) / 10n ** BigInt(srcAsset.decimals);\n const tooSmall = belowThorMinimums(amount1e8, src, null);\n if (tooSmall) throw new Error(`thorchain: ${tooSmall}`);\n return;\n }\n if (!sameTarget(src?.router, data.router) || !sameTarget(tx.to, data.router)) {\n throw new Error(\"thorchain: router rotated after quote\");\n }\n if (!tx.data) throw new Error(\"thorchain: missing depositWithExpiry calldata\");\n let decoded: {functionName: string; args?: readonly unknown[]};\n try {\n decoded = decodeFunctionData({abi: ROUTER_ABI, data: tx.data as `0x${string}`});\n } catch {\n throw new Error(\"thorchain: malformed depositWithExpiry calldata\");\n }\n const args = decoded.args;\n if (\n decoded.functionName !== \"depositWithExpiry\" || !args || args.length !== 5 ||\n !sameTarget(String(args[0]), data.inboundAddress) ||\n !sameTarget(String(args[1]), data.assetAddress) ||\n BigInt(args[2] as bigint) !== BigInt(quote.sourceAmount) ||\n String(args[3]) !== data.memo || BigInt(args[4] as bigint) !== BigInt(data.expiry) ||\n tx.chainId !== CHAIN_ID[data.sourceChain]\n ) {\n throw new Error(\"thorchain: calldata does not match the validated quote\");\n }\n const tokenSource = !sameTarget(data.assetAddress, NATIVE);\n if (\n tx.value !== (tokenSource ? \"0\" : quote.sourceAmount) ||\n (tokenSource ? !sameTarget(tx.approvalAddress, data.router) : tx.approvalAddress !== undefined)\n ) {\n throw new Error(\"thorchain: value/approval does not match the validated source asset\");\n }\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n if (!ref.sourceTxHash) return {state: \"pending\"}; // not broadcast yet\n // THORNode keys EVM inbounds by the tx hash without 0x, uppercase.\n if (!/^(?:0x)?[0-9a-fA-F]{64}$/.test(ref.sourceTxHash)) {\n throw new Error(\"thorchain: source transaction hash must be 32-byte hex\");\n }\n const hash = ref.sourceTxHash.replace(/^0x/i, \"\").toUpperCase();\n const j = await thornodeGet(`/thorchain/tx/status/${hash}`, undefined, hosts, clientId) ??\n await thornodeGet(`/thorchain/tx/${hash}`, undefined, hosts, clientId);\n if (!j) return {state: \"pending\"};\n const stages = j.stages as {\n inbound_observed?: {started?: boolean; completed?: boolean};\n inbound_finalised?: {completed?: boolean};\n outbound_signed?: {completed?: boolean};\n } | undefined;\n if (stages) {\n const planned = (j.planned_out_txs ?? []) as {refund?: boolean}[];\n const refunded = planned.some((out) => out.refund === true);\n const delivered = planned.some((out) => out.refund === false);\n const outTxs = (j.out_txs ?? []) as {id?: string; memo?: string}[];\n const outHash = outTxs.find((out) => typeof out.id === \"string\" && out.id.length > 0 && !/^0+$/.test(out.id))?.id;\n const deliveredHash = outTxs.find((out) =>\n typeof out.id === \"string\" && out.id.length > 0 && !/^0+$/.test(out.id) && typeof out.memo === \"string\" && !/^REFUND/i.test(out.memo)\n )?.id;\n if (stages.outbound_signed?.completed) {\n // `completed` describes the signing stage, not the economic outcome.\n // A truncated/malformed status response with no classified plan or\n // observed outbound must not be promoted to successful delivery.\n if ((!refunded && !delivered) || !outHash) {\n return {state: \"pending\", depositReceived: true};\n }\n return refunded && delivered\n // A refund hash is not a destination transaction. For mixed plans,\n // expose a hash only when the observed outbound is classifiable.\n ? {state: \"partial\", depositReceived: true, ...(deliveredHash ? {destTxHash: deliveredHash} : {})}\n : refunded\n ? {state: \"refunded\", depositReceived: true}\n : {state: \"completed\", depositReceived: true, ...(outHash ? {destTxHash: outHash} : {})};\n }\n return {\n state: \"pending\",\n depositReceived: !!(stages.inbound_observed?.started || stages.inbound_observed?.completed || stages.inbound_finalised?.completed),\n };\n }\n const obs = j.observed_tx as {status?: string; out_hashes?: string[]} | undefined;\n const outHash = obs?.out_hashes?.find((h) => typeof h === \"string\" && h.length > 0 && !/^0+$/.test(h));\n if (obs?.status === \"done\") {\n // A slipped-past-LIM (or halted) swap ALSO finalizes \"done\", but its\n // outbound is a REFUND to the source chain — never report that as a\n // completed swap (audit M1). Planned outbounds carry the memo.\n const planned = (j.planned_out_txs ?? j.out_txs ?? []) as {memo?: string; refund?: boolean}[];\n const refunded = planned.some(\n (o) => o?.refund === true || /^REFUND/i.test(o?.memo ?? \"\"),\n );\n const delivered = planned.some(\n (o) => o?.refund === false && !/^REFUND/i.test(o?.memo ?? \"\"),\n );\n if ((!refunded && !delivered) || !outHash) return {state: \"pending\", depositReceived: true};\n if (refunded && delivered) return {state: \"partial\", depositReceived: true};\n if (refunded) return {state: \"refunded\", depositReceived: true};\n return {state: \"completed\", ...(outHash ? {destTxHash: outHash} : {})};\n }\n return {state: \"pending\", depositReceived: !!obs};\n },\n };\n}\n","import {SingleProviderSwap2} from \"@anywalletkit/protocol-swap2-core/swap2/single\";\nimport type {Swap2Account, Swap2EngineConfig} from \"@anywalletkit/protocol-swap2-core/swap2/base\";\nimport {thorchain as thorchainCfg} from \"./config.js\";\nimport {thorchainProvider, type ThorchainProviderConfig} from \"./provider.js\";\n\nexport interface ThorchainSwap2Config extends Swap2EngineConfig, ThorchainProviderConfig {}\n\nexport class ThorchainSwap2Protocol extends SingleProviderSwap2 {\n protected readonly provider;\n constructor(account: Swap2Account | undefined, config: ThorchainSwap2Config) {\n super(account, config);\n this.provider = thorchainProvider(config);\n }\n protected override chainSupported(caip2: string): boolean {\n return thorchainCfg.supportsChain(caip2);\n }\n protected override pairSupported(fromChain: string, toChain: string): boolean {\n return this.provider.supportsRoute({chain: fromChain, token: \"\"}, {chain: toChain, token: \"\"});\n }\n}\n"],"mappings":"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","names":["import_util","isEvm","limitMode","outHash"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/activity.ts","../src/provider.ts","../src/protocol.ts"],"sourcesContent":["export * from \"./config.js\";\nexport * from \"./provider.js\";\nexport {ThorchainSwap2Protocol} from \"./protocol.js\";\nexport {ThorchainSwap2Protocol as default} from \"./protocol.js\";\nexport * from \"./activity.js\";\nexport type { ThorchainSwap2Config } from \"./protocol.js\"\n","import {evmRef, isEvm, namespace} from \"@anywalletkit/protocol-swap2-core/util\";\n\n// ── THORChain — native L1 assets: BTC/ETH/BSC/BASE/Cosmos/Tron/Solana, and\n// (2026-08, pools live) XRP/LTC/DOGE/BCH + GAIA.ATOM ──────────────────────\n// Only EVM source executors actually implemented by provider.ts.\nconst THOR_EVM = new Set([1, 8453, 56, 43114]); // ETH, BASE, BSC, AVAX (2026-09-16)\nconst THOR_NS = new Set([\"bitcoin\", \"cosmos\", \"solana\", \"tron\", \"xrp\", \"litecoin\", \"doge\", \"bch\"]);\nexport const thorchain = {\n enabled: () => true,\n affiliate: () => \"\",\n affiliateBps: () => \"\",\n supportsChain(chain: string): boolean {\n if (THOR_NS.has(namespace(chain))) return true;\n return isEvm(chain) && THOR_EVM.has(evmRef(chain));\n },\n supports(from: string, to: string): boolean {\n return this.supportsChain(from) && this.supportsChain(to);\n },\n};\n","/**\n * Activity recognition for THORChain on its EVM source chains.\n *\n * Routers and Asgard vaults rotate, so nothing is matched by address: the\n * THORChain router ABI is unique enough. `depositWithExpiry` is our source leg\n * (`bridge`, \"Bridged A\"; `swap` when the swap settled back on the same chain\n * and both legs netted). `transferOut` / `transferOutAndCall` are the router\n * paying a destination leg — recognized only when the owner actually received\n * something (\"Received A via THORChain\"). Native sends to an inbound vault with\n * a memo (Tron, BTC) carry no router call and are not recognizable offline.\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {callSelector, describeSwapLike, ownerAssets} from \"@anywalletkit/protocol-swap2-core/activity\";\nimport {thorchain as thorchainCfg} from \"./config.js\";\n\nexport const THORCHAIN_MODULE = \"@anywalletkit/protocol-swap2-thorchain\";\n\n/** depositWithExpiry(address,address,uint256,string,uint256) */\nexport const THORCHAIN_DEPOSIT_WITH_EXPIRY = \"0x44bc937b\";\n/** transferOut(address,address,uint256,string) */\nexport const THORCHAIN_TRANSFER_OUT = \"0x574da717\";\n/** transferOutAndCall(address,address,uint256,address,address,string) */\nexport const THORCHAIN_TRANSFER_OUT_AND_CALL = \"0xec341444\";\n\nexport function describeThorchainActivity(tx: ChainTx, ctx: DescribeActivityContext): ActivityItem | null {\n if (!tx.chain.startsWith(\"eip155:\") || !thorchainCfg.supportsChain(tx.chain)) return null;\n const selector = callSelector(tx);\n if (selector === THORCHAIN_DEPOSIT_WITH_EXPIRY) {\n // The owner must be the depositor: a stranger's deposit that paid us is a transferOut, not ours.\n const isOwn = (a: string) => ctx.own.has(a) || ctx.own.has(a.toLowerCase());\n if (!isOwn(tx.from)) return null;\n return describeSwapLike(tx, ctx, {protocol: THORCHAIN_MODULE, subtitle: \"THORChain\", kind: \"auto\"});\n }\n if (selector === THORCHAIN_TRANSFER_OUT || selector === THORCHAIN_TRANSFER_OUT_AND_CALL) {\n const {assetsIn} = ownerAssets(tx, ctx);\n if (assetsIn.length === 0) return null;\n return describeSwapLike(tx, ctx, {protocol: THORCHAIN_MODULE, subtitle: \"THORChain\", kind: \"bridge\", inSuffix: \"via THORChain\"});\n }\n return null;\n}\n","import {thorchain as thorCfg} from \"./config.js\";\nimport {describeThorchainActivity} from \"./activity.js\";\nimport {decodeFunctionData, encodeFunctionData} from \"viem\";\nimport {timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {ccAsset, ccAssetByToken} from \"@anywalletkit/swap2-assets\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\nimport {bigintToNumber} from \"@anywalletkit/core\";\n\n/**\n * THORChain — native L1 swaps via asgard vaults (no wrapping). Ported from\n * a production THORChain integration. Scope here is **EVM sources first**: the user\n * deposits on an EVM chain (Ethereum/Base/BSC/Avalanche) into the THORChain router with\n * `depositWithExpiry(vault, asset, amount, memo, expiry)`; THORChain settles the\n * swap and delivers ETH/stables to our mainnet vault. **Tron** (opt-in,\n * `tronSource`) executes as a native TRX send / TRC-20 transfer to the inbound\n * vault with the memo in `raw_data.data` — bifrost reads that field for both\n * TransferContract and TriggerSmartContract. BTC/Cosmos/Solana sources are not\n * routed yet (no memo-capable send surface).\n *\n * Safety: the MEMO and inbound vault come verbatim from the quote — we never\n * hand-build them (a wrong memo makes funds unrecoverable). The quote\n * embeds an on-chain LIM, so a bad-price swap refunds instead of filling:\n * `liquidity_tolerance_bps` when the caller passes a slippage (LIM = expected\n * output after fees × (1 − slippage)), `tolerance_bps` otherwise.\n *\n * Hosts (re-verified 2026-09-16): ninerealms retired, the Liquify vanity\n * hostnames went stale; dev.thorchain.org now lists exactly two THORNode\n * entries — Liquify's public GATEWAY (50k req/day per IP; x-client-id\n * identifies us for a bump) and thornode.thorchain.network (no DNS today, kept\n * as the documented fallback in case it returns). Hosts are tried in order and\n * a quote is only ever bound to an inbound snapshot from the SAME host, so a\n * lagging secondary can never be compared against a primary's vault. The\n * list is an explicit constructor option (`nodeUrl`, one or many); this\n * package never reads deployment environment values.\n */\n\nconst HOSTS = [\n \"https://gateway.liquify.com/chain/thorchain_api\",\n \"https://thornode.thorchain.network\",\n];\n\nconst DEFAULT_CLIENT_ID = \"anywalletkit\";\n\nconst NATIVE = \"0x0000000000000000000000000000000000000000\";\nconst TOLERANCE_BPS = \"300\"; // 3% max slippage, embedded as an on-chain LIM\n// Two ways to ask THORNode for the LIM:\n// - `liquidity_tolerance_bps` — measured from the expected output AFTER\n// THORChain's fees (liquidity, outbound, affiliate): LIM = expected × (1 −\n// slippage), the floor every other provider quotes and validQuote enforces.\n// Used whenever the caller passes a slippage, in one request.\n// - `tolerance_bps` — measured from the FEELESS spot: LIM = spot × (1 −\n// tolerance), so the room left is (tolerance − fees) and the node rejects\n// the quote outright when fees exceed it (\"emit asset X less than price\n// limit Y\"; 500 USDC Base → BTC at 1% paid ≈1.7%). Kept only for legacy\n// quotes without a slippage, which widen it to what the pool needs.\n// Both are hard-capped: a route whose THORChain fees alone exceed the cap\n// stays hidden, with a named reason.\nconst MAX_TOLERANCE_BPS = 500n;\n/** How long a quote stays executable (bounded by the memo's own expiry). */\nconst QUOTE_VALIDITY_MS = 5 * 60_000;\n\n// CAIP-2 → THORChain chain prefix. EVM chains execute via the router; TRON\n// executes via a native send to the inbound vault + memo (no router).\nconst THOR_CHAIN: Record<string, string> = {\n \"eip155:1\": \"ETH\",\n \"eip155:8453\": \"BASE\",\n \"eip155:56\": \"BSC\",\n // 2026-09-16: AVAX.AVAX/USDC/USDT pools Available (≈$2.5M/$0.3M/$0.2M),\n // router 0x00dc61…f1d4 live in inbound_addresses; same depositWithExpiry ABI.\n // Polygon has no THORChain pool any more — deliberately absent.\n \"eip155:43114\": \"AVAX\",\n \"tron:728126428\": \"TRON\",\n \"bitcoin:mainnet\": \"BTC\",\n // 2026-08 (pools verified live via the Liquify gateway): THORChain added\n // SOL/XRP, and our catalog now carries LTC/DOGE/BCH/ATOM — destination legs\n // for the step-2 off-ramp (source stays EVM/Tron, see supportsRoute).\n \"solana:mainnet\": \"SOL\",\n \"xrp:mainnet\": \"XRP\",\n \"litecoin:mainnet\": \"LTC\",\n \"doge:mainnet\": \"DOGE\",\n \"bch:mainnet\": \"BCH\",\n \"cosmos:cosmoshub-4\": \"GAIA\",\n};\nconst CHAIN_ID: Record<string, number> = {\"eip155:1\": 1, \"eip155:8453\": 8453, \"eip155:56\": 56, \"eip155:43114\": 43114};\nconst TRON_CAIP2 = \"tron:728126428\";\n// Sources executed as a plain send to the inbound vault + memo (no router).\n// Only chains whose account can attach the memo ON-CHAIN belong here; an\n// unsent memo strands the deposit in the vault.\nconst DEPOSIT_SOURCES = new Set([TRON_CAIP2]);\nconst NATIVE_ASSET: Record<string, string> = {\n ETH: \"ETH.ETH\",\n BASE: \"BASE.ETH\",\n BSC: \"BSC.BNB\",\n AVAX: \"AVAX.AVAX\",\n TRON: \"TRON.TRX\",\n BTC: \"BTC.BTC\",\n SOL: \"SOL.SOL\",\n XRP: \"XRP.XRP\",\n LTC: \"LTC.LTC\",\n DOGE: \"DOGE.DOGE\",\n BCH: \"BCH.BCH\",\n GAIA: \"GAIA.ATOM\",\n};\n\n// Curated token asset notation (UPPERCASE contract, as THORChain expects).\n// Pools come and go (all eight verified Available via the Liquify gateway,\n// 2026-09-16); a retired pool's quote just 404s to null, so entries stay harmless.\nconst TOKEN_ASSET: Record<string, string> = {\n \"ETH:USDC\": \"ETH.USDC-0XA0B86991C6218B36C1D19D4A2E9EB0CE3606EB48\",\n \"ETH:USDT\": \"ETH.USDT-0XDAC17F958D2EE523A2206206994597C13D831EC7\",\n \"BASE:USDC\": \"BASE.USDC-0X833589FCD6EDB6E08F4C7C32D4F71B54BDA02913\",\n \"BSC:USDC\": \"BSC.USDC-0X8AC76A51CC950D9822D68B83FE1AD97B32CD580D\",\n \"BSC:USDT\": \"BSC.USDT-0X55D398326F99059FF775485246999027B3197955\",\n \"AVAX:USDC\": \"AVAX.USDC-0XB97EF9EF8734C71904D8002F8B6BC66DD9C48A6E\",\n \"AVAX:USDT\": \"AVAX.USDT-0X9702230A8EA53601F5CD2DC00FDBC13D4DF4A8C7\",\n \"TRON:USDT\": \"TRON.USDT-TR7NHQJEKQXGTCI8Q8ZY4PL8OTSZGJLJ6T\",\n};\n\nconst ROUTER_ABI = [\n {\n type: \"function\",\n name: \"depositWithExpiry\",\n stateMutability: \"payable\",\n inputs: [\n {name: \"vault\", type: \"address\"},\n {name: \"asset\", type: \"address\"},\n {name: \"amount\", type: \"uint256\"},\n {name: \"memo\", type: \"string\"},\n {name: \"expiration\", type: \"uint256\"},\n ],\n outputs: [],\n },\n] as const;\n\nfunction isEvm(caip2: string): boolean {\n return caip2.startsWith(\"eip155:\");\n}\n\n/** THOR asset notation for a (chain, symbol) on either leg, or undefined. */\nfunction thorAsset(caip2: string, symbol: string): string | undefined {\n const chain = THOR_CHAIN[caip2];\n if (!chain) return undefined;\n const sym = symbol.toUpperCase();\n const token = TOKEN_ASSET[`${chain}:${sym}`];\n if (token) return token;\n const native = NATIVE_ASSET[chain];\n return native && native.split(\".\")[1] === sym ? native : undefined;\n}\n\n/**\n * Destination asset for either direction: inbound → the vault on Ethereum, or\n * the step-2 off-ramp → any THOR-supported chain (BTC/BASE/BSC/TRON). Resolved\n * from the catalog so we get the right symbol + decimals for the target chain.\n */\nfunction destAsset(destChain: string, destToken: string): {asset: string; decimals: number} | undefined {\n const a = ccAssetByToken(destChain, destToken);\n if (!a) return undefined;\n const asset = thorAsset(destChain, a.symbol);\n return asset ? {asset, decimals: a.decimals} : undefined;\n}\n\ninterface ThorQuoteResponse {\n expected_amount_out?: string;\n inbound_address?: string;\n router?: string;\n memo?: string;\n expiry?: number;\n total_swap_seconds?: number;\n /** 1e8 source units; below this the swap is refunded minus fees. */\n recommended_min_amount_in?: string;\n error?: string;\n /** thornode simulation rejections arrive as {code, message}. */\n message?: string;\n /** THORChain's fees on this quote; `total_bps` includes liquidity, outbound and affiliate. */\n fees?: {total_bps?: number};\n}\n\n/**\n * A host-level failure (unreachable, gateway error, rate-limited, blocked):\n * the next host may answer. Anything else the node says — including a 4xx\n * business rejection such as \"no pool\" — is an answer, not a reason to shop\n * the same question to another node.\n */\nclass HostUnavailable extends Error {\n constructor(host: string, reason: string) {\n super(`thorchain: ${host} unavailable (${reason})`);\n }\n}\n\ninterface HostResponse {\n ok: boolean;\n status: number;\n body: Record<string, unknown> | unknown[] | null;\n}\n\nasync function hostGet(host: string, path: string, clientId: string, signal?: AbortSignal): Promise<HostResponse> {\n let res: Response;\n try {\n res = await fetch(`${host}${path}`, {\n headers: {accept: \"application/json\", \"x-client-id\": clientId},\n cache: \"no-store\",\n signal: signal ?? timeoutSignal(8000),\n });\n } catch (error) {\n if (signal?.aborted) throw error; // the caller gave up — not the host's fault\n throw new HostUnavailable(host, error instanceof Error ? error.message : \"fetch failed\");\n }\n if (res.status >= 500 || res.status === 429 || res.status === 403) {\n throw new HostUnavailable(host, `HTTP ${res.status}`);\n }\n const body = (await res.json().catch(() => null)) as HostResponse[\"body\"];\n return {ok: res.ok, status: res.status, body};\n}\n\n/** Per-request failover for reads whose answer is host-independent (tx status). */\nasync function thornodeGet(\n path: string,\n signal: AbortSignal | undefined,\n hosts: string[],\n clientId: string,\n): Promise<Record<string, unknown> | null> {\n for (const host of hosts) {\n try {\n const res = await hostGet(host, path, clientId, signal);\n if (!res.ok) continue;\n return Array.isArray(res.body) ? null : res.body;\n } catch (error) {\n if (error instanceof HostUnavailable) continue;\n throw error;\n }\n }\n return null;\n}\n\ninterface InboundAddress {\n chain?: string;\n address?: string;\n router?: string;\n halted?: boolean;\n global_trading_paused?: boolean;\n chain_trading_paused?: boolean;\n /** 1e8 source units; inbounds at or below it are IGNORED by THORChain. */\n dust_threshold?: string;\n}\n\n/** Fail closed on amounts THORChain would ignore (dust) or refund (below the\n * recommended minimum). Both are quoted in 1e8 source units. */\nfunction belowThorMinimums(amount1e8: bigint, inbound: InboundAddress | undefined, quote: ThorQuoteResponse | null): string | null {\n const dust = inbound?.dust_threshold;\n if (dust !== undefined && (!/^\\d+$/.test(String(dust)) || amount1e8 <= BigInt(dust))) return \"amount at or below THORChain dust threshold\";\n const min = quote?.recommended_min_amount_in;\n if (min !== undefined && (!/^\\d+$/.test(String(min)) || amount1e8 < BigInt(min))) return \"amount below THORChain recommended minimum\";\n return null;\n}\n\n/** Inbound snapshot from ONE host. Throws HostUnavailable so the caller can\n * re-run the whole quote on the next host rather than mixing nodes. */\nasync function inboundAddressesOn(host: string, clientId: string): Promise<InboundAddress[]> {\n const res = await hostGet(host, \"/thorchain/inbound_addresses\", clientId);\n if (!res.ok || !Array.isArray(res.body)) throw new HostUnavailable(host, `inbound_addresses HTTP ${res.status}`);\n return res.body as InboundAddress[];\n}\n\n/** Pre-broadcast re-check: any live host is an acceptable authority — a\n * disagreeing secondary fails closed, which is the safe direction. */\nasync function inboundAddresses(hosts: string[], clientId: string): Promise<InboundAddress[] | null> {\n for (const host of hosts) {\n try {\n return await inboundAddressesOn(host, clientId);\n } catch (error) {\n if (error instanceof HostUnavailable) continue;\n throw error;\n }\n }\n return null;\n}\n\nfunction paused(entry: InboundAddress | undefined): boolean {\n return !entry || entry.halted === true || entry.global_trading_paused === true || entry.chain_trading_paused === true;\n}\n\nfunction sameTarget(a: string | undefined, b: string | undefined): boolean {\n if (!a || !b) return false;\n return a.startsWith(\"0x\") || b.startsWith(\"0x\") ? a.toLowerCase() === b.toLowerCase() : a === b;\n}\n\nfunction verifiedMemo(\n memo: string,\n expectedAsset: string,\n expectedDestination: string,\n expectedRefund: string,\n expectedAffiliate: string,\n expectedAffiliateBps: string,\n): {limit: bigint; canonical: string} | null {\n if (memo.includes(\"|\")) return null; // DEX-aggregator tail is a separate, unbound execution program.\n const parts = memo.split(\":\");\n if (parts.length !== 4 && parts.length !== 6) return null;\n const [op, asset, destination, limit, affiliate, bps] = parts;\n // Quote responses legitimately use THORChain fuzzy asset notation (`b` for\n // BTC.BTC). We never execute that untrusted spelling: after checking the\n // shape, destination/refund, limit and affiliate we rebuild a canonical memo\n // from our own route facts below.\n if (op !== \"=\" || !asset || !/^[A-Za-z0-9._~\\-]+$/.test(asset)) return null;\n const expectedTarget = expectedRefund ? `${expectedDestination}/${expectedRefund}` : expectedDestination;\n if (!sameTarget(destination, expectedTarget)) return null;\n if (parts.length === 6) {\n if (!expectedAffiliate || affiliate !== expectedAffiliate || bps !== expectedAffiliateBps) return null;\n } else if (expectedAffiliate || expectedAffiliateBps) {\n return null;\n }\n const stream = (limit ?? \"\").split(\"/\");\n // We never request streaming swaps. A provider-supplied LIM/INTERVAL/QTY\n // memo changes the floor to a per-sub-swap condition, so reject it instead\n // of presenting LIM as an atomic total guarantee.\n if (stream.length !== 1 || stream.some((v) => !/^\\d+$/.test(v))) return null;\n const floor = BigInt(stream[0] ?? \"0\");\n if (floor <= 0n) return null;\n const canonical = `=:${expectedAsset}:${expectedTarget}:${stream.join(\"/\")}${\n expectedAffiliate ? `:${expectedAffiliate}:${expectedAffiliateBps}` : \"\"\n }`;\n return {limit: floor, canonical};\n}\n\nfunction toThorUnitsCeil(amount: bigint, decimals: number): bigint {\n const scale = 10n ** BigInt(decimals);\n return (amount * 100_000_000n + scale - 1n) / scale;\n}\n\n/** Explicit constructor configuration; no deployment environment is read. */\nexport interface ThorchainProviderConfig {\n enabled?: boolean;\n affiliate?: string;\n affiliateBps?: string;\n /**\n * THORNode base URL(s), tried in order; a comma-separated string is\n * accepted for env-style configuration. Defaults to the documented public\n * hosts. Quote + inbound snapshot always come from the same host.\n */\n nodeUrl?: string | string[];\n /** Optional gateway identification; defaults to a neutral module name. */\n clientId?: string;\n /**\n * Opt-in Tron SOURCE execution: a native TRX send / TRC-20 transfer to the\n * inbound vault carrying the swap memo in `raw_data.data`. Ships dark: the\n * bound account MUST attach the memo on-chain (`raw_data.data`); a\n * memo-less send is unsettleable.\n */\n tronSource?: boolean;\n}\n\nexport function thorchainProvider(config: ThorchainProviderConfig = {}): CrossChainProvider {\n config = Object.freeze({...config});\n const configuredHosts = (Array.isArray(config.nodeUrl) ? config.nodeUrl : (config.nodeUrl ?? \"\").split(\",\"))\n .map((h) => h.trim())\n .filter(Boolean);\n const hosts = [...new Set((configuredHosts.length ? configuredHosts : HOSTS).map((h) => {\n let url: URL;\n try {\n url = new URL(h);\n } catch {\n throw new Error(\"thorchain: nodeUrl must be an absolute http(s) URL\");\n }\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") throw new Error(\"thorchain: nodeUrl must use http or https\");\n return url.toString().replace(/\\/$/, \"\");\n }))];\n const configuredAffiliate = config.affiliate ?? \"\";\n const configuredAffiliateBps = config.affiliateBps ?? \"\";\n if (!!configuredAffiliate !== !!configuredAffiliateBps) {\n throw new Error(\"thorchain: affiliate and affiliateBps must be configured together\");\n }\n if (configuredAffiliate && !/^[A-Za-z0-9._~-]+$/.test(configuredAffiliate)) {\n throw new Error(\"thorchain: affiliate contains unsupported memo characters\");\n }\n if (configuredAffiliateBps && (!/^\\d+$/.test(configuredAffiliateBps) || BigInt(configuredAffiliateBps) > 10_000n)) {\n throw new Error(\"thorchain: affiliateBps must be an integer between 0 and 10000\");\n }\n const clientId = config.clientId?.trim() || DEFAULT_CLIENT_ID;\n if (!/^[\\x21-\\x7e]{1,128}$/.test(clientId)) throw new Error(\"thorchain: clientId must contain 1-128 visible ASCII characters\");\n const tronSource = config.tronSource === true;\n const isDepositSource = (caip2: string): boolean => tronSource && DEPOSIT_SOURCES.has(caip2);\n return {\n name: \"thorchain\",\n describeActivity: describeThorchainActivity,\n enabled: () => config.enabled ?? true,\n\n // Capability discovery comes from the provider itself, so it can run alone\n // or inside the optional aggregator without a central capability table.\n supportsChain: (chain: string) => thorCfg.supportsChain(chain),\n supportsChainPair: (fromChain: string, toChain: string) => thorCfg.supports(fromChain, toChain),\n // Inbound: EVM/Tron source → the mainnet vault. Outbound (step-2 off-ramp):\n // EVM source (Ethereum) → any THOR-supported chain. The SOURCE must be EVM\n // (router calldata) or, when opted in, Tron (send + memo); both legs must\n // be THOR chains and differ.\n supportsRoute(from: Asset, to: Asset): boolean {\n const srcExec = isEvm(from.chain) || isDepositSource(from.chain);\n if (!(srcExec && !!THOR_CHAIN[from.chain] && !!THOR_CHAIN[to.chain] && from.chain !== to.chain)) return false;\n // Asset level too: claiming a chain pair whose assets THORChain has no\n // pool for (e.g. USDC on Solana) put the provider in every route list\n // and then answered a silent null.\n const fromAsset = thorAsset(from.chain, from.token) ?? thorAsset(from.chain, ccAssetByToken(from.chain, from.token)?.symbol ?? \"\");\n const toAsset = destAsset(to.chain, to.token) ?? (thorAsset(to.chain, to.token) ? {asset: thorAsset(to.chain, to.token)!} : undefined);\n return !!fromAsset && !!toAsset && fromAsset !== toAsset.asset;\n },\n\n async getQuote(params: QuoteParams, signal?: AbortSignal): Promise<Quote | null> {\n if (!(config.enabled ?? true)) return null;\n if (params.flex) return null; // memo/LIM embed the exact amount\n const chainId = CHAIN_ID[params.sourceChain];\n // EVM sources execute via the router; opted-in deposit sources (Tron)\n // via send + memo. Anything else has no safe executor.\n if (!chainId && !isDepositSource(params.sourceChain)) return null;\n if (params.sourceChain === params.destChain) return null; // same-chain: not a swap\n\n const src = ccAsset(params.sourceChain, params.sourceToken);\n const fromAsset = thorAsset(params.sourceChain, params.sourceToken);\n const dst = destAsset(params.destChain, params.destToken);\n if (!src || !fromAsset || !dst || fromAsset === dst.asset) {\n params.onRefusal?.(`thorchain: no pool for ${params.sourceToken} on ${params.sourceChain} → ${params.destToken} on ${params.destChain}`);\n return null;\n }\n\n // THORChain amounts are universally 1e8-scaled.\n const amountIn = BigInt(params.amountIn);\n const amount1e8 = (amountIn * 100000000n) / 10n ** BigInt(src.decimals);\n if (amount1e8 <= 0n) return null;\n // THOR quotes only 1e8 units. Never send a larger high-precision source\n // amount than the amount priced by the quote (the remainder is dust the\n // memo cannot account for and may be donated to the vault).\n if (amount1e8 * 10n ** BigInt(src.decimals) !== amountIn * 100_000_000n) {\n params.onRefusal?.(`thorchain: amount has more precision than THORChain's 8 decimals — round it to 8 decimals`);\n return null;\n }\n\n const requestedTolerance = params.slippageBps ?? Number(TOLERANCE_BPS);\n if (!Number.isInteger(requestedTolerance) || requestedTolerance < 0 || requestedTolerance > bigintToNumber(MAX_TOLERANCE_BPS)) {\n params.onRefusal?.(`thorchain: slippage ${String(params.slippageBps)} bps is outside 0–${MAX_TOLERANCE_BPS} bps`);\n return null;\n }\n // An explicit slippage → `liquidity_tolerance_bps`. The node floors LIM in\n // 1e8 units; for a destination with more than 8 decimals that floor lands\n // a hair below expected × (1 − slippage) in base units, so ask 1 bp\n // tighter there (never looser). 0 bp cannot carry a LIM that way: such a\n // request goes out as `tolerance_bps` and the node's answer stands.\n const explicitSlippage = params.slippageBps !== undefined;\n const liquidityBps = explicitSlippage ? (dst.decimals > 8 ? requestedTolerance - 1 : requestedTolerance) : 0;\n const limitMode = liquidityBps > 0 ? \"liquidity_tolerance_bps\" : \"tolerance_bps\";\n // `tolerance_bps` → LIM from the feeless spot output; `liquidity_tolerance_bps`\n // → LIM from the expected output after fees (the node accepts only one).\n const quoteOn = async (\n host: string,\n bps: string,\n limitMode: \"tolerance_bps\" | \"liquidity_tolerance_bps\" = \"tolerance_bps\",\n ): Promise<ThorQuoteResponse | null> => {\n const qs = new URLSearchParams({\n from_asset: fromAsset,\n to_asset: dst.asset,\n amount: amount1e8.toString(),\n destination: params.destAddress,\n [limitMode]: bps,\n // Pin a single (non-streaming) swap. Left to itself the node picks\n // streaming for thin pools (max_streaming_quantity > 1) and then\n // simulates the LIM per sub-swap — the adaptive retry could never\n // pass on BASE.ETH / BSC stables (verified 2026-09-16). We reject\n // streaming memos anyway, so the quote must be simulated atomically.\n streaming_quantity: \"1\",\n });\n if (configuredAffiliate && configuredAffiliateBps) {\n qs.set(\"affiliate\", configuredAffiliate);\n qs.set(\"affiliate_bps\", configuredAffiliateBps);\n }\n if (params.refundAddress) qs.set(\"refund_address\", params.refundAddress);\n const res = await hostGet(host, `/thorchain/quote/swap?${qs.toString()}`, clientId, signal);\n if (Array.isArray(res.body)) return null;\n // A 4xx carries the node's rejection body (used by the adaptive retry).\n return (res.body ?? (res.ok ? null : {error: `HTTP ${res.status}`})) as ThorQuoteResponse | null;\n };\n\n // Host failover: the quote AND the inbound snapshot it is bound to must\n // come from one node. If either call fails at the host level, the whole\n // pair is re-run on the next host; a node's business rejection is final.\n let q: ThorQuoteResponse | null = null;\n let checkedMemo: ReturnType<typeof verifiedMemo> = null;\n let inbounds: InboundAddress[] | null = null;\n for (const host of hosts) {\n try {\n if (limitMode === \"liquidity_tolerance_bps\") {\n q = await quoteOn(host, String(liquidityBps), \"liquidity_tolerance_bps\");\n const feeBps = Number(q?.fees?.total_bps);\n if (Number.isFinite(feeBps) && feeBps > bigintToNumber(MAX_TOLERANCE_BPS)) {\n // Dust amounts: a fixed outbound fee eats the swap.\n params.onRefusal?.(`thorchain: THORChain fees ${(feeBps / 100).toFixed(2)}% — too expensive at this amount (cap ${bigintToNumber(MAX_TOLERANCE_BPS) / 100}%)`);\n return null;\n }\n } else {\n q = await quoteOn(host, String(requestedTolerance));\n // Legacy quotes without a slippage: fees > tolerance makes the node\n // reject the quote; the rejection carries the actual emit vs the\n // limit the tolerance implied. ONE retry, on the same host, widens\n // the tolerance to what the pool needs (+buffer), capped. An\n // explicit 0 bp slippage is never widened — the rejection stands.\n const rejected = (q?.error ?? q?.message)?.match(/emit asset (\\d+) less than price limit (\\d+)/);\n if (rejected && !explicitSlippage) {\n const emit = BigInt(rejected[1] ?? \"0\");\n const limit = BigInt(rejected[2] ?? \"0\");\n if (emit > 0n && limit > emit) {\n // limit = spot × (1 − tolerance/10000) → spot; needed = 1 − emit/spot.\n const spot = (limit * 10000n) / (10000n - BigInt(requestedTolerance));\n const needed = 10000n - (emit * 10000n) / spot + 50n; // +0.5% buffer\n if (needed <= MAX_TOLERANCE_BPS) q = await quoteOn(host, needed.toString());\n }\n }\n }\n // Validate the node's answer BEFORE touching the network again: a\n // rejection, a malformed quote or an unbound memo is final.\n if (q?.error || q?.message) {\n // The node's own rejection (no pool, price limit, halted…) is the\n // caller's answer — surface it instead of an anonymous null.\n params.onRefusal?.(`thorchain: ${String(q.error ?? q.message).slice(0, 200)}`);\n return null;\n }\n if (!q || !q.expected_amount_out || !q.inbound_address || !q.memo || !q.expiry) {\n params.onRefusal?.(`thorchain: incomplete quote from ${host} (expected_amount_out / inbound_address / memo / expiry missing)`);\n return null;\n }\n // A router is required for EVM and must be ABSENT for a deposit\n // source: a router on a Tron quote means the venue changed its\n // execution model and a plain send would no longer settle.\n if (chainId ? !q.router : !!q.router) {\n params.onRefusal?.(chainId ? \"thorchain: quote has no router for an EVM source\" : \"thorchain: quote names a router for a deposit source — execution model changed\");\n return null;\n }\n checkedMemo = verifiedMemo(q.memo, dst.asset, params.destAddress, params.refundAddress ?? \"\", configuredAffiliate, configuredAffiliateBps);\n if (!checkedMemo) {\n params.onRefusal?.(`thorchain: memo failed verification (${String(q.memo).slice(0, 80)})`);\n return null;\n }\n const floor1e8 = params.minAmountOut !== undefined ? toThorUnitsCeil(BigInt(params.minAmountOut), dst.decimals) : undefined;\n if (floor1e8 !== undefined && checkedMemo.limit < floor1e8) {\n params.onRefusal?.(`thorchain: floor breach (limit=${checkedMemo.limit} < floor=${floor1e8}, 1e8 units)`);\n return null;\n }\n // A quote gateway is not an authority for rotating vault/router\n // state. Bind it against a separately fetched no-store inbound\n // snapshot from the SAME host now, then repeat the check before broadcast.\n inbounds = await inboundAddressesOn(host, clientId);\n break;\n } catch (error) {\n if (error instanceof HostUnavailable) {\n q = null;\n checkedMemo = null;\n inbounds = null;\n continue;\n }\n throw error;\n }\n }\n if (!q?.expected_amount_out || !q.inbound_address || !q.expiry || !checkedMemo || !inbounds) {\n params.onRefusal?.(!inbounds ? \"thorchain: inbound addresses unavailable from every node\" : \"thorchain: no quote from any node\");\n return null;\n }\n const limit1e8 = checkedMemo.limit;\n const srcInbound = inbounds.find((entry) => entry.chain === THOR_CHAIN[params.sourceChain]);\n const dstInbound = inbounds.find((entry) => entry.chain === THOR_CHAIN[params.destChain]);\n if (paused(srcInbound) || paused(dstInbound)) {\n params.onRefusal?.(`thorchain: ${paused(srcInbound) ? THOR_CHAIN[params.sourceChain] : THOR_CHAIN[params.destChain]} chain is halted / paused on THORChain`);\n return null;\n }\n if (!sameTarget(srcInbound?.address, q.inbound_address)) {\n params.onRefusal?.(\"thorchain: quote inbound address differs from the node's current inbound (vault rotated) — retry\");\n return null;\n }\n if (chainId && !sameTarget(srcInbound?.router, q.router)) {\n params.onRefusal?.(\"thorchain: quote router differs from the node's current router — retry\");\n return null;\n }\n const tooSmall = belowThorMinimums(amount1e8, srcInbound, q);\n if (tooSmall) {\n params.onRefusal?.(`thorchain: ${tooSmall}`);\n return null;\n }\n\n // expected_amount_out is 1e8 of the DEST asset → base units.\n const outUnits = (BigInt(q.expected_amount_out) * 10n ** BigInt(dst.decimals)) / 100000000n;\n if (outUnits <= 0n) {\n params.onRefusal?.(\"thorchain: expected output rounds to zero\");\n return null;\n }\n const memoMinUnits = (limit1e8 * 10n ** BigInt(dst.decimals)) / 100_000_000n;\n const minUnits = memoMinUnits;\n if (minUnits <= 0n || minUnits > outUnits) {\n params.onRefusal?.(`thorchain: memo limit ${limit1e8} inconsistent with expected output ${q.expected_amount_out}`);\n return null;\n }\n // The caller's slippage is measured from the quoted output, as validQuote\n // does for every provider. A memo LIM below that floor would only be\n // dropped later as an anonymous validation failure — name it here.\n if (params.slippageBps !== undefined) {\n const slippageFloor = (outUnits * BigInt(10_000 - params.slippageBps)) / 10_000n;\n if (minUnits < slippageFloor) {\n params.onRefusal?.(`thorchain: memo limit ${limit1e8} is below expected ${q.expected_amount_out} minus ${params.slippageBps} bps slippage (1e8 units)`);\n return null;\n }\n }\n\n const nowSeconds = Math.floor(Date.now() / 1000);\n const executionExpiry = Math.min(q.expiry, nowSeconds + 15 * 60);\n if (!Number.isInteger(executionExpiry) || executionExpiry <= nowSeconds + 30) {\n params.onRefusal?.(`thorchain: quote expires in ${Number.isInteger(executionExpiry) ? executionExpiry - nowSeconds : \"?\"} s — too soon to execute`);\n return null;\n }\n const assetAddr = (src.contract ? src.contract : NATIVE) as `0x${string}`;\n const common = {\n provider: \"thorchain\",\n intentId: `thorchain:${chainId ?? THOR_CHAIN[params.sourceChain]}`,\n sourceAmount: params.amountIn,\n destAmount: outUnits.toString(),\n minDestAmount: minUnits.toString(),\n feeUsd: 0, // destAmount is already net of THORChain fees\n etaSeconds: q.total_swap_seconds ?? 120,\n reliability: 0.9,\n // Validity must outlive the ERC-20 approval leg: for USDT that is\n // approve(0) + approve(n), each awaited to inclusion (≈2 blocks), so a\n // 60 s window expired before the deposit and only the revoke went out\n // (2026-09-16). The on-chain LIM bounds price movement and preflight\n // re-checks vault/router/halts right before broadcast, so a longer\n // window costs nothing in safety.\n validUntilMs: Math.min(Date.now() + QUOTE_VALIDITY_MS, executionExpiry * 1000),\n providerData: {\n sourceChain: params.sourceChain,\n destChain: params.destChain,\n inboundAddress: q.inbound_address,\n router: q.router ?? \"\",\n assetAddress: assetAddr,\n expiry: String(executionExpiry),\n memo: checkedMemo.canonical,\n },\n };\n\n // Deposit source (Tron): the engine sends `sourceAmount` of the source\n // asset to the inbound vault with the canonical memo attached on-chain.\n if (!chainId) {\n return {...common, depositAddress: q.inbound_address, depositMemo: checkedMemo.canonical};\n }\n\n // EVM: router calldata depositWithExpiry(asgardVault, asset, amount, memo, expiry).\n const data = encodeFunctionData({\n abi: ROUTER_ABI,\n functionName: \"depositWithExpiry\",\n args: [q.inbound_address as `0x${string}`, assetAddr, amountIn, checkedMemo.canonical, BigInt(executionExpiry)],\n });\n return {\n ...common,\n depositAddress: \"\",\n depositMemo: null,\n txRequest: {\n to: q.router!,\n data,\n value: src.contract ? \"0\" : params.amountIn,\n chainId: chainId!,\n ...(src.contract ? {approvalAddress: q.router!} : {}),\n },\n };\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n if (!quote.txRequest) {\n const sourceChain = quote.providerData?.sourceChain ?? \"\";\n if (!isDepositSource(sourceChain) || !quote.depositAddress || !quote.depositMemo) {\n throw new Error(\"thorchain: deposit-address execution is only supported for an opted-in Tron source\");\n }\n // Plain send to the inbound vault (the engine turns a TRC-20 source\n // into transfer()); the memo MUST ride on-chain in raw_data.data.\n return {chain: sourceChain, to: quote.depositAddress, value: quote.sourceAmount, memo: quote.depositMemo};\n }\n return {\n chain: \"\",\n to: quote.txRequest?.to ?? \"\",\n value: quote.txRequest?.value ?? \"0\",\n ...(quote.txRequest?.data ? {data: quote.txRequest.data} : {}),\n ...(quote.txRequest?.chainId !== undefined ? {chainId: quote.txRequest.chainId} : {}),\n ...(quote.txRequest?.gasLimit ? {gasLimit: quote.txRequest.gasLimit} : {}),\n ...(quote.txRequest?.approvalAddress ? {approvalAddress: quote.txRequest.approvalAddress} : {}),\n };\n },\n\n async preflightDeposit(quote: Quote, tx: UnsignedTx): Promise<void> {\n const data = quote.providerData;\n if (!data?.sourceChain || !data.destChain || !data.inboundAddress || !data.assetAddress || !data.expiry || !data.memo) {\n throw new Error(\"thorchain: quote is missing execution-bound metadata\");\n }\n const evmSource = CHAIN_ID[data.sourceChain] !== undefined;\n if (evmSource && !data.router) throw new Error(\"thorchain: quote is missing execution-bound metadata\");\n if (!evmSource && !isDepositSource(data.sourceChain)) throw new Error(\"thorchain: source chain has no executor\");\n if (!/^\\d+$/.test(data.expiry) || BigInt(data.expiry) <= BigInt(Math.floor(Date.now() / 1000))) {\n throw new Error(\"thorchain: quote expired before broadcast\");\n }\n const inbounds = await inboundAddresses(hosts, clientId);\n if (!inbounds) throw new Error(\"thorchain: cannot refresh inbound addresses before broadcast\");\n const src = inbounds.find((entry) => entry.chain === THOR_CHAIN[data.sourceChain!]);\n const dst = inbounds.find((entry) => entry.chain === THOR_CHAIN[data.destChain!]);\n if (paused(src) || paused(dst)) throw new Error(\"thorchain: source or destination chain trading is paused\");\n if (!sameTarget(src?.address, data.inboundAddress)) throw new Error(\"thorchain: inbound vault rotated after quote\");\n if (!evmSource) {\n // Deposit source: exactly a plain send of the validated amount to the\n // validated vault carrying the validated memo — nothing else.\n if (tx.data !== undefined || tx.approvalAddress !== undefined || tx.bodyBoc !== undefined || tx.typedData !== undefined || tx.serializedTx !== undefined || tx.stateInitBoc !== undefined) {\n throw new Error(\"thorchain: deposit-address execution must be a plain send with memo\");\n }\n if (!sameTarget(tx.to, data.inboundAddress) || tx.memo !== data.memo || tx.value !== quote.sourceAmount || (tx.chain && tx.chain !== data.sourceChain)) {\n throw new Error(\"thorchain: deposit does not match the validated quote\");\n }\n const srcAsset = ccAssetByToken(data.sourceChain, sameTarget(data.assetAddress, NATIVE) ? \"\" : data.assetAddress);\n if (!srcAsset) throw new Error(\"thorchain: unknown source asset\");\n const amount1e8 = (BigInt(quote.sourceAmount) * 100_000_000n) / 10n ** BigInt(srcAsset.decimals);\n const tooSmall = belowThorMinimums(amount1e8, src, null);\n if (tooSmall) throw new Error(`thorchain: ${tooSmall}`);\n return;\n }\n if (!sameTarget(src?.router, data.router) || !sameTarget(tx.to, data.router)) {\n throw new Error(\"thorchain: router rotated after quote\");\n }\n if (!tx.data) throw new Error(\"thorchain: missing depositWithExpiry calldata\");\n let decoded: {functionName: string; args?: readonly unknown[]};\n try {\n decoded = decodeFunctionData({abi: ROUTER_ABI, data: tx.data as `0x${string}`});\n } catch {\n throw new Error(\"thorchain: malformed depositWithExpiry calldata\");\n }\n const args = decoded.args;\n if (\n decoded.functionName !== \"depositWithExpiry\" || !args || args.length !== 5 ||\n !sameTarget(String(args[0]), data.inboundAddress) ||\n !sameTarget(String(args[1]), data.assetAddress) ||\n BigInt(args[2] as bigint) !== BigInt(quote.sourceAmount) ||\n String(args[3]) !== data.memo || BigInt(args[4] as bigint) !== BigInt(data.expiry) ||\n tx.chainId !== CHAIN_ID[data.sourceChain]\n ) {\n throw new Error(\"thorchain: calldata does not match the validated quote\");\n }\n const tokenSource = !sameTarget(data.assetAddress, NATIVE);\n if (\n tx.value !== (tokenSource ? \"0\" : quote.sourceAmount) ||\n (tokenSource ? !sameTarget(tx.approvalAddress, data.router) : tx.approvalAddress !== undefined)\n ) {\n throw new Error(\"thorchain: value/approval does not match the validated source asset\");\n }\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n if (!ref.sourceTxHash) return {state: \"pending\"}; // not broadcast yet\n // THORNode keys EVM inbounds by the tx hash without 0x, uppercase.\n if (!/^(?:0x)?[0-9a-fA-F]{64}$/.test(ref.sourceTxHash)) {\n throw new Error(\"thorchain: source transaction hash must be 32-byte hex\");\n }\n const hash = ref.sourceTxHash.replace(/^0x/i, \"\").toUpperCase();\n const j = await thornodeGet(`/thorchain/tx/status/${hash}`, undefined, hosts, clientId) ??\n await thornodeGet(`/thorchain/tx/${hash}`, undefined, hosts, clientId);\n if (!j) return {state: \"pending\"};\n const stages = j.stages as {\n inbound_observed?: {started?: boolean; completed?: boolean};\n inbound_finalised?: {completed?: boolean};\n outbound_signed?: {completed?: boolean};\n } | undefined;\n if (stages) {\n const planned = (j.planned_out_txs ?? []) as {refund?: boolean}[];\n const refunded = planned.some((out) => out.refund === true);\n const delivered = planned.some((out) => out.refund === false);\n const outTxs = (j.out_txs ?? []) as {id?: string; memo?: string}[];\n const outHash = outTxs.find((out) => typeof out.id === \"string\" && out.id.length > 0 && !/^0+$/.test(out.id))?.id;\n const deliveredHash = outTxs.find((out) =>\n typeof out.id === \"string\" && out.id.length > 0 && !/^0+$/.test(out.id) && typeof out.memo === \"string\" && !/^REFUND/i.test(out.memo)\n )?.id;\n if (stages.outbound_signed?.completed) {\n // `completed` describes the signing stage, not the economic outcome.\n // A truncated/malformed status response with no classified plan or\n // observed outbound must not be promoted to successful delivery.\n if ((!refunded && !delivered) || !outHash) {\n return {state: \"pending\", depositReceived: true};\n }\n return refunded && delivered\n // A refund hash is not a destination transaction. For mixed plans,\n // expose a hash only when the observed outbound is classifiable.\n ? {state: \"partial\", depositReceived: true, ...(deliveredHash ? {destTxHash: deliveredHash} : {})}\n : refunded\n ? {state: \"refunded\", depositReceived: true}\n : {state: \"completed\", depositReceived: true, ...(outHash ? {destTxHash: outHash} : {})};\n }\n return {\n state: \"pending\",\n depositReceived: !!(stages.inbound_observed?.started || stages.inbound_observed?.completed || stages.inbound_finalised?.completed),\n };\n }\n const obs = j.observed_tx as {status?: string; out_hashes?: string[]} | undefined;\n const outHash = obs?.out_hashes?.find((h) => typeof h === \"string\" && h.length > 0 && !/^0+$/.test(h));\n if (obs?.status === \"done\") {\n // A slipped-past-LIM (or halted) swap ALSO finalizes \"done\", but its\n // outbound is a REFUND to the source chain — never report that as a\n // completed swap (audit M1). Planned outbounds carry the memo.\n const planned = (j.planned_out_txs ?? j.out_txs ?? []) as {memo?: string; refund?: boolean}[];\n const refunded = planned.some(\n (o) => o?.refund === true || /^REFUND/i.test(o?.memo ?? \"\"),\n );\n const delivered = planned.some(\n (o) => o?.refund === false && !/^REFUND/i.test(o?.memo ?? \"\"),\n );\n if ((!refunded && !delivered) || !outHash) return {state: \"pending\", depositReceived: true};\n if (refunded && delivered) return {state: \"partial\", depositReceived: true};\n if (refunded) return {state: \"refunded\", depositReceived: true};\n return {state: \"completed\", ...(outHash ? {destTxHash: outHash} : {})};\n }\n return {state: \"pending\", depositReceived: !!obs};\n },\n };\n}\n","import {SingleProviderSwap2} from \"@anywalletkit/protocol-swap2-core/swap2/single\";\nimport type {Swap2Account, Swap2EngineConfig} from \"@anywalletkit/protocol-swap2-core/swap2/base\";\nimport {thorchain as thorchainCfg} from \"./config.js\";\nimport {thorchainProvider, type ThorchainProviderConfig} from \"./provider.js\";\n\nexport interface ThorchainSwap2Config extends Swap2EngineConfig, ThorchainProviderConfig {}\n\nexport class ThorchainSwap2Protocol extends SingleProviderSwap2 {\n protected readonly provider;\n constructor(account: Swap2Account | undefined, config: ThorchainSwap2Config) {\n super(account, config);\n this.provider = thorchainProvider(config);\n }\n protected override chainSupported(caip2: string): boolean {\n return thorchainCfg.supportsChain(caip2);\n }\n protected override pairSupported(fromChain: string, toChain: string): boolean {\n return this.provider.supportsRoute({chain: fromChain, token: \"\"}, {chain: toChain, token: \"\"});\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,kBAAuC;AAKvC,IAAM,WAAW,oBAAI,IAAI,CAAC,GAAG,MAAM,IAAI,KAAK,CAAC;AAC7C,IAAM,UAAU,oBAAI,IAAI,CAAC,WAAW,UAAU,UAAU,QAAQ,OAAO,YAAY,QAAQ,KAAK,CAAC;AAC1F,IAAM,YAAY;AAAA,EACvB,SAAS,MAAM;AAAA,EACf,WAAW,MAAM;AAAA,EACjB,cAAc,MAAM;AAAA,EACpB,cAAc,OAAwB;AACpC,QAAI,QAAQ,QAAI,uBAAU,KAAK,CAAC,EAAG,QAAO;AAC1C,eAAO,mBAAM,KAAK,KAAK,SAAS,QAAI,oBAAO,KAAK,CAAC;AAAA,EACnD;AAAA,EACA,SAAS,MAAc,IAAqB;AAC1C,WAAO,KAAK,cAAc,IAAI,KAAK,KAAK,cAAc,EAAE;AAAA,EAC1D;AACF;;;ACNA,sBAA0D;AAGnD,IAAM,mBAAmB;AAGzB,IAAM,gCAAgC;AAEtC,IAAM,yBAAyB;AAE/B,IAAM,kCAAkC;AAExC,SAAS,0BAA0B,IAAa,KAAmD;AACxG,MAAI,CAAC,GAAG,MAAM,WAAW,SAAS,KAAK,CAAC,UAAa,cAAc,GAAG,KAAK,EAAG,QAAO;AACrF,QAAM,eAAW,8BAAa,EAAE;AAChC,MAAI,aAAa,+BAA+B;AAE9C,UAAM,QAAQ,CAAC,MAAc,IAAI,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,IAAI,EAAE,YAAY,CAAC;AAC1E,QAAI,CAAC,MAAM,GAAG,IAAI,EAAG,QAAO;AAC5B,eAAO,kCAAiB,IAAI,KAAK,EAAC,UAAU,kBAAkB,UAAU,aAAa,MAAM,OAAM,CAAC;AAAA,EACpG;AACA,MAAI,aAAa,0BAA0B,aAAa,iCAAiC;AACvF,UAAM,EAAC,SAAQ,QAAI,6BAAY,IAAI,GAAG;AACtC,QAAI,SAAS,WAAW,EAAG,QAAO;AAClC,eAAO,kCAAiB,IAAI,KAAK,EAAC,UAAU,kBAAkB,UAAU,aAAa,MAAM,UAAU,UAAU,gBAAe,CAAC;AAAA,EACjI;AACA,SAAO;AACT;;;ACrCA,kBAAqD;AACrD,IAAAA,eAA4B;AAC5B,0BAAsC;AAEtC,kBAA6B;AA8B7B,IAAM,QAAQ;AAAA,EACZ;AAAA,EACA;AACF;AAEA,IAAM,oBAAoB;AAE1B,IAAM,SAAS;AACf,IAAM,gBAAgB;AAatB,IAAM,oBAAoB;AAE1B,IAAM,oBAAoB,IAAI;AAI9B,IAAM,aAAqC;AAAA,EACzC,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,aAAa;AAAA;AAAA;AAAA;AAAA,EAIb,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,mBAAmB;AAAA;AAAA;AAAA;AAAA,EAInB,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,sBAAsB;AACxB;AACA,IAAM,WAAmC,EAAC,YAAY,GAAG,eAAe,MAAM,aAAa,IAAI,gBAAgB,MAAK;AACpH,IAAM,aAAa;AAInB,IAAM,kBAAkB,oBAAI,IAAI,CAAC,UAAU,CAAC;AAC5C,IAAM,eAAuC;AAAA,EAC3C,KAAK;AAAA,EACL,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM;AAAA,EACN,MAAM;AAAA,EACN,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM;AACR;AAKA,IAAM,cAAsC;AAAA,EAC1C,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AACf;AAEA,IAAM,aAAa;AAAA,EACjB;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,iBAAiB;AAAA,IACjB,QAAQ;AAAA,MACN,EAAC,MAAM,SAAS,MAAM,UAAS;AAAA,MAC/B,EAAC,MAAM,SAAS,MAAM,UAAS;AAAA,MAC/B,EAAC,MAAM,UAAU,MAAM,UAAS;AAAA,MAChC,EAAC,MAAM,QAAQ,MAAM,SAAQ;AAAA,MAC7B,EAAC,MAAM,cAAc,MAAM,UAAS;AAAA,IACtC;AAAA,IACA,SAAS,CAAC;AAAA,EACZ;AACF;AAEA,SAASC,OAAM,OAAwB;AACrC,SAAO,MAAM,WAAW,SAAS;AACnC;AAGA,SAAS,UAAU,OAAe,QAAoC;AACpE,QAAM,QAAQ,WAAW,KAAK;AAC9B,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,MAAM,OAAO,YAAY;AAC/B,QAAM,QAAQ,YAAY,GAAG,KAAK,IAAI,GAAG,EAAE;AAC3C,MAAI,MAAO,QAAO;AAClB,QAAM,SAAS,aAAa,KAAK;AACjC,SAAO,UAAU,OAAO,MAAM,GAAG,EAAE,CAAC,MAAM,MAAM,SAAS;AAC3D;AAOA,SAAS,UAAU,WAAmB,WAAkE;AACtG,QAAM,QAAI,oCAAe,WAAW,SAAS;AAC7C,MAAI,CAAC,EAAG,QAAO;AACf,QAAM,QAAQ,UAAU,WAAW,EAAE,MAAM;AAC3C,SAAO,QAAQ,EAAC,OAAO,UAAU,EAAE,SAAQ,IAAI;AACjD;AAwBA,IAAM,kBAAN,cAA8B,MAAM;AAAA,EAClC,YAAY,MAAc,QAAgB;AACxC,UAAM,cAAc,IAAI,iBAAiB,MAAM,GAAG;AAAA,EACpD;AACF;AAQA,eAAe,QAAQ,MAAc,MAAc,UAAkB,QAA6C;AAChH,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,MAAM,GAAG,IAAI,GAAG,IAAI,IAAI;AAAA,MAClC,SAAS,EAAC,QAAQ,oBAAoB,eAAe,SAAQ;AAAA,MAC7D,OAAO;AAAA,MACP,QAAQ,cAAU,4BAAc,GAAI;AAAA,IACtC,CAAC;AAAA,EACH,SAAS,OAAO;AACd,QAAI,QAAQ,QAAS,OAAM;AAC3B,UAAM,IAAI,gBAAgB,MAAM,iBAAiB,QAAQ,MAAM,UAAU,cAAc;AAAA,EACzF;AACA,MAAI,IAAI,UAAU,OAAO,IAAI,WAAW,OAAO,IAAI,WAAW,KAAK;AACjE,UAAM,IAAI,gBAAgB,MAAM,QAAQ,IAAI,MAAM,EAAE;AAAA,EACtD;AACA,QAAM,OAAQ,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,IAAI;AAC/C,SAAO,EAAC,IAAI,IAAI,IAAI,QAAQ,IAAI,QAAQ,KAAI;AAC9C;AAGA,eAAe,YACb,MACA,QACA,OACA,UACyC;AACzC,aAAW,QAAQ,OAAO;AACxB,QAAI;AACF,YAAM,MAAM,MAAM,QAAQ,MAAM,MAAM,UAAU,MAAM;AACtD,UAAI,CAAC,IAAI,GAAI;AACb,aAAO,MAAM,QAAQ,IAAI,IAAI,IAAI,OAAO,IAAI;AAAA,IAC9C,SAAS,OAAO;AACd,UAAI,iBAAiB,gBAAiB;AACtC,YAAM;AAAA,IACR;AAAA,EACF;AACA,SAAO;AACT;AAeA,SAAS,kBAAkB,WAAmB,SAAqC,OAAgD;AACjI,QAAM,OAAO,SAAS;AACtB,MAAI,SAAS,WAAc,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,KAAK,aAAa,OAAO,IAAI,GAAI,QAAO;AAC7F,QAAM,MAAM,OAAO;AACnB,MAAI,QAAQ,WAAc,CAAC,QAAQ,KAAK,OAAO,GAAG,CAAC,KAAK,YAAY,OAAO,GAAG,GAAI,QAAO;AACzF,SAAO;AACT;AAIA,eAAe,mBAAmB,MAAc,UAA6C;AAC3F,QAAM,MAAM,MAAM,QAAQ,MAAM,gCAAgC,QAAQ;AACxE,MAAI,CAAC,IAAI,MAAM,CAAC,MAAM,QAAQ,IAAI,IAAI,EAAG,OAAM,IAAI,gBAAgB,MAAM,0BAA0B,IAAI,MAAM,EAAE;AAC/G,SAAO,IAAI;AACb;AAIA,eAAe,iBAAiB,OAAiB,UAAoD;AACnG,aAAW,QAAQ,OAAO;AACxB,QAAI;AACF,aAAO,MAAM,mBAAmB,MAAM,QAAQ;AAAA,IAChD,SAAS,OAAO;AACd,UAAI,iBAAiB,gBAAiB;AACtC,YAAM;AAAA,IACR;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,OAAO,OAA4C;AAC1D,SAAO,CAAC,SAAS,MAAM,WAAW,QAAQ,MAAM,0BAA0B,QAAQ,MAAM,yBAAyB;AACnH;AAEA,SAAS,WAAW,GAAuB,GAAgC;AACzE,MAAI,CAAC,KAAK,CAAC,EAAG,QAAO;AACrB,SAAO,EAAE,WAAW,IAAI,KAAK,EAAE,WAAW,IAAI,IAAI,EAAE,YAAY,MAAM,EAAE,YAAY,IAAI,MAAM;AAChG;AAEA,SAAS,aACP,MACA,eACA,qBACA,gBACA,mBACA,sBAC2C;AAC3C,MAAI,KAAK,SAAS,GAAG,EAAG,QAAO;AAC/B,QAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,MAAI,MAAM,WAAW,KAAK,MAAM,WAAW,EAAG,QAAO;AACrD,QAAM,CAAC,IAAI,OAAO,aAAa,OAAO,WAAW,GAAG,IAAI;AAKxD,MAAI,OAAO,OAAO,CAAC,SAAS,CAAC,sBAAsB,KAAK,KAAK,EAAG,QAAO;AACvE,QAAM,iBAAiB,iBAAiB,GAAG,mBAAmB,IAAI,cAAc,KAAK;AACrF,MAAI,CAAC,WAAW,aAAa,cAAc,EAAG,QAAO;AACrD,MAAI,MAAM,WAAW,GAAG;AACtB,QAAI,CAAC,qBAAqB,cAAc,qBAAqB,QAAQ,qBAAsB,QAAO;AAAA,EACpG,WAAW,qBAAqB,sBAAsB;AACpD,WAAO;AAAA,EACT;AACA,QAAM,UAAU,SAAS,IAAI,MAAM,GAAG;AAItC,MAAI,OAAO,WAAW,KAAK,OAAO,KAAK,CAAC,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC,EAAG,QAAO;AACxE,QAAM,QAAQ,OAAO,OAAO,CAAC,KAAK,GAAG;AACrC,MAAI,SAAS,GAAI,QAAO;AACxB,QAAM,YAAY,KAAK,aAAa,IAAI,cAAc,IAAI,OAAO,KAAK,GAAG,CAAC,GACxE,oBAAoB,IAAI,iBAAiB,IAAI,oBAAoB,KAAK,EACxE;AACA,SAAO,EAAC,OAAO,OAAO,UAAS;AACjC;AAEA,SAAS,gBAAgB,QAAgB,UAA0B;AACjE,QAAM,QAAQ,OAAO,OAAO,QAAQ;AACpC,UAAQ,SAAS,aAAe,QAAQ,MAAM;AAChD;AAwBO,SAAS,kBAAkB,SAAkC,CAAC,GAAuB;AAC1F,WAAS,OAAO,OAAO,EAAC,GAAG,OAAM,CAAC;AAClC,QAAM,mBAAmB,MAAM,QAAQ,OAAO,OAAO,IAAI,OAAO,WAAW,OAAO,WAAW,IAAI,MAAM,GAAG,GACvG,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO;AACjB,QAAM,QAAQ,CAAC,GAAG,IAAI,KAAK,gBAAgB,SAAS,kBAAkB,OAAO,IAAI,CAAC,MAAM;AACtF,QAAI;AACJ,QAAI;AACF,YAAM,IAAI,IAAI,CAAC;AAAA,IACjB,QAAQ;AACN,YAAM,IAAI,MAAM,oDAAoD;AAAA,IACtE;AACA,QAAI,IAAI,aAAa,YAAY,IAAI,aAAa,QAAS,OAAM,IAAI,MAAM,2CAA2C;AACtH,WAAO,IAAI,SAAS,EAAE,QAAQ,OAAO,EAAE;AAAA,EACzC,CAAC,CAAC,CAAC;AACH,QAAM,sBAAsB,OAAO,aAAa;AAChD,QAAM,yBAAyB,OAAO,gBAAgB;AACtD,MAAI,CAAC,CAAC,wBAAwB,CAAC,CAAC,wBAAwB;AACtD,UAAM,IAAI,MAAM,mEAAmE;AAAA,EACrF;AACA,MAAI,uBAAuB,CAAC,qBAAqB,KAAK,mBAAmB,GAAG;AAC1E,UAAM,IAAI,MAAM,2DAA2D;AAAA,EAC7E;AACA,MAAI,2BAA2B,CAAC,QAAQ,KAAK,sBAAsB,KAAK,OAAO,sBAAsB,IAAI,SAAU;AACjH,UAAM,IAAI,MAAM,gEAAgE;AAAA,EAClF;AACA,QAAM,WAAW,OAAO,UAAU,KAAK,KAAK;AAC5C,MAAI,CAAC,uBAAuB,KAAK,QAAQ,EAAG,OAAM,IAAI,MAAM,iEAAiE;AAC7H,QAAM,aAAa,OAAO,eAAe;AACzC,QAAM,kBAAkB,CAAC,UAA2B,cAAc,gBAAgB,IAAI,KAAK;AAC3F,SAAO;AAAA,IACL,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,SAAS,MAAM,OAAO,WAAW;AAAA;AAAA;AAAA,IAIjC,eAAe,CAAC,UAAkB,UAAQ,cAAc,KAAK;AAAA,IAC7D,mBAAmB,CAAC,WAAmB,YAAoB,UAAQ,SAAS,WAAW,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,IAK9F,cAAc,MAAa,IAAoB;AAC7C,YAAM,UAAUA,OAAM,KAAK,KAAK,KAAK,gBAAgB,KAAK,KAAK;AAC/D,UAAI,EAAE,WAAW,CAAC,CAAC,WAAW,KAAK,KAAK,KAAK,CAAC,CAAC,WAAW,GAAG,KAAK,KAAK,KAAK,UAAU,GAAG,OAAQ,QAAO;AAIxG,YAAM,YAAY,UAAU,KAAK,OAAO,KAAK,KAAK,KAAK,UAAU,KAAK,WAAO,oCAAe,KAAK,OAAO,KAAK,KAAK,GAAG,UAAU,EAAE;AACjI,YAAM,UAAU,UAAU,GAAG,OAAO,GAAG,KAAK,MAAM,UAAU,GAAG,OAAO,GAAG,KAAK,IAAI,EAAC,OAAO,UAAU,GAAG,OAAO,GAAG,KAAK,EAAE,IAAI;AAC5H,aAAO,CAAC,CAAC,aAAa,CAAC,CAAC,WAAW,cAAc,QAAQ;AAAA,IAC3D;AAAA,IAEA,MAAM,SAAS,QAAqB,QAA6C;AAC/E,UAAI,EAAE,OAAO,WAAW,MAAO,QAAO;AACtC,UAAI,OAAO,KAAM,QAAO;AACxB,YAAM,UAAU,SAAS,OAAO,WAAW;AAG3C,UAAI,CAAC,WAAW,CAAC,gBAAgB,OAAO,WAAW,EAAG,QAAO;AAC7D,UAAI,OAAO,gBAAgB,OAAO,UAAW,QAAO;AAEpD,YAAM,UAAM,6BAAQ,OAAO,aAAa,OAAO,WAAW;AAC1D,YAAM,YAAY,UAAU,OAAO,aAAa,OAAO,WAAW;AAClE,YAAM,MAAM,UAAU,OAAO,WAAW,OAAO,SAAS;AACxD,UAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,cAAc,IAAI,OAAO;AACzD,eAAO,YAAY,0BAA0B,OAAO,WAAW,OAAO,OAAO,WAAW,WAAM,OAAO,SAAS,OAAO,OAAO,SAAS,EAAE;AACvI,eAAO;AAAA,MACT;AAGA,YAAM,WAAW,OAAO,OAAO,QAAQ;AACvC,YAAM,YAAa,WAAW,aAAc,OAAO,OAAO,IAAI,QAAQ;AACtE,UAAI,aAAa,GAAI,QAAO;AAI5B,UAAI,YAAY,OAAO,OAAO,IAAI,QAAQ,MAAM,WAAW,YAAc;AACvE,eAAO,YAAY,gGAA2F;AAC9G,eAAO;AAAA,MACT;AAEA,YAAM,qBAAqB,OAAO,eAAe,OAAO,aAAa;AACrE,UAAI,CAAC,OAAO,UAAU,kBAAkB,KAAK,qBAAqB,KAAK,yBAAqB,4BAAe,iBAAiB,GAAG;AAC7H,eAAO,YAAY,uBAAuB,OAAO,OAAO,WAAW,CAAC,0BAAqB,iBAAiB,MAAM;AAChH,eAAO;AAAA,MACT;AAMA,YAAM,mBAAmB,OAAO,gBAAgB;AAChD,YAAM,eAAe,mBAAoB,IAAI,WAAW,IAAI,qBAAqB,IAAI,qBAAsB;AAC3G,YAAM,YAAY,eAAe,IAAI,4BAA4B;AAGjE,YAAM,UAAU,OACd,MACA,KACAC,aAAyD,oBACnB;AACtC,cAAM,KAAK,IAAI,gBAAgB;AAAA,UAC7B,YAAY;AAAA,UACZ,UAAU,IAAI;AAAA,UACd,QAAQ,UAAU,SAAS;AAAA,UAC3B,aAAa,OAAO;AAAA,UACpB,CAACA,UAAS,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAMb,oBAAoB;AAAA,QACtB,CAAC;AACD,YAAI,uBAAuB,wBAAwB;AACjD,aAAG,IAAI,aAAa,mBAAmB;AACvC,aAAG,IAAI,iBAAiB,sBAAsB;AAAA,QAChD;AACA,YAAI,OAAO,cAAe,IAAG,IAAI,kBAAkB,OAAO,aAAa;AACvE,cAAM,MAAM,MAAM,QAAQ,MAAM,yBAAyB,GAAG,SAAS,CAAC,IAAI,UAAU,MAAM;AAC1F,YAAI,MAAM,QAAQ,IAAI,IAAI,EAAG,QAAO;AAEpC,eAAQ,IAAI,SAAS,IAAI,KAAK,OAAO,EAAC,OAAO,QAAQ,IAAI,MAAM,GAAE;AAAA,MACnE;AAKA,UAAI,IAA8B;AAClC,UAAI,cAA+C;AACnD,UAAI,WAAoC;AACxC,iBAAW,QAAQ,OAAO;AACxB,YAAI;AACF,cAAI,cAAc,2BAA2B;AAC3C,gBAAI,MAAM,QAAQ,MAAM,OAAO,YAAY,GAAG,yBAAyB;AACvE,kBAAM,SAAS,OAAO,GAAG,MAAM,SAAS;AACxC,gBAAI,OAAO,SAAS,MAAM,KAAK,aAAS,4BAAe,iBAAiB,GAAG;AAEzE,qBAAO,YAAY,8BAA8B,SAAS,KAAK,QAAQ,CAAC,CAAC,kDAAyC,4BAAe,iBAAiB,IAAI,GAAG,IAAI;AAC7J,qBAAO;AAAA,YACT;AAAA,UACF,OAAO;AACL,gBAAI,MAAM,QAAQ,MAAM,OAAO,kBAAkB,CAAC;AAMlD,kBAAM,YAAY,GAAG,SAAS,GAAG,UAAU,MAAM,8CAA8C;AAC/F,gBAAI,YAAY,CAAC,kBAAkB;AACjC,oBAAM,OAAO,OAAO,SAAS,CAAC,KAAK,GAAG;AACtC,oBAAM,QAAQ,OAAO,SAAS,CAAC,KAAK,GAAG;AACvC,kBAAI,OAAO,MAAM,QAAQ,MAAM;AAE7B,sBAAM,OAAQ,QAAQ,UAAW,SAAS,OAAO,kBAAkB;AACnE,sBAAM,SAAS,SAAU,OAAO,SAAU,OAAO;AACjD,oBAAI,UAAU,kBAAmB,KAAI,MAAM,QAAQ,MAAM,OAAO,SAAS,CAAC;AAAA,cAC5E;AAAA,YACF;AAAA,UACF;AAGA,cAAI,GAAG,SAAS,GAAG,SAAS;AAG1B,mBAAO,YAAY,cAAc,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC,EAAE;AAC7E,mBAAO;AAAA,UACT;AACA,cAAI,CAAC,KAAK,CAAC,EAAE,uBAAuB,CAAC,EAAE,mBAAmB,CAAC,EAAE,QAAQ,CAAC,EAAE,QAAQ;AAC9E,mBAAO,YAAY,oCAAoC,IAAI,kEAAkE;AAC7H,mBAAO;AAAA,UACT;AAIA,cAAI,UAAU,CAAC,EAAE,SAAS,CAAC,CAAC,EAAE,QAAQ;AACpC,mBAAO,YAAY,UAAU,qDAAqD,qFAAgF;AAClK,mBAAO;AAAA,UACT;AACA,wBAAc,aAAa,EAAE,MAAM,IAAI,OAAO,OAAO,aAAa,OAAO,iBAAiB,IAAI,qBAAqB,sBAAsB;AACzI,cAAI,CAAC,aAAa;AAChB,mBAAO,YAAY,wCAAwC,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG;AACzF,mBAAO;AAAA,UACT;AACA,gBAAM,WAAW,OAAO,iBAAiB,SAAY,gBAAgB,OAAO,OAAO,YAAY,GAAG,IAAI,QAAQ,IAAI;AAClH,cAAI,aAAa,UAAa,YAAY,QAAQ,UAAU;AAC1D,mBAAO,YAAY,kCAAkC,YAAY,KAAK,YAAY,QAAQ,cAAc;AACxG,mBAAO;AAAA,UACT;AAIA,qBAAW,MAAM,mBAAmB,MAAM,QAAQ;AAClD;AAAA,QACF,SAAS,OAAO;AACd,cAAI,iBAAiB,iBAAiB;AACpC,gBAAI;AACJ,0BAAc;AACd,uBAAW;AACX;AAAA,UACF;AACA,gBAAM;AAAA,QACR;AAAA,MACF;AACA,UAAI,CAAC,GAAG,uBAAuB,CAAC,EAAE,mBAAmB,CAAC,EAAE,UAAU,CAAC,eAAe,CAAC,UAAU;AAC3F,eAAO,YAAY,CAAC,WAAW,6DAA6D,mCAAmC;AAC/H,eAAO;AAAA,MACT;AACA,YAAM,WAAW,YAAY;AAC7B,YAAM,aAAa,SAAS,KAAK,CAAC,UAAU,MAAM,UAAU,WAAW,OAAO,WAAW,CAAC;AAC1F,YAAM,aAAa,SAAS,KAAK,CAAC,UAAU,MAAM,UAAU,WAAW,OAAO,SAAS,CAAC;AACxF,UAAI,OAAO,UAAU,KAAK,OAAO,UAAU,GAAG;AAC5C,eAAO,YAAY,cAAc,OAAO,UAAU,IAAI,WAAW,OAAO,WAAW,IAAI,WAAW,OAAO,SAAS,CAAC,wCAAwC;AAC3J,eAAO;AAAA,MACT;AACA,UAAI,CAAC,WAAW,YAAY,SAAS,EAAE,eAAe,GAAG;AACvD,eAAO,YAAY,uGAAkG;AACrH,eAAO;AAAA,MACT;AACA,UAAI,WAAW,CAAC,WAAW,YAAY,QAAQ,EAAE,MAAM,GAAG;AACxD,eAAO,YAAY,6EAAwE;AAC3F,eAAO;AAAA,MACT;AACA,YAAM,WAAW,kBAAkB,WAAW,YAAY,CAAC;AAC3D,UAAI,UAAU;AACZ,eAAO,YAAY,cAAc,QAAQ,EAAE;AAC3C,eAAO;AAAA,MACT;AAGA,YAAM,WAAY,OAAO,EAAE,mBAAmB,IAAI,OAAO,OAAO,IAAI,QAAQ,IAAK;AACjF,UAAI,YAAY,IAAI;AAClB,eAAO,YAAY,2CAA2C;AAC9D,eAAO;AAAA,MACT;AACA,YAAM,eAAgB,WAAW,OAAO,OAAO,IAAI,QAAQ,IAAK;AAChE,YAAM,WAAW;AACjB,UAAI,YAAY,MAAM,WAAW,UAAU;AACzC,eAAO,YAAY,yBAAyB,QAAQ,sCAAsC,EAAE,mBAAmB,EAAE;AACjH,eAAO;AAAA,MACT;AAIA,UAAI,OAAO,gBAAgB,QAAW;AACpC,cAAM,gBAAiB,WAAW,OAAO,MAAS,OAAO,WAAW,IAAK;AACzE,YAAI,WAAW,eAAe;AAC5B,iBAAO,YAAY,yBAAyB,QAAQ,sBAAsB,EAAE,mBAAmB,UAAU,OAAO,WAAW,2BAA2B;AACtJ,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,YAAM,aAAa,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAC/C,YAAM,kBAAkB,KAAK,IAAI,EAAE,QAAQ,aAAa,KAAK,EAAE;AAC/D,UAAI,CAAC,OAAO,UAAU,eAAe,KAAK,mBAAmB,aAAa,IAAI;AAC5E,eAAO,YAAY,+BAA+B,OAAO,UAAU,eAAe,IAAI,kBAAkB,aAAa,GAAG,+BAA0B;AAClJ,eAAO;AAAA,MACT;AACA,YAAM,YAAa,IAAI,WAAW,IAAI,WAAW;AACjD,YAAM,SAAS;AAAA,QACb,UAAU;AAAA,QACV,UAAU,aAAa,WAAW,WAAW,OAAO,WAAW,CAAC;AAAA,QAChE,cAAc,OAAO;AAAA,QACrB,YAAY,SAAS,SAAS;AAAA,QAC9B,eAAe,SAAS,SAAS;AAAA,QACjC,QAAQ;AAAA;AAAA,QACR,YAAY,EAAE,sBAAsB;AAAA,QACpC,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOb,cAAc,KAAK,IAAI,KAAK,IAAI,IAAI,mBAAmB,kBAAkB,GAAI;AAAA,QAC7E,cAAc;AAAA,UACZ,aAAa,OAAO;AAAA,UACpB,WAAW,OAAO;AAAA,UAClB,gBAAgB,EAAE;AAAA,UAClB,QAAQ,EAAE,UAAU;AAAA,UACpB,cAAc;AAAA,UACd,QAAQ,OAAO,eAAe;AAAA,UAC9B,MAAM,YAAY;AAAA,QACpB;AAAA,MACF;AAIA,UAAI,CAAC,SAAS;AACZ,eAAO,EAAC,GAAG,QAAQ,gBAAgB,EAAE,iBAAiB,aAAa,YAAY,UAAS;AAAA,MAC1F;AAGA,YAAM,WAAO,gCAAmB;AAAA,QAC9B,KAAK;AAAA,QACL,cAAc;AAAA,QACd,MAAM,CAAC,EAAE,iBAAkC,WAAW,UAAU,YAAY,WAAW,OAAO,eAAe,CAAC;AAAA,MAChH,CAAC;AACD,aAAO;AAAA,QACL,GAAG;AAAA,QACH,gBAAgB;AAAA,QAChB,aAAa;AAAA,QACb,WAAW;AAAA,UACT,IAAI,EAAE;AAAA,UACN;AAAA,UACA,OAAO,IAAI,WAAW,MAAM,OAAO;AAAA,UACnC;AAAA,UACA,GAAI,IAAI,WAAW,EAAC,iBAAiB,EAAE,OAAO,IAAI,CAAC;AAAA,QACrD;AAAA,MACF;AAAA,IACF;AAAA,IAEA,MAAM,aAAa,OAAmC;AACpD,UAAI,CAAC,MAAM,WAAW;AACpB,cAAM,cAAc,MAAM,cAAc,eAAe;AACvD,YAAI,CAAC,gBAAgB,WAAW,KAAK,CAAC,MAAM,kBAAkB,CAAC,MAAM,aAAa;AAChF,gBAAM,IAAI,MAAM,oFAAoF;AAAA,QACtG;AAGA,eAAO,EAAC,OAAO,aAAa,IAAI,MAAM,gBAAgB,OAAO,MAAM,cAAc,MAAM,MAAM,YAAW;AAAA,MAC1G;AACA,aAAO;AAAA,QACL,OAAO;AAAA,QACP,IAAI,MAAM,WAAW,MAAM;AAAA,QAC3B,OAAO,MAAM,WAAW,SAAS;AAAA,QACjC,GAAI,MAAM,WAAW,OAAO,EAAC,MAAM,MAAM,UAAU,KAAI,IAAI,CAAC;AAAA,QAC5D,GAAI,MAAM,WAAW,YAAY,SAAY,EAAC,SAAS,MAAM,UAAU,QAAO,IAAI,CAAC;AAAA,QACnF,GAAI,MAAM,WAAW,WAAW,EAAC,UAAU,MAAM,UAAU,SAAQ,IAAI,CAAC;AAAA,QACxE,GAAI,MAAM,WAAW,kBAAkB,EAAC,iBAAiB,MAAM,UAAU,gBAAe,IAAI,CAAC;AAAA,MAC/F;AAAA,IACF;AAAA,IAEA,MAAM,iBAAiB,OAAc,IAA+B;AAClE,YAAM,OAAO,MAAM;AACnB,UAAI,CAAC,MAAM,eAAe,CAAC,KAAK,aAAa,CAAC,KAAK,kBAAkB,CAAC,KAAK,gBAAgB,CAAC,KAAK,UAAU,CAAC,KAAK,MAAM;AACrH,cAAM,IAAI,MAAM,sDAAsD;AAAA,MACxE;AACA,YAAM,YAAY,SAAS,KAAK,WAAW,MAAM;AACjD,UAAI,aAAa,CAAC,KAAK,OAAQ,OAAM,IAAI,MAAM,sDAAsD;AACrG,UAAI,CAAC,aAAa,CAAC,gBAAgB,KAAK,WAAW,EAAG,OAAM,IAAI,MAAM,yCAAyC;AAC/G,UAAI,CAAC,QAAQ,KAAK,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,CAAC,GAAG;AAC9F,cAAM,IAAI,MAAM,2CAA2C;AAAA,MAC7D;AACA,YAAM,WAAW,MAAM,iBAAiB,OAAO,QAAQ;AACvD,UAAI,CAAC,SAAU,OAAM,IAAI,MAAM,8DAA8D;AAC7F,YAAM,MAAM,SAAS,KAAK,CAAC,UAAU,MAAM,UAAU,WAAW,KAAK,WAAY,CAAC;AAClF,YAAM,MAAM,SAAS,KAAK,CAAC,UAAU,MAAM,UAAU,WAAW,KAAK,SAAU,CAAC;AAChF,UAAI,OAAO,GAAG,KAAK,OAAO,GAAG,EAAG,OAAM,IAAI,MAAM,0DAA0D;AAC1G,UAAI,CAAC,WAAW,KAAK,SAAS,KAAK,cAAc,EAAG,OAAM,IAAI,MAAM,8CAA8C;AAClH,UAAI,CAAC,WAAW;AAGd,YAAI,GAAG,SAAS,UAAa,GAAG,oBAAoB,UAAa,GAAG,YAAY,UAAa,GAAG,cAAc,UAAa,GAAG,iBAAiB,UAAa,GAAG,iBAAiB,QAAW;AACzL,gBAAM,IAAI,MAAM,qEAAqE;AAAA,QACvF;AACA,YAAI,CAAC,WAAW,GAAG,IAAI,KAAK,cAAc,KAAK,GAAG,SAAS,KAAK,QAAQ,GAAG,UAAU,MAAM,gBAAiB,GAAG,SAAS,GAAG,UAAU,KAAK,aAAc;AACtJ,gBAAM,IAAI,MAAM,uDAAuD;AAAA,QACzE;AACA,cAAM,eAAW,oCAAe,KAAK,aAAa,WAAW,KAAK,cAAc,MAAM,IAAI,KAAK,KAAK,YAAY;AAChH,YAAI,CAAC,SAAU,OAAM,IAAI,MAAM,iCAAiC;AAChE,cAAM,YAAa,OAAO,MAAM,YAAY,IAAI,aAAgB,OAAO,OAAO,SAAS,QAAQ;AAC/F,cAAM,WAAW,kBAAkB,WAAW,KAAK,IAAI;AACvD,YAAI,SAAU,OAAM,IAAI,MAAM,cAAc,QAAQ,EAAE;AACtD;AAAA,MACF;AACA,UAAI,CAAC,WAAW,KAAK,QAAQ,KAAK,MAAM,KAAK,CAAC,WAAW,GAAG,IAAI,KAAK,MAAM,GAAG;AAC5E,cAAM,IAAI,MAAM,uCAAuC;AAAA,MACzD;AACA,UAAI,CAAC,GAAG,KAAM,OAAM,IAAI,MAAM,+CAA+C;AAC7E,UAAI;AACJ,UAAI;AACF,sBAAU,gCAAmB,EAAC,KAAK,YAAY,MAAM,GAAG,KAAqB,CAAC;AAAA,MAChF,QAAQ;AACN,cAAM,IAAI,MAAM,iDAAiD;AAAA,MACnE;AACA,YAAM,OAAO,QAAQ;AACrB,UACE,QAAQ,iBAAiB,uBAAuB,CAAC,QAAQ,KAAK,WAAW,KACzE,CAAC,WAAW,OAAO,KAAK,CAAC,CAAC,GAAG,KAAK,cAAc,KAChD,CAAC,WAAW,OAAO,KAAK,CAAC,CAAC,GAAG,KAAK,YAAY,KAC9C,OAAO,KAAK,CAAC,CAAW,MAAM,OAAO,MAAM,YAAY,KACvD,OAAO,KAAK,CAAC,CAAC,MAAM,KAAK,QAAQ,OAAO,KAAK,CAAC,CAAW,MAAM,OAAO,KAAK,MAAM,KACjF,GAAG,YAAY,SAAS,KAAK,WAAW,GACxC;AACA,cAAM,IAAI,MAAM,wDAAwD;AAAA,MAC1E;AACA,YAAM,cAAc,CAAC,WAAW,KAAK,cAAc,MAAM;AACzD,UACE,GAAG,WAAW,cAAc,MAAM,MAAM,kBACvC,cAAc,CAAC,WAAW,GAAG,iBAAiB,KAAK,MAAM,IAAI,GAAG,oBAAoB,SACrF;AACA,cAAM,IAAI,MAAM,qEAAqE;AAAA,MACvF;AAAA,IACF;AAAA,IAEA,MAAM,YAAY,KAAuC;AACvD,UAAI,CAAC,IAAI,aAAc,QAAO,EAAC,OAAO,UAAS;AAE/C,UAAI,CAAC,2BAA2B,KAAK,IAAI,YAAY,GAAG;AACtD,cAAM,IAAI,MAAM,wDAAwD;AAAA,MAC1E;AACA,YAAM,OAAO,IAAI,aAAa,QAAQ,QAAQ,EAAE,EAAE,YAAY;AAC9D,YAAM,IAAI,MAAM,YAAY,wBAAwB,IAAI,IAAI,QAAW,OAAO,QAAQ,KACpF,MAAM,YAAY,iBAAiB,IAAI,IAAI,QAAW,OAAO,QAAQ;AACvE,UAAI,CAAC,EAAG,QAAO,EAAC,OAAO,UAAS;AAChC,YAAM,SAAS,EAAE;AAKjB,UAAI,QAAQ;AACV,cAAM,UAAW,EAAE,mBAAmB,CAAC;AACvC,cAAM,WAAW,QAAQ,KAAK,CAAC,QAAQ,IAAI,WAAW,IAAI;AAC1D,cAAM,YAAY,QAAQ,KAAK,CAAC,QAAQ,IAAI,WAAW,KAAK;AAC5D,cAAM,SAAU,EAAE,WAAW,CAAC;AAC9B,cAAMC,WAAU,OAAO,KAAK,CAAC,QAAQ,OAAO,IAAI,OAAO,YAAY,IAAI,GAAG,SAAS,KAAK,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC,GAAG;AAC/G,cAAM,gBAAgB,OAAO;AAAA,UAAK,CAAC,QACjC,OAAO,IAAI,OAAO,YAAY,IAAI,GAAG,SAAS,KAAK,CAAC,OAAO,KAAK,IAAI,EAAE,KAAK,OAAO,IAAI,SAAS,YAAY,CAAC,WAAW,KAAK,IAAI,IAAI;AAAA,QACtI,GAAG;AACH,YAAI,OAAO,iBAAiB,WAAW;AAIrC,cAAK,CAAC,YAAY,CAAC,aAAc,CAACA,UAAS;AACzC,mBAAO,EAAC,OAAO,WAAW,iBAAiB,KAAI;AAAA,UACjD;AACA,iBAAO,YAAY,YAGf,EAAC,OAAO,WAAW,iBAAiB,MAAM,GAAI,gBAAgB,EAAC,YAAY,cAAa,IAAI,CAAC,EAAE,IAC/F,WACA,EAAC,OAAO,YAAY,iBAAiB,KAAI,IACzC,EAAC,OAAO,aAAa,iBAAiB,MAAM,GAAIA,WAAU,EAAC,YAAYA,SAAO,IAAI,CAAC,EAAE;AAAA,QAC3F;AACA,eAAO;AAAA,UACL,OAAO;AAAA,UACP,iBAAiB,CAAC,EAAE,OAAO,kBAAkB,WAAW,OAAO,kBAAkB,aAAa,OAAO,mBAAmB;AAAA,QAC1H;AAAA,MACF;AACA,YAAM,MAAM,EAAE;AACd,YAAM,UAAU,KAAK,YAAY,KAAK,CAAC,MAAM,OAAO,MAAM,YAAY,EAAE,SAAS,KAAK,CAAC,OAAO,KAAK,CAAC,CAAC;AACrG,UAAI,KAAK,WAAW,QAAQ;AAI1B,cAAM,UAAW,EAAE,mBAAmB,EAAE,WAAW,CAAC;AACpD,cAAM,WAAW,QAAQ;AAAA,UACvB,CAAC,MAAM,GAAG,WAAW,QAAQ,WAAW,KAAK,GAAG,QAAQ,EAAE;AAAA,QAC5D;AACA,cAAM,YAAY,QAAQ;AAAA,UACxB,CAAC,MAAM,GAAG,WAAW,SAAS,CAAC,WAAW,KAAK,GAAG,QAAQ,EAAE;AAAA,QAC9D;AACA,YAAK,CAAC,YAAY,CAAC,aAAc,CAAC,QAAS,QAAO,EAAC,OAAO,WAAW,iBAAiB,KAAI;AAC1F,YAAI,YAAY,UAAW,QAAO,EAAC,OAAO,WAAW,iBAAiB,KAAI;AAC1E,YAAI,SAAU,QAAO,EAAC,OAAO,YAAY,iBAAiB,KAAI;AAC9D,eAAO,EAAC,OAAO,aAAa,GAAI,UAAU,EAAC,YAAY,QAAO,IAAI,CAAC,EAAE;AAAA,MACvE;AACA,aAAO,EAAC,OAAO,WAAW,iBAAiB,CAAC,CAAC,IAAG;AAAA,IAClD;AAAA,EACF;AACF;;;AC7yBA,oBAAkC;AAO3B,IAAM,yBAAN,cAAqC,kCAAoB;AAAA,EAC3C;AAAA,EACnB,YAAY,SAAmC,QAA8B;AAC3E,UAAM,SAAS,MAAM;AACrB,SAAK,WAAW,kBAAkB,MAAM;AAAA,EAC1C;AAAA,EACmB,eAAe,OAAwB;AACxD,WAAO,UAAa,cAAc,KAAK;AAAA,EACzC;AAAA,EACmB,cAAc,WAAmB,SAA0B;AAC5E,WAAO,KAAK,SAAS,cAAc,EAAC,OAAO,WAAW,OAAO,GAAE,GAAG,EAAC,OAAO,SAAS,OAAO,GAAE,CAAC;AAAA,EAC/F;AACF;","names":["import_util","isEvm","limitMode","outHash"]}
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { thorchain } from './config.cjs';
2
2
  export { ThorchainProviderConfig, thorchainProvider } from './provider.cjs';
3
- export { ThorchainSwap2Protocol, ThorchainSwap2Protocol as default } from './protocol.cjs';
3
+ export { ThorchainSwap2Config, ThorchainSwap2Protocol, ThorchainSwap2Protocol as default } from './protocol.cjs';
4
4
  export { THORCHAIN_DEPOSIT_WITH_EXPIRY, THORCHAIN_MODULE, THORCHAIN_TRANSFER_OUT, THORCHAIN_TRANSFER_OUT_AND_CALL, describeThorchainActivity } from './activity.cjs';
5
5
  import '@anywalletkit/protocol-swap2-core/types';
6
6
  import '@anywalletkit/protocol-swap2-core/swap2/single';
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { thorchain } from './config.js';
2
2
  export { ThorchainProviderConfig, thorchainProvider } from './provider.js';
3
- export { ThorchainSwap2Protocol, ThorchainSwap2Protocol as default } from './protocol.js';
3
+ export { ThorchainSwap2Config, ThorchainSwap2Protocol, ThorchainSwap2Protocol as default } from './protocol.js';
4
4
  export { THORCHAIN_DEPOSIT_WITH_EXPIRY, THORCHAIN_MODULE, THORCHAIN_TRANSFER_OUT, THORCHAIN_TRANSFER_OUT_AND_CALL, describeThorchainActivity } from './activity.js';
5
5
  import '@anywalletkit/protocol-swap2-core/types';
6
6
  import '@anywalletkit/protocol-swap2-core/swap2/single';
@@ -1,6 +1,6 @@
1
1
  import * as _anywalletkit_protocol_swap2_core_types from '@anywalletkit/protocol-swap2-core/types';
2
2
  import { SingleProviderSwap2 } from '@anywalletkit/protocol-swap2-core/swap2/single';
3
- import { Swap2Account, Swap2EngineConfig } from '@anywalletkit/protocol-swap2-core/swap2/base';
3
+ import { Swap2EngineConfig, Swap2Account } from '@anywalletkit/protocol-swap2-core/swap2/base';
4
4
  import { ThorchainProviderConfig } from './provider.cjs';
5
5
 
6
6
  interface ThorchainSwap2Config extends Swap2EngineConfig, ThorchainProviderConfig {
@@ -1,6 +1,6 @@
1
1
  import * as _anywalletkit_protocol_swap2_core_types from '@anywalletkit/protocol-swap2-core/types';
2
2
  import { SingleProviderSwap2 } from '@anywalletkit/protocol-swap2-core/swap2/single';
3
- import { Swap2Account, Swap2EngineConfig } from '@anywalletkit/protocol-swap2-core/swap2/base';
3
+ import { Swap2EngineConfig, Swap2Account } from '@anywalletkit/protocol-swap2-core/swap2/base';
4
4
  import { ThorchainProviderConfig } from './provider.js';
5
5
 
6
6
  interface ThorchainSwap2Config extends Swap2EngineConfig, ThorchainProviderConfig {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@anywalletkit/protocol-swap2-thorchain",
3
- "version": "0.1.8",
4
- "description": "",
3
+ "version": "0.1.9",
4
+ "description": "THORChain native cross-chain swaps for Any Wallet Kit: EVM deposits into the THORChain router and Tron sends to the inbound vault with a memo; standalone or as a provider of the swap2 router.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://docs.anywallet.tech",
7
7
  "bugs": {
@@ -50,19 +50,27 @@
50
50
  ],
51
51
  "dependencies": {
52
52
  "viem": "^2.45.0",
53
- "@anywalletkit/swap2-assets": "0.2.1",
54
- "@anywalletkit/protocol-swap2-core": "0.6.0"
53
+ "@anywalletkit/protocol-swap2-core": "0.6.1",
54
+ "@anywalletkit/swap2-assets": "0.2.2"
55
55
  },
56
56
  "peerDependencies": {
57
- "@anywalletkit/core": "0.6.0"
57
+ "@anywalletkit/core": "0.6.1"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@types/node": "^22",
61
61
  "vitest": "^5.0.3",
62
- "@anywalletkit/conformance": "0.4.3",
63
- "@anywalletkit/core": "0.6.0"
62
+ "@anywalletkit/conformance": "0.4.4",
63
+ "@anywalletkit/core": "0.6.1"
64
64
  },
65
- "keywords": [],
65
+ "keywords": [
66
+ "swap2",
67
+ "swap",
68
+ "thorchain",
69
+ "cross-chain",
70
+ "evm",
71
+ "tron",
72
+ "anywalletkit"
73
+ ],
66
74
  "publishConfig": {
67
75
  "access": "public",
68
76
  "provenance": true