@peachprojects/aggregator-sdk 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2 -2
- package/dist/index.d.ts +140 -1
- package/dist/index.mjs +635 -485
- package/package.json +3 -2
package/dist/index.mjs
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { ethers as
|
|
2
|
-
const
|
|
3
|
-
function
|
|
4
|
-
return
|
|
1
|
+
import { ethers as m } from "ethers";
|
|
2
|
+
const J = "https://api.peach.ag", Se = 50, _ = 10000n, U = 500, Ie = 5e3, N = 1200, G = 6e4, M = [50, 100, 200, 400, 800, 1200], q = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
|
3
|
+
function T(f) {
|
|
4
|
+
return f.toLowerCase() === q.toLowerCase();
|
|
5
5
|
}
|
|
6
|
-
const
|
|
7
|
-
var
|
|
8
|
-
const
|
|
6
|
+
const Pe = 4001;
|
|
7
|
+
var d = /* @__PURE__ */ ((f) => (f.PancakeV1 = "PancakeV1", f.PancakeV2 = "PancakeV2", f.PancakeV3 = "PancakeV3", f.PancakeInfinityCl = "Pancake_Infinity_Cl", f.PancakeInfinityLb = "Pancake_Infinity_Lb", f.UniswapV2 = "UniswapV2", f.UniswapV3 = "UniswapV3", f.UniswapV4 = "UniswapV4", f.Dodo = "Dodo", f.ThenaV3 = "ThenaV3", f.ThenaFusion = "Thena_Fusion", f.NomiswapStable = "Nomiswap_Stable", f.Biswap = "Biswap", f.Apeswap = "Apeswap", f.BabyDogeSwap = "BabyDogeSwap", f.BabySwap = "BabySwap", f.BakerySwap = "BakerySwap", f.PancakeStable = "Pancake_Stable", f.ListaStable = "Lista_Stable", f.SquadSwapV3 = "SquadSwap_V3", f.SquadSwapV2 = "SquadSwap_V2", f.Wombat = "Wombat", f.SushiSwapV2 = "SushiSwap_V2", f.SushiSwapV3 = "SushiSwap_V3", f))(d || {});
|
|
8
|
+
const ke = {
|
|
9
9
|
chainId: 56,
|
|
10
10
|
rpcUrl: "https://bsc-dataseed.binance.org",
|
|
11
11
|
weth: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
|
|
12
12
|
// WBNB
|
|
13
13
|
adapters: []
|
|
14
|
-
},
|
|
14
|
+
}, Ee = {
|
|
15
15
|
chainId: 97,
|
|
16
16
|
rpcUrl: "https://bsc-testnet-rpc.publicnode.com",
|
|
17
17
|
weth: "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd",
|
|
@@ -23,53 +23,53 @@ class B extends Error {
|
|
|
23
23
|
super(e), this.name = "CustomFeeError";
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
class
|
|
26
|
+
class Q extends Error {
|
|
27
27
|
constructor(e, t, n) {
|
|
28
28
|
super(e), this.name = "ExecuteTimeoutError", this.stage = t, this.txHash = n;
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
-
const
|
|
31
|
+
const O = "0x000000000022D473030F116dDEE9F6B43aC78BA3", $ = (1n << 160n) - 1n, E = {
|
|
32
32
|
/** Default route search depth */
|
|
33
33
|
depth: 3,
|
|
34
34
|
/** Default trade split count */
|
|
35
35
|
splitCount: 20,
|
|
36
36
|
/** Default DEX providers */
|
|
37
|
-
providers: ["PANCAKEV2", "PANCAKEV3", "PANCAKE_INFINITY_CL", "PANCAKE_INFINITY_LB", "UNISWAPV3", "UNISWAPV4", "DODO", "THENAV3", "NOMISWAP_STABLE", "BISWAP", "APESWAP", "BABYDOGESWAP", "BABYSWAP", "PANCAKE_STABLE", "LISTA_STABLE", "SQUADSWAP_V3", "SQUADSWAP_V2", "WOMBAT", "THENA_FUSION", "SUSHISWAP_V2", "SUSHISWAP_V3"],
|
|
37
|
+
providers: ["PANCAKEV1", "PANCAKEV2", "PANCAKEV3", "PANCAKE_INFINITY_CL", "PANCAKE_INFINITY_LB", "UNISWAPV2", "UNISWAPV3", "UNISWAPV4", "DODO", "THENAV3", "NOMISWAP_STABLE", "BISWAP", "APESWAP", "BABYDOGESWAP", "BABYSWAP", "BAKERYSWAP", "PANCAKE_STABLE", "LISTA_STABLE", "SQUADSWAP_V3", "SQUADSWAP_V2", "WOMBAT", "THENA_FUSION", "SUSHISWAP_V2", "SUSHISWAP_V3"],
|
|
38
38
|
/** Default client version for V3 API */
|
|
39
39
|
clientVersion: 1001500
|
|
40
|
-
},
|
|
41
|
-
function
|
|
40
|
+
}, ee = 1e4;
|
|
41
|
+
function te(f) {
|
|
42
42
|
const e = {};
|
|
43
|
-
return
|
|
43
|
+
return f.forEach((t, n) => {
|
|
44
44
|
e[n] = t;
|
|
45
45
|
}), e;
|
|
46
46
|
}
|
|
47
|
-
class
|
|
47
|
+
class ne {
|
|
48
48
|
constructor(e = {}) {
|
|
49
|
-
this.baseUrl = e.baseUrl ||
|
|
49
|
+
this.baseUrl = e.baseUrl || J, this.timeout = e.timeout || ee, this.extraHeaders = e.headers ? { ...e.headers } : {};
|
|
50
50
|
}
|
|
51
51
|
async findRoutes(e) {
|
|
52
52
|
const {
|
|
53
53
|
from: t,
|
|
54
54
|
target: n,
|
|
55
|
-
amount:
|
|
56
|
-
byAmountIn:
|
|
57
|
-
depth:
|
|
58
|
-
splitCount: a =
|
|
59
|
-
providers: i =
|
|
55
|
+
amount: s,
|
|
56
|
+
byAmountIn: o = !0,
|
|
57
|
+
depth: r = E.depth,
|
|
58
|
+
splitCount: a = E.splitCount,
|
|
59
|
+
providers: i = E.providers,
|
|
60
60
|
includeResponseHeaders: c = !1
|
|
61
61
|
} = e, u = new URLSearchParams({
|
|
62
62
|
from: t,
|
|
63
63
|
target: n,
|
|
64
|
-
amount:
|
|
65
|
-
by_amount_in:
|
|
66
|
-
depth:
|
|
64
|
+
amount: s.toString(),
|
|
65
|
+
by_amount_in: o.toString(),
|
|
66
|
+
depth: r.toString(),
|
|
67
67
|
split_count: a.toString(),
|
|
68
68
|
providers: i.join(","),
|
|
69
|
-
v:
|
|
70
|
-
}),
|
|
69
|
+
v: E.clientVersion.toString()
|
|
70
|
+
}), l = `${this.baseUrl}/router/find_routes?${u}`, p = new AbortController(), A = setTimeout(() => p.abort(), this.timeout);
|
|
71
71
|
try {
|
|
72
|
-
const
|
|
72
|
+
const w = await fetch(l, {
|
|
73
73
|
method: "GET",
|
|
74
74
|
headers: {
|
|
75
75
|
Accept: "application/json",
|
|
@@ -77,22 +77,22 @@ class ee {
|
|
|
77
77
|
},
|
|
78
78
|
signal: p.signal
|
|
79
79
|
});
|
|
80
|
-
if (clearTimeout(A), !
|
|
81
|
-
throw new
|
|
82
|
-
`API request failed: ${
|
|
83
|
-
|
|
80
|
+
if (clearTimeout(A), !w.ok)
|
|
81
|
+
throw new S(
|
|
82
|
+
`API request failed: ${w.status} ${w.statusText}`,
|
|
83
|
+
w.status
|
|
84
84
|
);
|
|
85
|
-
const v = await
|
|
85
|
+
const v = await w.json();
|
|
86
86
|
if (v.code !== 200)
|
|
87
|
-
throw new
|
|
87
|
+
throw new S(v.msg || "Route not found", v.code);
|
|
88
88
|
if (!v.data || !v.data.paths || v.data.paths.length === 0)
|
|
89
|
-
throw new
|
|
89
|
+
throw new S("No routes found", 404);
|
|
90
90
|
return c ? {
|
|
91
91
|
data: v.data,
|
|
92
|
-
responseHeaders:
|
|
92
|
+
responseHeaders: te(w.headers)
|
|
93
93
|
} : v.data;
|
|
94
|
-
} catch (
|
|
95
|
-
throw clearTimeout(A),
|
|
94
|
+
} catch (w) {
|
|
95
|
+
throw clearTimeout(A), w instanceof S ? w : w instanceof Error ? w.name === "AbortError" ? new S("API request timeout", 408) : new S(`API request failed: ${w.message}`, 0) : new S("Unknown API error", 0);
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
/**
|
|
@@ -101,7 +101,7 @@ class ee {
|
|
|
101
101
|
async getStatus() {
|
|
102
102
|
const e = `${this.baseUrl}/router/status`, t = new AbortController(), n = setTimeout(() => t.abort(), this.timeout);
|
|
103
103
|
try {
|
|
104
|
-
const
|
|
104
|
+
const s = await fetch(e, {
|
|
105
105
|
method: "GET",
|
|
106
106
|
headers: {
|
|
107
107
|
Accept: "application/json",
|
|
@@ -109,17 +109,17 @@ class ee {
|
|
|
109
109
|
},
|
|
110
110
|
signal: t.signal
|
|
111
111
|
});
|
|
112
|
-
if (clearTimeout(n), !
|
|
113
|
-
throw new
|
|
114
|
-
`API request failed: ${
|
|
115
|
-
|
|
112
|
+
if (clearTimeout(n), !s.ok)
|
|
113
|
+
throw new S(
|
|
114
|
+
`API request failed: ${s.status} ${s.statusText}`,
|
|
115
|
+
s.status
|
|
116
116
|
);
|
|
117
|
-
const
|
|
118
|
-
if (
|
|
119
|
-
throw new
|
|
120
|
-
return
|
|
121
|
-
} catch (
|
|
122
|
-
throw clearTimeout(n),
|
|
117
|
+
const o = await s.json();
|
|
118
|
+
if (o.code !== 200)
|
|
119
|
+
throw new S(o.msg || "Failed to get status", o.code);
|
|
120
|
+
return o.data;
|
|
121
|
+
} catch (s) {
|
|
122
|
+
throw clearTimeout(n), s instanceof S ? s : s instanceof Error ? s.name === "AbortError" ? new S("API request timeout", 408) : new S(`API request failed: ${s.message}`, 0) : new S("Unknown API error", 0);
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
/**
|
|
@@ -141,22 +141,22 @@ class ee {
|
|
|
141
141
|
return this.baseUrl;
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
|
-
class
|
|
144
|
+
class S extends Error {
|
|
145
145
|
constructor(e, t) {
|
|
146
146
|
super(e), this.name = "ApiError", this.code = t;
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
|
-
async function
|
|
149
|
+
async function W(f, e = G) {
|
|
150
150
|
if (e <= 0)
|
|
151
|
-
return
|
|
151
|
+
return f;
|
|
152
152
|
let t;
|
|
153
153
|
try {
|
|
154
154
|
return await Promise.race([
|
|
155
|
-
|
|
156
|
-
new Promise((n,
|
|
155
|
+
f,
|
|
156
|
+
new Promise((n, s) => {
|
|
157
157
|
t = setTimeout(() => {
|
|
158
|
-
|
|
159
|
-
new
|
|
158
|
+
s(
|
|
159
|
+
new Q(
|
|
160
160
|
`Wallet did not settle sendTransaction within ${e}ms.`,
|
|
161
161
|
"wallet_send"
|
|
162
162
|
)
|
|
@@ -171,6 +171,10 @@ async function $(h, e = K) {
|
|
|
171
171
|
const R = [
|
|
172
172
|
"function swap((address srcToken, address dstToken, uint256 amountIn, uint256 amountOutMin, (address adapter, address pool, address tokenIn, address tokenOut, uint256 amountIn, bytes extraData)[] steps, address[] intermediateTokens, uint256 deadline, bytes32 quoteId, uint256 expectAmountOut, address feeReceiver, uint16 feeBps) params) external returns (uint256 amountOut)",
|
|
173
173
|
"function swapETH((address srcToken, address dstToken, uint256 amountIn, uint256 amountOutMin, (address adapter, address pool, address tokenIn, address tokenOut, uint256 amountIn, bytes extraData)[] steps, address[] intermediateTokens, uint256 deadline, bytes32 quoteId, uint256 expectAmountOut, address feeReceiver, uint16 feeBps) params) external payable returns (uint256 amountOut)",
|
|
174
|
+
// Permit2 (AllowanceTransfer) entrypoints. Second arg is the Permit2Sig tuple:
|
|
175
|
+
// ((PermitDetails details, address spender, uint256 sigDeadline) permitSingle, bytes signature)
|
|
176
|
+
"function swapWithPermit2((address srcToken, address dstToken, uint256 amountIn, uint256 amountOutMin, (address adapter, address pool, address tokenIn, address tokenOut, uint256 amountIn, bytes extraData)[] steps, address[] intermediateTokens, uint256 deadline, bytes32 quoteId, uint256 expectAmountOut, address feeReceiver, uint16 feeBps) params, (((address token, uint160 amount, uint48 expiration, uint48 nonce) details, address spender, uint256 sigDeadline) permitSingle, bytes signature) p2) external returns (uint256 amountOut)",
|
|
177
|
+
"function swapETHWithPermit2((address srcToken, address dstToken, uint256 amountIn, uint256 amountOutMin, (address adapter, address pool, address tokenIn, address tokenOut, uint256 amountIn, bytes extraData)[] steps, address[] intermediateTokens, uint256 deadline, bytes32 quoteId, uint256 expectAmountOut, address feeReceiver, uint16 feeBps) params, (((address token, uint160 amount, uint48 expiration, uint48 nonce) details, address spender, uint256 sigDeadline) permitSingle, bytes signature) p2) external returns (uint256 amountOut)",
|
|
174
178
|
"function isAdapterRegistered(address adapter) external view returns (bool)",
|
|
175
179
|
"function getAdapterProtocolId(address adapter) external view returns (bytes32)",
|
|
176
180
|
"function WETH() external view returns (address)",
|
|
@@ -187,42 +191,59 @@ const R = [
|
|
|
187
191
|
"function balanceOf(address account) external view returns (uint256)",
|
|
188
192
|
"function decimals() external view returns (uint8)",
|
|
189
193
|
"function symbol() external view returns (string)"
|
|
190
|
-
],
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
194
|
+
], se = [
|
|
195
|
+
"function allowance(address user, address token, address spender) external view returns (uint160 amount, uint48 expiration, uint48 nonce)"
|
|
196
|
+
], re = {
|
|
197
|
+
PermitDetails: [
|
|
198
|
+
{ name: "token", type: "address" },
|
|
199
|
+
{ name: "amount", type: "uint160" },
|
|
200
|
+
{ name: "expiration", type: "uint48" },
|
|
201
|
+
{ name: "nonce", type: "uint48" }
|
|
202
|
+
],
|
|
203
|
+
PermitSingle: [
|
|
204
|
+
{ name: "details", type: "PermitDetails" },
|
|
205
|
+
{ name: "spender", type: "address" },
|
|
206
|
+
{ name: "sigDeadline", type: "uint256" }
|
|
207
|
+
]
|
|
208
|
+
}, oe = "0xa0FfB9c1CE1Fe56963B0321B32E7A0302114058b", ae = "0xC697d2898e0D09264376196696c51D7aBbbAA4a9", ie = "0x28e2ea090877bf75740558f6bfb36a5ffee9e9df", H = {
|
|
209
|
+
PANCAKEV3: d.PancakeV3,
|
|
210
|
+
PANCAKEV2: d.PancakeV2,
|
|
211
|
+
PANCAKEV1: d.PancakeV1,
|
|
212
|
+
PANCAKE_INFINITY_CL: d.PancakeInfinityCl,
|
|
213
|
+
PANCAKE_INFINITY_LB: d.PancakeInfinityLb,
|
|
214
|
+
UNISWAPV2: d.UniswapV2,
|
|
215
|
+
UNISWAPV3: d.UniswapV3,
|
|
216
|
+
UNISWAPV4: d.UniswapV4,
|
|
217
|
+
DODO: d.Dodo,
|
|
218
|
+
THENAV3: d.ThenaV3,
|
|
219
|
+
NOMISWAP_STABLE: d.NomiswapStable,
|
|
220
|
+
BISWAP: d.Biswap,
|
|
221
|
+
APESWAP: d.Apeswap,
|
|
222
|
+
BABYDOGESWAP: d.BabyDogeSwap,
|
|
223
|
+
BABYSWAP: d.BabySwap,
|
|
224
|
+
BAKERYSWAP: d.BakerySwap,
|
|
225
|
+
PANCAKE_STABLE: d.PancakeStable,
|
|
226
|
+
LISTA_STABLE: d.ListaStable,
|
|
227
|
+
SQUADSWAP_V3: d.SquadSwapV3,
|
|
228
|
+
SQUADSWAP_V2: d.SquadSwapV2,
|
|
229
|
+
WOMBAT: d.Wombat,
|
|
230
|
+
THENA_FUSION: d.ThenaFusion,
|
|
231
|
+
SUSHISWAP_V2: d.SushiSwapV2,
|
|
232
|
+
SUSHISWAP_V3: d.SushiSwapV3
|
|
233
|
+
}, C = class C {
|
|
213
234
|
constructor(e, t, n) {
|
|
214
|
-
this.config = e, this.provider = t || new
|
|
215
|
-
e.routerAddress ||
|
|
235
|
+
this.config = e, this.provider = t || new m.JsonRpcProvider(e.rpcUrl), this.routerContract = new m.Contract(
|
|
236
|
+
e.routerAddress || m.ZeroAddress,
|
|
216
237
|
R,
|
|
217
238
|
this.provider
|
|
218
|
-
), this.apiClient = new
|
|
239
|
+
), this.apiClient = new ne(n?.api);
|
|
219
240
|
}
|
|
220
241
|
/**
|
|
221
242
|
* Get the effective router address for a quote.
|
|
222
243
|
*/
|
|
223
244
|
getRouterAddress(e) {
|
|
224
245
|
const t = e.routerAddress || this.config.routerAddress;
|
|
225
|
-
if (!t || t ===
|
|
246
|
+
if (!t || t === m.ZeroAddress)
|
|
226
247
|
throw new Error("No router address available. Provide routerAddress in config or use API-based getQuote.");
|
|
227
248
|
return t;
|
|
228
249
|
}
|
|
@@ -232,25 +253,25 @@ const R = [
|
|
|
232
253
|
applySlippage(e, t) {
|
|
233
254
|
if (t < 0 || t > 1e4)
|
|
234
255
|
throw new Error("slippageBps must be between 0 and 10000");
|
|
235
|
-
const n = e.amountOutMin * (
|
|
256
|
+
const n = e.amountOutMin * (_ - BigInt(t)) / _;
|
|
236
257
|
return { ...e, amountOutMin: n };
|
|
237
258
|
}
|
|
238
259
|
/**
|
|
239
260
|
* Build transaction requests for an approval (if needed) and the swap itself.
|
|
240
261
|
*/
|
|
241
262
|
async swap(e, t, n) {
|
|
242
|
-
const
|
|
263
|
+
const s = this.getRouterAddress(e), { tx: o, method: r } = this.buildSwapTransactionRequest(e, n);
|
|
243
264
|
let a;
|
|
244
265
|
return e.srcNative || (a = await this.buildApprovalRequest(
|
|
245
266
|
e.srcToken,
|
|
246
267
|
t,
|
|
247
268
|
e.amountIn,
|
|
248
|
-
|
|
269
|
+
s,
|
|
249
270
|
n
|
|
250
271
|
)), {
|
|
251
|
-
routerAddress:
|
|
252
|
-
method:
|
|
253
|
-
tx:
|
|
272
|
+
routerAddress: s,
|
|
273
|
+
method: r,
|
|
274
|
+
tx: o,
|
|
254
275
|
approval: a
|
|
255
276
|
};
|
|
256
277
|
}
|
|
@@ -260,20 +281,20 @@ const R = [
|
|
|
260
281
|
* @deprecated Prefer swap(), then send the returned tx request with your wallet/client.
|
|
261
282
|
*/
|
|
262
283
|
async execute(e, t, n) {
|
|
263
|
-
const
|
|
284
|
+
const s = await t.getAddress(), o = await this.swap(e, s, n);
|
|
264
285
|
try {
|
|
265
|
-
return
|
|
286
|
+
return o.approval && await (await this.sendTransactionWithTimeout(
|
|
266
287
|
t,
|
|
267
|
-
|
|
288
|
+
o.approval.tx,
|
|
268
289
|
n
|
|
269
|
-
)).wait(), await this.sendTransactionWithTimeout(t,
|
|
270
|
-
} catch (
|
|
271
|
-
const a =
|
|
290
|
+
)).wait(), await this.sendTransactionWithTimeout(t, o.tx, n);
|
|
291
|
+
} catch (r) {
|
|
292
|
+
const a = r instanceof Error ? r.message : String(r), i = /estimateGas/i.test(a), c = /missing revert data/i.test(a) || a.includes("reason=null") && a.includes("data=null");
|
|
272
293
|
if (i && (c || /reason=null|data=null/.test(a))) {
|
|
273
|
-
const u = "Transaction reverted during gas estimation and the RPC did not return a revert reason. Try: 1) Get a fresh quote and confirm immediately 2) Switch network or RPC 3) Increase slippage.",
|
|
274
|
-
throw
|
|
294
|
+
const u = "Transaction reverted during gas estimation and the RPC did not return a revert reason. Try: 1) Get a fresh quote and confirm immediately 2) Switch network or RPC 3) Increase slippage.", l = new Error(`${u} (estimateGas/missing revert data)`);
|
|
295
|
+
throw l.cause = r, l;
|
|
275
296
|
}
|
|
276
|
-
throw
|
|
297
|
+
throw r;
|
|
277
298
|
}
|
|
278
299
|
}
|
|
279
300
|
/**
|
|
@@ -302,8 +323,8 @@ const R = [
|
|
|
302
323
|
};
|
|
303
324
|
}
|
|
304
325
|
getProtocolForProvider(e) {
|
|
305
|
-
if (e in
|
|
306
|
-
return
|
|
326
|
+
if (e in H)
|
|
327
|
+
return H[e];
|
|
307
328
|
throw new Error(`Unsupported provider: ${e}`);
|
|
308
329
|
}
|
|
309
330
|
/**
|
|
@@ -315,9 +336,9 @@ const R = [
|
|
|
315
336
|
* @returns Encoded calldata and transaction info (to address, value)
|
|
316
337
|
*/
|
|
317
338
|
encodeSwapCalldata(e, t) {
|
|
318
|
-
const n = e.routerAddress ?? this.config.routerAddress ?? this.routerContract.target,
|
|
319
|
-
if (
|
|
320
|
-
const a = this.routerContract.interface.encodeFunctionData("swapETH", [
|
|
339
|
+
const n = e.routerAddress ?? this.config.routerAddress ?? this.routerContract.target, s = this.applySlippage(e.params, t), o = e.srcNative === !0 || e.dstNative === !0, r = this.encodeParams(s);
|
|
340
|
+
if (o) {
|
|
341
|
+
const a = this.routerContract.interface.encodeFunctionData("swapETH", [r]);
|
|
321
342
|
return {
|
|
322
343
|
to: n,
|
|
323
344
|
data: a,
|
|
@@ -325,7 +346,7 @@ const R = [
|
|
|
325
346
|
method: "swapETH"
|
|
326
347
|
};
|
|
327
348
|
} else {
|
|
328
|
-
const a = this.routerContract.interface.encodeFunctionData("swap", [
|
|
349
|
+
const a = this.routerContract.interface.encodeFunctionData("swap", [r]);
|
|
329
350
|
return {
|
|
330
351
|
to: n,
|
|
331
352
|
data: a,
|
|
@@ -335,66 +356,187 @@ const R = [
|
|
|
335
356
|
}
|
|
336
357
|
}
|
|
337
358
|
buildSwapTransactionRequest(e, t) {
|
|
338
|
-
const { to: n, data:
|
|
359
|
+
const { to: n, data: s, value: o, method: r } = this.encodeSwapCalldata(e, t.slippageBps);
|
|
339
360
|
return {
|
|
340
|
-
method:
|
|
341
|
-
tx: this.applyTxOverrides({ to: n, data:
|
|
361
|
+
method: r,
|
|
362
|
+
tx: this.applyTxOverrides({ to: n, data: s, value: o }, t, !0)
|
|
342
363
|
};
|
|
343
364
|
}
|
|
344
|
-
async buildApprovalRequest(e, t, n,
|
|
345
|
-
const
|
|
346
|
-
if (!(
|
|
365
|
+
async buildApprovalRequest(e, t, n, s, o) {
|
|
366
|
+
const r = await this.getAllowance(e, t, s);
|
|
367
|
+
if (!(r >= n))
|
|
347
368
|
return {
|
|
348
369
|
token: e,
|
|
349
370
|
owner: t,
|
|
350
|
-
spender:
|
|
351
|
-
currentAllowance:
|
|
371
|
+
spender: s,
|
|
372
|
+
currentAllowance: r,
|
|
352
373
|
requiredAmount: n,
|
|
353
|
-
approveAmount:
|
|
354
|
-
tx: this.buildApprovalTransactionRequest(e,
|
|
374
|
+
approveAmount: m.MaxUint256,
|
|
375
|
+
tx: this.buildApprovalTransactionRequest(e, s, o)
|
|
355
376
|
};
|
|
356
377
|
}
|
|
357
378
|
buildApprovalTransactionRequest(e, t, n) {
|
|
358
|
-
const
|
|
359
|
-
return this.applyTxOverrides({ to: e, data:
|
|
379
|
+
const o = new m.Interface(b).encodeFunctionData("approve", [t, m.MaxUint256]);
|
|
380
|
+
return this.applyTxOverrides({ to: e, data: o, value: 0n }, n, !1);
|
|
360
381
|
}
|
|
361
382
|
async getAllowance(e, t, n) {
|
|
362
|
-
return new
|
|
383
|
+
return new m.Contract(e, b, this.provider).allowance(t, n);
|
|
384
|
+
}
|
|
385
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
386
|
+
// Permit2 (AllowanceTransfer)
|
|
387
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
388
|
+
/**
|
|
389
|
+
* Read the current Permit2 AllowanceTransfer state for (owner, token, spender).
|
|
390
|
+
* `spender` defaults to the router address. The returned `nonce` feeds the next PermitSingle;
|
|
391
|
+
* `amount` / `expiration` decide whether a fresh signature is needed.
|
|
392
|
+
*/
|
|
393
|
+
async getPermit2Allowance(e, t, n) {
|
|
394
|
+
const s = new m.Contract(O, se, this.provider), o = n ?? this.resolveRouterAddress(), [r, a, i] = await s.allowance(t, e, o);
|
|
395
|
+
return { amount: BigInt(r), expiration: Number(a), nonce: Number(i) };
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Build the ONE-TIME `token.approve(PERMIT2, max)` tx, or undefined when the token's existing
|
|
399
|
+
* Permit2 allowance already covers `amount`. This is the only on-chain approval Permit2 needs;
|
|
400
|
+
* once set, every future swap of this token is signature-only.
|
|
401
|
+
*/
|
|
402
|
+
async buildPermit2TokenApproval(e, t, n, s = {}) {
|
|
403
|
+
if (await this.getAllowance(e, t, O) >= n)
|
|
404
|
+
return;
|
|
405
|
+
const a = new m.Interface(b).encodeFunctionData("approve", [O, m.MaxUint256]), i = { to: e, data: a, value: 0n };
|
|
406
|
+
return s.gasPrice && (i.gasPrice = s.gasPrice), i;
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Build the EIP-712 PermitSingle the user signs to grant the router a Permit2 allowance.
|
|
410
|
+
* Reads the current sequential nonce from Permit2; `permitSingle.spender` is the router.
|
|
411
|
+
* Pass the result straight into `signer.signTypedData(domain, types, values)`.
|
|
412
|
+
*/
|
|
413
|
+
async buildPermit2TypedData(e, t, n = {}) {
|
|
414
|
+
if (e.srcNative)
|
|
415
|
+
throw new Error("Permit2 cannot be used for native-token input; use swapETH instead.");
|
|
416
|
+
const s = this.getRouterAddress(e);
|
|
417
|
+
this.assertUint160(e.amountIn);
|
|
418
|
+
const { nonce: o } = await this.getPermit2Allowance(e.srcToken, t, s), r = Math.floor(Date.now() / 1e3), a = n.permitAmount ?? $;
|
|
419
|
+
this.assertUint160(a);
|
|
420
|
+
const i = {
|
|
421
|
+
details: {
|
|
422
|
+
token: e.srcToken,
|
|
423
|
+
amount: a,
|
|
424
|
+
expiration: n.expiration ?? r + 720 * 60 * 60,
|
|
425
|
+
// 30 days
|
|
426
|
+
nonce: o
|
|
427
|
+
},
|
|
428
|
+
spender: s,
|
|
429
|
+
sigDeadline: n.sigDeadline ?? BigInt(r + 1800)
|
|
430
|
+
// 30 min
|
|
431
|
+
};
|
|
432
|
+
return {
|
|
433
|
+
domain: { name: "Permit2", chainId: this.config.chainId, verifyingContract: O },
|
|
434
|
+
types: re,
|
|
435
|
+
values: i
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Encode calldata for swapWithPermit2 / swapETHWithPermit2. Routes to swapETHWithPermit2
|
|
440
|
+
* when the quote's dstToken is native. Pass `"0x"` as `signature` to reuse an existing
|
|
441
|
+
* on-chain Permit2 allowance (the router then skips the permit() call).
|
|
442
|
+
*/
|
|
443
|
+
encodeSwapWithPermit2Calldata(e, t, n, s) {
|
|
444
|
+
if (e.srcNative)
|
|
445
|
+
throw new Error("Permit2 cannot be used for native-token input; use swapETH instead.");
|
|
446
|
+
const o = this.getRouterAddress(e), r = this.applySlippage(e.params, t), a = this.encodeParams(r), i = { permitSingle: n, signature: s }, c = e.dstNative ? "swapETHWithPermit2" : "swapWithPermit2", u = this.routerContract.interface.encodeFunctionData(c, [a, i]);
|
|
447
|
+
return { to: o, data: u, value: 0n, method: c };
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Prepare a single-transaction Permit2 swap. Returns the optional one-time token->Permit2
|
|
451
|
+
* approval, the EIP-712 payload to sign (or undefined when an existing allowance can be
|
|
452
|
+
* reused), and a `buildSwapTx(signature)` closure for the final swap tx.
|
|
453
|
+
*
|
|
454
|
+
* Integrator flow:
|
|
455
|
+
* const req = await client.swapWithPermit2(quote, owner, { slippageBps: 50 });
|
|
456
|
+
* if (req.permit2Approval) await signer.sendTransaction(req.permit2Approval); // once per token
|
|
457
|
+
* const sig = req.typedData
|
|
458
|
+
* ? await signer.signTypedData(req.typedData.domain, req.typedData.types, req.typedData.values)
|
|
459
|
+
* : "0x";
|
|
460
|
+
* await signer.sendTransaction(req.buildSwapTx(sig));
|
|
461
|
+
*/
|
|
462
|
+
async swapWithPermit2(e, t, n) {
|
|
463
|
+
if (e.srcNative)
|
|
464
|
+
throw new Error("Permit2 cannot be used for native-token input; use swapETH instead.");
|
|
465
|
+
const s = this.getRouterAddress(e);
|
|
466
|
+
this.assertUint160(e.amountIn);
|
|
467
|
+
const o = await this.buildPermit2TokenApproval(
|
|
468
|
+
e.srcToken,
|
|
469
|
+
t,
|
|
470
|
+
e.amountIn,
|
|
471
|
+
n
|
|
472
|
+
), r = await this.getPermit2Allowance(e.srcToken, t, s), a = Math.floor(Date.now() / 1e3), i = !o && r.amount >= e.amountIn && r.expiration > a;
|
|
473
|
+
let c, u;
|
|
474
|
+
i ? u = {
|
|
475
|
+
details: {
|
|
476
|
+
token: e.srcToken,
|
|
477
|
+
amount: r.amount,
|
|
478
|
+
expiration: r.expiration,
|
|
479
|
+
nonce: r.nonce
|
|
480
|
+
},
|
|
481
|
+
spender: s,
|
|
482
|
+
sigDeadline: 0n
|
|
483
|
+
} : (c = await this.buildPermit2TypedData(e, t, n), u = c.values);
|
|
484
|
+
const l = e.dstNative ? "swapETHWithPermit2" : "swapWithPermit2";
|
|
485
|
+
return {
|
|
486
|
+
routerAddress: s,
|
|
487
|
+
method: l,
|
|
488
|
+
permit2Approval: o,
|
|
489
|
+
typedData: c,
|
|
490
|
+
permitSingle: u,
|
|
491
|
+
buildSwapTx: (p) => {
|
|
492
|
+
const { to: A, data: w, value: v } = this.encodeSwapWithPermit2Calldata(
|
|
493
|
+
e,
|
|
494
|
+
n.slippageBps,
|
|
495
|
+
u,
|
|
496
|
+
p
|
|
497
|
+
);
|
|
498
|
+
return this.applyTxOverrides({ to: A, data: w, value: v }, n, !0);
|
|
499
|
+
}
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
assertUint160(e) {
|
|
503
|
+
if (e > $)
|
|
504
|
+
throw new Error(`amount ${e} exceeds Permit2 uint160 max`);
|
|
363
505
|
}
|
|
364
506
|
applyTxOverrides(e, t, n) {
|
|
365
|
-
const
|
|
366
|
-
return t.gasPrice && (
|
|
507
|
+
const s = { ...e };
|
|
508
|
+
return t.gasPrice && (s.gasPrice = t.gasPrice), n && t.gasLimit && (s.gasLimit = t.gasLimit), s;
|
|
367
509
|
}
|
|
368
510
|
async sendTransactionWithTimeout(e, t, n) {
|
|
369
|
-
const
|
|
370
|
-
if (
|
|
511
|
+
const s = n.timeoutMs ?? G;
|
|
512
|
+
if (s <= 0)
|
|
371
513
|
return e.sendTransaction(t);
|
|
372
|
-
const
|
|
373
|
-
if (typeof
|
|
374
|
-
const
|
|
375
|
-
|
|
376
|
-
|
|
514
|
+
const o = e;
|
|
515
|
+
if (typeof o.sendUncheckedTransaction == "function" && o.provider) {
|
|
516
|
+
const r = await W(
|
|
517
|
+
o.sendUncheckedTransaction(t),
|
|
518
|
+
s
|
|
377
519
|
), a = await this.waitForTransactionResponse(
|
|
378
|
-
|
|
520
|
+
o.provider,
|
|
521
|
+
r,
|
|
379
522
|
s,
|
|
380
|
-
o,
|
|
381
523
|
n.transactionResponsePollingIntervalsMs
|
|
382
524
|
);
|
|
383
525
|
if (a.response)
|
|
384
526
|
return a.response;
|
|
385
527
|
const i = a.rpcErrors > 0 ? `${a.rpcErrors} transient provider error(s) and ${a.nullResponses} null response(s)` : `${a.nullResponses} null response(s)`;
|
|
386
|
-
throw new
|
|
387
|
-
`Transaction was broadcast but provider did not return TransactionResponse within ${
|
|
528
|
+
throw new Q(
|
|
529
|
+
`Transaction was broadcast but provider did not return TransactionResponse within ${s}ms (${i}).`,
|
|
388
530
|
"provider_index",
|
|
389
|
-
|
|
531
|
+
r
|
|
390
532
|
);
|
|
391
533
|
}
|
|
392
|
-
return
|
|
534
|
+
return W(e.sendTransaction(t), s);
|
|
393
535
|
}
|
|
394
|
-
async waitForTransactionResponse(e, t, n,
|
|
395
|
-
const
|
|
396
|
-
let
|
|
397
|
-
for (; Date.now() <
|
|
536
|
+
async waitForTransactionResponse(e, t, n, s = M) {
|
|
537
|
+
const o = Date.now() + n;
|
|
538
|
+
let r = 0, a = 0, i = 0;
|
|
539
|
+
for (; Date.now() < o; ) {
|
|
398
540
|
try {
|
|
399
541
|
const u = await e.getTransaction(t);
|
|
400
542
|
if (u)
|
|
@@ -403,8 +545,8 @@ const R = [
|
|
|
403
545
|
} catch {
|
|
404
546
|
i++;
|
|
405
547
|
}
|
|
406
|
-
const c = this.getNextPollingDelay(
|
|
407
|
-
|
|
548
|
+
const c = this.getNextPollingDelay(s, r);
|
|
549
|
+
r++, await this.delay(Math.min(c, Math.max(25, o - Date.now())));
|
|
408
550
|
}
|
|
409
551
|
return { response: null, nullResponses: a, rpcErrors: i };
|
|
410
552
|
}
|
|
@@ -414,24 +556,24 @@ const R = [
|
|
|
414
556
|
});
|
|
415
557
|
}
|
|
416
558
|
getNextPollingDelay(e, t) {
|
|
417
|
-
return e.length === 0 ?
|
|
559
|
+
return e.length === 0 ? M.at(-1) ?? 1200 : e[Math.min(t, e.length - 1)] ?? 1200;
|
|
418
560
|
}
|
|
419
561
|
/**
|
|
420
562
|
* Get token metadata and, optionally, the balance for a specific owner.
|
|
421
563
|
*/
|
|
422
564
|
async getTokenInfo(e, t) {
|
|
423
|
-
const n = new
|
|
565
|
+
const n = new m.Contract(e, b, this.provider), [s, o, r] = await Promise.all([
|
|
424
566
|
n.symbol(),
|
|
425
567
|
n.decimals(),
|
|
426
568
|
t ? n.balanceOf(t) : Promise.resolve(void 0)
|
|
427
569
|
]);
|
|
428
|
-
return
|
|
570
|
+
return r === void 0 ? { symbol: s, decimals: o } : { symbol: s, decimals: o, balance: r };
|
|
429
571
|
}
|
|
430
572
|
/**
|
|
431
573
|
* Get user token balance
|
|
432
574
|
*/
|
|
433
575
|
async getBalance(e, t) {
|
|
434
|
-
return new
|
|
576
|
+
return new m.Contract(e, b, this.provider).balanceOf(t);
|
|
435
577
|
}
|
|
436
578
|
/**
|
|
437
579
|
* Get quote via API
|
|
@@ -439,57 +581,57 @@ const R = [
|
|
|
439
581
|
* @throws CustomFeeError if `options.customFee` is malformed
|
|
440
582
|
*/
|
|
441
583
|
async getQuote(e) {
|
|
442
|
-
const { srcToken: t, dstToken: n, amountIn:
|
|
443
|
-
byAmountIn:
|
|
444
|
-
depth: a =
|
|
445
|
-
splitCount: i =
|
|
446
|
-
providers: c =
|
|
447
|
-
deadlineSeconds: u =
|
|
448
|
-
includeResponseHeaders:
|
|
584
|
+
const { srcToken: t, dstToken: n, amountIn: s, options: o = {} } = e, {
|
|
585
|
+
byAmountIn: r = !0,
|
|
586
|
+
depth: a = E.depth,
|
|
587
|
+
splitCount: i = E.splitCount,
|
|
588
|
+
providers: c = E.providers,
|
|
589
|
+
deadlineSeconds: u = N,
|
|
590
|
+
includeResponseHeaders: l = !1,
|
|
449
591
|
customFee: p
|
|
450
|
-
} =
|
|
451
|
-
|
|
452
|
-
const A =
|
|
453
|
-
if (
|
|
454
|
-
const { data:
|
|
592
|
+
} = o;
|
|
593
|
+
C.validateCustomFee(p);
|
|
594
|
+
const A = T(t), w = T(n), v = A ? this.config.weth : t, g = w ? this.config.weth : n;
|
|
595
|
+
if (l) {
|
|
596
|
+
const { data: k, responseHeaders: x } = await this.apiClient.findRoutes({
|
|
455
597
|
from: v,
|
|
456
|
-
target:
|
|
457
|
-
amount:
|
|
458
|
-
byAmountIn:
|
|
598
|
+
target: g,
|
|
599
|
+
amount: s,
|
|
600
|
+
byAmountIn: r,
|
|
459
601
|
depth: a,
|
|
460
602
|
splitCount: i,
|
|
461
603
|
providers: c,
|
|
462
604
|
includeResponseHeaders: !0
|
|
463
605
|
});
|
|
464
606
|
return this.buildQuoteFromApi(
|
|
465
|
-
|
|
607
|
+
k,
|
|
466
608
|
v,
|
|
467
|
-
|
|
609
|
+
g,
|
|
468
610
|
u,
|
|
469
611
|
c,
|
|
470
612
|
A,
|
|
471
|
-
|
|
472
|
-
|
|
613
|
+
w,
|
|
614
|
+
x,
|
|
473
615
|
p
|
|
474
616
|
);
|
|
475
617
|
}
|
|
476
|
-
const
|
|
618
|
+
const P = await this.apiClient.findRoutes({
|
|
477
619
|
from: v,
|
|
478
|
-
target:
|
|
479
|
-
amount:
|
|
480
|
-
byAmountIn:
|
|
620
|
+
target: g,
|
|
621
|
+
amount: s,
|
|
622
|
+
byAmountIn: r,
|
|
481
623
|
depth: a,
|
|
482
624
|
splitCount: i,
|
|
483
625
|
providers: c
|
|
484
626
|
});
|
|
485
627
|
return this.buildQuoteFromApi(
|
|
486
|
-
|
|
628
|
+
P,
|
|
487
629
|
v,
|
|
488
|
-
|
|
630
|
+
g,
|
|
489
631
|
u,
|
|
490
632
|
c,
|
|
491
633
|
A,
|
|
492
|
-
|
|
634
|
+
w,
|
|
493
635
|
void 0,
|
|
494
636
|
p
|
|
495
637
|
);
|
|
@@ -501,15 +643,15 @@ const R = [
|
|
|
501
643
|
static validateCustomFee(e) {
|
|
502
644
|
if (!e) return;
|
|
503
645
|
const { feeAccount: t, feeBps: n } = e;
|
|
504
|
-
if (!Number.isInteger(n) || n < 1 || n >
|
|
646
|
+
if (!Number.isInteger(n) || n < 1 || n > U)
|
|
505
647
|
throw new B(
|
|
506
|
-
`customFee.feeBps must be an integer in [1, ${
|
|
648
|
+
`customFee.feeBps must be an integer in [1, ${U}] (5%), got ${n}`
|
|
507
649
|
);
|
|
508
|
-
if (!t || !
|
|
650
|
+
if (!t || !m.isAddress(t))
|
|
509
651
|
throw new B(
|
|
510
652
|
`customFee.feeAccount must be a valid address, got ${t}`
|
|
511
653
|
);
|
|
512
|
-
if (t ===
|
|
654
|
+
if (t === m.ZeroAddress)
|
|
513
655
|
throw new B("customFee.feeAccount must not be the zero address");
|
|
514
656
|
}
|
|
515
657
|
/**
|
|
@@ -519,7 +661,7 @@ const R = [
|
|
|
519
661
|
*/
|
|
520
662
|
resolveRouterAddress(e) {
|
|
521
663
|
const t = e ?? this.config.routerAddress;
|
|
522
|
-
if (!t || t ===
|
|
664
|
+
if (!t || t === m.ZeroAddress)
|
|
523
665
|
throw new Error(
|
|
524
666
|
"No router address available. Pass one explicitly or set config.routerAddress."
|
|
525
667
|
);
|
|
@@ -537,13 +679,13 @@ const R = [
|
|
|
537
679
|
* Pass an explicit address when reading from a different deployment.
|
|
538
680
|
*/
|
|
539
681
|
async getProtocolFeeConfig(e) {
|
|
540
|
-
const t = this.resolveRouterAddress(e), n = new
|
|
682
|
+
const t = this.resolveRouterAddress(e), n = new m.Contract(t, R, this.provider), [s, o] = await Promise.all([
|
|
541
683
|
n.protocolFeeReceiver(),
|
|
542
684
|
n.protocolCutBps()
|
|
543
685
|
]);
|
|
544
686
|
return {
|
|
545
|
-
protocolFeeReceiver:
|
|
546
|
-
protocolCutBps: Number(
|
|
687
|
+
protocolFeeReceiver: s,
|
|
688
|
+
protocolCutBps: Number(o)
|
|
547
689
|
};
|
|
548
690
|
}
|
|
549
691
|
/**
|
|
@@ -572,15 +714,15 @@ const R = [
|
|
|
572
714
|
* @param routerAddress Optional router address. Defaults to `config.routerAddress`.
|
|
573
715
|
*/
|
|
574
716
|
async getRouterConfig(e) {
|
|
575
|
-
const t = this.resolveRouterAddress(e), n = new
|
|
717
|
+
const t = this.resolveRouterAddress(e), n = new m.Contract(t, R, this.provider), [
|
|
718
|
+
s,
|
|
576
719
|
o,
|
|
577
720
|
r,
|
|
578
|
-
s,
|
|
579
721
|
a,
|
|
580
722
|
i,
|
|
581
723
|
c,
|
|
582
724
|
u,
|
|
583
|
-
|
|
725
|
+
l
|
|
584
726
|
] = await Promise.all([
|
|
585
727
|
n.WETH(),
|
|
586
728
|
n.owner(),
|
|
@@ -593,15 +735,15 @@ const R = [
|
|
|
593
735
|
]);
|
|
594
736
|
return {
|
|
595
737
|
address: t,
|
|
596
|
-
weth:
|
|
597
|
-
owner:
|
|
598
|
-
pendingOwner:
|
|
738
|
+
weth: s,
|
|
739
|
+
owner: o,
|
|
740
|
+
pendingOwner: r,
|
|
599
741
|
paused: !!a,
|
|
600
742
|
maxCustomFeeBps: Number(i),
|
|
601
743
|
maxProtocolCutBps: Number(c),
|
|
602
744
|
protocolFee: {
|
|
603
745
|
protocolFeeReceiver: u,
|
|
604
|
-
protocolCutBps: Number(
|
|
746
|
+
protocolCutBps: Number(l)
|
|
605
747
|
}
|
|
606
748
|
};
|
|
607
749
|
}
|
|
@@ -609,28 +751,28 @@ const R = [
|
|
|
609
751
|
* Filter paths by allowed providers, removing paths with disallowed providers
|
|
610
752
|
* and cascade-removing orphaned paths that depend on removed paths.
|
|
611
753
|
*/
|
|
612
|
-
filterPathsByProviders(e, t, n,
|
|
613
|
-
const
|
|
614
|
-
let
|
|
615
|
-
if (
|
|
616
|
-
return
|
|
617
|
-
const a = n.toLowerCase(), i =
|
|
754
|
+
filterPathsByProviders(e, t, n, s) {
|
|
755
|
+
const o = new Set(t.map((p) => p.toUpperCase()));
|
|
756
|
+
let r = e.filter((p) => o.has(p.provider.toUpperCase()));
|
|
757
|
+
if (r.length === e.length)
|
|
758
|
+
return r;
|
|
759
|
+
const a = n.toLowerCase(), i = s.toLowerCase(), c = /* @__PURE__ */ new Set();
|
|
618
760
|
c.add(a);
|
|
619
761
|
let u = !0;
|
|
620
762
|
for (; u; ) {
|
|
621
763
|
u = !1;
|
|
622
|
-
for (const p of
|
|
764
|
+
for (const p of r)
|
|
623
765
|
c.has(p.token_in.toLowerCase()) && !c.has(p.token_out.toLowerCase()) && (c.add(p.token_out.toLowerCase()), u = !0);
|
|
624
766
|
}
|
|
625
|
-
const
|
|
626
|
-
for (
|
|
767
|
+
const l = /* @__PURE__ */ new Set();
|
|
768
|
+
for (l.add(i), u = !0; u; ) {
|
|
627
769
|
u = !1;
|
|
628
|
-
for (const p of
|
|
629
|
-
|
|
770
|
+
for (const p of r)
|
|
771
|
+
l.has(p.token_out.toLowerCase()) && !l.has(p.token_in.toLowerCase()) && (l.add(p.token_in.toLowerCase()), u = !0);
|
|
630
772
|
}
|
|
631
|
-
return
|
|
632
|
-
(p) => c.has(p.token_in.toLowerCase()) &&
|
|
633
|
-
),
|
|
773
|
+
return r.length, r = r.filter(
|
|
774
|
+
(p) => c.has(p.token_in.toLowerCase()) && l.has(p.token_out.toLowerCase())
|
|
775
|
+
), r;
|
|
634
776
|
}
|
|
635
777
|
/**
|
|
636
778
|
* Build Quote from route data (e.g. from JSON file or API response).
|
|
@@ -641,119 +783,119 @@ const R = [
|
|
|
641
783
|
* @param dstToken - Destination token address (last path token_out)
|
|
642
784
|
* @param deadlineSeconds - Optional deadline in seconds from now (default: 20 min)
|
|
643
785
|
*/
|
|
644
|
-
buildQuoteFromRouteData(e, t, n,
|
|
645
|
-
const
|
|
786
|
+
buildQuoteFromRouteData(e, t, n, s, o) {
|
|
787
|
+
const r = this.buildQuoteFromRouteDataInternal(
|
|
646
788
|
e,
|
|
647
789
|
t,
|
|
648
790
|
n,
|
|
649
|
-
|
|
791
|
+
s ?? N,
|
|
650
792
|
void 0
|
|
651
793
|
);
|
|
652
|
-
return
|
|
794
|
+
return o?.srcNative && (r.srcNative = !0), o?.dstNative && (r.dstNative = !0), r;
|
|
653
795
|
}
|
|
654
796
|
/**
|
|
655
797
|
* Build Quote from API response
|
|
656
798
|
*/
|
|
657
|
-
buildQuoteFromApi(e, t, n, o, r,
|
|
799
|
+
buildQuoteFromApi(e, t, n, s, o, r, a, i, c) {
|
|
658
800
|
const u = this.buildQuoteFromRouteDataInternal(
|
|
659
801
|
e,
|
|
660
802
|
t,
|
|
661
803
|
n,
|
|
804
|
+
s,
|
|
662
805
|
o,
|
|
663
|
-
r,
|
|
664
806
|
c
|
|
665
807
|
);
|
|
666
|
-
return
|
|
808
|
+
return r && (u.srcNative = !0), a && (u.dstNative = !0), i && (u.responseHeaders = i), u;
|
|
667
809
|
}
|
|
668
|
-
buildQuoteFromRouteDataInternal(e, t, n, o, r
|
|
810
|
+
buildQuoteFromRouteDataInternal(e, t, n, s, o, r) {
|
|
669
811
|
const a = t.toLowerCase();
|
|
670
812
|
e.paths.length;
|
|
671
|
-
let i = e.paths.filter((
|
|
813
|
+
let i = e.paths.filter((h) => !(!(h.token_in.toLowerCase() === a) && BigInt(h.amount_in) === 0n && BigInt(h.amount_out) === 0n));
|
|
672
814
|
if (i.length === 0)
|
|
673
|
-
throw new
|
|
674
|
-
if (
|
|
675
|
-
throw new
|
|
815
|
+
throw new S("All route paths have zero amounts", 4001);
|
|
816
|
+
if (o && o.length > 0 && (i = this.filterPathsByProviders(i, o, t, n), i.length === 0))
|
|
817
|
+
throw new S("No valid route paths remaining after provider filtering", 4001);
|
|
676
818
|
const c = n.toLowerCase();
|
|
677
|
-
let u = 0n,
|
|
678
|
-
for (const
|
|
679
|
-
|
|
819
|
+
let u = 0n, l = 0n;
|
|
820
|
+
for (const h of i)
|
|
821
|
+
h.token_in.toLowerCase() === a && (u += BigInt(h.amount_in)), h.token_out.toLowerCase() === c && (l += BigInt(h.amount_out));
|
|
680
822
|
const p = BigInt(
|
|
681
|
-
Math.floor(Date.now() / 1e3) +
|
|
823
|
+
Math.floor(Date.now() / 1e3) + s
|
|
682
824
|
), A = /* @__PURE__ */ new Map();
|
|
683
|
-
for (const
|
|
684
|
-
const I =
|
|
825
|
+
for (const h of i) {
|
|
826
|
+
const I = h.token_in.toLowerCase();
|
|
685
827
|
A.set(I, (A.get(I) ?? 0) + 1);
|
|
686
828
|
}
|
|
687
|
-
const
|
|
688
|
-
const I =
|
|
689
|
-
|
|
690
|
-
const
|
|
829
|
+
const w = /* @__PURE__ */ new Map(), v = i.map((h) => {
|
|
830
|
+
const I = h.token_in.toLowerCase(), V = (w.get(I) ?? 0) + 1;
|
|
831
|
+
w.set(I, V);
|
|
832
|
+
const L = A.get(I), z = L > 1 && V < L, X = I === a;
|
|
691
833
|
return {
|
|
692
|
-
adapter:
|
|
693
|
-
pool:
|
|
694
|
-
tokenIn:
|
|
695
|
-
tokenOut:
|
|
696
|
-
amountIn:
|
|
697
|
-
extraData:
|
|
834
|
+
adapter: h.adapter,
|
|
835
|
+
pool: h.provider.toUpperCase() === "PANCAKE_INFINITY_CL" ? oe : h.provider.toUpperCase() === "PANCAKE_INFINITY_LB" ? ae : h.provider.toUpperCase() === "UNISWAPV4" ? ie : h.pool,
|
|
836
|
+
tokenIn: h.token_in,
|
|
837
|
+
tokenOut: h.token_out,
|
|
838
|
+
amountIn: X || z ? BigInt(h.amount_in) : 0n,
|
|
839
|
+
extraData: h.extra_data || "0x"
|
|
698
840
|
};
|
|
699
|
-
}),
|
|
700
|
-
for (const
|
|
701
|
-
|
|
702
|
-
const
|
|
841
|
+
}), g = /* @__PURE__ */ new Set();
|
|
842
|
+
for (const h of i)
|
|
843
|
+
h.token_out.toLowerCase() !== c && g.add(h.token_out);
|
|
844
|
+
const P = Array.from(g), k = r?.feeBps ?? 0, x = r?.feeAccount ?? m.ZeroAddress, D = l, F = k > 0 ? D * BigInt(k) / _ : 0n, y = D - F, Z = {
|
|
703
845
|
srcToken: t,
|
|
704
846
|
dstToken: n,
|
|
705
847
|
amountIn: u,
|
|
706
|
-
amountOutMin:
|
|
848
|
+
amountOutMin: y,
|
|
707
849
|
steps: v,
|
|
708
|
-
intermediateTokens:
|
|
850
|
+
intermediateTokens: P,
|
|
709
851
|
deadline: p,
|
|
710
|
-
quoteId: e.request_id ?
|
|
711
|
-
expectAmountOut:
|
|
712
|
-
feeReceiver:
|
|
713
|
-
feeBps:
|
|
714
|
-
},
|
|
852
|
+
quoteId: e.request_id ? m.id(e.request_id).slice(0, 66) : m.ZeroHash,
|
|
853
|
+
expectAmountOut: y,
|
|
854
|
+
feeReceiver: x,
|
|
855
|
+
feeBps: k
|
|
856
|
+
}, j = {
|
|
715
857
|
routes: [
|
|
716
858
|
{
|
|
717
|
-
steps: i.map((
|
|
859
|
+
steps: i.map((h) => ({
|
|
718
860
|
pool: {
|
|
719
|
-
address:
|
|
720
|
-
token0:
|
|
721
|
-
token1:
|
|
722
|
-
protocol: this.getProtocolForProvider(
|
|
723
|
-
fee:
|
|
861
|
+
address: h.pool,
|
|
862
|
+
token0: h.token_in,
|
|
863
|
+
token1: h.token_out,
|
|
864
|
+
protocol: this.getProtocolForProvider(h.provider),
|
|
865
|
+
fee: h.fee_rate ? Math.round(parseFloat(h.fee_rate) * 1e6) : void 0
|
|
724
866
|
},
|
|
725
|
-
tokenIn:
|
|
726
|
-
tokenOut:
|
|
727
|
-
amountIn: BigInt(
|
|
728
|
-
amountOut: BigInt(
|
|
867
|
+
tokenIn: h.token_in,
|
|
868
|
+
tokenOut: h.token_out,
|
|
869
|
+
amountIn: BigInt(h.amount_in),
|
|
870
|
+
amountOut: BigInt(h.amount_out)
|
|
729
871
|
})),
|
|
730
872
|
amountIn: u,
|
|
731
|
-
amountOut:
|
|
873
|
+
amountOut: l,
|
|
732
874
|
gasEstimate: BigInt(e.gas)
|
|
733
875
|
}
|
|
734
876
|
],
|
|
735
877
|
percentages: [1e4],
|
|
736
878
|
totalAmountIn: u,
|
|
737
|
-
totalAmountOut:
|
|
879
|
+
totalAmountOut: l,
|
|
738
880
|
totalGasEstimate: BigInt(e.gas)
|
|
739
881
|
};
|
|
740
882
|
if (!e.contracts?.router)
|
|
741
|
-
throw new
|
|
883
|
+
throw new S("API response missing contracts.router address", 4002);
|
|
742
884
|
return {
|
|
743
885
|
srcToken: t,
|
|
744
886
|
dstToken: n,
|
|
745
887
|
amountIn: u,
|
|
746
888
|
// Quote.amountOut reflects the user-perceived output (post custom fee).
|
|
747
889
|
// Wallets / UIs should display this number; the gross figure is at route.totalAmountOut.
|
|
748
|
-
amountOut:
|
|
890
|
+
amountOut: y,
|
|
749
891
|
priceImpact: parseFloat(e.deviation_ratio || "0"),
|
|
750
|
-
route:
|
|
751
|
-
params:
|
|
892
|
+
route: j,
|
|
893
|
+
params: Z,
|
|
752
894
|
gasEstimate: BigInt(e.gas),
|
|
753
895
|
routerAddress: e.contracts?.router,
|
|
754
|
-
customFee:
|
|
755
|
-
feeAccount:
|
|
756
|
-
feeBps:
|
|
896
|
+
customFee: k > 0 ? {
|
|
897
|
+
feeAccount: x,
|
|
898
|
+
feeBps: k,
|
|
757
899
|
feeAmount: F
|
|
758
900
|
} : void 0
|
|
759
901
|
};
|
|
@@ -775,23 +917,23 @@ const R = [
|
|
|
775
917
|
* @param stateOverrides - Optional state overrides for ERC20 balance/allowance
|
|
776
918
|
* @returns Simulated amountOut and method used
|
|
777
919
|
*/
|
|
778
|
-
async simulate(e, t, n,
|
|
779
|
-
const
|
|
780
|
-
if (
|
|
781
|
-
const u = this.getJsonRpcProviderForStateOverrides(),
|
|
782
|
-
{ from:
|
|
920
|
+
async simulate(e, t, n, s) {
|
|
921
|
+
const o = n || m.ZeroAddress, { to: r, data: a, value: i, method: c } = this.encodeSwapCalldata(e, t);
|
|
922
|
+
if (s) {
|
|
923
|
+
const u = this.getJsonRpcProviderForStateOverrides(), l = i > 0n ? "0x" + i.toString(16) : void 0, p = await u.send("eth_call", [
|
|
924
|
+
{ from: o, to: r, data: a, value: l },
|
|
783
925
|
"latest",
|
|
784
|
-
|
|
926
|
+
s
|
|
785
927
|
]), [A] = this.routerContract.interface.decodeFunctionResult(c, p);
|
|
786
928
|
return { amountOut: A, method: c };
|
|
787
929
|
} else {
|
|
788
930
|
const u = await this.provider.call({
|
|
789
|
-
from:
|
|
790
|
-
to:
|
|
931
|
+
from: o,
|
|
932
|
+
to: r,
|
|
791
933
|
data: a,
|
|
792
934
|
value: i > 0n ? i : void 0
|
|
793
|
-
}), [
|
|
794
|
-
return { amountOut:
|
|
935
|
+
}), [l] = this.routerContract.interface.decodeFunctionResult(c, u);
|
|
936
|
+
return { amountOut: l, method: c };
|
|
795
937
|
}
|
|
796
938
|
}
|
|
797
939
|
getJsonRpcProviderForStateOverrides() {
|
|
@@ -804,17 +946,17 @@ const R = [
|
|
|
804
946
|
/**
|
|
805
947
|
* Format simulate error with human-readable details
|
|
806
948
|
*/
|
|
807
|
-
formatSimulateError(e, t, n,
|
|
808
|
-
const
|
|
949
|
+
formatSimulateError(e, t, n, s) {
|
|
950
|
+
const o = e instanceof Error ? e : new Error(String(e)), r = e;
|
|
809
951
|
let a = "unknown";
|
|
810
|
-
if (
|
|
811
|
-
a =
|
|
812
|
-
else if (
|
|
813
|
-
const
|
|
814
|
-
|
|
815
|
-
} else
|
|
952
|
+
if (r.reason && typeof r.reason == "string")
|
|
953
|
+
a = r.reason;
|
|
954
|
+
else if (r.revert && typeof r.revert == "object") {
|
|
955
|
+
const l = r.revert;
|
|
956
|
+
l.args && Array.isArray(l.args) && (a = l.args.join(", "));
|
|
957
|
+
} else o.message && (a = o.message);
|
|
816
958
|
const i = t.params.steps.map(
|
|
817
|
-
(
|
|
959
|
+
(l, p) => ` Step ${p}: ${l.tokenIn.slice(0, 10)}→${l.tokenOut.slice(0, 10)} via adapter ${l.adapter.slice(0, 10)} pool ${l.pool.slice(0, 10)}`
|
|
818
960
|
).join(`
|
|
819
961
|
`), c = [
|
|
820
962
|
`Simulate ${n} failed: ${a}`,
|
|
@@ -822,12 +964,12 @@ const R = [
|
|
|
822
964
|
` AmountIn: ${t.amountIn}`,
|
|
823
965
|
` AmountOutMin: ${t.params.amountOutMin}`,
|
|
824
966
|
` Router: ${t.routerAddress}`,
|
|
825
|
-
` Caller: ${
|
|
967
|
+
` Caller: ${s}`,
|
|
826
968
|
` Steps (${t.params.steps.length}):`,
|
|
827
969
|
i
|
|
828
970
|
].join(`
|
|
829
971
|
`), u = new Error(c);
|
|
830
|
-
return u.cause =
|
|
972
|
+
return u.cause = o, u.reason = a, u;
|
|
831
973
|
}
|
|
832
974
|
/**
|
|
833
975
|
* Pinpoint the first problematic step in a route.
|
|
@@ -852,43 +994,43 @@ const R = [
|
|
|
852
994
|
* @param deviationThresholdBps - Maximum tolerated per-step shortfall vs quoted amountOut before flagging the step (default 50 = 0.5%).
|
|
853
995
|
* @returns The first step matching the criteria above, or null if every prefix simulates within tolerance.
|
|
854
996
|
*/
|
|
855
|
-
async findFailingStep(e, t, n, o, r
|
|
997
|
+
async findFailingStep(e, t, n, s, o, r = 50) {
|
|
856
998
|
const a = e.params.steps;
|
|
857
999
|
if (!a.length) return null;
|
|
858
|
-
const i =
|
|
1000
|
+
const i = o != null ? this.normalizeRevertReason(o) : void 0;
|
|
859
1001
|
for (let c = 1; c <= a.length; c++) {
|
|
860
1002
|
const u = this.buildTruncatedQuote(e, c);
|
|
861
|
-
let
|
|
1003
|
+
let l, p;
|
|
862
1004
|
try {
|
|
863
|
-
|
|
864
|
-
} catch (
|
|
865
|
-
p =
|
|
1005
|
+
l = (await this.simulate(u, t, n, s)).amountOut;
|
|
1006
|
+
} catch (g) {
|
|
1007
|
+
p = g;
|
|
866
1008
|
}
|
|
867
1009
|
if (p !== void 0) {
|
|
868
|
-
const
|
|
869
|
-
if (i == null ||
|
|
1010
|
+
const g = this.normalizeRevertReason(p), P = p?.shortMessage ?? p?.reason ?? p?.message;
|
|
1011
|
+
if (i == null || g === i)
|
|
870
1012
|
return {
|
|
871
1013
|
stepIndex: c - 1,
|
|
872
1014
|
step: a[c - 1],
|
|
873
1015
|
error: p,
|
|
874
|
-
revertMessage: typeof
|
|
1016
|
+
revertMessage: typeof P == "string" ? P : g,
|
|
875
1017
|
fullRouteRevertMessage: i
|
|
876
1018
|
};
|
|
877
1019
|
continue;
|
|
878
1020
|
}
|
|
879
|
-
if (
|
|
1021
|
+
if (l === void 0) continue;
|
|
880
1022
|
const A = this.getQuotedStepAmountOut(e, c - 1);
|
|
881
1023
|
if (A === void 0 || A === 0n) continue;
|
|
882
|
-
const
|
|
883
|
-
if (
|
|
884
|
-
const v =
|
|
885
|
-
if (v > BigInt(
|
|
886
|
-
const
|
|
1024
|
+
const w = A > l ? A - l : 0n;
|
|
1025
|
+
if (w === 0n) continue;
|
|
1026
|
+
const v = w * _ / A;
|
|
1027
|
+
if (v > BigInt(r)) {
|
|
1028
|
+
const g = `Step ${c - 1} deviates: quoted=${A} simulated=${l} shortfall=${w} (${v}bps, threshold=${r}bps). Likely cause: transfer-tax on ${a[c - 1].tokenOut}, stale pool data, or dynamic-fee drift.`;
|
|
887
1029
|
return {
|
|
888
1030
|
stepIndex: c - 1,
|
|
889
1031
|
step: a[c - 1],
|
|
890
|
-
error: new Error(
|
|
891
|
-
revertMessage:
|
|
1032
|
+
error: new Error(g),
|
|
1033
|
+
revertMessage: g,
|
|
892
1034
|
fullRouteRevertMessage: i
|
|
893
1035
|
};
|
|
894
1036
|
}
|
|
@@ -903,33 +1045,33 @@ const R = [
|
|
|
903
1045
|
const n = this.extractRevertData(e);
|
|
904
1046
|
if (n && n.length >= 10) {
|
|
905
1047
|
const c = n.slice(0, 10).toLowerCase();
|
|
906
|
-
return
|
|
1048
|
+
return C.KNOWN_ERROR_SELECTORS[c] ?? c;
|
|
907
1049
|
}
|
|
908
|
-
const
|
|
909
|
-
if (typeof
|
|
910
|
-
const
|
|
1050
|
+
const s = t.shortMessage ?? t.message;
|
|
1051
|
+
if (typeof s != "string") return;
|
|
1052
|
+
const o = s.match(/reason="([^"]+)"/);
|
|
1053
|
+
if (o) return o[1];
|
|
1054
|
+
const r = s.match(/reverted:\s*"([^"]+)"/);
|
|
911
1055
|
if (r) return r[1];
|
|
912
|
-
const
|
|
913
|
-
if (s) return s[1];
|
|
914
|
-
const a = o.match(/execution reverted:\s*"([^"]+)"/);
|
|
1056
|
+
const a = s.match(/execution reverted:\s*"([^"]+)"/);
|
|
915
1057
|
if (a) return a[1];
|
|
916
|
-
const i =
|
|
1058
|
+
const i = s.match(/\b0x[0-9a-fA-F]{8}\b/);
|
|
917
1059
|
if (i) {
|
|
918
1060
|
const c = i[0].toLowerCase();
|
|
919
|
-
return
|
|
1061
|
+
return C.KNOWN_ERROR_SELECTORS[c] ?? c;
|
|
920
1062
|
}
|
|
921
1063
|
}
|
|
922
1064
|
/** Walk an error object (including nested `info`/`error`/`cause`/`revert`) for the first hex revert-data blob. */
|
|
923
1065
|
extractRevertData(e) {
|
|
924
1066
|
const t = /* @__PURE__ */ new Set(), n = [e];
|
|
925
1067
|
for (; n.length; ) {
|
|
926
|
-
const
|
|
927
|
-
if (
|
|
928
|
-
t.add(
|
|
929
|
-
const
|
|
930
|
-
if (typeof
|
|
1068
|
+
const s = n.shift();
|
|
1069
|
+
if (s == null || typeof s != "object" || t.has(s)) continue;
|
|
1070
|
+
t.add(s);
|
|
1071
|
+
const o = s, r = o.data;
|
|
1072
|
+
if (typeof r == "string" && /^0x[0-9a-fA-F]{8,}$/.test(r)) return r;
|
|
931
1073
|
for (const a of ["info", "error", "cause", "revert", "originalError"])
|
|
932
|
-
|
|
1074
|
+
o[a] && n.push(o[a]);
|
|
933
1075
|
}
|
|
934
1076
|
}
|
|
935
1077
|
/** Read the aggregator's quoted per-step amountOut from the quote's flattened route. */
|
|
@@ -944,24 +1086,24 @@ const R = [
|
|
|
944
1086
|
* original dstToken to arrive, which never happens for an intermediate prefix.
|
|
945
1087
|
*/
|
|
946
1088
|
buildTruncatedQuote(e, t) {
|
|
947
|
-
const n = e.params.steps.slice(0, t),
|
|
948
|
-
for (const
|
|
949
|
-
const p =
|
|
950
|
-
p ===
|
|
1089
|
+
const n = e.params.steps.slice(0, t), o = n[n.length - 1].tokenOut, r = o.toLowerCase(), a = e.srcToken.toLowerCase(), i = t === e.params.steps.length, c = /* @__PURE__ */ new Set(), u = [];
|
|
1090
|
+
for (const l of n) {
|
|
1091
|
+
const p = l.tokenOut.toLowerCase();
|
|
1092
|
+
p === r || p === a || c.has(p) || (c.add(p), u.push(l.tokenOut));
|
|
951
1093
|
}
|
|
952
1094
|
return {
|
|
953
1095
|
...e,
|
|
954
|
-
dstToken:
|
|
1096
|
+
dstToken: o,
|
|
955
1097
|
// Native unwrap only makes sense when we're simulating the true dstToken.
|
|
956
1098
|
dstNative: i ? e.dstNative : !1,
|
|
957
1099
|
amountOut: i ? e.amountOut : 0n,
|
|
958
1100
|
customFee: i ? e.customFee : void 0,
|
|
959
1101
|
params: {
|
|
960
1102
|
...e.params,
|
|
961
|
-
dstToken:
|
|
1103
|
+
dstToken: o,
|
|
962
1104
|
amountOutMin: i ? e.params.amountOutMin : 0n,
|
|
963
1105
|
expectAmountOut: i ? e.params.expectAmountOut : 0n,
|
|
964
|
-
feeReceiver: i ? e.params.feeReceiver :
|
|
1106
|
+
feeReceiver: i ? e.params.feeReceiver : m.ZeroAddress,
|
|
965
1107
|
feeBps: i ? e.params.feeBps : 0,
|
|
966
1108
|
steps: n,
|
|
967
1109
|
intermediateTokens: u
|
|
@@ -985,57 +1127,57 @@ const R = [
|
|
|
985
1127
|
* @param balance - Balance to inject (default: 1M tokens with 18 decimals)
|
|
986
1128
|
* @param spenderAddress - Spender to approve (default: routerAddress). Pass quote.routerAddress when simulating API quotes.
|
|
987
1129
|
*/
|
|
988
|
-
buildStateOverrides(e, t, n, o, r
|
|
989
|
-
if (
|
|
1130
|
+
buildStateOverrides(e, t, n, s, o, r) {
|
|
1131
|
+
if (r?.isNative || T(e))
|
|
990
1132
|
return {};
|
|
991
|
-
if (!n || n ===
|
|
1133
|
+
if (!n || n === m.ZeroAddress)
|
|
992
1134
|
throw new Error("buildStateOverrides requires a non-zero routerAddress.");
|
|
993
|
-
const a =
|
|
994
|
-
for (const
|
|
995
|
-
const v =
|
|
1135
|
+
const a = m.AbiCoder.defaultAbiCoder(), i = s || m.parseUnits("1000000", 18), c = o ?? n, u = m.zeroPadValue(m.toBeHex(i), 32), l = m.zeroPadValue(m.toBeHex(m.MaxUint256), 32), p = {}, A = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 50, 51, 52, 100, 101, 102];
|
|
1136
|
+
for (const w of A) {
|
|
1137
|
+
const v = m.keccak256(a.encode(["address", "uint256"], [t, w]));
|
|
996
1138
|
p[v] = u;
|
|
997
|
-
const
|
|
998
|
-
p[
|
|
1139
|
+
const g = m.keccak256(a.encode(["address", "uint256"], [t, w])), P = m.keccak256(a.encode(["address", "bytes32"], [c, g]));
|
|
1140
|
+
p[P] = l;
|
|
999
1141
|
}
|
|
1000
1142
|
return {
|
|
1001
1143
|
[e.toLowerCase()]: { stateDiff: p }
|
|
1002
1144
|
};
|
|
1003
1145
|
}
|
|
1004
1146
|
};
|
|
1005
|
-
|
|
1147
|
+
C.KNOWN_ERROR_SELECTORS = {
|
|
1006
1148
|
"0x2c19b8b8": "InsufficientOutput"
|
|
1007
1149
|
};
|
|
1008
|
-
let
|
|
1009
|
-
const
|
|
1150
|
+
let K = C;
|
|
1151
|
+
const Y = [
|
|
1010
1152
|
"function token0() external view returns (address)",
|
|
1011
1153
|
"function token1() external view returns (address)",
|
|
1012
1154
|
"function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast)"
|
|
1013
|
-
],
|
|
1155
|
+
], ce = [
|
|
1014
1156
|
"function token0() external view returns (address)",
|
|
1015
1157
|
"function token1() external view returns (address)",
|
|
1016
1158
|
"function fee() external view returns (uint24)",
|
|
1017
1159
|
"function liquidity() external view returns (uint128)",
|
|
1018
1160
|
"function slot0() external view returns (uint160 sqrtPriceX96, int24 tick, uint16 observationIndex, uint16 observationCardinality, uint16 observationCardinalityNext, uint32 feeProtocol, bool unlocked)"
|
|
1019
|
-
],
|
|
1161
|
+
], ue = "0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73", de = [
|
|
1020
1162
|
"function getPair(address tokenA, address tokenB) external view returns (address pair)"
|
|
1021
|
-
],
|
|
1163
|
+
], le = "0x86407bEa2078ea5f5EB5A52B2caA963bC1F889Da", pe = [
|
|
1022
1164
|
"function getPair(address tokenA, address tokenB) external view returns (address pair)"
|
|
1023
|
-
],
|
|
1165
|
+
], me = "0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865", fe = [
|
|
1024
1166
|
"function getPool(address tokenA, address tokenB, uint24 fee) external view returns (address pool)"
|
|
1025
|
-
],
|
|
1026
|
-
class
|
|
1167
|
+
], he = [100, 500, 2500, 1e4], we = 60000n, Ae = 120000n, ve = 100000n;
|
|
1168
|
+
class Ce {
|
|
1027
1169
|
constructor(e, t) {
|
|
1028
|
-
this.poolCache = /* @__PURE__ */ new Map(), this.provider = e, this.v2Factory = new
|
|
1029
|
-
se,
|
|
1030
|
-
ae,
|
|
1031
|
-
e
|
|
1032
|
-
), this.v3Factory = new f.Contract(
|
|
1170
|
+
this.poolCache = /* @__PURE__ */ new Map(), this.provider = e, this.v2Factory = new m.Contract(
|
|
1033
1171
|
ue,
|
|
1034
1172
|
de,
|
|
1035
1173
|
e
|
|
1036
|
-
), this.
|
|
1037
|
-
|
|
1038
|
-
|
|
1174
|
+
), this.v3Factory = new m.Contract(
|
|
1175
|
+
me,
|
|
1176
|
+
fe,
|
|
1177
|
+
e
|
|
1178
|
+
), this.babySwapFactory = new m.Contract(
|
|
1179
|
+
le,
|
|
1180
|
+
pe,
|
|
1039
1181
|
e
|
|
1040
1182
|
);
|
|
1041
1183
|
}
|
|
@@ -1043,11 +1185,11 @@ class Ie {
|
|
|
1043
1185
|
* Discover optimal route
|
|
1044
1186
|
*/
|
|
1045
1187
|
async findBestRoute(e, t, n) {
|
|
1046
|
-
const
|
|
1047
|
-
if (
|
|
1188
|
+
const s = await this.discoverPools(e, t);
|
|
1189
|
+
if (s.length === 0)
|
|
1048
1190
|
throw new Error(`No pools found for ${e} -> ${t}`);
|
|
1049
|
-
const
|
|
1050
|
-
|
|
1191
|
+
const r = (await this.calculateRoutes(
|
|
1192
|
+
s,
|
|
1051
1193
|
e,
|
|
1052
1194
|
t,
|
|
1053
1195
|
n
|
|
@@ -1055,12 +1197,12 @@ class Ie {
|
|
|
1055
1197
|
(a, i) => i.amountOut > a.amountOut ? i : a
|
|
1056
1198
|
);
|
|
1057
1199
|
return {
|
|
1058
|
-
routes: [
|
|
1200
|
+
routes: [r],
|
|
1059
1201
|
percentages: [1e4],
|
|
1060
1202
|
// 100%
|
|
1061
1203
|
totalAmountIn: n,
|
|
1062
|
-
totalAmountOut:
|
|
1063
|
-
totalGasEstimate:
|
|
1204
|
+
totalAmountOut: r.amountOut,
|
|
1205
|
+
totalGasEstimate: r.gasEstimate
|
|
1064
1206
|
};
|
|
1065
1207
|
}
|
|
1066
1208
|
/**
|
|
@@ -1069,19 +1211,19 @@ class Ie {
|
|
|
1069
1211
|
async discoverPools(e, t) {
|
|
1070
1212
|
const n = [];
|
|
1071
1213
|
try {
|
|
1072
|
-
const
|
|
1073
|
-
|
|
1214
|
+
const s = await this.findV2Pool(e, t);
|
|
1215
|
+
s && n.push(s);
|
|
1074
1216
|
} catch {
|
|
1075
1217
|
}
|
|
1076
|
-
for (const
|
|
1218
|
+
for (const s of he)
|
|
1077
1219
|
try {
|
|
1078
|
-
const
|
|
1079
|
-
|
|
1220
|
+
const o = await this.findV3Pool(e, t, s);
|
|
1221
|
+
o && n.push(o);
|
|
1080
1222
|
} catch {
|
|
1081
1223
|
}
|
|
1082
1224
|
try {
|
|
1083
|
-
const
|
|
1084
|
-
|
|
1225
|
+
const s = await this.findBabySwapPool(e, t);
|
|
1226
|
+
s && n.push(s);
|
|
1085
1227
|
} catch {
|
|
1086
1228
|
}
|
|
1087
1229
|
return n;
|
|
@@ -1093,18 +1235,18 @@ class Ie {
|
|
|
1093
1235
|
const n = `v2-${e}-${t}`;
|
|
1094
1236
|
if (this.poolCache.has(n))
|
|
1095
1237
|
return this.poolCache.get(n);
|
|
1096
|
-
const
|
|
1097
|
-
if (
|
|
1238
|
+
const s = await this.v2Factory.getPair(e, t);
|
|
1239
|
+
if (s === m.ZeroAddress)
|
|
1098
1240
|
return null;
|
|
1099
|
-
const
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1241
|
+
const o = new m.Contract(s, Y, this.provider), [r, a, i] = await Promise.all([
|
|
1242
|
+
o.token0(),
|
|
1243
|
+
o.token1(),
|
|
1244
|
+
o.getReserves()
|
|
1103
1245
|
]), c = {
|
|
1104
|
-
address:
|
|
1105
|
-
token0:
|
|
1246
|
+
address: s,
|
|
1247
|
+
token0: r,
|
|
1106
1248
|
token1: a,
|
|
1107
|
-
protocol:
|
|
1249
|
+
protocol: d.PancakeV2,
|
|
1108
1250
|
reserve0: i.reserve0,
|
|
1109
1251
|
reserve1: i.reserve1
|
|
1110
1252
|
};
|
|
@@ -1114,28 +1256,28 @@ class Ie {
|
|
|
1114
1256
|
* Find V3 pool
|
|
1115
1257
|
*/
|
|
1116
1258
|
async findV3Pool(e, t, n) {
|
|
1117
|
-
const
|
|
1118
|
-
if (this.poolCache.has(
|
|
1119
|
-
return this.poolCache.get(
|
|
1120
|
-
const
|
|
1121
|
-
if (
|
|
1259
|
+
const s = `v3-${e}-${t}-${n}`;
|
|
1260
|
+
if (this.poolCache.has(s))
|
|
1261
|
+
return this.poolCache.get(s);
|
|
1262
|
+
const o = await this.v3Factory.getPool(e, t, n);
|
|
1263
|
+
if (o === m.ZeroAddress)
|
|
1122
1264
|
return null;
|
|
1123
|
-
const
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1265
|
+
const r = new m.Contract(o, ce, this.provider), [a, i, c] = await Promise.all([
|
|
1266
|
+
r.token0(),
|
|
1267
|
+
r.token1(),
|
|
1268
|
+
r.liquidity()
|
|
1127
1269
|
]);
|
|
1128
1270
|
if (c === 0n)
|
|
1129
1271
|
return null;
|
|
1130
1272
|
const u = {
|
|
1131
|
-
address:
|
|
1273
|
+
address: o,
|
|
1132
1274
|
token0: a,
|
|
1133
1275
|
token1: i,
|
|
1134
|
-
protocol:
|
|
1276
|
+
protocol: d.PancakeV3,
|
|
1135
1277
|
fee: n,
|
|
1136
1278
|
liquidity: c
|
|
1137
1279
|
};
|
|
1138
|
-
return this.poolCache.set(
|
|
1280
|
+
return this.poolCache.set(s, u), u;
|
|
1139
1281
|
}
|
|
1140
1282
|
/**
|
|
1141
1283
|
* Find BabySwap pool (V2 fork, 0.2% fee)
|
|
@@ -1144,18 +1286,18 @@ class Ie {
|
|
|
1144
1286
|
const n = `babyswap-${e}-${t}`;
|
|
1145
1287
|
if (this.poolCache.has(n))
|
|
1146
1288
|
return this.poolCache.get(n);
|
|
1147
|
-
const
|
|
1148
|
-
if (
|
|
1289
|
+
const s = await this.babySwapFactory.getPair(e, t);
|
|
1290
|
+
if (s === m.ZeroAddress)
|
|
1149
1291
|
return null;
|
|
1150
|
-
const
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1292
|
+
const o = new m.Contract(s, Y, this.provider), [r, a, i] = await Promise.all([
|
|
1293
|
+
o.token0(),
|
|
1294
|
+
o.token1(),
|
|
1295
|
+
o.getReserves()
|
|
1154
1296
|
]), c = {
|
|
1155
|
-
address:
|
|
1156
|
-
token0:
|
|
1297
|
+
address: s,
|
|
1298
|
+
token0: r,
|
|
1157
1299
|
token1: a,
|
|
1158
|
-
protocol:
|
|
1300
|
+
protocol: d.BabySwap,
|
|
1159
1301
|
reserve0: i.reserve0,
|
|
1160
1302
|
reserve1: i.reserve1
|
|
1161
1303
|
};
|
|
@@ -1164,66 +1306,66 @@ class Ie {
|
|
|
1164
1306
|
/**
|
|
1165
1307
|
* Calculate route quotes
|
|
1166
1308
|
*/
|
|
1167
|
-
async calculateRoutes(e, t, n,
|
|
1168
|
-
const
|
|
1169
|
-
for (const
|
|
1309
|
+
async calculateRoutes(e, t, n, s) {
|
|
1310
|
+
const o = [];
|
|
1311
|
+
for (const r of e)
|
|
1170
1312
|
try {
|
|
1171
1313
|
const a = await this.getAmountOut(
|
|
1172
|
-
|
|
1314
|
+
r,
|
|
1173
1315
|
t,
|
|
1174
1316
|
n,
|
|
1175
|
-
|
|
1317
|
+
s
|
|
1176
1318
|
);
|
|
1177
|
-
a > 0n &&
|
|
1319
|
+
a > 0n && o.push({
|
|
1178
1320
|
steps: [
|
|
1179
1321
|
{
|
|
1180
|
-
pool:
|
|
1322
|
+
pool: r,
|
|
1181
1323
|
tokenIn: t,
|
|
1182
1324
|
tokenOut: n,
|
|
1183
|
-
amountIn:
|
|
1325
|
+
amountIn: s,
|
|
1184
1326
|
amountOut: a
|
|
1185
1327
|
}
|
|
1186
1328
|
],
|
|
1187
|
-
amountIn:
|
|
1329
|
+
amountIn: s,
|
|
1188
1330
|
amountOut: a,
|
|
1189
|
-
gasEstimate:
|
|
1331
|
+
gasEstimate: r.protocol === d.PancakeV2 || r.protocol === d.BabySwap ? we : r.protocol === d.Dodo ? ve : Ae
|
|
1190
1332
|
});
|
|
1191
1333
|
} catch {
|
|
1192
1334
|
}
|
|
1193
|
-
return
|
|
1335
|
+
return o;
|
|
1194
1336
|
}
|
|
1195
1337
|
/**
|
|
1196
1338
|
* Get output for a single pool
|
|
1197
1339
|
*/
|
|
1198
|
-
async getAmountOut(e, t, n,
|
|
1199
|
-
if (e.protocol ===
|
|
1200
|
-
return this.getV2AmountOut(e, t,
|
|
1201
|
-
if (e.protocol ===
|
|
1202
|
-
return this.getBabySwapAmountOut(e, t,
|
|
1203
|
-
if (e.protocol ===
|
|
1340
|
+
async getAmountOut(e, t, n, s) {
|
|
1341
|
+
if (e.protocol === d.PancakeV2)
|
|
1342
|
+
return this.getV2AmountOut(e, t, s);
|
|
1343
|
+
if (e.protocol === d.BabySwap)
|
|
1344
|
+
return this.getBabySwapAmountOut(e, t, s);
|
|
1345
|
+
if (e.protocol === d.Dodo)
|
|
1204
1346
|
throw new Error("DODO amount out not supported in local route discovery");
|
|
1205
|
-
return this.estimateV3AmountOut(e, t,
|
|
1347
|
+
return this.estimateV3AmountOut(e, t, s);
|
|
1206
1348
|
}
|
|
1207
1349
|
/**
|
|
1208
1350
|
* V2 output calculation
|
|
1209
1351
|
*/
|
|
1210
1352
|
getV2AmountOut(e, t, n) {
|
|
1211
|
-
const
|
|
1353
|
+
const s = t.toLowerCase() === e.token0.toLowerCase(), [o, r] = s ? [e.reserve0, e.reserve1] : [e.reserve1, e.reserve0], a = n * 9975n, i = a * r, c = o * 10000n + a;
|
|
1212
1354
|
return i / c;
|
|
1213
1355
|
}
|
|
1214
1356
|
/**
|
|
1215
1357
|
* BabySwap output calculation (V2 fork, 0.2% fee — coefficient 2 in 1000-scale)
|
|
1216
1358
|
*/
|
|
1217
1359
|
getBabySwapAmountOut(e, t, n) {
|
|
1218
|
-
const
|
|
1360
|
+
const s = t.toLowerCase() === e.token0.toLowerCase(), [o, r] = s ? [e.reserve0, e.reserve1] : [e.reserve1, e.reserve0], a = n * 998n, i = a * r, c = o * 1000n + a;
|
|
1219
1361
|
return i / c;
|
|
1220
1362
|
}
|
|
1221
1363
|
/**
|
|
1222
1364
|
* V3 output estimation (simplified)
|
|
1223
1365
|
*/
|
|
1224
1366
|
estimateV3AmountOut(e, t, n) {
|
|
1225
|
-
const
|
|
1226
|
-
return n *
|
|
1367
|
+
const o = 1000000n - BigInt(e.fee || 2500);
|
|
1368
|
+
return n * o / 1000000n;
|
|
1227
1369
|
}
|
|
1228
1370
|
/**
|
|
1229
1371
|
* Clear cache
|
|
@@ -1232,33 +1374,33 @@ class Ie {
|
|
|
1232
1374
|
this.poolCache.clear();
|
|
1233
1375
|
}
|
|
1234
1376
|
}
|
|
1235
|
-
class
|
|
1377
|
+
class be {
|
|
1236
1378
|
constructor(e) {
|
|
1237
1379
|
this.adapters = e;
|
|
1238
1380
|
}
|
|
1239
1381
|
/**
|
|
1240
1382
|
* Build SwapParams from split route
|
|
1241
1383
|
*/
|
|
1242
|
-
build(e, t, n,
|
|
1243
|
-
const
|
|
1384
|
+
build(e, t, n, s, o = N) {
|
|
1385
|
+
const r = this.flattenRoutes(e), a = this.mergeIdenticalPools(r), i = this.topologicalSort(a, t), c = this.convertToSwapSteps(i), u = this.extractIntermediates(
|
|
1244
1386
|
i,
|
|
1245
1387
|
t,
|
|
1246
1388
|
n
|
|
1247
|
-
),
|
|
1389
|
+
), l = BigInt(Math.floor(Date.now() / 1e3) + o);
|
|
1248
1390
|
return {
|
|
1249
1391
|
srcToken: t,
|
|
1250
1392
|
dstToken: n,
|
|
1251
1393
|
amountIn: e.totalAmountIn,
|
|
1252
|
-
amountOutMin:
|
|
1394
|
+
amountOutMin: s,
|
|
1253
1395
|
steps: c,
|
|
1254
1396
|
intermediateTokens: u,
|
|
1255
|
-
deadline:
|
|
1256
|
-
quoteId:
|
|
1397
|
+
deadline: l,
|
|
1398
|
+
quoteId: m.ZeroHash,
|
|
1257
1399
|
expectAmountOut: e.totalAmountOut,
|
|
1258
1400
|
// SwapBuilder is the legacy direct-build path that does not know about custom fees.
|
|
1259
1401
|
// Integrators that want custom fees should use PeachClient.getQuote with options.customFee
|
|
1260
1402
|
// instead, which sets these fields and adjusts amountOutMin accordingly.
|
|
1261
|
-
feeReceiver:
|
|
1403
|
+
feeReceiver: m.ZeroAddress,
|
|
1262
1404
|
feeBps: 0
|
|
1263
1405
|
};
|
|
1264
1406
|
}
|
|
@@ -1268,15 +1410,15 @@ class Ce {
|
|
|
1268
1410
|
flattenRoutes(e) {
|
|
1269
1411
|
const t = [];
|
|
1270
1412
|
for (let n = 0; n < e.routes.length; n++) {
|
|
1271
|
-
const
|
|
1272
|
-
for (let a = 0; a <
|
|
1273
|
-
const i =
|
|
1413
|
+
const s = e.routes[n], o = e.percentages[n], r = e.totalAmountIn * BigInt(o) / _;
|
|
1414
|
+
for (let a = 0; a < s.steps.length; a++) {
|
|
1415
|
+
const i = s.steps[a];
|
|
1274
1416
|
t.push({
|
|
1275
1417
|
pool: i.pool,
|
|
1276
1418
|
tokenIn: i.tokenIn,
|
|
1277
1419
|
tokenOut: i.tokenOut,
|
|
1278
1420
|
// Only first step has fixed amount, subsequent steps depend on previous output
|
|
1279
|
-
amountIn: a === 0 ?
|
|
1421
|
+
amountIn: a === 0 ? r : 0n,
|
|
1280
1422
|
routeIndex: n,
|
|
1281
1423
|
stepIndex: a
|
|
1282
1424
|
});
|
|
@@ -1290,21 +1432,21 @@ class Ce {
|
|
|
1290
1432
|
*/
|
|
1291
1433
|
mergeIdenticalPools(e) {
|
|
1292
1434
|
const t = /* @__PURE__ */ new Map(), n = [];
|
|
1293
|
-
for (const
|
|
1294
|
-
const
|
|
1295
|
-
if (t.has(
|
|
1296
|
-
const
|
|
1297
|
-
|
|
1435
|
+
for (const s of e) {
|
|
1436
|
+
const o = `${s.pool.address}-${s.tokenIn}-${s.tokenOut}`;
|
|
1437
|
+
if (t.has(o)) {
|
|
1438
|
+
const r = t.get(o);
|
|
1439
|
+
s.amountIn > 0n && r.amountIn > 0n && (r.amountIn = 0n);
|
|
1298
1440
|
} else {
|
|
1299
|
-
const
|
|
1300
|
-
t.set(
|
|
1441
|
+
const r = { ...s };
|
|
1442
|
+
t.set(o, r), n.push(r);
|
|
1301
1443
|
}
|
|
1302
1444
|
}
|
|
1303
|
-
for (const
|
|
1304
|
-
const
|
|
1445
|
+
for (const s of n) {
|
|
1446
|
+
const o = `${s.pool.address}-${s.tokenIn}-${s.tokenOut}`;
|
|
1305
1447
|
e.filter(
|
|
1306
|
-
(a) => `${a.pool.address}-${a.tokenIn}-${a.tokenOut}` ===
|
|
1307
|
-
).length > 1 && (
|
|
1448
|
+
(a) => `${a.pool.address}-${a.tokenIn}-${a.tokenOut}` === o
|
|
1449
|
+
).length > 1 && (s.amountIn = 0n);
|
|
1308
1450
|
}
|
|
1309
1451
|
return n;
|
|
1310
1452
|
}
|
|
@@ -1312,31 +1454,31 @@ class Ce {
|
|
|
1312
1454
|
* Topological sort (Kahn's Algorithm)
|
|
1313
1455
|
*/
|
|
1314
1456
|
topologicalSort(e, t) {
|
|
1315
|
-
const n = /* @__PURE__ */ new Map(),
|
|
1457
|
+
const n = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map();
|
|
1316
1458
|
for (const i of e) {
|
|
1317
1459
|
const c = this.stepKey(i);
|
|
1318
|
-
|
|
1460
|
+
s.set(c, i), n.set(c, 0), o.set(c, []);
|
|
1319
1461
|
}
|
|
1320
1462
|
for (const i of e) {
|
|
1321
1463
|
const c = this.stepKey(i);
|
|
1322
1464
|
if (i.tokenIn !== t) {
|
|
1323
1465
|
for (const u of e)
|
|
1324
1466
|
if (u.tokenOut === i.tokenIn) {
|
|
1325
|
-
const
|
|
1326
|
-
|
|
1467
|
+
const l = this.stepKey(u);
|
|
1468
|
+
l !== c && (o.get(l).push(c), n.set(c, (n.get(c) || 0) + 1));
|
|
1327
1469
|
}
|
|
1328
1470
|
}
|
|
1329
1471
|
}
|
|
1330
|
-
const
|
|
1472
|
+
const r = [];
|
|
1331
1473
|
for (const [i, c] of n)
|
|
1332
|
-
c === 0 &&
|
|
1474
|
+
c === 0 && r.push(i);
|
|
1333
1475
|
const a = [];
|
|
1334
|
-
for (;
|
|
1335
|
-
const i =
|
|
1476
|
+
for (; r.length > 0; ) {
|
|
1477
|
+
const i = r.shift(), c = s.get(i);
|
|
1336
1478
|
a.push(c);
|
|
1337
|
-
for (const u of
|
|
1338
|
-
const
|
|
1339
|
-
n.set(u,
|
|
1479
|
+
for (const u of o.get(i) || []) {
|
|
1480
|
+
const l = (n.get(u) || 0) - 1;
|
|
1481
|
+
n.set(u, l), l === 0 && r.push(u);
|
|
1340
1482
|
}
|
|
1341
1483
|
}
|
|
1342
1484
|
if (a.length !== e.length)
|
|
@@ -1366,41 +1508,47 @@ class Ce {
|
|
|
1366
1508
|
*/
|
|
1367
1509
|
encodeExtraData(e) {
|
|
1368
1510
|
switch (e.protocol) {
|
|
1369
|
-
case
|
|
1511
|
+
case d.PancakeV1:
|
|
1512
|
+
return "0x";
|
|
1513
|
+
case d.PancakeV2:
|
|
1370
1514
|
return "0x";
|
|
1371
1515
|
// V2 doesn't need extra parameters
|
|
1372
|
-
case
|
|
1373
|
-
|
|
1374
|
-
case
|
|
1375
|
-
case
|
|
1376
|
-
case
|
|
1516
|
+
case d.UniswapV2:
|
|
1517
|
+
return "0x";
|
|
1518
|
+
case d.PancakeV3:
|
|
1519
|
+
case d.UniswapV3:
|
|
1520
|
+
case d.UniswapV4:
|
|
1521
|
+
case d.SquadSwapV3:
|
|
1522
|
+
case d.ThenaFusion:
|
|
1377
1523
|
return "0x";
|
|
1378
|
-
case
|
|
1379
|
-
case
|
|
1524
|
+
case d.PancakeInfinityCl:
|
|
1525
|
+
case d.PancakeInfinityLb:
|
|
1380
1526
|
return "0x";
|
|
1381
|
-
case
|
|
1527
|
+
case d.Dodo:
|
|
1382
1528
|
return "0x";
|
|
1383
|
-
case
|
|
1529
|
+
case d.NomiswapStable:
|
|
1384
1530
|
return "0x";
|
|
1385
|
-
case
|
|
1531
|
+
case d.Biswap:
|
|
1386
1532
|
return "0x";
|
|
1387
|
-
case
|
|
1533
|
+
case d.Apeswap:
|
|
1388
1534
|
return "0x";
|
|
1389
|
-
case
|
|
1535
|
+
case d.BabyDogeSwap:
|
|
1390
1536
|
return "0x";
|
|
1391
|
-
case
|
|
1537
|
+
case d.BabySwap:
|
|
1392
1538
|
return "0x";
|
|
1393
|
-
case
|
|
1539
|
+
case d.BakerySwap:
|
|
1394
1540
|
return "0x";
|
|
1395
|
-
case
|
|
1541
|
+
case d.SquadSwapV2:
|
|
1396
1542
|
return "0x";
|
|
1397
|
-
case
|
|
1543
|
+
case d.SushiSwapV2:
|
|
1398
1544
|
return "0x";
|
|
1399
|
-
case
|
|
1545
|
+
case d.SushiSwapV3:
|
|
1400
1546
|
return "0x";
|
|
1401
|
-
case
|
|
1547
|
+
case d.PancakeStable:
|
|
1402
1548
|
return "0x";
|
|
1403
|
-
case
|
|
1549
|
+
case d.ListaStable:
|
|
1550
|
+
return "0x";
|
|
1551
|
+
case d.Wombat:
|
|
1404
1552
|
return "0x";
|
|
1405
1553
|
default:
|
|
1406
1554
|
return "0x";
|
|
@@ -1410,10 +1558,10 @@ class Ce {
|
|
|
1410
1558
|
* Extract intermediate tokens
|
|
1411
1559
|
*/
|
|
1412
1560
|
extractIntermediates(e, t, n) {
|
|
1413
|
-
const
|
|
1414
|
-
for (const
|
|
1415
|
-
|
|
1416
|
-
return
|
|
1561
|
+
const s = /* @__PURE__ */ new Set();
|
|
1562
|
+
for (const o of e)
|
|
1563
|
+
o.tokenOut !== n && s.add(o.tokenOut);
|
|
1564
|
+
return s.delete(t), s.delete(n), Array.from(s);
|
|
1417
1565
|
}
|
|
1418
1566
|
/**
|
|
1419
1567
|
* Generate unique step key
|
|
@@ -1423,28 +1571,30 @@ class Ce {
|
|
|
1423
1571
|
}
|
|
1424
1572
|
}
|
|
1425
1573
|
export {
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1574
|
+
E as API_DEFAULTS,
|
|
1575
|
+
ne as ApiClient,
|
|
1576
|
+
S as ApiError,
|
|
1577
|
+
_ as BPS_DENOMINATOR,
|
|
1578
|
+
ke as BSC_MAINNET_CONFIG,
|
|
1579
|
+
Ee as BSC_TESTNET_CONFIG,
|
|
1432
1580
|
B as CustomFeeError,
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1581
|
+
J as DEFAULT_API_URL,
|
|
1582
|
+
N as DEFAULT_DEADLINE_SECONDS,
|
|
1583
|
+
G as DEFAULT_EXECUTE_TIMEOUT_MS,
|
|
1584
|
+
Se as DEFAULT_SLIPPAGE_BPS,
|
|
1585
|
+
M as DEFAULT_TRANSACTION_RESPONSE_POLL_INTERVALS_MS,
|
|
1586
|
+
Pe as ERR_ZERO_AMOUNT_PATHS,
|
|
1587
|
+
Q as ExecuteTimeoutError,
|
|
1588
|
+
U as MAX_FEE_BPS,
|
|
1589
|
+
Ie as MAX_PLATFORM_CUT_BPS,
|
|
1590
|
+
q as NATIVE_TOKEN_ADDRESS,
|
|
1591
|
+
O as PERMIT2_ADDRESS,
|
|
1592
|
+
$ as PERMIT2_MAX_AMOUNT,
|
|
1593
|
+
K as PeachClient,
|
|
1594
|
+
d as ProtocolType,
|
|
1595
|
+
Ce as RouteDiscovery,
|
|
1596
|
+
be as SwapBuilder,
|
|
1597
|
+
T as isNativeTokenAddress,
|
|
1598
|
+
W as withWalletSendTimeout
|
|
1449
1599
|
};
|
|
1450
1600
|
//# sourceMappingURL=index.mjs.map
|