@anywalletkit/protocol-swap2-lifi 0.4.0 → 0.5.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 +8 -4
- package/dist/{chunk-TQYG23FS.js → chunk-67QPKWAY.js} +286 -89
- package/dist/chunk-67QPKWAY.js.map +1 -0
- package/dist/{chunk-7SUAXOPF.js → chunk-V56FCCBC.js} +2 -2
- package/dist/index.cjs +290 -93
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/protocol.cjs +290 -93
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.js +2 -2
- package/dist/provider.cjs +290 -93
- package/dist/provider.cjs.map +1 -1
- package/dist/provider.d.cts +2 -1
- package/dist/provider.d.ts +2 -1
- package/dist/provider.js +1 -1
- package/package.json +5 -5
- package/dist/chunk-TQYG23FS.js.map +0 -1
- /package/dist/{chunk-7SUAXOPF.js.map → chunk-V56FCCBC.js.map} +0 -0
package/README.md
CHANGED
|
@@ -24,9 +24,13 @@ do the same: a same-chain swap (GenericSwapFacet / V3) pays the reviewed recipie
|
|
|
24
24
|
reviewed minimum, spending the input token and delivering the requested one; a bridge call must be
|
|
25
25
|
one of LI.FI's listed `startBridgeTokensVia*` / `swapAndStartBridgeTokensVia*` entry points (packed
|
|
26
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).
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
input token (or what its source swaps make of it). Every refund, depositor or fallback address a
|
|
28
|
+
bridge carries in its own data (Stargate's LayerZero fee refund, an expired Across deposit or LI.FI
|
|
29
|
+
intent, a Mayan Swift order's trader, Chainflip's refund address, …) must be the sender or the
|
|
30
|
+
recipient. Refused, because the recipient cannot be read from the calldata: routes with a destination call, EVM-source routes to a non-EVM chain, and the
|
|
31
|
+
bridges whose facet does not bind the delivery to `BridgeData` (Relay, Garden, deBridge DLN,
|
|
32
|
+
ThorSwap, Squid, Symbiosis) — cross-chain requests ask LI.FI to route around Relay, Garden, Squid
|
|
33
|
+
and Symbiosis, so their pairs get another bridge. Unknown calldata is refused.
|
|
30
34
|
|
|
31
35
|
Every swap step is read, not only the ends: each must spend what the step before delivered, only
|
|
32
36
|
steps that spend the input token may pull from the wallet (`requiresDeposit`), and together at most
|
|
@@ -46,7 +50,7 @@ When the provider runs on your server, spread its pins into the app's stub:
|
|
|
46
50
|
`remoteProvider({name: "lifi", baseUrl, ...lifiPins})`. The engine then lets the EVM route call and
|
|
47
51
|
approve only the LI.FI Diamond of that chain, never an address the backend names, and `lifiVerifyQuote` decodes the
|
|
48
52
|
server's Diamond call on the device with the same check the provider runs on LI.FI's answer (receiver, minimum, input
|
|
49
|
-
token and amount, output token, destination chain; value and approval for the input kind). Without the pins the stub
|
|
53
|
+
token and amount, output token, destination chain, refund addresses; value and approval for the input kind). Without the pins the stub
|
|
50
54
|
gets no EVM calldata route (fail closed).
|
|
51
55
|
|
|
52
56
|
## Activity
|
|
@@ -26,144 +26,162 @@ var GENERIC_SWAPS = {
|
|
|
26
26
|
var BRIDGE_INPUT_FEE_MAX_BPS = 100n;
|
|
27
27
|
var kindOf = (asset) => /^0x0{40}$/i.test(asset) ? "native" : "erc20";
|
|
28
28
|
var BRIDGE_CALLS = {
|
|
29
|
-
"0x1fd8010c": { sourceSwaps: false },
|
|
29
|
+
"0x1fd8010c": { sourceSwaps: false, facet: "Across" },
|
|
30
30
|
// startBridgeTokensViaAcross (AcrossFacet)
|
|
31
|
-
"0x3a3f7332": { sourceSwaps: true },
|
|
31
|
+
"0x3a3f7332": { sourceSwaps: true, facet: "Across" },
|
|
32
32
|
// swapAndStartBridgeTokensViaAcross (AcrossFacet)
|
|
33
|
-
"0xa1f1ce43": { sourceSwaps: false },
|
|
33
|
+
"0xa1f1ce43": { sourceSwaps: false, facet: "AcrossV4" },
|
|
34
34
|
// startBridgeTokensViaAcrossV4 (AcrossFacetV4)
|
|
35
|
-
"0x1794958f": { sourceSwaps: true },
|
|
35
|
+
"0x1794958f": { sourceSwaps: true, facet: "AcrossV4" },
|
|
36
36
|
// swapAndStartBridgeTokensViaAcrossV4 (AcrossFacetV4)
|
|
37
|
-
"0x6a90d66e": { sourceSwaps: false },
|
|
37
|
+
"0x6a90d66e": { sourceSwaps: false, facet: "AcrossV4Swap" },
|
|
38
38
|
// startBridgeTokensViaAcrossV4Swap (AcrossV4SwapFacet)
|
|
39
|
-
"0x9b054bc4": { sourceSwaps: true },
|
|
39
|
+
"0x9b054bc4": { sourceSwaps: true, facet: "AcrossV4Swap" },
|
|
40
40
|
// swapAndStartBridgeTokensViaAcrossV4Swap (AcrossV4SwapFacet)
|
|
41
|
-
"0x6a51e9a9": { sourceSwaps: false },
|
|
41
|
+
"0x6a51e9a9": { sourceSwaps: false, facet: "AllBridge" },
|
|
42
42
|
// startBridgeTokensViaAllBridge (AllBridgeFacet)
|
|
43
|
-
"0x63267469": { sourceSwaps: true },
|
|
43
|
+
"0x63267469": { sourceSwaps: true, facet: "AllBridge" },
|
|
44
44
|
// swapAndStartBridgeTokensViaAllBridge (AllBridgeFacet)
|
|
45
|
-
"0xc9851d0b": { sourceSwaps: false },
|
|
45
|
+
"0xc9851d0b": { sourceSwaps: false, facet: "ArbitrumBridge" },
|
|
46
46
|
// startBridgeTokensViaArbitrumBridge (ArbitrumBridgeFacet)
|
|
47
|
-
"0x3cc9517b": { sourceSwaps: true },
|
|
47
|
+
"0x3cc9517b": { sourceSwaps: true, facet: "ArbitrumBridge" },
|
|
48
48
|
// swapAndStartBridgeTokensViaArbitrumBridge (ArbitrumBridgeFacet)
|
|
49
|
-
"0xe0a4201c": { sourceSwaps: false },
|
|
49
|
+
"0xe0a4201c": { sourceSwaps: false, facet: "CelerCircleBridge" },
|
|
50
50
|
// startBridgeTokensViaCelerCircleBridge (CelerCircleBridgeFacet)
|
|
51
|
-
"0x4f3b0759": { sourceSwaps: true },
|
|
51
|
+
"0x4f3b0759": { sourceSwaps: true, facet: "CelerCircleBridge" },
|
|
52
52
|
// swapAndStartBridgeTokensViaCelerCircleBridge (CelerCircleBridgeFacet)
|
|
53
|
-
"0x0315138f": { sourceSwaps: false },
|
|
53
|
+
"0x0315138f": { sourceSwaps: false, facet: "Centrifuge" },
|
|
54
54
|
// startBridgeTokensViaCentrifuge (CentrifugeFacet)
|
|
55
|
-
"0x8fd4d4dd": { sourceSwaps: true },
|
|
55
|
+
"0x8fd4d4dd": { sourceSwaps: true, facet: "Centrifuge" },
|
|
56
56
|
// swapAndStartBridgeTokensViaCentrifuge (CentrifugeFacet)
|
|
57
|
-
"0x0ad553b3": { sourceSwaps: false },
|
|
57
|
+
"0x0ad553b3": { sourceSwaps: false, facet: "Chainflip" },
|
|
58
58
|
// startBridgeTokensViaChainflip (ChainflipFacet)
|
|
59
|
-
"0xee3314a1": { sourceSwaps: true },
|
|
59
|
+
"0xee3314a1": { sourceSwaps: true, facet: "Chainflip" },
|
|
60
60
|
// swapAndStartBridgeTokensViaChainflip (ChainflipFacet)
|
|
61
|
-
"
|
|
62
|
-
// startBridgeTokensViaDeBridgeDln (DeBridgeDlnFacet)
|
|
63
|
-
"0x2c7d2db0": { sourceSwaps: true },
|
|
64
|
-
// swapAndStartBridgeTokensViaDeBridgeDln (DeBridgeDlnFacet)
|
|
65
|
-
"0xbff90b61": { sourceSwaps: false },
|
|
61
|
+
"0xbff90b61": { sourceSwaps: false, facet: "Eco" },
|
|
66
62
|
// startBridgeTokensViaEco (EcoFacet)
|
|
67
|
-
"0x762aea18": { sourceSwaps: true },
|
|
63
|
+
"0x762aea18": { sourceSwaps: true, facet: "Eco" },
|
|
68
64
|
// swapAndStartBridgeTokensViaEco (EcoFacet)
|
|
69
|
-
"0x678786ea": { sourceSwaps: false },
|
|
65
|
+
"0x678786ea": { sourceSwaps: false, facet: "Frax" },
|
|
70
66
|
// startBridgeTokensViaFrax (FraxFacet)
|
|
71
|
-
"0x07b8e4c7": { sourceSwaps: true },
|
|
67
|
+
"0x07b8e4c7": { sourceSwaps: true, facet: "Frax" },
|
|
72
68
|
// swapAndStartBridgeTokensViaFrax (FraxFacet)
|
|
73
|
-
"
|
|
74
|
-
// startBridgeTokensViaGarden (GardenFacet)
|
|
75
|
-
"0x76ad76fe": { sourceSwaps: true },
|
|
76
|
-
// swapAndStartBridgeTokensViaGarden (GardenFacet)
|
|
77
|
-
"0xfc5f1003": { sourceSwaps: false },
|
|
69
|
+
"0xfc5f1003": { sourceSwaps: false, facet: "GasZip" },
|
|
78
70
|
// startBridgeTokensViaGasZip (GasZipFacet)
|
|
79
|
-
"0x606326ff": { sourceSwaps: true },
|
|
71
|
+
"0x606326ff": { sourceSwaps: true, facet: "GasZip" },
|
|
80
72
|
// swapAndStartBridgeTokensViaGasZip (GasZipFacet)
|
|
81
|
-
"0x6f9206ba": { sourceSwaps: false },
|
|
73
|
+
"0x6f9206ba": { sourceSwaps: false, facet: "Glacis" },
|
|
82
74
|
// startBridgeTokensViaGlacis (GlacisFacet)
|
|
83
|
-
"0x9c4b6dd9": { sourceSwaps: true },
|
|
75
|
+
"0x9c4b6dd9": { sourceSwaps: true, facet: "Glacis" },
|
|
84
76
|
// swapAndStartBridgeTokensViaGlacis (GlacisFacet)
|
|
85
|
-
"0xf66fe519": { sourceSwaps: false },
|
|
77
|
+
"0xf66fe519": { sourceSwaps: false, facet: "GnosisBridge" },
|
|
86
78
|
// startBridgeTokensViaGnosisBridge (GnosisBridgeFacet)
|
|
87
|
-
"0x7bf96e0a": { sourceSwaps: true },
|
|
79
|
+
"0x7bf96e0a": { sourceSwaps: true, facet: "GnosisBridge" },
|
|
88
80
|
// swapAndStartBridgeTokensViaGnosisBridge (GnosisBridgeFacet)
|
|
89
|
-
"0xee9e98e0": { sourceSwaps: false },
|
|
81
|
+
"0xee9e98e0": { sourceSwaps: false, facet: "LayerSwap" },
|
|
90
82
|
// startBridgeTokensViaLayerSwap (LayerSwapFacet)
|
|
91
|
-
"0x4c279d6b": { sourceSwaps: true },
|
|
83
|
+
"0x4c279d6b": { sourceSwaps: true, facet: "LayerSwap" },
|
|
92
84
|
// swapAndStartBridgeTokensViaLayerSwap (LayerSwapFacet)
|
|
93
|
-
"0x7dbcf1d9": { sourceSwaps: false },
|
|
85
|
+
"0x7dbcf1d9": { sourceSwaps: false, facet: "LiFiIntentEscrowV2" },
|
|
94
86
|
// startBridgeTokensViaLiFiIntentEscrowV2 (LiFiIntentEscrowFacetV2)
|
|
95
|
-
"0x6d21c5df": { sourceSwaps: true },
|
|
87
|
+
"0x6d21c5df": { sourceSwaps: true, facet: "LiFiIntentEscrowV2" },
|
|
96
88
|
// swapAndStartBridgeTokensViaLiFiIntentEscrowV2 (LiFiIntentEscrowFacetV2)
|
|
97
|
-
"0x65782c4b": { sourceSwaps: false },
|
|
89
|
+
"0x65782c4b": { sourceSwaps: false, facet: "M0" },
|
|
98
90
|
// startBridgeTokensViaM0 (M0Facet)
|
|
99
|
-
"0xb9eaf86d": { sourceSwaps: true },
|
|
91
|
+
"0xb9eaf86d": { sourceSwaps: true, facet: "M0" },
|
|
100
92
|
// swapAndStartBridgeTokensViaM0 (M0Facet)
|
|
101
|
-
"0xb4875292": { sourceSwaps: false },
|
|
93
|
+
"0xb4875292": { sourceSwaps: false, facet: "Mayan" },
|
|
102
94
|
// startBridgeTokensViaMayan (MayanFacet)
|
|
103
|
-
"0x80c65808": { sourceSwaps: true },
|
|
95
|
+
"0x80c65808": { sourceSwaps: true, facet: "Mayan" },
|
|
104
96
|
// swapAndStartBridgeTokensViaMayan (MayanFacet)
|
|
105
|
-
"0x4213dfff": { sourceSwaps: false },
|
|
97
|
+
"0x4213dfff": { sourceSwaps: false, facet: "MegaETHBridge" },
|
|
106
98
|
// startBridgeTokensViaMegaETHBridge (MegaETHBridgeFacet)
|
|
107
|
-
"0x22256e89": { sourceSwaps: true },
|
|
99
|
+
"0x22256e89": { sourceSwaps: true, facet: "MegaETHBridge" },
|
|
108
100
|
// swapAndStartBridgeTokensViaMegaETHBridge (MegaETHBridgeFacet)
|
|
109
|
-
"0x4698f032": { sourceSwaps: false },
|
|
101
|
+
"0x4698f032": { sourceSwaps: false, facet: "NEARIntents" },
|
|
110
102
|
// startBridgeTokensViaNEARIntents (NEARIntentsFacet)
|
|
111
|
-
"0x02631b09": { sourceSwaps: true },
|
|
103
|
+
"0x02631b09": { sourceSwaps: true, facet: "NEARIntents" },
|
|
112
104
|
// swapAndStartBridgeTokensViaNEARIntents (NEARIntentsFacet)
|
|
113
|
-
"0x782621d8": { sourceSwaps: false },
|
|
105
|
+
"0x782621d8": { sourceSwaps: false, facet: "OmniBridge" },
|
|
114
106
|
// startBridgeTokensViaOmniBridge (OmniBridgeFacet)
|
|
115
|
-
"0x95726782": { sourceSwaps: true },
|
|
107
|
+
"0x95726782": { sourceSwaps: true, facet: "OmniBridge" },
|
|
116
108
|
// swapAndStartBridgeTokensViaOmniBridge (OmniBridgeFacet)
|
|
117
|
-
"0xce8a97a5": { sourceSwaps: false },
|
|
109
|
+
"0xce8a97a5": { sourceSwaps: false, facet: "OptimismBridge" },
|
|
118
110
|
// startBridgeTokensViaOptimismBridge (OptimismBridgeFacet)
|
|
119
|
-
"0x5bb5d448": { sourceSwaps: true },
|
|
111
|
+
"0x5bb5d448": { sourceSwaps: true, facet: "OptimismBridge" },
|
|
120
112
|
// swapAndStartBridgeTokensViaOptimismBridge (OptimismBridgeFacet)
|
|
121
|
-
"0xaf62c7d6": { sourceSwaps: false },
|
|
113
|
+
"0xaf62c7d6": { sourceSwaps: false, facet: "PolygonBridge" },
|
|
122
114
|
// startBridgeTokensViaPolygonBridge (PolygonBridgeFacet)
|
|
123
|
-
"0xb4f37581": { sourceSwaps: true },
|
|
115
|
+
"0xb4f37581": { sourceSwaps: true, facet: "PolygonBridge" },
|
|
124
116
|
// swapAndStartBridgeTokensViaPolygonBridge (PolygonBridgeFacet)
|
|
125
|
-
"0xf434d6ca": { sourceSwaps: false },
|
|
117
|
+
"0xf434d6ca": { sourceSwaps: false, facet: "PolymerCCTP" },
|
|
126
118
|
// startBridgeTokensViaPolymerCCTP (PolymerCCTPFacet)
|
|
127
|
-
"0x17917a4e": { sourceSwaps: true },
|
|
119
|
+
"0x17917a4e": { sourceSwaps: true, facet: "PolymerCCTP" },
|
|
128
120
|
// swapAndStartBridgeTokensViaPolymerCCTP (PolymerCCTPFacet)
|
|
129
|
-
"
|
|
130
|
-
// startBridgeTokensViaRelayDepository (RelayDepositoryFacet)
|
|
131
|
-
"0xa3443faa": { sourceSwaps: true },
|
|
132
|
-
// swapAndStartBridgeTokensViaRelayDepository (RelayDepositoryFacet)
|
|
133
|
-
"0x3f313808": { sourceSwaps: false },
|
|
134
|
-
// startBridgeTokensViaSquid (SquidFacet)
|
|
135
|
-
"0xa8f66666": { sourceSwaps: true },
|
|
136
|
-
// swapAndStartBridgeTokensViaSquid (SquidFacet)
|
|
137
|
-
"0x14d53077": { sourceSwaps: false },
|
|
121
|
+
"0x14d53077": { sourceSwaps: false, facet: "Stargate" },
|
|
138
122
|
// startBridgeTokensViaStargate (StargateFacetV2)
|
|
139
|
-
"0xa6010a66": { sourceSwaps: true },
|
|
123
|
+
"0xa6010a66": { sourceSwaps: true, facet: "Stargate" },
|
|
140
124
|
// swapAndStartBridgeTokensViaStargate (StargateFacetV2)
|
|
141
|
-
"0x0691ff78": { sourceSwaps: false },
|
|
125
|
+
"0x0691ff78": { sourceSwaps: false, facet: "Superset" },
|
|
142
126
|
// startBridgeTokensViaSuperset (SupersetFacet)
|
|
143
|
-
"0xf26e657f": { sourceSwaps: true },
|
|
127
|
+
"0xf26e657f": { sourceSwaps: true, facet: "Superset" },
|
|
144
128
|
// swapAndStartBridgeTokensViaSuperset (SupersetFacet)
|
|
145
|
-
"
|
|
146
|
-
// startBridgeTokensViaSymbiosis (SymbiosisFacet)
|
|
147
|
-
"0xc46059b2": { sourceSwaps: true },
|
|
148
|
-
// swapAndStartBridgeTokensViaSymbiosis (SymbiosisFacet)
|
|
149
|
-
"0x2541ec57": { sourceSwaps: false },
|
|
150
|
-
// startBridgeTokensViaThorSwap (ThorSwapFacet)
|
|
151
|
-
"0xad673d88": { sourceSwaps: true },
|
|
152
|
-
// swapAndStartBridgeTokensViaThorSwap (ThorSwapFacet)
|
|
153
|
-
"0x64261d58": { sourceSwaps: false },
|
|
129
|
+
"0x64261d58": { sourceSwaps: false, facet: "Unit" },
|
|
154
130
|
// startBridgeTokensViaUnit (UnitFacet)
|
|
155
|
-
"0x21a3af52": { sourceSwaps: true }
|
|
131
|
+
"0x21a3af52": { sourceSwaps: true, facet: "Unit" }
|
|
156
132
|
// swapAndStartBridgeTokensViaUnit (UnitFacet)
|
|
157
133
|
};
|
|
158
|
-
var
|
|
134
|
+
var UNBOUND_BRIDGES = {
|
|
135
|
+
"0x092e8fa4": "Relay",
|
|
136
|
+
// startBridgeTokensViaRelayDepository
|
|
137
|
+
"0xa3443faa": "Relay",
|
|
138
|
+
// swapAndStartBridgeTokensViaRelayDepository
|
|
139
|
+
"0x5f9af35d": "Garden",
|
|
140
|
+
// startBridgeTokensViaGarden
|
|
141
|
+
"0x76ad76fe": "Garden",
|
|
142
|
+
// swapAndStartBridgeTokensViaGarden
|
|
143
|
+
"0x4004633e": "deBridge DLN",
|
|
144
|
+
// startBridgeTokensViaDeBridgeDln
|
|
145
|
+
"0x2c7d2db0": "deBridge DLN",
|
|
146
|
+
// swapAndStartBridgeTokensViaDeBridgeDln
|
|
147
|
+
"0x2541ec57": "ThorSwap",
|
|
148
|
+
// startBridgeTokensViaThorSwap
|
|
149
|
+
"0xad673d88": "ThorSwap",
|
|
150
|
+
// swapAndStartBridgeTokensViaThorSwap
|
|
151
|
+
"0x3f313808": "Squid",
|
|
152
|
+
// startBridgeTokensViaSquid
|
|
153
|
+
"0xa8f66666": "Squid",
|
|
154
|
+
// swapAndStartBridgeTokensViaSquid
|
|
155
|
+
"0xe23b7a08": "Symbiosis",
|
|
156
|
+
// startBridgeTokensViaSymbiosis
|
|
157
|
+
"0xc46059b2": "Symbiosis"
|
|
158
|
+
// swapAndStartBridgeTokensViaSymbiosis
|
|
159
|
+
};
|
|
160
|
+
var Reader = class _Reader {
|
|
159
161
|
b;
|
|
160
|
-
constructor(
|
|
161
|
-
if (
|
|
162
|
-
|
|
162
|
+
constructor(src) {
|
|
163
|
+
if (typeof src !== "string") {
|
|
164
|
+
this.b = src;
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (!/^0x([0-9a-fA-F]{2})*$/.test(src)) throw new Error("not hex");
|
|
168
|
+
this.b = Uint8Array.from(src.slice(2).match(/../g) ?? [], (h) => Number.parseInt(h, 16));
|
|
163
169
|
}
|
|
164
170
|
get length() {
|
|
165
171
|
return this.b.length;
|
|
166
172
|
}
|
|
173
|
+
/** `n` raw bytes at `at`, as 0x-hex. */
|
|
174
|
+
raw(at, n) {
|
|
175
|
+
if (at < 0 || at + n > this.b.length) throw new Error("out of bounds");
|
|
176
|
+
return `0x${Array.from(this.b.subarray(at, at + n), (x) => x.toString(16).padStart(2, "0")).join("")}`;
|
|
177
|
+
}
|
|
178
|
+
/** The `bytes` whose offset word sits at `head` (relative to `base`), as a reader over its contents only. */
|
|
179
|
+
bytes(base, head) {
|
|
180
|
+
const at = base + this.small(head);
|
|
181
|
+
const n = this.small(at);
|
|
182
|
+
if (at + 32 + n > this.b.length) throw new Error("bytes out of bounds");
|
|
183
|
+
return new _Reader(this.b.subarray(at + 32, at + 32 + n));
|
|
184
|
+
}
|
|
167
185
|
word(at) {
|
|
168
186
|
if (at < 0 || at + 32 > this.b.length) throw new Error("out of bounds");
|
|
169
187
|
let v = 0n;
|
|
@@ -221,6 +239,79 @@ function checkSteps(steps, e, finalAsset) {
|
|
|
221
239
|
if (!same(last.receivingAssetId, finalAsset)) return `delivers ${last.receivingAssetId}, not ${finalAsset}`;
|
|
222
240
|
return null;
|
|
223
241
|
}
|
|
242
|
+
var MAYAN_REFUND_AT = {
|
|
243
|
+
"0xa3a30834": 4 + 32 * 3,
|
|
244
|
+
// Swift v2 createOrderWithToken(tokenIn, amountIn, (payloadType, trader, destAddr, …), customPayload)
|
|
245
|
+
"0x6147435b": 4 + 32 * 3,
|
|
246
|
+
// Swift v2 createOrderWithSig: the same order tuple
|
|
247
|
+
"0xb866e173": 4,
|
|
248
|
+
// Swift createOrderWithEth((trader, tokenOut, …))
|
|
249
|
+
"0x8e8d142b": 4 + 32 * 2,
|
|
250
|
+
// Swift createOrderWithToken(tokenIn, amountIn, (trader, tokenOut, …))
|
|
251
|
+
"0x6111ad25": 4 + 32 * 9,
|
|
252
|
+
// MayanSwap swap(relayerFees, (mayanAddr, mayanChainId, auctionAddr, destAddr, destChainId, referrer, refundAddr), …)
|
|
253
|
+
"0x1eb1cff0": 4 + 32 * 9
|
|
254
|
+
// MayanSwap wrapAndSwapETH: the same recipient tuple
|
|
255
|
+
};
|
|
256
|
+
function mayanRefunds(r, at) {
|
|
257
|
+
const p = r.bytes(at, at + 32 * 2);
|
|
258
|
+
const pos = MAYAN_REFUND_AT[p.raw(0, 4)];
|
|
259
|
+
return pos === void 0 ? [] : [["the Mayan order's refund address", p.address(pos)]];
|
|
260
|
+
}
|
|
261
|
+
function chainflipRefunds(r, at) {
|
|
262
|
+
const p = r.bytes(at, at + 32 * 5);
|
|
263
|
+
if (p.length < 25 || p.raw(0, 1) !== "0x01") throw new Error("unknown Chainflip parameters");
|
|
264
|
+
return [["the Chainflip refund address", p.raw(5, 20)]];
|
|
265
|
+
}
|
|
266
|
+
function acrossSwapRefunds(r, at) {
|
|
267
|
+
const target = r.word(at);
|
|
268
|
+
const c = r.bytes(at, at + 32);
|
|
269
|
+
if (target === 0n) return [["the Across deposit's depositor", c.address(c.small(0)), true]];
|
|
270
|
+
if (target === 1n) {
|
|
271
|
+
const swap = c.small(0);
|
|
272
|
+
return [["the Across deposit's depositor", c.address(swap + c.small(swap + 64) + 96), true]];
|
|
273
|
+
}
|
|
274
|
+
if (target === 2n) return [["the sponsored OFT refund recipient", c.address(c.small(0) + 32), true]];
|
|
275
|
+
if (target === 3n) return [["the sponsored CCTP refund recipient", c.address(64), true]];
|
|
276
|
+
throw new Error("unknown Across Swap API target");
|
|
277
|
+
}
|
|
278
|
+
var FACET_DATA = {
|
|
279
|
+
AcrossV4: { refunds: [["refundAddress", 1]], zeroRefused: true },
|
|
280
|
+
// the SpokePool depositor: an expired deposit refunds the input there
|
|
281
|
+
AcrossV4Swap: { nested: acrossSwapRefunds },
|
|
282
|
+
Centrifuge: { inline: 2, refunds: [["refundRecipient", 1]], zeroRefused: true },
|
|
283
|
+
Chainflip: { nested: chainflipRefunds },
|
|
284
|
+
Eco: { refunds: [["refundRecipient", 5]], zeroRefused: true },
|
|
285
|
+
// the intent's creator, refunded its reward (the input) on expiry
|
|
286
|
+
Frax: { inline: 5, refunds: [["refundRecipient", 3]], zeroRefused: true },
|
|
287
|
+
Glacis: { inline: 4, refunds: [["refundAddress", 1]], zeroRefused: true },
|
|
288
|
+
LayerSwap: { refunds: [["refundRecipient", 2]], zeroRefused: true },
|
|
289
|
+
LiFiIntentEscrowV2: { refunds: [["depositAndRefundAddress", 2]], zeroRefused: true },
|
|
290
|
+
// the escrow order's user
|
|
291
|
+
M0: { inline: 7, refunds: [["refundRecipient", 1], ["orderOwner", 2]], zeroRefused: true },
|
|
292
|
+
// orderOwner gets a cancelled order back
|
|
293
|
+
Mayan: { refunds: [["refundRecipient", 7]], nested: mayanRefunds, zeroRefused: true },
|
|
294
|
+
NEARIntents: { refunds: [["refundRecipient", 6]], zeroRefused: true },
|
|
295
|
+
// also the 1Click quote's refundTo
|
|
296
|
+
PolymerCCTP: { refunds: [["refundRecipient", 5]], zeroRefused: true },
|
|
297
|
+
Stargate: { refunds: [["refundAddress", 4]] },
|
|
298
|
+
// (assetId, sendParams, fee.nativeFee, fee.lzTokenFee, refundAddress): LayerZero's fee refund
|
|
299
|
+
Superset: { refunds: [["refundAddress", 2], ["fallbackEoA", 3]], zeroRefused: true }
|
|
300
|
+
};
|
|
301
|
+
var NO_REFUND_FIELDS = /* @__PURE__ */ new Set(["Across", "AllBridge", "ArbitrumBridge", "CelerCircleBridge", "GasZip", "GnosisBridge", "MegaETHBridge", "OmniBridge", "OptimismBridge", "PolygonBridge", "Unit"]);
|
|
302
|
+
function refundMismatch(r, bridge, e) {
|
|
303
|
+
const spec = FACET_DATA[bridge.facet];
|
|
304
|
+
if (!spec) return NO_REFUND_FIELDS.has(bridge.facet) ? null : `no known refund layout for ${bridge.facet}`;
|
|
305
|
+
const slot = 4 + (bridge.sourceSwaps ? 64 : 32);
|
|
306
|
+
const at = spec.inline ? slot : 4 + r.small(slot);
|
|
307
|
+
const paid = (spec.refunds ?? []).map(([field, word]) => [`${bridge.facet} ${field}`, r.address(at + 32 * word), spec.zeroRefused === true]);
|
|
308
|
+
paid.push(...spec.nested?.(r, at) ?? []);
|
|
309
|
+
for (const [what, to, zeroRefused] of paid) {
|
|
310
|
+
if (zeroRefused && /^0x0{40}$/.test(to)) continue;
|
|
311
|
+
if (!same(to, e.sender) && !same(to, e.receiver)) return `${what} pays ${to}, neither the sender ${e.sender} nor the recipient`;
|
|
312
|
+
}
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
224
315
|
function diamondCallMismatch(data, e) {
|
|
225
316
|
let r;
|
|
226
317
|
try {
|
|
@@ -245,6 +336,8 @@ function diamondCallMismatch(data, e) {
|
|
|
245
336
|
}
|
|
246
337
|
return checkSteps(steps, e, e.toToken);
|
|
247
338
|
}
|
|
339
|
+
const unbound = UNBOUND_BRIDGES[selector];
|
|
340
|
+
if (unbound) return `${unbound} delivers to a recipient the transaction does not bind (an off-chain order or unchecked facet data)`;
|
|
248
341
|
const bridge = BRIDGE_CALLS[selector];
|
|
249
342
|
if (!bridge) return `unknown Diamond call ${selector}`;
|
|
250
343
|
const head = r.small(4);
|
|
@@ -263,6 +356,8 @@ function diamondCallMismatch(data, e) {
|
|
|
263
356
|
if (!e.evmDestination) return "the recipient on a non-EVM destination sits in bridge-specific data and cannot be checked here";
|
|
264
357
|
if (!same(receiver, e.receiver)) return `pays ${receiver}, not ${e.receiver}`;
|
|
265
358
|
if (hasSourceSwaps !== bridge.sourceSwaps) return `unknown Diamond call ${selector}`;
|
|
359
|
+
const refund = refundMismatch(r, bridge, e);
|
|
360
|
+
if (refund) return refund;
|
|
266
361
|
if (hasSourceSwaps) {
|
|
267
362
|
if (minAmount === 0n) return "bridges nothing after the source swaps";
|
|
268
363
|
return checkSteps(swapsAt(r, 4, 4 + 32), e, sendingAssetId);
|
|
@@ -274,8 +369,98 @@ function diamondCallMismatch(data, e) {
|
|
|
274
369
|
}
|
|
275
370
|
}
|
|
276
371
|
|
|
372
|
+
// src/solana.ts
|
|
373
|
+
import { base64Bytes } from "@anywalletkit/protocol-swap2-core/util";
|
|
374
|
+
var ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
375
|
+
var MAYAN_ENTRY_PROGRAMS = /* @__PURE__ */ new Set([
|
|
376
|
+
"D8C8iW6zmoKg5TRr8nQ7h14TMWqQX8FiBdj2ju5MF3wa",
|
|
377
|
+
// CPI_PROXY_PROGRAM_ID
|
|
378
|
+
"BLZRi6frs4X4DNLw56V4EXai1b6QVESN1BhHBTYM9VcY",
|
|
379
|
+
// SWIFT_PROGRAM_ID
|
|
380
|
+
"mayan34VedncxdK2XobtvWFDXQASUTBXhUVzt2kKgny",
|
|
381
|
+
// SWIFT_V2_PROGRAM_ID
|
|
382
|
+
"dkpZqrxHFrhziEMQ931GLtfy11nFkCsfMftH9u6QwBU",
|
|
383
|
+
// MCTP_PROGRAM_ID
|
|
384
|
+
"Gx9rivpS3YR8pBFwMuP6omYqVxunpLvLkNn7ubNyuZZ5"
|
|
385
|
+
// FAST_MCTP_PROGRAM_ID
|
|
386
|
+
]);
|
|
387
|
+
var SYSTEM_PROGRAM = "11111111111111111111111111111111";
|
|
388
|
+
var LIFI_SOLANA_FEE_WALLET = "34FKjAdVcTax2DHqV2XnbXa9J3zmyKcFuFKWbcmgxjgm";
|
|
389
|
+
function base58(bytes) {
|
|
390
|
+
let n = 0n;
|
|
391
|
+
for (const b of bytes) n = n << 8n | BigInt(b);
|
|
392
|
+
let out = "";
|
|
393
|
+
while (n > 0n) {
|
|
394
|
+
out = ALPHABET[Number(n % 58n)] + out;
|
|
395
|
+
n /= 58n;
|
|
396
|
+
}
|
|
397
|
+
for (const b of bytes) {
|
|
398
|
+
if (b !== 0) break;
|
|
399
|
+
out = `1${out}`;
|
|
400
|
+
}
|
|
401
|
+
return out;
|
|
402
|
+
}
|
|
403
|
+
var Cursor = class {
|
|
404
|
+
constructor(b) {
|
|
405
|
+
this.b = b;
|
|
406
|
+
}
|
|
407
|
+
b;
|
|
408
|
+
at = 0;
|
|
409
|
+
byte() {
|
|
410
|
+
if (this.at >= this.b.length) throw new Error("truncated");
|
|
411
|
+
return this.b[this.at++];
|
|
412
|
+
}
|
|
413
|
+
bytes(n) {
|
|
414
|
+
if (n < 0 || this.at + n > this.b.length) throw new Error("truncated");
|
|
415
|
+
const out = this.b.subarray(this.at, this.at + n);
|
|
416
|
+
this.at += n;
|
|
417
|
+
return out;
|
|
418
|
+
}
|
|
419
|
+
/** compact-u16 */
|
|
420
|
+
short() {
|
|
421
|
+
let v = 0;
|
|
422
|
+
for (let shift = 0; shift < 21; shift += 7) {
|
|
423
|
+
const b = this.byte();
|
|
424
|
+
v |= (b & 127) << shift;
|
|
425
|
+
if (!(b & 128)) return v;
|
|
426
|
+
}
|
|
427
|
+
throw new Error("bad length");
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
function solanaBridgeTxMismatch(base64, sender) {
|
|
431
|
+
const bytes = base64Bytes(base64);
|
|
432
|
+
if (!bytes) return "the Solana transaction is not base64";
|
|
433
|
+
const c = new Cursor(bytes);
|
|
434
|
+
try {
|
|
435
|
+
c.bytes(64 * c.short());
|
|
436
|
+
const first = c.byte();
|
|
437
|
+
if ((first & 128) === 0) c.at--;
|
|
438
|
+
c.bytes(3);
|
|
439
|
+
const keys = Array.from({ length: c.short() }, () => base58(c.bytes(32)));
|
|
440
|
+
if (keys[0] !== sender) return `the Solana transaction is paid by ${keys[0] ?? "nobody"}, not the sender ${sender}`;
|
|
441
|
+
c.bytes(32);
|
|
442
|
+
let mayan = false;
|
|
443
|
+
const payees = [];
|
|
444
|
+
const n = c.short();
|
|
445
|
+
for (let i = 0; i < n; i++) {
|
|
446
|
+
const program = keys[c.byte()];
|
|
447
|
+
const accounts = Array.from(c.bytes(c.short()));
|
|
448
|
+
const data = c.bytes(c.short());
|
|
449
|
+
if (program !== void 0 && MAYAN_ENTRY_PROGRAMS.has(program)) mayan = true;
|
|
450
|
+
if (program === SYSTEM_PROGRAM && data.length === 12 && data[0] === 2 && data[1] === 0 && data[2] === 0 && data[3] === 0) {
|
|
451
|
+
const to = keys[accounts[1] ?? -1];
|
|
452
|
+
if (to !== void 0 && to !== sender && to !== LIFI_SOLANA_FEE_WALLET) payees.push(to);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
return mayan && payees.length ? `the Solana transaction transfers SOL to ${payees[0]}, which is neither the sender nor LI.FI's fee wallet` : null;
|
|
456
|
+
} catch (err) {
|
|
457
|
+
return `the Solana transaction does not decode (${err instanceof Error ? err.message : String(err)})`;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
277
461
|
// src/provider.ts
|
|
278
462
|
import { timeoutSignal, sourceAssetOf } from "@anywalletkit/protocol-swap2-core/util";
|
|
463
|
+
import { slippageFloor } from "@anywalletkit/protocol-swap2-core/validate";
|
|
279
464
|
import { bigintToNumber } from "@anywalletkit/core";
|
|
280
465
|
var DEFAULT_LIFI_BASE = "https://li.quest/v1";
|
|
281
466
|
var LIFI_CHAIN = {
|
|
@@ -412,7 +597,8 @@ function headers(key) {
|
|
|
412
597
|
return h;
|
|
413
598
|
}
|
|
414
599
|
var TOOL_KEY = /^[A-Za-z0-9_-]{1,64}$/;
|
|
415
|
-
|
|
600
|
+
var UNBOUND_TOOLS = Object.freeze(["relaydepository", "garden", "squid", "symbiosis"]);
|
|
601
|
+
function routeOptions(body, excluded) {
|
|
416
602
|
const routes = body?.routes;
|
|
417
603
|
if (!Array.isArray(routes)) return [];
|
|
418
604
|
const out = [];
|
|
@@ -422,7 +608,7 @@ function routeOptions(body) {
|
|
|
422
608
|
const cross = Array.isArray(step.includedSteps) ? step.includedSteps.find((i) => i?.type === "cross")?.tool : void 0;
|
|
423
609
|
const tool = typeof cross === "string" ? cross : step.tool;
|
|
424
610
|
const eta = step.estimate?.executionDuration;
|
|
425
|
-
if (typeof tool !== "string" || !TOOL_KEY.test(tool) || typeof eta !== "number" || !Number.isFinite(eta) || eta < 0) continue;
|
|
611
|
+
if (typeof tool !== "string" || !TOOL_KEY.test(tool) || excluded.includes(tool) || typeof eta !== "number" || !Number.isFinite(eta) || eta < 0) continue;
|
|
426
612
|
if (typeof r.toAmount !== "string" || typeof r.toAmountMin !== "string" || !/^\d{1,60}$/.test(r.toAmount) || !/^\d{1,60}$/.test(r.toAmountMin)) continue;
|
|
427
613
|
out.push({
|
|
428
614
|
tool,
|
|
@@ -508,12 +694,12 @@ function lifiProvider(config = {}) {
|
|
|
508
694
|
fromAmount: params.amountIn,
|
|
509
695
|
fromAddress,
|
|
510
696
|
toAddress,
|
|
511
|
-
options: { slippage: slippageBps / 1e4, ...integrator().trim() ? { integrator: integrator().trim() } : {} }
|
|
697
|
+
options: { slippage: slippageBps / 1e4, ...solanaSource ? {} : { bridges: { deny: UNBOUND_TOOLS } }, ...integrator().trim() ? { integrator: integrator().trim() } : {} }
|
|
512
698
|
}),
|
|
513
699
|
signal: signal ?? timeoutSignal(8e3)
|
|
514
700
|
});
|
|
515
701
|
if (res.ok) {
|
|
516
|
-
const options = routeOptions(await res.json());
|
|
702
|
+
const options = routeOptions(await res.json(), solanaSource ? [] : UNBOUND_TOOLS);
|
|
517
703
|
if (options.length) choice = cleanChoice(config.chooseRoute(options, params));
|
|
518
704
|
}
|
|
519
705
|
} catch {
|
|
@@ -533,8 +719,9 @@ function lifiProvider(config = {}) {
|
|
|
533
719
|
if (sentSlippage !== void 0) {
|
|
534
720
|
url.searchParams.set("slippage", String(sentSlippage));
|
|
535
721
|
}
|
|
536
|
-
|
|
537
|
-
for (const t of choice?.
|
|
722
|
+
const unbound = params.sourceChain !== params.destChain && !solanaSource ? UNBOUND_TOOLS : [];
|
|
723
|
+
for (const t of (choice?.allowBridges ?? []).filter((b) => solanaSource || !UNBOUND_TOOLS.includes(b))) url.searchParams.append("allowBridges", t);
|
|
724
|
+
for (const t of /* @__PURE__ */ new Set([...choice?.denyBridges ?? [], ...unbound])) url.searchParams.append("denyBridges", t);
|
|
538
725
|
if (choice?.order) url.searchParams.set("order", choice.order);
|
|
539
726
|
deadline = signal ? void 0 : timeoutSignal(12e3);
|
|
540
727
|
const res = await fetch(url, { headers: headers(apiKey()), signal: signal ?? deadline });
|
|
@@ -578,6 +765,10 @@ function lifiProvider(config = {}) {
|
|
|
578
765
|
if (solanaSource) {
|
|
579
766
|
if (!tr.data || tr.data.length < 64 || tr.data.length % 4 !== 0 || !BASE64.test(tr.data)) return reject("the Solana transaction is not base64");
|
|
580
767
|
if (tr.to !== void 0 || tr.value !== void 0 || tr.gasLimit !== void 0) return reject("the Solana transaction carries EVM fields");
|
|
768
|
+
if (fromChain !== toChain) {
|
|
769
|
+
const why = solanaBridgeTxMismatch(tr.data, fromAddress);
|
|
770
|
+
if (why) return reject(why);
|
|
771
|
+
}
|
|
581
772
|
} else if (!isHexData(tr.data) || !normalizeAddress(tr.to) || !normalizeAddress(tr.from) || tr.chainId !== expectedFromChain || !tr.value || !tr.gasLimit || !trustedAddress(params.sourceChain, tr.to, trustedTransactionTargets) || !sameAddress(tr.from, fromAddress)) return reject("the transaction is malformed or targets an untrusted contract");
|
|
582
773
|
if (sentSlippage !== void 0 && (typeof action.slippage !== "number" || Math.abs(action.slippage - sentSlippage) > 1e-12)) return reject("the quote ignored the requested slippage");
|
|
583
774
|
const sourceIsToken = fromToken !== EVM_ZERO && fromToken !== SOLANA_NATIVE;
|
|
@@ -615,7 +806,7 @@ function lifiProvider(config = {}) {
|
|
|
615
806
|
if (sentSlippage !== void 0) {
|
|
616
807
|
const dest = BigInt(est.toAmount);
|
|
617
808
|
const min = BigInt(minDestAmount);
|
|
618
|
-
if (dest > 0n && min < dest
|
|
809
|
+
if (dest > 0n && min < slippageFloor(dest, slippageBps)) {
|
|
619
810
|
const effective = bigintToNumber((dest - min) * 1000000n / dest) / 1e6;
|
|
620
811
|
const requested = slippageBps / 1e4;
|
|
621
812
|
const scaled = Math.floor(sentSlippage * requested / effective * 0.995 * 1e6) / 1e6;
|
|
@@ -644,6 +835,7 @@ function lifiProvider(config = {}) {
|
|
|
644
835
|
toToken: expectedToToken,
|
|
645
836
|
amountIn: BigInt(params.amountIn),
|
|
646
837
|
receiver: toAddress,
|
|
838
|
+
sender: fromAddress,
|
|
647
839
|
minOut: BigInt(minDestAmount),
|
|
648
840
|
destChainId: BigInt(toChain),
|
|
649
841
|
sameChain: fromChain === toChain,
|
|
@@ -662,6 +854,7 @@ function lifiProvider(config = {}) {
|
|
|
662
854
|
sourceAmount: params.amountIn,
|
|
663
855
|
destAmount: est.toAmount,
|
|
664
856
|
minDestAmount,
|
|
857
|
+
...Number.isInteger(action.toToken?.decimals) && action.toToken.decimals >= 0 && action.toToken.decimals <= 36 ? { destDecimals: action.toToken.decimals } : {},
|
|
665
858
|
feeUsd,
|
|
666
859
|
etaSeconds: est.executionDuration ?? 120,
|
|
667
860
|
reliability: 0.97,
|
|
@@ -729,7 +922,10 @@ function lifiVerifyQuote(params, quote) {
|
|
|
729
922
|
if (!fromChain || !toChain) return "not a LI.FI chain pair";
|
|
730
923
|
const tx = quote.txRequest;
|
|
731
924
|
if (!tx) return "the quote carries no transaction";
|
|
732
|
-
if (isSolana(params.sourceChain))
|
|
925
|
+
if (isSolana(params.sourceChain)) {
|
|
926
|
+
if (!tx.serializedTx || tx.data !== void 0 || tx.to !== void 0) return "a Solana source carries a serialized transaction only";
|
|
927
|
+
return fromChain === toChain ? null : solanaBridgeTxMismatch(tx.serializedTx, params.refundAddress || (params.dry !== false ? SOLANA_PLACEHOLDER : ""));
|
|
928
|
+
}
|
|
733
929
|
if (!isHexData(tx.data) || !tx.to || tx.serializedTx !== void 0) return "the quote carries no Diamond call";
|
|
734
930
|
if (!sameAddress(tx.to, diamondFor(params.sourceChain))) return `the call targets ${tx.to}, not the LI.FI Diamond`;
|
|
735
931
|
if (tx.chainId !== void 0 && String(tx.chainId) !== fromChain) return `the call is for chain ${tx.chainId}, not ${fromChain}`;
|
|
@@ -764,6 +960,7 @@ function lifiVerifyQuote(params, quote) {
|
|
|
764
960
|
toToken: nativeFor(params.destChain, params.destToken),
|
|
765
961
|
amountIn,
|
|
766
962
|
receiver: toAddress,
|
|
963
|
+
sender: fromAddress,
|
|
767
964
|
minOut,
|
|
768
965
|
destChainId: BigInt(toChain),
|
|
769
966
|
sameChain: fromChain === toChain,
|
|
@@ -782,4 +979,4 @@ export {
|
|
|
782
979
|
lifiVerifyQuote,
|
|
783
980
|
lifiPins
|
|
784
981
|
};
|
|
785
|
-
//# sourceMappingURL=chunk-
|
|
982
|
+
//# sourceMappingURL=chunk-67QPKWAY.js.map
|