@anywalletkit/protocol-swap2-lifi 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anywalletkit/protocol-swap2-lifi",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://docs.anywallet.tech",
@@ -13,6 +13,9 @@
13
13
  "directory": "packages/protocol-swap2-lifi"
14
14
  },
15
15
  "type": "module",
16
+ "engines": {
17
+ "node": ">=20"
18
+ },
16
19
  "sideEffects": false,
17
20
  "main": "./dist/index.cjs",
18
21
  "module": "./dist/index.js",
@@ -46,17 +49,17 @@
46
49
  "module.json"
47
50
  ],
48
51
  "dependencies": {
49
- "@anywalletkit/protocol-swap2-core": "0.3.1",
50
- "@anywalletkit/swap2-assets": "0.1.3"
52
+ "@anywalletkit/swap2-assets": "0.1.5",
53
+ "@anywalletkit/protocol-swap2-core": "0.4.0"
51
54
  },
52
55
  "peerDependencies": {
53
- "@anywalletkit/core": "0.3.1"
56
+ "@anywalletkit/core": "0.4.0"
54
57
  },
55
58
  "devDependencies": {
56
59
  "@types/node": "^22",
57
60
  "vitest": "^5.0.3",
58
- "@anywalletkit/conformance": "0.3.1",
59
- "@anywalletkit/core": "0.3.1"
61
+ "@anywalletkit/conformance": "0.4.0",
62
+ "@anywalletkit/core": "0.4.0"
60
63
  },
61
64
  "keywords": [],
62
65
  "publishConfig": {
@@ -67,6 +70,6 @@
67
70
  "build": "tsup",
68
71
  "typecheck": "tsc --noEmit",
69
72
  "test": "vitest run",
70
- "lint": "echo ok"
73
+ "lint": "eslint src"
71
74
  }
72
75
  }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/provider.ts"],"sourcesContent":["import {LIFI_SOLANA_CAIP2, lifi as lifiCfg} from \"./config.js\";\nimport {describeLifiActivity} from \"./activity.js\";\nimport {ccAsset} from \"@anywalletkit/swap2-assets\";\nimport {timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\n\n/**\n * LI.FI meta-aggregator — the CALLDATA execution model: the quote returns a\n * `transactionRequest` the USER'S WALLET must execute. There is no deposit\n * address — a plain transfer to `transactionRequest.to` would lose funds, so\n * the client branches on `quote.txRequest`. Live-verified shapes (2026-07):\n * EVM → {to, data, value, chainId, gasLimit}; Solana → {data: base64 tx}, a\n * fully built v0 transaction (Jupiter route) the account signs after proving\n * its balance effects (`serializedTx`). Tron returns a raw protobuf we can't\n * hand to wallets yet — Tron stays on the direct NEAR Intents route (LI.FI\n * routes it through NEAR anyway, so nothing is lost).\n */\n\nconst DEFAULT_LIFI_BASE = \"https://li.quest/v1\";\n\n/** Our CAIP-2 → LI.FI chain ids. */\nconst LIFI_CHAIN: Record<string, string> = {\n \"eip155:1\": \"1\",\n \"eip155:8453\": \"8453\",\n \"eip155:56\": \"56\",\n \"eip155:137\": \"137\",\n \"eip155:42161\": \"42161\",\n \"eip155:10\": \"10\",\n \"eip155:100\": \"100\",\n \"eip155:143\": \"143\",\n \"eip155:130\": \"130\",\n \"eip155:999\": \"999\",\n \"eip155:4663\": \"4663\",\n // 2026-08 sweep additions (all live on li.quest/v1/chains).\n \"eip155:43114\": \"43114\",\n \"eip155:534352\": \"534352\",\n \"eip155:80094\": \"80094\",\n // 2026-10-12: zkSync Era, Celo, MegaETH (live on li.quest/v1/chains).\n \"eip155:324\": \"324\",\n \"eip155:42220\": \"42220\",\n \"eip155:4326\": \"4326\",\n \"eip155:9745\": \"9745\",\n \"eip155:59144\": \"59144\",\n \"eip155:146\": \"146\",\n // 2026-10-13: World Chain, Sei, Ink, Plume, X Layer (live on li.quest/v1/chains).\n \"eip155:480\": \"480\",\n \"eip155:1329\": \"1329\",\n \"eip155:57073\": \"57073\",\n \"eip155:98866\": \"98866\",\n \"eip155:196\": \"196\",\n // 2026-10-14: Arc, Mantle, Katana, Morph, Flare (live on li.quest/v1/chains). On Arc LI.FI's \"native\" is the USDC\n // ERC-20 interface 0x3600…: a 0x0 fromToken is rewritten to it and the Diamond pulls via transferFrom (value 0), so\n // the catalog lists Arc USDC as that token — the engine then runs the ordinary approve + call path.\n \"eip155:5042\": \"5042\",\n \"eip155:5000\": \"5000\",\n \"eip155:747474\": \"747474\",\n \"eip155:2818\": \"2818\",\n \"eip155:14\": \"14\",\n [LIFI_SOLANA_CAIP2]: \"1151111081099710\",\n};\nconst CAIP2_BY_LIFI_CHAIN: Record<string, string> = Object.fromEntries(Object.entries(LIFI_CHAIN).map(([caip2, id]) => [id, caip2]));\n\nconst EVM_ZERO = \"0x0000000000000000000000000000000000000000\";\n/** LI.FI's native-SOL token id (the System program address). */\nconst SOLANA_NATIVE = \"11111111111111111111111111111111\";\nconst EVM_PLACEHOLDER = \"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\";\n/** Dry-quote sender on Solana: the publicly known BIP-39 \"abandon\" account 0. */\nconst SOLANA_PLACEHOLDER = \"HAgk14JpMQLgt6rVgv7cBQFJWFto5Dqxi472uT3DKpqk\";\nconst isSolana = (chain: string) => chain === LIFI_SOLANA_CAIP2;\nconst BASE58 = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;\nconst BASE64 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;\n/** Chain-aware address equality: EVM case-insensitive, Solana exact base58. */\n/** Longest execution a same-chain route may claim and still be an atomic swap (DEX routes report 0–30 s). */\nconst SAME_CHAIN_MAX_SECONDS = 90;\n/** Largest fee a bridge may take from the input itself (glacis ≈ 0.25 %, 2026-10). Above it the quote is refused, named. */\nconst MAX_INPUT_FEE_BPS = 300;\n\nfunction sameChainAddress(chain: string, actual: string | undefined, expected: string): boolean {\n if (isSolana(chain)) return !!actual && BASE58.test(actual) && actual === expected;\n return sameAddress(actual, expected);\n}\n/** The engine's native sentinel (`0x0…`) in the chain's own notation. */\nfunction nativeFor(chain: string, token: string): string {\n if (/^0x0+$/.test(token) || token === SOLANA_NATIVE) return isSolana(chain) ? SOLANA_NATIVE : EVM_ZERO;\n return token;\n}\n/** LI.FI's documented Diamond entry point on most supported EVM networks. */\nconst LIFI_DIAMOND = \"0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE\";\n/**\n * Chains where the Diamond lives at a different address — from\n * github.com/lifinance/contracts `deployments/<chain>.json` (`LiFiDiamond`).\n * On these chains ONLY that address is the entry point; the canonical one is\n * not deployed there and is therefore not trusted.\n */\nconst LIFI_DIAMONDS: Readonly<Record<string, string>> = {\n \"eip155:4663\": \"0xB477751B76CF82d00a686A1232f5fCD772414Af3\", // Robinhood Chain (deployments/robinhood.json, verified 2026-10-09)\n \"eip155:999\": \"0x0a0758d937d1059c356D4714e57F5df0239bce1A\", // HyperEVM (deployments/hyperevm.json, verified 2026-10-09)\n \"eip155:143\": \"0x026F252016A7C47CDEf1F05a3Fc9E20C92a49C37\", // Monad (deployments/monad.json, verified 2026-10-11)\n \"eip155:130\": \"0x864b314D4C5a0399368609581d3E8933a63b9232\", // Unichain (deployments/unichain.json, verified 2026-10-11)\n \"eip155:80094\": \"0xf909c4Ae16622898b885B89d7F839E0244851c66\", // Berachain (deployments/berachain.json, verified 2026-10-11)\n \"eip155:324\": \"0x341e94069f53234fE6DabeF707aD424830525715\", // zkSync Era (deployments/zksync.json, matches a live quote 2026-10-12)\n \"eip155:9745\": \"0x026F252016A7C47CDEf1F05a3Fc9E20C92a49C37\", // Plasma (deployments/plasma.json, 2026-10-13)\n \"eip155:59144\": \"0xDE1E598b81620773454588B85D6b5D4eEC32573e\", // Linea (deployments/linea.json, 2026-10-13)\n \"eip155:57073\": \"0x864b314D4C5a0399368609581d3E8933a63b9232\", // Ink (deployments/ink.json, 2026-10-13)\n \"eip155:98866\": \"0x6f5C8Bb0C5Fe4ECeAC40EE1C238EaB6bbb29761c\", // Plume (deployments/plume.json, 2026-10-13)\n // 2026-10-14: li.quest/v1/chains `diamondAddress`, eth_getCode non-empty on each. Mantle and Flare carry the canonical\n // 0x1231… Diamond (the default).\n \"eip155:5042\": \"0xA4072583658Fae592A3506A42431cb6316a8d40b\", // Arc\n \"eip155:747474\": \"0xC59fe32C9549e3E8B5dCcdAbC45BD287Bd5bA2bc\", // Katana\n \"eip155:2818\": \"0xF7aB42D00D2399f8A4Fba2F15466Be40709fe307\", // Morph\n \"eip155:14\": \"0x198FC70Dfe05E755C81e54bd67Bff3F729344B9b\", // Flare (li.quest diamondAddress 2026-10-14; the canonical 0x1231… has no code there)\n \"eip155:4326\": \"0x026F252016A7C47CDEf1F05a3Fc9E20C92a49C37\", // MegaETH (deployments/megaeth.json, matches a live quote 2026-10-12)\n};\nconst diamondFor = (chain: string): string => LIFI_DIAMONDS[chain] ?? LIFI_DIAMOND;\nconst DEFAULT_QUOTE_TTL_MS = 55_000;\n\nfunction normalizeAddress(value: string | undefined): string | null {\n return value && /^0x[0-9a-fA-F]{40}$/.test(value) ? value.toLowerCase() : null;\n}\n\nfunction sameAddress(actual: string | undefined, expected: string): boolean {\n return normalizeAddress(actual) === normalizeAddress(expected);\n}\n\nfunction isHexData(value: string | undefined): value is string {\n return !!value && /^0x(?:[0-9a-fA-F]{2})+$/.test(value);\n}\n\nfunction trustedAddress(\n chain: string,\n address: string | undefined,\n configured: ReadonlyMap<string, ReadonlySet<string>>,\n): boolean {\n const normalized = normalizeAddress(address);\n if (!normalized) return false;\n return normalizeAddress(diamondFor(chain)) === normalized || configured.get(chain)?.has(normalized) === true;\n}\n\nfunction trustMap(input: Readonly<Record<string, readonly string[]>> | undefined, label: string): ReadonlyMap<string, ReadonlySet<string>> {\n const out = new Map<string, ReadonlySet<string>>();\n for (const [chain, addresses] of Object.entries(input ?? {})) {\n const normalized = new Set<string>();\n for (const address of addresses) {\n const value = normalizeAddress(address);\n if (!value) throw new Error(`lifi: invalid ${label} address for ${chain}`);\n normalized.add(value);\n }\n out.set(chain, normalized);\n }\n return out;\n}\n\n/** LI.FI token id on the source chain: contract, or the chain's native id. */\nfunction lifiToken(sourceChain: string, symbol: string): string | null {\n const asset = ccAsset(sourceChain, symbol);\n if (!asset) return null;\n if (asset.contract) return asset.contract;\n return isSolana(sourceChain) ? SOLANA_NATIVE : EVM_ZERO;\n}\n\nfunction headers(key: string | undefined): Record<string, string> {\n const h: Record<string, string> = {accept: \"application/json\"};\n if (key) h[\"x-lifi-api-key\"] = key;\n return h;\n}\n\n/** Explicit constructor configuration; no deployment environment is read. */\nexport interface LifiProviderConfig {\n enabled?: boolean;\n /** LI.FI REST base URL. Explicitly injectable for proxies and tests. */\n apiUrl?: string;\n apiKey?: string;\n integrator?: string;\n /** Additional audited LI.FI entry points for networks whose Diamond differs. */\n trustedTransactionTargets?: Readonly<Record<string, readonly string[]>>;\n /** Additional audited ERC-20 spenders returned by LI.FI for direct routes. */\n trustedApprovalAddresses?: Readonly<Record<string, readonly string[]>>;\n /** Fail-closed local lifetime for the provider's documented ~60s quote window. */\n quoteTtlMs?: number;\n /**\n * Slippage sent when the caller names none (bps, default 50 = LI.FI's own\n * documented default). Left unset, LI.FI picks it per request and it swings\n * (0.9%–6% within a minute on Base ETH → Robinhood, 2026-10-12): the display\n * quote's minimum then sits above the live one and the execution floor\n * refuses a route that hasn't moved.\n */\n defaultSlippageBps?: number;\n /**\n * Route policy hook. When set, a cross-chain quote first asks LI.FI's\n * `/advanced/routes` for the candidates, hands them to this function and\n * restricts `/quote` to what it returns (allowBridges / denyBridges /\n * order). Returning null/undefined, or any failure of the routes call,\n * leaves LI.FI's default pick. The policy itself (tie band, max ETA, deny\n * list) belongs to the app; the module only carries the choice.\n */\n chooseRoute?: (routes: readonly LifiRouteOption[], params: QuoteParams) => LifiRouteChoice | null | undefined;\n}\n\n/** One single-transaction candidate from `/advanced/routes`, as a route policy sees it. */\nexport interface LifiRouteOption {\n /** LI.FI tool key of the bridge the route crosses with (e.g. \"stargateV2\"); a same-chain route carries its swap tool. */\n tool: string;\n toAmount: bigint;\n toAmountMin: bigint;\n /** LI.FI's execution-duration estimate, seconds. */\n etaSeconds: number;\n gasCostUsd: number;\n /** LI.FI's own labels: RECOMMENDED, CHEAPEST, FASTEST, … */\n tags: readonly string[];\n}\n\n/** What `/quote` is restricted to. LI.FI tool keys; an empty choice means LI.FI's default. */\nexport interface LifiRouteChoice {\n allowBridges?: readonly string[];\n denyBridges?: readonly string[];\n order?: \"CHEAPEST\" | \"FASTEST\";\n}\n\nconst TOOL_KEY = /^[A-Za-z0-9_-]{1,64}$/;\n\nfunction routeOptions(body: unknown): LifiRouteOption[] {\n const routes = (body as {routes?: unknown})?.routes;\n if (!Array.isArray(routes)) return [];\n const out: LifiRouteOption[] = [];\n for (const r of routes as {toAmount?: unknown; toAmountMin?: unknown; gasCostUSD?: unknown; containsSwitchChain?: unknown; tags?: unknown; steps?: {tool?: unknown; estimate?: {executionDuration?: unknown}; includedSteps?: {tool?: unknown; type?: unknown}[]}[]}[]) {\n // The engine executes one source transaction: multi-step routes are not candidates.\n if (!Array.isArray(r?.steps) || r.steps.length !== 1 || r.containsSwitchChain === true) continue;\n const step = r.steps[0]!;\n const cross = Array.isArray(step.includedSteps) ? step.includedSteps.find((i) => i?.type === \"cross\")?.tool : undefined;\n const tool = typeof cross === \"string\" ? cross : step.tool;\n const eta = step.estimate?.executionDuration;\n if (typeof tool !== \"string\" || !TOOL_KEY.test(tool) || typeof eta !== \"number\" || !Number.isFinite(eta) || eta < 0) continue;\n if (typeof r.toAmount !== \"string\" || typeof r.toAmountMin !== \"string\" || !/^\\d{1,60}$/.test(r.toAmount) || !/^\\d{1,60}$/.test(r.toAmountMin)) continue;\n out.push({\n tool,\n toAmount: BigInt(r.toAmount),\n toAmountMin: BigInt(r.toAmountMin),\n etaSeconds: eta,\n gasCostUsd: Number(r.gasCostUSD ?? 0) || 0,\n tags: Array.isArray(r.tags) ? r.tags.filter((t): t is string => typeof t === \"string\") : [],\n });\n }\n return out;\n}\n\nfunction cleanChoice(choice: LifiRouteChoice | null | undefined): LifiRouteChoice | null {\n if (!choice) return null;\n const allow = (choice.allowBridges ?? []).filter((t) => TOOL_KEY.test(t));\n const deny = (choice.denyBridges ?? []).filter((t) => TOOL_KEY.test(t));\n const order = choice.order === \"CHEAPEST\" || choice.order === \"FASTEST\" ? choice.order : undefined;\n if (!allow.length && !deny.length && !order) return null;\n return {...(allow.length ? {allowBridges: allow} : {}), ...(deny.length ? {denyBridges: deny} : {}), ...(order ? {order} : {})};\n}\n\nexport function lifiProvider(config: LifiProviderConfig = {}): CrossChainProvider {\n config = Object.freeze({...config});\n const apiKey = () => config.apiKey;\n const integrator = () => config.integrator ?? \"\";\n const parsedApiUrl = new URL(config.apiUrl ?? DEFAULT_LIFI_BASE);\n if (parsedApiUrl.protocol !== \"https:\" && parsedApiUrl.protocol !== \"http:\") {\n throw new Error(\"lifi: apiUrl must use http or https\");\n }\n const apiBase = parsedApiUrl.toString().replace(/\\/$/, \"\");\n const trustedTransactionTargets = trustMap(config.trustedTransactionTargets, \"transaction target\");\n const trustedApprovalAddresses = trustMap(config.trustedApprovalAddresses, \"approval\");\n const quoteTtlMs = config.quoteTtlMs ?? DEFAULT_QUOTE_TTL_MS;\n const defaultSlippageBps = config.defaultSlippageBps ?? 50;\n if (!Number.isInteger(defaultSlippageBps) || defaultSlippageBps <= 0 || defaultSlippageBps >= 10_000) {\n throw new Error(\"lifi: defaultSlippageBps must be an integer between 1 and 9999\");\n }\n if (!Number.isInteger(quoteTtlMs) || quoteTtlMs <= 0 || quoteTtlMs > 60_000) {\n throw new Error(\"lifi: quoteTtlMs must be an integer between 1 and 60000\");\n }\n return {\n name: \"lifi\",\n describeActivity: (tx, ctx) => describeLifiActivity(tx, ctx, (chain, address) => trustedAddress(chain, address, trustedTransactionTargets)),\n supportsSameChain: true,\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) => lifiCfg.supportsChain(chain),\n supportsChainPair: (fromChain: string, toChain: string) => lifiCfg.supports(fromChain, toChain),\n supportsRoute(from: Asset, to: Asset): boolean {\n // EVM only: LI.FI's Solana/Tron legs come back as provider-serialized\n // transactions, which the swap2 engine does not execute yet.\n return !!LIFI_CHAIN[from.chain] && !!LIFI_CHAIN[to.chain];\n },\n\n async getQuote(params: QuoteParams, signal?: AbortSignal): Promise<Quote | null> {\n /** Every refusal after LI.FI answered is named — a bare null hides which check failed (matrix v7: 4 silent nulls). */\n const reject = (why: string): null => { params.onRefusal?.(`lifi: ${why}`); return null; };\n if (params.flex) return null; // calldata model — the amount is baked in\n const fromChain = LIFI_CHAIN[params.sourceChain];\n const toChain = LIFI_CHAIN[params.destChain];\n if (!fromChain || !toChain) return null;\n const fromToken = lifiToken(params.sourceChain, params.sourceToken);\n if (!fromToken) return null;\n\n const solanaSource = isSolana(params.sourceChain);\n const fromAddress = params.refundAddress ?? (solanaSource ? SOLANA_PLACEHOLDER : EVM_PLACEHOLDER);\n\n // LI.FI applies `slippage` to EACH step of a multi-step route (bridge +\n // destination swap), so its minimum can sit ~2× the requested slippage\n // under the quote (seen 2026-10-10 on 479 of 4 000 matrix quotes), and\n // it truncates toAmountMin to a few significant digits. The engine\n // rejects a floor below the requested one, so the quote is asked once\n // more with the slippage scaled down to land the floor inside it.\n const slippageBps = params.slippageBps ?? defaultSlippageBps;\n let sentSlippage: number | undefined = slippageBps / 10_000;\n let deadline: AbortSignal | undefined;\n let choice: LifiRouteChoice | null = null;\n if (config.chooseRoute && params.sourceChain !== params.destChain) {\n try {\n const res = await fetch(`${apiBase}/advanced/routes`, {\n method: \"POST\",\n headers: {...headers(apiKey()), \"content-type\": \"application/json\"},\n body: JSON.stringify({\n fromChainId: Number(fromChain),\n toChainId: Number(toChain),\n fromTokenAddress: fromToken,\n toTokenAddress: nativeFor(params.destChain, params.destToken),\n fromAmount: params.amountIn,\n fromAddress,\n toAddress: params.destAddress || fromAddress,\n options: {slippage: slippageBps / 10_000, ...(integrator().trim() ? {integrator: integrator().trim()} : {})},\n }),\n signal: signal ?? timeoutSignal(8_000),\n });\n if (res.ok) {\n const options = routeOptions(await res.json());\n if (options.length) choice = cleanChoice(config.chooseRoute(options, params));\n }\n } catch {\n // The policy is an optimisation: no candidates means LI.FI's default pick.\n }\n }\n for (let attempt = 0; attempt < 2; attempt++) try {\n const url = new URL(`${apiBase}/quote`);\n url.searchParams.set(\"fromChain\", fromChain);\n url.searchParams.set(\"toChain\", toChain);\n url.searchParams.set(\"fromToken\", fromToken);\n // Native dest is chain-notation-specific: EVM zero address vs the\n // Solana system program — sending the EVM zero to an SVM dest 400s.\n url.searchParams.set(\"toToken\", nativeFor(params.destChain, params.destToken));\n url.searchParams.set(\"fromAmount\", params.amountIn);\n url.searchParams.set(\"fromAddress\", fromAddress);\n const toAddress = params.destAddress || fromAddress;\n url.searchParams.set(\"toAddress\", toAddress);\n const integratorId = integrator().trim();\n if (integratorId) url.searchParams.set(\"integrator\", integratorId);\n if (sentSlippage !== undefined) {\n url.searchParams.set(\"slippage\", String(sentSlippage));\n }\n for (const t of choice?.allowBridges ?? []) url.searchParams.append(\"allowBridges\", t);\n for (const t of choice?.denyBridges ?? []) url.searchParams.append(\"denyBridges\", t);\n if (choice?.order) url.searchParams.set(\"order\", choice.order);\n deadline = signal ? undefined : timeoutSignal(12_000);\n const res = await fetch(url, {headers: headers(apiKey()), signal: signal ?? deadline!});\n if (!res.ok && choice) {\n // The chosen bridge went away between the two calls: LI.FI's default pick instead.\n choice = null;\n attempt--;\n continue;\n }\n if (!res.ok) {\n // LI.FI's 404 \"No available quotes for the requested transfer\" and\n // 400 validation messages are the caller's answer, not a silent null.\n const body = (await res.json().catch(() => null)) as {message?: unknown; errors?: {filteredOut?: {reason?: unknown}[]}} | null;\n // When every candidate route was dropped for the same reason (Sei: \"wallet is not linked to\n // the original SEI address\"), that reason is the real answer — the message alone is generic.\n const reasons = [...new Set((body?.errors?.filteredOut ?? []).map((f) => f.reason).filter((r): r is string => typeof r === \"string\"))];\n const why = reasons.length === 1 ? ` (${reasons[0]!.slice(0, 200)})` : \"\";\n params.onRefusal?.(`lifi: ${typeof body?.message === \"string\" ? body.message.slice(0, 200) : `HTTP ${res.status}`}${why}`);\n return null;\n }\n const q = (await res.json()) as {\n type?: string;\n id?: string;\n action?: {\n fromToken?: {address?: string; chainId?: number};\n toToken?: {address?: string; chainId?: number};\n fromAmount?: string;\n fromChainId?: number;\n toChainId?: number;\n slippage?: number;\n fromAddress?: string;\n toAddress?: string;\n };\n estimate?: {\n fromAmount?: string;\n toAmount?: string;\n toAmountMin?: string;\n executionDuration?: number;\n approvalAddress?: string;\n feeCosts?: {amountUSD?: string}[];\n gasCosts?: {amountUSD?: string}[];\n };\n transactionRequest?: {\n to?: string;\n data?: string;\n value?: string;\n chainId?: number;\n gasLimit?: string;\n from?: string;\n };\n };\n const receivedAt = Date.now();\n const action = q.action;\n const est = q.estimate;\n const tr = q.transactionRequest;\n const expectedToToken = nativeFor(params.destChain, params.destToken);\n const expectedFromChain = Number(fromChain);\n const expectedToChain = Number(toChain);\n if (q.type !== \"lifi\" || !q.id || !action || !est?.toAmount || !est.fromAmount || !tr) return reject(\"incomplete quote (no action, estimate or transaction)\");\n const mismatch = [\n action.fromChainId !== expectedFromChain && \"source chain\",\n action.toChainId !== expectedToChain && \"destination chain\",\n (action.fromToken?.chainId !== expectedFromChain || !sameChainAddress(params.sourceChain, action.fromToken?.address, fromToken)) && \"source token\",\n (action.toToken?.chainId !== expectedToChain || !sameChainAddress(params.destChain, action.toToken?.address, expectedToToken)) && \"destination token\",\n action.fromAmount !== params.amountIn && \"amount spent\",\n !sameChainAddress(params.sourceChain, action.fromAddress, fromAddress) && \"sender\",\n !sameChainAddress(params.destChain, action.toAddress, toAddress) && \"recipient\",\n ].filter(Boolean);\n if (mismatch.length) return reject(`quote does not match the request (${mismatch.join(\", \")})`);\n // The transaction spends exactly the input (action.fromAmount, checked above). Some bridges\n // (glacis, 2026-10) take their fee from the input, so estimate.fromAmount — what is bridged —\n // is a little lower and toAmount already reflects it. Accept a bounded input-side fee instead\n // of a silent null; never an estimate that bridges MORE than is spent.\n const bridged = BigInt(est.fromAmount);\n const spent = BigInt(params.amountIn);\n if (bridged > spent) return reject(`the estimate bridges ${est.fromAmount}, more than the ${params.amountIn} spent`);\n if ((spent - bridged) * 10_000n > spent * BigInt(MAX_INPUT_FEE_BPS)) {\n return reject(`the route takes ${Number(((spent - bridged) * 10_000n) / spent) / 100}% of the input as a fee (over ${MAX_INPUT_FEE_BPS / 100}%)`);\n }\n // Source-VM execution payload. EVM: calldata to a trusted target.\n // Solana: a base64 transaction the account proves before signing —\n // there is no target to trust here, the balance proof replaces it.\n if (solanaSource) {\n if (!tr.data || tr.data.length < 64 || tr.data.length % 4 !== 0 || !BASE64.test(tr.data)) return reject(\"the Solana transaction is not base64\");\n if (tr.to !== undefined || tr.value !== undefined || tr.gasLimit !== undefined) return reject(\"the Solana transaction carries EVM fields\");\n // `estimate.approvalAddress` is ignored for a Solana source: LI.FI\n // returns its EVM diamond here on Mayan routes too (seen 2026-10-09,\n // SOL → Base USDC via mayanFastMCTP), and Solana has no allowances —\n // the account's post-state balance proof is the guard, not an\n // approval target. It is never propagated.\n } else if (\n !isHexData(tr.data) || !normalizeAddress(tr.to) || !normalizeAddress(tr.from) ||\n tr.chainId !== expectedFromChain || !tr.value || !tr.gasLimit ||\n !trustedAddress(params.sourceChain, tr.to, trustedTransactionTargets) ||\n !sameAddress(tr.from, fromAddress)\n ) return reject(\"the transaction is malformed or targets an untrusted contract\");\n if (\n sentSlippage !== undefined &&\n (typeof action.slippage !== \"number\" || Math.abs(action.slippage - sentSlippage) > 1e-12)\n ) return reject(\"the quote ignored the requested slippage\");\n\n const sourceIsToken = fromToken !== EVM_ZERO && fromToken !== SOLANA_NATIVE;\n if (solanaSource) {\n // No allowances on Solana; nothing to trust beyond the balance proof.\n } else if (sourceIsToken) {\n if (!trustedAddress(params.sourceChain, est.approvalAddress, trustedApprovalAddresses)) return reject(\"the approval target is not a trusted LI.FI contract\");\n } else if (est.approvalAddress !== undefined) {\n // LI.FI started returning an approvalAddress for NATIVE sources too\n // (seen 2026-09 on every ETH-source quote, e.g. ETH → Robinhood via\n // relay: approvalAddress = the diamond the tx already calls). An\n // approval is meaningless for the native asset, so it is not a\n // reason to refuse the quote — but it must still be a trusted\n // target, and it is never propagated for a native source.\n if (!trustedAddress(params.sourceChain, est.approvalAddress, trustedApprovalAddresses)) return reject(\"the approval target is not a trusted LI.FI contract\");\n }\n\n let txRequest: NonNullable<Quote[\"txRequest\"]>;\n if (solanaSource) {\n // `value` declares what the account may let the tx take in native\n // coin: the input for a SOL source, nothing for a token source.\n txRequest = {serializedTx: tr.data!, value: sourceIsToken ? \"0\" : params.amountIn};\n } else {\n try {\n if (BigInt(tr.value!) < 0n || BigInt(tr.gasLimit!) <= 0n) return reject(\"the transaction has a negative value or no gas limit\");\n } catch {\n return reject(\"the transaction value or gas limit is not a number\");\n }\n // Some bridges charge a native messaging fee inside `value`: for a\n // token source the whole value is that fee; for a native source it\n // is whatever exceeds the input (seen 2026-10-10: DAI Optimism →\n // Base, POL Polygon → Optimism). Declared here, sealed with the\n // quote, bounded by the engine — never silently attached.\n const value = BigInt(tr.value!);\n const nativeFee = sourceIsToken ? value : value > BigInt(params.amountIn) ? value - BigInt(params.amountIn) : 0n;\n if (!sourceIsToken && value < BigInt(params.amountIn)) return reject(\"the transaction sends less native coin than the input\");\n txRequest = {\n to: tr.to!,\n data: tr.data!,\n value: value.toString(),\n chainId: tr.chainId!,\n gasLimit: BigInt(tr.gasLimit!).toString(),\n ...(sourceIsToken && est.approvalAddress ? {approvalAddress: est.approvalAddress} : {}),\n ...(nativeFee > 0n ? {nativeFee: nativeFee.toString()} : {}),\n };\n }\n\n // Route fees only (bridge / protocol / integrator). The source\n // transaction's gas is the network fee the wallet shows on its own line —\n // counting it here too made LI.FI look dearer than on-chain venues whose\n // fee excludes gas (2026-10-13).\n const feeUsd = (est.feeCosts ?? []).reduce((a, f) => a + Number(f.amountUSD ?? 0), 0);\n\n // The optimistic output is not a safety floor. A quote without the\n // provider's minimum cannot satisfy an exact-input execution contract.\n if (!est.toAmountMin) return reject(\"the quote has no minimum output\");\n const minDestAmount = est.toAmountMin;\n if (sentSlippage !== undefined) {\n const dest = BigInt(est.toAmount);\n const min = BigInt(minDestAmount);\n if (dest > 0n && min < (dest * BigInt(10_000 - slippageBps)) / 10_000n) {\n const effective = Number(((dest - min) * 1_000_000n) / dest) / 1_000_000;\n const requested = slippageBps / 10_000;\n const scaled: number = Math.floor(((sentSlippage * requested) / effective) * 0.995 * 1_000_000) / 1_000_000;\n if (attempt === 0 && effective > 0 && scaled > 0) {\n sentSlippage = scaled;\n continue;\n }\n params.onRefusal?.(\n `lifi: this route's minimum is ${(effective * 100).toFixed(2)}% under the quote (LI.FI applies slippage on every step) — more than the requested ${slippageBps / 100}%`,\n );\n return null;\n }\n }\n if (params.minAmountOut !== undefined && BigInt(minDestAmount) < BigInt(params.minAmountOut)) {\n params.onRefusal?.(`lifi: floor breach (min=${minDestAmount} < floor=${params.minAmountOut})`);\n return null;\n }\n // A same-chain swap must deliver in the same transaction. LI.FI sometimes routes a\n // same-chain pair through a solver (Relay-style intents, 2026-10: USDC → ARB on\n // Ethereum, 625 s): the tx only takes the input and the output arrives later from the\n // solver, so the engine's \"output ≥ quoted minimum\" preflight would refuse it anyway.\n // Name it here, before anything is built.\n const duration = est.executionDuration ?? 0;\n if (fromChain === toChain && duration > SAME_CHAIN_MAX_SECONDS) {\n params.onRefusal?.(`lifi: same-chain route settles asynchronously (${duration} s via ${(q as {tool?: string}).tool ?? \"unknown tool\"}) — a same-chain swap must deliver in the same transaction`);\n return null;\n }\n return {\n provider: \"lifi\",\n // Status is tracked by SOURCE TX HASH + the chain pair.\n intentId: `lifi:${fromChain}:${toChain}`,\n depositAddress: \"\",\n depositMemo: null,\n txRequest,\n // What the wallet spends (action.fromAmount, = the input); an input-side bridge fee is inside destAmount.\n sourceAmount: params.amountIn,\n destAmount: est.toAmount,\n minDestAmount,\n feeUsd,\n etaSeconds: est.executionDuration ?? 120,\n reliability: 0.97,\n // LI.FI documents an approximately 60-second lifetime. Use a slightly\n // shorter local deadline and re-quote again at execution time.\n validUntilMs: receivedAt + quoteTtlMs,\n };\n } catch {\n // Our own 12 s deadline (not the caller's signal): say so instead of a silent null.\n if (deadline?.aborted) params.onRefusal?.(\"lifi: no quote within 12 s\");\n return null;\n }\n return null;\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n const tx = quote.txRequest;\n if (!tx) throw new Error(\"swap2: LI.FI quote has no transaction request\");\n // The intent id carries the LI.FI source chain; a serialized leg names\n // its chain so the engine can refuse a mismatched account.\n const [, fromChain] = quote.intentId.split(\":\");\n return {\n chain: tx.serializedTx ? CAIP2_BY_LIFI_CHAIN[fromChain ?? \"\"] ?? \"\" : \"\",\n to: tx.to ?? \"\",\n value: tx.value ?? \"0\",\n ...(tx.data ? {data: tx.data} : {}),\n ...(tx.chainId !== undefined ? {chainId: tx.chainId} : {}),\n ...(tx.gasLimit ? {gasLimit: tx.gasLimit} : {}),\n ...(tx.approvalAddress ? {approvalAddress: tx.approvalAddress} : {}),\n ...(tx.serializedTx ? {serializedTx: tx.serializedTx} : {}),\n };\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n if (!ref.sourceTxHash) return {state: \"pending\"}; // not broadcast yet\n const [, fromChain, toChain] = ref.intentId.split(\":\");\n try {\n const url = new URL(`${apiBase}/status`);\n url.searchParams.set(\"txHash\", ref.sourceTxHash);\n if (fromChain) url.searchParams.set(\"fromChain\", fromChain);\n if (toChain) url.searchParams.set(\"toChain\", toChain);\n const res = await fetch(url, {headers: headers(apiKey()), signal: timeoutSignal(12_000)});\n if (!res.ok) return {state: \"pending\"};\n const s = (await res.json()) as {status?: string; substatus?: string; receiving?: {txHash?: string}};\n const map: Record<string, IntentStatus[\"state\"]> = {\n DONE: \"completed\",\n FAILED: \"failed\",\n PENDING: \"pending\",\n NOT_FOUND: \"pending\",\n };\n // LI.FI reports refunds and partial fills as top-level DONE. Treating\n // those as completed would falsely claim that the destination was fully\n // funded. Keep the explicit partial/refund lifecycle states.\n const state = s.substatus === \"REFUNDED\"\n ? \"refunded\"\n : s.substatus === \"EXPIRED\"\n ? \"expired\"\n : s.substatus === \"NOT_PROCESSABLE_REFUND_NEEDED\"\n ? \"action-required\"\n : s.substatus === \"REFUND_IN_PROGRESS\"\n ? \"refund-pending\"\n : s.status === \"DONE\" && s.substatus === \"PARTIAL\"\n ? \"partial\"\n : map[s.status ?? \"PENDING\"] ?? \"pending\";\n const depositReceived = state === \"pending\" && s.status === \"PENDING\";\n const destTxHash = typeof s.receiving?.txHash === \"string\" && s.receiving.txHash.length > 0\n ? s.receiving.txHash\n : undefined;\n return {\n state,\n depositReceived,\n ...(destTxHash ? {destTxHash} : {}),\n };\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n"],"mappings":"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","names":[]}