@anywalletkit/protocol-swap2-lifi 0.5.0 → 0.6.1
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 +19 -4
- package/dist/{chunk-67QPKWAY.js → chunk-IZ7TP4KT.js} +64 -12
- package/dist/chunk-IZ7TP4KT.js.map +1 -0
- package/dist/{chunk-V56FCCBC.js → chunk-YABKNR7N.js} +2 -2
- package/dist/index.cjs +63 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/protocol.cjs +63 -11
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.js +2 -2
- package/dist/provider.cjs +63 -11
- package/dist/provider.cjs.map +1 -1
- package/dist/provider.d.cts +9 -0
- package/dist/provider.d.ts +9 -0
- package/dist/provider.js +1 -1
- package/package.json +4 -4
- package/dist/chunk-67QPKWAY.js.map +0 -1
- /package/dist/{chunk-V56FCCBC.js.map → chunk-YABKNR7N.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
LifiSwap2Protocol
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-YABKNR7N.js";
|
|
4
4
|
import {
|
|
5
5
|
lifiPins,
|
|
6
6
|
lifiProvider,
|
|
7
7
|
lifiVerifyQuote
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-IZ7TP4KT.js";
|
|
9
9
|
import {
|
|
10
10
|
LIFI_SOLANA_CAIP2,
|
|
11
11
|
lifi
|
package/dist/protocol.cjs
CHANGED
|
@@ -125,10 +125,10 @@ var BRIDGE_CALLS = {
|
|
|
125
125
|
// startBridgeTokensViaChainflip (ChainflipFacet)
|
|
126
126
|
"0xee3314a1": { sourceSwaps: true, facet: "Chainflip" },
|
|
127
127
|
// swapAndStartBridgeTokensViaChainflip (ChainflipFacet)
|
|
128
|
-
"
|
|
129
|
-
// startBridgeTokensViaEco (EcoFacet)
|
|
130
|
-
"
|
|
131
|
-
// swapAndStartBridgeTokensViaEco (EcoFacet)
|
|
128
|
+
"0x05c54990": { sourceSwaps: false, facet: "Eco" },
|
|
129
|
+
// startBridgeTokensViaEco (EcoFacet v3.0.0, 9001792)
|
|
130
|
+
"0x8352664c": { sourceSwaps: true, facet: "Eco" },
|
|
131
|
+
// swapAndStartBridgeTokensViaEco (EcoFacet v3.0.0, 9001792)
|
|
132
132
|
"0x678786ea": { sourceSwaps: false, facet: "Frax" },
|
|
133
133
|
// startBridgeTokensViaFrax (FraxFacet)
|
|
134
134
|
"0x07b8e4c7": { sourceSwaps: true, facet: "Frax" },
|
|
@@ -342,20 +342,50 @@ function acrossSwapRefunds(r, at) {
|
|
|
342
342
|
if (target === 3n) return [["the sponsored CCTP refund recipient", c.address(64), true]];
|
|
343
343
|
throw new Error("unknown Across Swap API target");
|
|
344
344
|
}
|
|
345
|
+
var ERC20_TRANSFER = "0xa9059cbb";
|
|
346
|
+
function ecoDelivery(r, at, e) {
|
|
347
|
+
if (kindOf(e.toToken) === "native") return "an Eco route to the native token cannot be checked here";
|
|
348
|
+
const destination = r.word(at + 32 * 3);
|
|
349
|
+
if (destination !== e.destChainId) return `the Eco intent executes on chain ${destination}, not the destination ${e.destChainId} \u2014 a route whose delivery cannot be checked here`;
|
|
350
|
+
const route = r.bytes(at, at + 32 * 4);
|
|
351
|
+
const tuple = route.small(0);
|
|
352
|
+
const calls = tuple + route.small(tuple + 32 * 5);
|
|
353
|
+
const n = route.small(calls);
|
|
354
|
+
if (n === 0) return "the Eco route makes no calls on the destination chain";
|
|
355
|
+
if (n > 16) return `the Eco route makes ${n} calls on the destination chain, more than the 16 read here`;
|
|
356
|
+
const last = calls + 32 + route.small(calls + 32 + 32 * (n - 1));
|
|
357
|
+
const target = route.address(last);
|
|
358
|
+
const data = route.bytes(last, last + 32);
|
|
359
|
+
if (route.word(last + 64) !== 0n || data.length !== 68 || data.raw(0, 4) !== ERC20_TRANSFER) return "the Eco route does not end in a token transfer";
|
|
360
|
+
const to = data.address(4);
|
|
361
|
+
const amount = data.word(36);
|
|
362
|
+
if (!same(target, e.toToken)) return `the Eco route delivers ${target}, not ${e.toToken}`;
|
|
363
|
+
if (!same(to, e.receiver)) return `the Eco route pays ${to}, not ${e.receiver}`;
|
|
364
|
+
if (amount < e.minOut) return `the Eco route delivers ${amount}, below the ${e.minOut} shown`;
|
|
365
|
+
return null;
|
|
366
|
+
}
|
|
367
|
+
function m0Delivery(r, at, e) {
|
|
368
|
+
if (kindOf(e.toToken) === "native") return "an M0 order cannot deliver the native token";
|
|
369
|
+
const tokenOut = r.address(at + 32 * 3);
|
|
370
|
+
const amountOut = r.word(at + 32 * 5);
|
|
371
|
+
if (!same(tokenOut, e.toToken)) return `the M0 order asks for ${tokenOut}, not ${e.toToken}`;
|
|
372
|
+
if (amountOut < e.minOut) return `the M0 order asks for ${amountOut}, below the ${e.minOut} shown`;
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
345
375
|
var FACET_DATA = {
|
|
346
376
|
AcrossV4: { refunds: [["refundAddress", 1]], zeroRefused: true },
|
|
347
377
|
// the SpokePool depositor: an expired deposit refunds the input there
|
|
348
378
|
AcrossV4Swap: { nested: acrossSwapRefunds },
|
|
349
379
|
Centrifuge: { inline: 2, refunds: [["refundRecipient", 1]], zeroRefused: true },
|
|
350
380
|
Chainflip: { nested: chainflipRefunds },
|
|
351
|
-
Eco: { refunds: [["refundRecipient",
|
|
381
|
+
Eco: { refunds: [["refundRecipient", 6]], zeroRefused: true, delivery: ecoDelivery },
|
|
352
382
|
// the intent's creator, refunded its reward (the input) on expiry
|
|
353
383
|
Frax: { inline: 5, refunds: [["refundRecipient", 3]], zeroRefused: true },
|
|
354
384
|
Glacis: { inline: 4, refunds: [["refundAddress", 1]], zeroRefused: true },
|
|
355
385
|
LayerSwap: { refunds: [["refundRecipient", 2]], zeroRefused: true },
|
|
356
386
|
LiFiIntentEscrowV2: { refunds: [["depositAndRefundAddress", 2]], zeroRefused: true },
|
|
357
387
|
// the escrow order's user
|
|
358
|
-
M0: { inline: 7, refunds: [["refundRecipient", 1], ["orderOwner", 2]], zeroRefused: true },
|
|
388
|
+
M0: { inline: 7, refunds: [["refundRecipient", 1], ["orderOwner", 2]], zeroRefused: true, delivery: m0Delivery },
|
|
359
389
|
// orderOwner gets a cancelled order back
|
|
360
390
|
Mayan: { refunds: [["refundRecipient", 7]], nested: mayanRefunds, zeroRefused: true },
|
|
361
391
|
NEARIntents: { refunds: [["refundRecipient", 6]], zeroRefused: true },
|
|
@@ -366,11 +396,14 @@ var FACET_DATA = {
|
|
|
366
396
|
Superset: { refunds: [["refundAddress", 2], ["fallbackEoA", 3]], zeroRefused: true }
|
|
367
397
|
};
|
|
368
398
|
var NO_REFUND_FIELDS = /* @__PURE__ */ new Set(["Across", "AllBridge", "ArbitrumBridge", "CelerCircleBridge", "GasZip", "GnosisBridge", "MegaETHBridge", "OmniBridge", "OptimismBridge", "PolygonBridge", "Unit"]);
|
|
399
|
+
function facetDataAt(r, bridge, spec) {
|
|
400
|
+
const slot = 4 + (bridge.sourceSwaps ? 64 : 32);
|
|
401
|
+
return spec.inline ? slot : 4 + r.small(slot);
|
|
402
|
+
}
|
|
369
403
|
function refundMismatch(r, bridge, e) {
|
|
370
404
|
const spec = FACET_DATA[bridge.facet];
|
|
371
405
|
if (!spec) return NO_REFUND_FIELDS.has(bridge.facet) ? null : `no known refund layout for ${bridge.facet}`;
|
|
372
|
-
const
|
|
373
|
-
const at = spec.inline ? slot : 4 + r.small(slot);
|
|
406
|
+
const at = facetDataAt(r, bridge, spec);
|
|
374
407
|
const paid = (spec.refunds ?? []).map(([field, word]) => [`${bridge.facet} ${field}`, r.address(at + 32 * word), spec.zeroRefused === true]);
|
|
375
408
|
paid.push(...spec.nested?.(r, at) ?? []);
|
|
376
409
|
for (const [what, to, zeroRefused] of paid) {
|
|
@@ -425,6 +458,9 @@ function diamondCallMismatch(data, e) {
|
|
|
425
458
|
if (hasSourceSwaps !== bridge.sourceSwaps) return `unknown Diamond call ${selector}`;
|
|
426
459
|
const refund = refundMismatch(r, bridge, e);
|
|
427
460
|
if (refund) return refund;
|
|
461
|
+
const spec = FACET_DATA[bridge.facet];
|
|
462
|
+
const delivery = spec?.delivery?.(r, facetDataAt(r, bridge, spec), e);
|
|
463
|
+
if (delivery) return delivery;
|
|
428
464
|
if (hasSourceSwaps) {
|
|
429
465
|
if (minAmount === 0n) return "bridges nothing after the source swaps";
|
|
430
466
|
return checkSteps(swapsAt(r, 4, 4 + 32), e, sendingAssetId);
|
|
@@ -739,6 +775,9 @@ function lifiProvider(config = {}) {
|
|
|
739
775
|
const fromToken = lifiToken(params);
|
|
740
776
|
if (!fromToken) return null;
|
|
741
777
|
const solanaSource = isSolana(params.sourceChain);
|
|
778
|
+
const crossChain = params.sourceChain !== params.destChain;
|
|
779
|
+
const noDestinationCall = crossChain && !solanaSource;
|
|
780
|
+
let routeScope = config.routeWideSlippage === true && !solanaSource && !isSolana(params.destChain);
|
|
742
781
|
const dry = params.dry !== false;
|
|
743
782
|
const fromAddress = params.refundAddress || (dry ? solanaSource ? SOLANA_PLACEHOLDER : EVM_PLACEHOLDER : "");
|
|
744
783
|
const toAddress = params.destAddress || (dry ? fromAddress : "");
|
|
@@ -748,7 +787,7 @@ function lifiProvider(config = {}) {
|
|
|
748
787
|
let sentSlippage = slippageBps / 1e4;
|
|
749
788
|
let deadline;
|
|
750
789
|
let choice = null;
|
|
751
|
-
if (config.chooseRoute &&
|
|
790
|
+
if (config.chooseRoute && crossChain) {
|
|
752
791
|
try {
|
|
753
792
|
const res = await fetch(`${apiBase}/advanced/routes`, {
|
|
754
793
|
method: "POST",
|
|
@@ -761,7 +800,13 @@ function lifiProvider(config = {}) {
|
|
|
761
800
|
fromAmount: params.amountIn,
|
|
762
801
|
fromAddress,
|
|
763
802
|
toAddress,
|
|
764
|
-
options: {
|
|
803
|
+
options: {
|
|
804
|
+
slippage: slippageBps / 1e4,
|
|
805
|
+
...routeScope ? { slippageScope: "route" } : {},
|
|
806
|
+
...solanaSource ? {} : { bridges: { deny: UNBOUND_TOOLS } },
|
|
807
|
+
...noDestinationCall ? { allowDestinationCall: false } : {},
|
|
808
|
+
...integrator().trim() ? { integrator: integrator().trim() } : {}
|
|
809
|
+
}
|
|
765
810
|
}),
|
|
766
811
|
signal: signal ?? (0, import_util3.timeoutSignal)(8e3)
|
|
767
812
|
});
|
|
@@ -786,7 +831,9 @@ function lifiProvider(config = {}) {
|
|
|
786
831
|
if (sentSlippage !== void 0) {
|
|
787
832
|
url.searchParams.set("slippage", String(sentSlippage));
|
|
788
833
|
}
|
|
789
|
-
|
|
834
|
+
if (routeScope) url.searchParams.set("slippageScope", "route");
|
|
835
|
+
if (noDestinationCall) url.searchParams.set("allowDestinationCall", "false");
|
|
836
|
+
const unbound = crossChain && !solanaSource ? UNBOUND_TOOLS : [];
|
|
790
837
|
for (const t of (choice?.allowBridges ?? []).filter((b) => solanaSource || !UNBOUND_TOOLS.includes(b))) url.searchParams.append("allowBridges", t);
|
|
791
838
|
for (const t of /* @__PURE__ */ new Set([...choice?.denyBridges ?? [], ...unbound])) url.searchParams.append("denyBridges", t);
|
|
792
839
|
if (choice?.order) url.searchParams.set("order", choice.order);
|
|
@@ -800,6 +847,11 @@ function lifiProvider(config = {}) {
|
|
|
800
847
|
if (!res.ok) {
|
|
801
848
|
const body = await res.json().catch(() => null);
|
|
802
849
|
const reasons = [...new Set((body?.errors?.filteredOut ?? []).map((f) => f.reason).filter((r) => typeof r === "string"))];
|
|
850
|
+
if (routeScope && [typeof body?.message === "string" ? body.message : "", ...reasons].some((r) => /^ROUTE_SLIPPAGE_(UNSUPPORTED|UNAVAILABLE)/.test(r))) {
|
|
851
|
+
routeScope = false;
|
|
852
|
+
attempt--;
|
|
853
|
+
continue;
|
|
854
|
+
}
|
|
803
855
|
const why = reasons.length === 1 ? ` (${reasons[0].slice(0, 200)})` : "";
|
|
804
856
|
params.onRefusal?.(`lifi: ${typeof body?.message === "string" ? body.message.slice(0, 200) : `HTTP ${res.status}`}${why}`);
|
|
805
857
|
return null;
|