@anywalletkit/protocol-swap2-lifi 0.2.4 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,6 +16,22 @@ npm install @anywalletkit/protocol-swap2-lifi @anywalletkit/core
16
16
 
17
17
  On npm: [@anywalletkit/protocol-swap2-lifi](https://www.npmjs.com/package/@anywalletkit/protocol-swap2-lifi), published from the [release workflow](https://github.com/ultratestbro/anywalletkit/blob/main/RELEASING.md) with provenance.
18
18
 
19
+ ## What is checked before a quote is used
20
+
21
+ The quote's `action` must match the request (chains, tokens, amount, sender, recipient), the
22
+ transaction must target the chain's LI.FI Diamond, and the Diamond **calldata** is decoded and must
23
+ do the same: a same-chain swap (GenericSwapFacet / V3) pays the reviewed recipient at least the
24
+ reviewed minimum, spending the input token and delivering the requested one; a bridge call must be
25
+ one of LI.FI's listed `startBridgeTokensVia*` / `swapAndStartBridgeTokensVia*` entry points (packed
26
+ calls are refused) and its `BridgeData` must name the reviewed recipient and chain and bridge the
27
+ input token (or what its source swaps make of it). Refused, because the recipient cannot be read
28
+ from the calldata: routes with a destination call, and EVM-source routes to a non-EVM chain.
29
+ Unknown calldata is refused.
30
+
31
+ Not checked: a bridge's output. The destination minimum — and for some bridges (Relay, Across)
32
+ what finally reaches the recipient — sits in bridge-specific data, so on cross-chain routes the
33
+ reviewed minimum relies on LI.FI's API (or your `apiUrl` proxy) answering honestly.
34
+
19
35
  ## Activity
20
36
 
21
37
  `describeActivity(tx, ctx)` recognizes any call into the LI.FI Diamond on an
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  lifiProvider
3
- } from "./chunk-5A36OZDJ.js";
3
+ } from "./chunk-VSRA5QBR.js";
4
4
  import {
5
5
  lifi
6
6
  } from "./chunk-6N4HZ5XX.js";
@@ -24,4 +24,4 @@ var LifiSwap2Protocol = class extends SingleProviderSwap2 {
24
24
  export {
25
25
  LifiSwap2Protocol
26
26
  };
27
- //# sourceMappingURL=chunk-GK5UHEIY.js.map
27
+ //# sourceMappingURL=chunk-5ZA66NJP.js.map
@@ -6,9 +6,258 @@ import {
6
6
  describeLifiActivity
7
7
  } from "./chunk-EU7XQVZQ.js";
8
8
 
9
+ // src/calldata.ts
10
+ var GENERIC_SWAPS = {
11
+ "0x4630a0d8": { single: false },
12
+ // swapTokensGeneric
13
+ "0x4666fc80": { single: true },
14
+ // swapTokensSingleV3ERC20ToERC20
15
+ "0x733214a3": { single: true },
16
+ // swapTokensSingleV3ERC20ToNative
17
+ "0xaf7060fd": { single: true },
18
+ // swapTokensSingleV3NativeToERC20
19
+ "0x5fd9ae2e": { single: false },
20
+ // swapTokensMultipleV3ERC20ToERC20
21
+ "0x2c57e884": { single: false },
22
+ // swapTokensMultipleV3ERC20ToNative
23
+ "0x736eac0b": { single: false }
24
+ // swapTokensMultipleV3NativeToERC20
25
+ };
26
+ var BRIDGE_CALLS = {
27
+ "0x1fd8010c": { sourceSwaps: false },
28
+ // startBridgeTokensViaAcross (AcrossFacet)
29
+ "0x3a3f7332": { sourceSwaps: true },
30
+ // swapAndStartBridgeTokensViaAcross (AcrossFacet)
31
+ "0xa1f1ce43": { sourceSwaps: false },
32
+ // startBridgeTokensViaAcrossV4 (AcrossFacetV4)
33
+ "0x1794958f": { sourceSwaps: true },
34
+ // swapAndStartBridgeTokensViaAcrossV4 (AcrossFacetV4)
35
+ "0x6a90d66e": { sourceSwaps: false },
36
+ // startBridgeTokensViaAcrossV4Swap (AcrossV4SwapFacet)
37
+ "0x9b054bc4": { sourceSwaps: true },
38
+ // swapAndStartBridgeTokensViaAcrossV4Swap (AcrossV4SwapFacet)
39
+ "0x6a51e9a9": { sourceSwaps: false },
40
+ // startBridgeTokensViaAllBridge (AllBridgeFacet)
41
+ "0x63267469": { sourceSwaps: true },
42
+ // swapAndStartBridgeTokensViaAllBridge (AllBridgeFacet)
43
+ "0xc9851d0b": { sourceSwaps: false },
44
+ // startBridgeTokensViaArbitrumBridge (ArbitrumBridgeFacet)
45
+ "0x3cc9517b": { sourceSwaps: true },
46
+ // swapAndStartBridgeTokensViaArbitrumBridge (ArbitrumBridgeFacet)
47
+ "0xe0a4201c": { sourceSwaps: false },
48
+ // startBridgeTokensViaCelerCircleBridge (CelerCircleBridgeFacet)
49
+ "0x4f3b0759": { sourceSwaps: true },
50
+ // swapAndStartBridgeTokensViaCelerCircleBridge (CelerCircleBridgeFacet)
51
+ "0x0315138f": { sourceSwaps: false },
52
+ // startBridgeTokensViaCentrifuge (CentrifugeFacet)
53
+ "0x8fd4d4dd": { sourceSwaps: true },
54
+ // swapAndStartBridgeTokensViaCentrifuge (CentrifugeFacet)
55
+ "0x0ad553b3": { sourceSwaps: false },
56
+ // startBridgeTokensViaChainflip (ChainflipFacet)
57
+ "0xee3314a1": { sourceSwaps: true },
58
+ // swapAndStartBridgeTokensViaChainflip (ChainflipFacet)
59
+ "0x4004633e": { sourceSwaps: false },
60
+ // startBridgeTokensViaDeBridgeDln (DeBridgeDlnFacet)
61
+ "0x2c7d2db0": { sourceSwaps: true },
62
+ // swapAndStartBridgeTokensViaDeBridgeDln (DeBridgeDlnFacet)
63
+ "0xbff90b61": { sourceSwaps: false },
64
+ // startBridgeTokensViaEco (EcoFacet)
65
+ "0x762aea18": { sourceSwaps: true },
66
+ // swapAndStartBridgeTokensViaEco (EcoFacet)
67
+ "0x678786ea": { sourceSwaps: false },
68
+ // startBridgeTokensViaFrax (FraxFacet)
69
+ "0x07b8e4c7": { sourceSwaps: true },
70
+ // swapAndStartBridgeTokensViaFrax (FraxFacet)
71
+ "0x5f9af35d": { sourceSwaps: false },
72
+ // startBridgeTokensViaGarden (GardenFacet)
73
+ "0x76ad76fe": { sourceSwaps: true },
74
+ // swapAndStartBridgeTokensViaGarden (GardenFacet)
75
+ "0xfc5f1003": { sourceSwaps: false },
76
+ // startBridgeTokensViaGasZip (GasZipFacet)
77
+ "0x606326ff": { sourceSwaps: true },
78
+ // swapAndStartBridgeTokensViaGasZip (GasZipFacet)
79
+ "0x6f9206ba": { sourceSwaps: false },
80
+ // startBridgeTokensViaGlacis (GlacisFacet)
81
+ "0x9c4b6dd9": { sourceSwaps: true },
82
+ // swapAndStartBridgeTokensViaGlacis (GlacisFacet)
83
+ "0xf66fe519": { sourceSwaps: false },
84
+ // startBridgeTokensViaGnosisBridge (GnosisBridgeFacet)
85
+ "0x7bf96e0a": { sourceSwaps: true },
86
+ // swapAndStartBridgeTokensViaGnosisBridge (GnosisBridgeFacet)
87
+ "0xee9e98e0": { sourceSwaps: false },
88
+ // startBridgeTokensViaLayerSwap (LayerSwapFacet)
89
+ "0x4c279d6b": { sourceSwaps: true },
90
+ // swapAndStartBridgeTokensViaLayerSwap (LayerSwapFacet)
91
+ "0x7dbcf1d9": { sourceSwaps: false },
92
+ // startBridgeTokensViaLiFiIntentEscrowV2 (LiFiIntentEscrowFacetV2)
93
+ "0x6d21c5df": { sourceSwaps: true },
94
+ // swapAndStartBridgeTokensViaLiFiIntentEscrowV2 (LiFiIntentEscrowFacetV2)
95
+ "0x65782c4b": { sourceSwaps: false },
96
+ // startBridgeTokensViaM0 (M0Facet)
97
+ "0xb9eaf86d": { sourceSwaps: true },
98
+ // swapAndStartBridgeTokensViaM0 (M0Facet)
99
+ "0xb4875292": { sourceSwaps: false },
100
+ // startBridgeTokensViaMayan (MayanFacet)
101
+ "0x80c65808": { sourceSwaps: true },
102
+ // swapAndStartBridgeTokensViaMayan (MayanFacet)
103
+ "0x4213dfff": { sourceSwaps: false },
104
+ // startBridgeTokensViaMegaETHBridge (MegaETHBridgeFacet)
105
+ "0x22256e89": { sourceSwaps: true },
106
+ // swapAndStartBridgeTokensViaMegaETHBridge (MegaETHBridgeFacet)
107
+ "0x4698f032": { sourceSwaps: false },
108
+ // startBridgeTokensViaNEARIntents (NEARIntentsFacet)
109
+ "0x02631b09": { sourceSwaps: true },
110
+ // swapAndStartBridgeTokensViaNEARIntents (NEARIntentsFacet)
111
+ "0x782621d8": { sourceSwaps: false },
112
+ // startBridgeTokensViaOmniBridge (OmniBridgeFacet)
113
+ "0x95726782": { sourceSwaps: true },
114
+ // swapAndStartBridgeTokensViaOmniBridge (OmniBridgeFacet)
115
+ "0xce8a97a5": { sourceSwaps: false },
116
+ // startBridgeTokensViaOptimismBridge (OptimismBridgeFacet)
117
+ "0x5bb5d448": { sourceSwaps: true },
118
+ // swapAndStartBridgeTokensViaOptimismBridge (OptimismBridgeFacet)
119
+ "0xaf62c7d6": { sourceSwaps: false },
120
+ // startBridgeTokensViaPolygonBridge (PolygonBridgeFacet)
121
+ "0xb4f37581": { sourceSwaps: true },
122
+ // swapAndStartBridgeTokensViaPolygonBridge (PolygonBridgeFacet)
123
+ "0xf434d6ca": { sourceSwaps: false },
124
+ // startBridgeTokensViaPolymerCCTP (PolymerCCTPFacet)
125
+ "0x17917a4e": { sourceSwaps: true },
126
+ // swapAndStartBridgeTokensViaPolymerCCTP (PolymerCCTPFacet)
127
+ "0x092e8fa4": { sourceSwaps: false },
128
+ // startBridgeTokensViaRelayDepository (RelayDepositoryFacet)
129
+ "0xa3443faa": { sourceSwaps: true },
130
+ // swapAndStartBridgeTokensViaRelayDepository (RelayDepositoryFacet)
131
+ "0x3f313808": { sourceSwaps: false },
132
+ // startBridgeTokensViaSquid (SquidFacet)
133
+ "0xa8f66666": { sourceSwaps: true },
134
+ // swapAndStartBridgeTokensViaSquid (SquidFacet)
135
+ "0x14d53077": { sourceSwaps: false },
136
+ // startBridgeTokensViaStargate (StargateFacetV2)
137
+ "0xa6010a66": { sourceSwaps: true },
138
+ // swapAndStartBridgeTokensViaStargate (StargateFacetV2)
139
+ "0x0691ff78": { sourceSwaps: false },
140
+ // startBridgeTokensViaSuperset (SupersetFacet)
141
+ "0xf26e657f": { sourceSwaps: true },
142
+ // swapAndStartBridgeTokensViaSuperset (SupersetFacet)
143
+ "0xe23b7a08": { sourceSwaps: false },
144
+ // startBridgeTokensViaSymbiosis (SymbiosisFacet)
145
+ "0xc46059b2": { sourceSwaps: true },
146
+ // swapAndStartBridgeTokensViaSymbiosis (SymbiosisFacet)
147
+ "0x2541ec57": { sourceSwaps: false },
148
+ // startBridgeTokensViaThorSwap (ThorSwapFacet)
149
+ "0xad673d88": { sourceSwaps: true },
150
+ // swapAndStartBridgeTokensViaThorSwap (ThorSwapFacet)
151
+ "0x64261d58": { sourceSwaps: false },
152
+ // startBridgeTokensViaUnit (UnitFacet)
153
+ "0x21a3af52": { sourceSwaps: true }
154
+ // swapAndStartBridgeTokensViaUnit (UnitFacet)
155
+ };
156
+ var Reader = class {
157
+ b;
158
+ constructor(hex) {
159
+ if (!/^0x([0-9a-fA-F]{2})*$/.test(hex)) throw new Error("not hex");
160
+ this.b = Uint8Array.from(hex.slice(2).match(/../g) ?? [], (h) => Number.parseInt(h, 16));
161
+ }
162
+ get length() {
163
+ return this.b.length;
164
+ }
165
+ word(at) {
166
+ if (at < 0 || at + 32 > this.b.length) throw new Error("out of bounds");
167
+ let v = 0n;
168
+ for (let i = at; i < at + 32; i++) v = v << 8n | BigInt(this.b[i]);
169
+ return v;
170
+ }
171
+ /** A word that must fit a JS offset / length (bounded by the calldata). */
172
+ small(at) {
173
+ const v = this.word(at);
174
+ if (v > BigInt(this.b.length)) throw new Error("offset out of bounds");
175
+ return Number(v.toString());
176
+ }
177
+ address(at) {
178
+ const v = this.word(at);
179
+ if (v >> 160n !== 0n) throw new Error("not an address");
180
+ return `0x${v.toString(16).padStart(40, "0")}`;
181
+ }
182
+ bool(at) {
183
+ const v = this.word(at);
184
+ if (v > 1n) throw new Error("not a bool");
185
+ return v === 1n;
186
+ }
187
+ };
188
+ var same = (a, b) => a.toLowerCase() === b.toLowerCase();
189
+ function swapAt(r, at) {
190
+ r.address(at);
191
+ r.address(at + 32);
192
+ const step = { sendingAssetId: r.address(at + 64), receivingAssetId: r.address(at + 96), fromAmount: r.word(at + 128) };
193
+ const bytesAt = at + r.small(at + 160);
194
+ r.small(bytesAt);
195
+ r.bool(at + 192);
196
+ return step;
197
+ }
198
+ function swapsAt(r, base, head) {
199
+ const array = base + r.small(head);
200
+ const n = r.small(array);
201
+ if (n === 0 || n > 16) throw new Error("bad swap count");
202
+ const items = array + 32;
203
+ return Array.from({ length: n }, (_, i) => swapAt(r, items + r.small(items + 32 * i)));
204
+ }
205
+ function checkSteps(steps, e, finalAsset) {
206
+ const first = steps[0];
207
+ const last = steps[steps.length - 1];
208
+ if (!same(first.sendingAssetId, e.fromToken)) return `spends ${first.sendingAssetId}, not ${e.fromToken}`;
209
+ if (first.fromAmount === 0n || first.fromAmount > e.amountIn) return `swaps ${first.fromAmount}, not the ${e.amountIn} spent`;
210
+ if (!same(last.receivingAssetId, finalAsset)) return `delivers ${last.receivingAssetId}, not ${finalAsset}`;
211
+ return null;
212
+ }
213
+ function diamondCallMismatch(data, e) {
214
+ let r;
215
+ try {
216
+ r = new Reader(data);
217
+ } catch {
218
+ return "the calldata is not hex";
219
+ }
220
+ if (r.length < 4 + 32 * 2) return "the calldata is too short";
221
+ const selector = data.slice(0, 10).toLowerCase();
222
+ const generic = GENERIC_SWAPS[selector];
223
+ try {
224
+ if (generic) {
225
+ if (!e.sameChain) return "a same-chain swap call on a cross-chain route";
226
+ const receiver2 = r.address(4 + 96);
227
+ const minAmount2 = r.word(4 + 128);
228
+ const steps = generic.single ? [swapAt(r, 4 + r.small(4 + 160))] : swapsAt(r, 4, 4 + 160);
229
+ if (!e.evmDestination || !same(receiver2, e.receiver)) return `pays ${receiver2}, not ${e.receiver}`;
230
+ if (minAmount2 < e.minOut) return `accepts ${minAmount2}, below the ${e.minOut} shown`;
231
+ return checkSteps(steps, e, e.toToken);
232
+ }
233
+ const bridge = BRIDGE_CALLS[selector];
234
+ if (!bridge) return `unknown Diamond call ${selector}`;
235
+ const head = r.small(4);
236
+ if (head < (bridge.sourceSwaps ? 96 : 64) || head % 32 !== 0 || head > 32 * 32) return `unknown Diamond call ${selector}`;
237
+ const at = 4 + head;
238
+ if (r.small(at + 32) !== 320) return `unknown Diamond call ${selector}`;
239
+ const sendingAssetId = r.address(at + 128);
240
+ const receiver = r.address(at + 160);
241
+ const minAmount = r.word(at + 192);
242
+ const destinationChainId = r.word(at + 224);
243
+ const hasSourceSwaps = r.bool(at + 256);
244
+ const hasDestinationCall = r.bool(at + 288);
245
+ if (e.sameChain) return "a bridge call on a same-chain route";
246
+ if (destinationChainId !== e.destChainId) return `bridges to chain ${destinationChainId}, not ${e.destChainId}`;
247
+ if (hasDestinationCall) return "the route runs a call on the destination chain, whose recipient cannot be checked here";
248
+ if (!e.evmDestination) return "the recipient on a non-EVM destination sits in bridge-specific data and cannot be checked here";
249
+ if (!same(receiver, e.receiver)) return `pays ${receiver}, not ${e.receiver}`;
250
+ if (hasSourceSwaps !== bridge.sourceSwaps) return `unknown Diamond call ${selector}`;
251
+ if (hasSourceSwaps) return checkSteps(swapsAt(r, 4, 4 + 32), e, sendingAssetId);
252
+ if (minAmount === 0n || minAmount > e.amountIn) return `bridges ${minAmount}, not the ${e.amountIn} spent`;
253
+ return same(sendingAssetId, e.fromToken) ? null : `bridges ${sendingAssetId}, not ${e.fromToken}`;
254
+ } catch (err) {
255
+ return `the Diamond calldata does not decode (${err instanceof Error ? err.message : String(err)})`;
256
+ }
257
+ }
258
+
9
259
  // src/provider.ts
10
- import { ccAsset } from "@anywalletkit/swap2-assets";
11
- import { timeoutSignal } from "@anywalletkit/protocol-swap2-core/util";
260
+ import { timeoutSignal, sourceAssetOf } from "@anywalletkit/protocol-swap2-core/util";
12
261
  import { bigintToNumber } from "@anywalletkit/core";
13
262
  var DEFAULT_LIFI_BASE = "https://li.quest/v1";
14
263
  var LIFI_CHAIN = {
@@ -132,8 +381,9 @@ function trustMap(input, label) {
132
381
  }
133
382
  return out;
134
383
  }
135
- function lifiToken(sourceChain, symbol) {
136
- const asset = ccAsset(sourceChain, symbol);
384
+ function lifiToken(params) {
385
+ const sourceChain = params.sourceChain;
386
+ const asset = sourceAssetOf(params);
137
387
  if (!asset) return null;
138
388
  if (asset.contract) return asset.contract;
139
389
  return isSolana(sourceChain) ? SOLANA_NATIVE : EVM_ZERO;
@@ -215,10 +465,14 @@ function lifiProvider(config = {}) {
215
465
  const fromChain = LIFI_CHAIN[params.sourceChain];
216
466
  const toChain = LIFI_CHAIN[params.destChain];
217
467
  if (!fromChain || !toChain) return null;
218
- const fromToken = lifiToken(params.sourceChain, params.sourceToken);
468
+ const fromToken = lifiToken(params);
219
469
  if (!fromToken) return null;
220
470
  const solanaSource = isSolana(params.sourceChain);
221
- const fromAddress = params.refundAddress ?? (solanaSource ? SOLANA_PLACEHOLDER : EVM_PLACEHOLDER);
471
+ const dry = params.dry !== false;
472
+ const fromAddress = params.refundAddress || (dry ? solanaSource ? SOLANA_PLACEHOLDER : EVM_PLACEHOLDER : "");
473
+ const toAddress = params.destAddress || (dry ? fromAddress : "");
474
+ if (!fromAddress) return reject("a live quote needs the sender's address");
475
+ if (!toAddress) return reject("a live quote needs a recipient");
222
476
  const slippageBps = params.slippageBps ?? defaultSlippageBps;
223
477
  let sentSlippage = slippageBps / 1e4;
224
478
  let deadline;
@@ -235,7 +489,7 @@ function lifiProvider(config = {}) {
235
489
  toTokenAddress: nativeFor(params.destChain, params.destToken),
236
490
  fromAmount: params.amountIn,
237
491
  fromAddress,
238
- toAddress: params.destAddress || fromAddress,
492
+ toAddress,
239
493
  options: { slippage: slippageBps / 1e4, ...integrator().trim() ? { integrator: integrator().trim() } : {} }
240
494
  }),
241
495
  signal: signal ?? timeoutSignal(8e3)
@@ -255,7 +509,6 @@ function lifiProvider(config = {}) {
255
509
  url.searchParams.set("toToken", nativeFor(params.destChain, params.destToken));
256
510
  url.searchParams.set("fromAmount", params.amountIn);
257
511
  url.searchParams.set("fromAddress", fromAddress);
258
- const toAddress = params.destAddress || fromAddress;
259
512
  url.searchParams.set("toAddress", toAddress);
260
513
  const integratorId = integrator().trim();
261
514
  if (integratorId) url.searchParams.set("integrator", integratorId);
@@ -367,6 +620,19 @@ function lifiProvider(config = {}) {
367
620
  params.onRefusal?.(`lifi: same-chain route settles asynchronously (${duration} s via ${q.tool ?? "unknown tool"}) \u2014 a same-chain swap must deliver in the same transaction`);
368
621
  return null;
369
622
  }
623
+ if (!solanaSource) {
624
+ const why = diamondCallMismatch(tr.data, {
625
+ fromToken,
626
+ toToken: expectedToToken,
627
+ amountIn: BigInt(params.amountIn),
628
+ receiver: toAddress,
629
+ minOut: BigInt(minDestAmount),
630
+ destChainId: BigInt(toChain),
631
+ sameChain: fromChain === toChain,
632
+ evmDestination: !isSolana(params.destChain)
633
+ });
634
+ if (why) return reject(`the transaction does not match the quote: ${why}`);
635
+ }
370
636
  return {
371
637
  provider: "lifi",
372
638
  // Status is tracked by SOURCE TX HASH + the chain pair.
@@ -441,4 +707,4 @@ function lifiProvider(config = {}) {
441
707
  export {
442
708
  lifiProvider
443
709
  };
444
- //# sourceMappingURL=chunk-5A36OZDJ.js.map
710
+ //# sourceMappingURL=chunk-VSRA5QBR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/calldata.ts","../src/provider.ts"],"sourcesContent":["/**\n * What the LI.FI Diamond call really does, read from its calldata — not from the `action` /\n * `estimate` next to it (round 3, H9). The API (or an `apiUrl` proxy) could pair a reviewed\n * recipient and minimum with calldata that pays someone else, or accepts 1 wei.\n *\n * Same-chain swaps run through GenericSwapFacet(V3): receiver, minimum, the input token and amount,\n * and the output token are in the arguments. Bridges take `ILiFi.BridgeData` as their first\n * argument: its receiver, destination chain and bridged asset are checked, for the listed bridge\n * entry points only; a destination call (the final recipient sits in calldata for another chain)\n * and a non-EVM destination (the receiver sits in facet-specific data) are refused.\n *\n * Not checked here: a bridge's OUTPUT. The destination minimum (and for some bridges, e.g. Relay\n * and Across, what the receiver finally gets) lives in facet-specific data, so for bridges the\n * reviewed minimum still relies on LI.FI's API answering honestly.\n */\n\nconst GENERIC_SWAPS: Readonly<Record<string, {single: boolean}>> = {\n \"0x4630a0d8\": {single: false}, // swapTokensGeneric\n \"0x4666fc80\": {single: true}, // swapTokensSingleV3ERC20ToERC20\n \"0x733214a3\": {single: true}, // swapTokensSingleV3ERC20ToNative\n \"0xaf7060fd\": {single: true}, // swapTokensSingleV3NativeToERC20\n \"0x5fd9ae2e\": {single: false}, // swapTokensMultipleV3ERC20ToERC20\n \"0x2c57e884\": {single: false}, // swapTokensMultipleV3ERC20ToNative\n \"0x736eac0b\": {single: false}, // swapTokensMultipleV3NativeToERC20\n};\n\n/**\n * The ABI-encoded bridge entry points of the LI.FI Diamond — `startBridgeTokensVia*` and\n * `swapAndStartBridgeTokensVia*`, whose first argument is `ILiFi.BridgeData` — computed from the\n * facet sources in lifinance/contracts (86c3729, 2026-10-26). Packed facets and `*Min` variants read\n * raw calldata, not BridgeData, and are not listed: any other selector is refused.\n */\nconst BRIDGE_CALLS: Readonly<Record<string, {sourceSwaps: boolean}>> = {\n \"0x1fd8010c\": {sourceSwaps: false}, // startBridgeTokensViaAcross (AcrossFacet)\n \"0x3a3f7332\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaAcross (AcrossFacet)\n \"0xa1f1ce43\": {sourceSwaps: false}, // startBridgeTokensViaAcrossV4 (AcrossFacetV4)\n \"0x1794958f\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaAcrossV4 (AcrossFacetV4)\n \"0x6a90d66e\": {sourceSwaps: false}, // startBridgeTokensViaAcrossV4Swap (AcrossV4SwapFacet)\n \"0x9b054bc4\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaAcrossV4Swap (AcrossV4SwapFacet)\n \"0x6a51e9a9\": {sourceSwaps: false}, // startBridgeTokensViaAllBridge (AllBridgeFacet)\n \"0x63267469\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaAllBridge (AllBridgeFacet)\n \"0xc9851d0b\": {sourceSwaps: false}, // startBridgeTokensViaArbitrumBridge (ArbitrumBridgeFacet)\n \"0x3cc9517b\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaArbitrumBridge (ArbitrumBridgeFacet)\n \"0xe0a4201c\": {sourceSwaps: false}, // startBridgeTokensViaCelerCircleBridge (CelerCircleBridgeFacet)\n \"0x4f3b0759\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaCelerCircleBridge (CelerCircleBridgeFacet)\n \"0x0315138f\": {sourceSwaps: false}, // startBridgeTokensViaCentrifuge (CentrifugeFacet)\n \"0x8fd4d4dd\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaCentrifuge (CentrifugeFacet)\n \"0x0ad553b3\": {sourceSwaps: false}, // startBridgeTokensViaChainflip (ChainflipFacet)\n \"0xee3314a1\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaChainflip (ChainflipFacet)\n \"0x4004633e\": {sourceSwaps: false}, // startBridgeTokensViaDeBridgeDln (DeBridgeDlnFacet)\n \"0x2c7d2db0\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaDeBridgeDln (DeBridgeDlnFacet)\n \"0xbff90b61\": {sourceSwaps: false}, // startBridgeTokensViaEco (EcoFacet)\n \"0x762aea18\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaEco (EcoFacet)\n \"0x678786ea\": {sourceSwaps: false}, // startBridgeTokensViaFrax (FraxFacet)\n \"0x07b8e4c7\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaFrax (FraxFacet)\n \"0x5f9af35d\": {sourceSwaps: false}, // startBridgeTokensViaGarden (GardenFacet)\n \"0x76ad76fe\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaGarden (GardenFacet)\n \"0xfc5f1003\": {sourceSwaps: false}, // startBridgeTokensViaGasZip (GasZipFacet)\n \"0x606326ff\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaGasZip (GasZipFacet)\n \"0x6f9206ba\": {sourceSwaps: false}, // startBridgeTokensViaGlacis (GlacisFacet)\n \"0x9c4b6dd9\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaGlacis (GlacisFacet)\n \"0xf66fe519\": {sourceSwaps: false}, // startBridgeTokensViaGnosisBridge (GnosisBridgeFacet)\n \"0x7bf96e0a\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaGnosisBridge (GnosisBridgeFacet)\n \"0xee9e98e0\": {sourceSwaps: false}, // startBridgeTokensViaLayerSwap (LayerSwapFacet)\n \"0x4c279d6b\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaLayerSwap (LayerSwapFacet)\n \"0x7dbcf1d9\": {sourceSwaps: false}, // startBridgeTokensViaLiFiIntentEscrowV2 (LiFiIntentEscrowFacetV2)\n \"0x6d21c5df\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaLiFiIntentEscrowV2 (LiFiIntentEscrowFacetV2)\n \"0x65782c4b\": {sourceSwaps: false}, // startBridgeTokensViaM0 (M0Facet)\n \"0xb9eaf86d\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaM0 (M0Facet)\n \"0xb4875292\": {sourceSwaps: false}, // startBridgeTokensViaMayan (MayanFacet)\n \"0x80c65808\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaMayan (MayanFacet)\n \"0x4213dfff\": {sourceSwaps: false}, // startBridgeTokensViaMegaETHBridge (MegaETHBridgeFacet)\n \"0x22256e89\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaMegaETHBridge (MegaETHBridgeFacet)\n \"0x4698f032\": {sourceSwaps: false}, // startBridgeTokensViaNEARIntents (NEARIntentsFacet)\n \"0x02631b09\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaNEARIntents (NEARIntentsFacet)\n \"0x782621d8\": {sourceSwaps: false}, // startBridgeTokensViaOmniBridge (OmniBridgeFacet)\n \"0x95726782\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaOmniBridge (OmniBridgeFacet)\n \"0xce8a97a5\": {sourceSwaps: false}, // startBridgeTokensViaOptimismBridge (OptimismBridgeFacet)\n \"0x5bb5d448\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaOptimismBridge (OptimismBridgeFacet)\n \"0xaf62c7d6\": {sourceSwaps: false}, // startBridgeTokensViaPolygonBridge (PolygonBridgeFacet)\n \"0xb4f37581\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaPolygonBridge (PolygonBridgeFacet)\n \"0xf434d6ca\": {sourceSwaps: false}, // startBridgeTokensViaPolymerCCTP (PolymerCCTPFacet)\n \"0x17917a4e\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaPolymerCCTP (PolymerCCTPFacet)\n \"0x092e8fa4\": {sourceSwaps: false}, // startBridgeTokensViaRelayDepository (RelayDepositoryFacet)\n \"0xa3443faa\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaRelayDepository (RelayDepositoryFacet)\n \"0x3f313808\": {sourceSwaps: false}, // startBridgeTokensViaSquid (SquidFacet)\n \"0xa8f66666\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaSquid (SquidFacet)\n \"0x14d53077\": {sourceSwaps: false}, // startBridgeTokensViaStargate (StargateFacetV2)\n \"0xa6010a66\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaStargate (StargateFacetV2)\n \"0x0691ff78\": {sourceSwaps: false}, // startBridgeTokensViaSuperset (SupersetFacet)\n \"0xf26e657f\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaSuperset (SupersetFacet)\n \"0xe23b7a08\": {sourceSwaps: false}, // startBridgeTokensViaSymbiosis (SymbiosisFacet)\n \"0xc46059b2\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaSymbiosis (SymbiosisFacet)\n \"0x2541ec57\": {sourceSwaps: false}, // startBridgeTokensViaThorSwap (ThorSwapFacet)\n \"0xad673d88\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaThorSwap (ThorSwapFacet)\n \"0x64261d58\": {sourceSwaps: false}, // startBridgeTokensViaUnit (UnitFacet)\n \"0x21a3af52\": {sourceSwaps: true}, // swapAndStartBridgeTokensViaUnit (UnitFacet)\n};\n\n/** What the quote promised, in the forms the calldata carries. */\nexport interface DiamondExpectation {\n /** Source token (EVM address; the zero address for the native coin). */\n fromToken: string;\n /** Destination token as LI.FI names it (the zero address for an EVM native coin). */\n toToken: string;\n /** Input, base units. */\n amountIn: bigint;\n /** The recipient (an EVM address, or another chain's address for a non-EVM destination). */\n receiver: string;\n /** The floor the review shows. */\n minOut: bigint;\n /** LI.FI's id of the destination chain; equal to the source's for a swap. */\n destChainId: bigint;\n sameChain: boolean;\n /** The destination is an EVM chain (its receiver is a 20-byte address). */\n evmDestination: boolean;\n}\n\ninterface SwapStep {sendingAssetId: string; receivingAssetId: string; fromAmount: bigint}\n\nclass Reader {\n private readonly b: Uint8Array;\n constructor(hex: string) {\n if (!/^0x([0-9a-fA-F]{2})*$/.test(hex)) throw new Error(\"not hex\");\n this.b = Uint8Array.from(hex.slice(2).match(/../g) ?? [], (h) => Number.parseInt(h, 16));\n }\n get length() { return this.b.length; }\n word(at: number): bigint {\n if (at < 0 || at + 32 > this.b.length) throw new Error(\"out of bounds\");\n let v = 0n;\n for (let i = at; i < at + 32; i++) v = (v << 8n) | BigInt(this.b[i]!);\n return v;\n }\n /** A word that must fit a JS offset / length (bounded by the calldata). */\n small(at: number): number {\n const v = this.word(at);\n if (v > BigInt(this.b.length)) throw new Error(\"offset out of bounds\");\n return Number(v.toString()); // ≤ the calldata length\n }\n address(at: number): string {\n const v = this.word(at);\n if (v >> 160n !== 0n) throw new Error(\"not an address\");\n return `0x${v.toString(16).padStart(40, \"0\")}`;\n }\n bool(at: number): boolean {\n const v = this.word(at);\n if (v > 1n) throw new Error(\"not a bool\");\n return v === 1n;\n }\n}\n\nconst same = (a: string, b: string) => a.toLowerCase() === b.toLowerCase();\n\n/** SwapData tuple at `at`: (callTo, approveTo, sendingAssetId, receivingAssetId, fromAmount, callData, requiresDeposit). */\nfunction swapAt(r: Reader, at: number): SwapStep {\n r.address(at); r.address(at + 32);\n const step = {sendingAssetId: r.address(at + 64), receivingAssetId: r.address(at + 96), fromAmount: r.word(at + 128)};\n const bytesAt = at + r.small(at + 160);\n r.small(bytesAt); // length within the calldata\n r.bool(at + 192);\n return step;\n}\n\n/** SwapData[] whose offset word sits at `head`, relative to `base`. */\nfunction swapsAt(r: Reader, base: number, head: number): SwapStep[] {\n const array = base + r.small(head);\n const n = r.small(array);\n if (n === 0 || n > 16) throw new Error(\"bad swap count\");\n const items = array + 32;\n return Array.from({length: n}, (_, i) => swapAt(r, items + r.small(items + 32 * i)));\n}\n\nfunction checkSteps(steps: SwapStep[], e: DiamondExpectation, finalAsset: string): string | null {\n const first = steps[0]!;\n const last = steps[steps.length - 1]!;\n if (!same(first.sendingAssetId, e.fromToken)) return `spends ${first.sendingAssetId}, not ${e.fromToken}`;\n if (first.fromAmount === 0n || first.fromAmount > e.amountIn) return `swaps ${first.fromAmount}, not the ${e.amountIn} spent`;\n if (!same(last.receivingAssetId, finalAsset)) return `delivers ${last.receivingAssetId}, not ${finalAsset}`;\n return null;\n}\n\n/** Why the Diamond calldata does not do what the quote says, or null when it does. */\nexport function diamondCallMismatch(data: string, e: DiamondExpectation): string | null {\n let r: Reader;\n try { r = new Reader(data); } catch { return \"the calldata is not hex\"; }\n if (r.length < 4 + 32 * 2) return \"the calldata is too short\";\n const selector = data.slice(0, 10).toLowerCase();\n const generic = GENERIC_SWAPS[selector];\n try {\n if (generic) {\n if (!e.sameChain) return \"a same-chain swap call on a cross-chain route\";\n // (bytes32 txId, string integrator, string referrer, address receiver, uint256 minAmount, SwapData | SwapData[])\n const receiver = r.address(4 + 96);\n const minAmount = r.word(4 + 128);\n const steps = generic.single ? [swapAt(r, 4 + r.small(4 + 160))] : swapsAt(r, 4, 4 + 160);\n if (!e.evmDestination || !same(receiver, e.receiver)) return `pays ${receiver}, not ${e.receiver}`;\n if (minAmount < e.minOut) return `accepts ${minAmount}, below the ${e.minOut} shown`;\n return checkSteps(steps, e, e.toToken);\n }\n // Bridge facets: (BridgeData, [SwapData[],] FacetData), only the listed ABI entry points.\n // BridgeData is dynamic (it holds strings), so its offset is the head size.\n const bridge = BRIDGE_CALLS[selector];\n if (!bridge) return `unknown Diamond call ${selector}`;\n const head = r.small(4);\n if (head < (bridge.sourceSwaps ? 96 : 64) || head % 32 !== 0 || head > 32 * 32) return `unknown Diamond call ${selector}`;\n const at = 4 + head;\n // BridgeData: (txId, string bridge, string integrator, referrer, sendingAssetId, receiver, minAmount, destinationChainId, hasSourceSwaps, hasDestinationCall)\n if (r.small(at + 32) !== 320) return `unknown Diamond call ${selector}`;\n const sendingAssetId = r.address(at + 128);\n const receiver = r.address(at + 160);\n const minAmount = r.word(at + 192);\n const destinationChainId = r.word(at + 224);\n const hasSourceSwaps = r.bool(at + 256);\n const hasDestinationCall = r.bool(at + 288);\n if (e.sameChain) return \"a bridge call on a same-chain route\";\n if (destinationChainId !== e.destChainId) return `bridges to chain ${destinationChainId}, not ${e.destChainId}`;\n if (hasDestinationCall) return \"the route runs a call on the destination chain, whose recipient cannot be checked here\";\n if (!e.evmDestination) return \"the recipient on a non-EVM destination sits in bridge-specific data and cannot be checked here\";\n if (!same(receiver, e.receiver)) return `pays ${receiver}, not ${e.receiver}`;\n if (hasSourceSwaps !== bridge.sourceSwaps) return `unknown Diamond call ${selector}`;\n // After source swaps the bridged amount is in the swapped token's units: only the swaps' input is comparable.\n if (hasSourceSwaps) return checkSteps(swapsAt(r, 4, 4 + 32), e, sendingAssetId);\n if (minAmount === 0n || minAmount > e.amountIn) return `bridges ${minAmount}, not the ${e.amountIn} spent`;\n return same(sendingAssetId, e.fromToken) ? null : `bridges ${sendingAssetId}, not ${e.fromToken}`;\n } catch (err) {\n return `the Diamond calldata does not decode (${err instanceof Error ? err.message : String(err)})`;\n }\n}\n","import {LIFI_SOLANA_CAIP2, lifi as lifiCfg} from \"./config.js\";\nimport {describeLifiActivity} from \"./activity.js\";\nimport {diamondCallMismatch} from \"./calldata.js\";\nimport {timeoutSignal, sourceAssetOf} from \"@anywalletkit/protocol-swap2-core/util\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\nimport {bigintToNumber} from \"@anywalletkit/core\";\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(params: Pick<QuoteParams, \"sourceChain\" | \"sourceToken\" | \"sourceDecimals\">): string | null {\n const sourceChain = params.sourceChain;\n const asset = sourceAssetOf(params);\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);\n if (!fromToken) return null;\n\n const solanaSource = isSolana(params.sourceChain);\n // The placeholders price a dry quote; a live one is built for real addresses only (round 3, H8).\n const dry = params.dry !== false;\n const fromAddress = params.refundAddress || (dry ? (solanaSource ? SOLANA_PLACEHOLDER : EVM_PLACEHOLDER) : \"\");\n const toAddress = params.destAddress || (dry ? fromAddress : \"\");\n if (!fromAddress) return reject(\"a live quote needs the sender's address\");\n if (!toAddress) return reject(\"a live quote needs a recipient\");\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,\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 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 ${bigintToNumber(((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 = bigintToNumber(((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 // The calldata is what gets signed: it must pay the reviewed recipient at least the reviewed\n // minimum, in the requested tokens (round 3, H9).\n if (!solanaSource) {\n const why = diamondCallMismatch(tr.data!, {\n fromToken, toToken: expectedToToken, amountIn: BigInt(params.amountIn), receiver: toAddress, minOut: BigInt(minDestAmount),\n destChainId: BigInt(toChain), sameChain: fromChain === toChain, evmDestination: !isSolana(params.destChain),\n });\n if (why) return reject(`the transaction does not match the quote: ${why}`);\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":";;;;;;;;;AAgBA,IAAM,gBAA6D;AAAA,EACjE,cAAc,EAAC,QAAQ,MAAK;AAAA;AAAA,EAC5B,cAAc,EAAC,QAAQ,KAAI;AAAA;AAAA,EAC3B,cAAc,EAAC,QAAQ,KAAI;AAAA;AAAA,EAC3B,cAAc,EAAC,QAAQ,KAAI;AAAA;AAAA,EAC3B,cAAc,EAAC,QAAQ,MAAK;AAAA;AAAA,EAC5B,cAAc,EAAC,QAAQ,MAAK;AAAA;AAAA,EAC5B,cAAc,EAAC,QAAQ,MAAK;AAAA;AAC9B;AAQA,IAAM,eAAiE;AAAA,EACrE,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,cAAc,EAAC,aAAa,MAAK;AAAA;AAAA,EACjC,cAAc,EAAC,aAAa,KAAI;AAAA;AAAA,EAChC,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","names":["receiver","minAmount"]}