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