@peachprojects/aggregator-sdk 0.1.1 → 0.1.2

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.mjs CHANGED
@@ -1,111 +1,125 @@
1
- import { ethers as h } from "ethers";
2
- const V = "https://api.peach.ag", et = 50, O = 10000n, y = 1200, D = 6e4, x = [50, 100, 200, 400, 800, 1200], $ = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
3
- function _(m) {
4
- return m.toLowerCase() === $.toLowerCase();
1
+ import { ethers as l } from "ethers";
2
+ const q = "https://api.peach.ag", he = 50, b = 10000n, L = 500, fe = 5e3, T = 1200, W = 6e4, $ = [50, 100, 200, 400, 800, 1200], Q = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
3
+ function _(w) {
4
+ return w.toLowerCase() === Q.toLowerCase();
5
5
  }
6
- const nt = 4001;
7
- var w = /* @__PURE__ */ ((m) => (m.PancakeV2 = "PancakeV2", m.PancakeV3 = "PancakeV3", m.PancakeInfinityCl = "Pancake_Infinity_Cl", m.UniswapV3 = "UniswapV3", m.UniswapV4 = "UniswapV4", m.Dodo = "Dodo", m.Thena = "Thena", m))(w || {});
8
- const ot = {
6
+ const we = 4001;
7
+ var f = /* @__PURE__ */ ((w) => (w.PancakeV2 = "PancakeV2", w.PancakeV3 = "PancakeV3", w.PancakeInfinityCl = "Pancake_Infinity_Cl", w.UniswapV3 = "UniswapV3", w.UniswapV4 = "UniswapV4", w.Dodo = "Dodo", w.Thena = "Thena", w.NomiswapStable = "Nomiswap_Stable", w.Biswap = "Biswap", w.Apeswap = "Apeswap", w.BabyDogeSwap = "BabyDogeSwap", w.BabySwap = "BabySwap", w))(f || {});
8
+ const me = {
9
9
  chainId: 56,
10
10
  rpcUrl: "https://bsc-dataseed.binance.org",
11
11
  weth: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
12
12
  // WBNB
13
13
  adapters: []
14
- }, rt = {
14
+ }, ve = {
15
15
  chainId: 97,
16
16
  rpcUrl: "https://bsc-testnet-rpc.publicnode.com",
17
17
  weth: "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd",
18
18
  // WBNB Testnet
19
19
  adapters: []
20
20
  };
21
- class N extends Error {
22
- constructor(t, e, n) {
23
- super(t), this.name = "ExecuteTimeoutError", this.stage = e, this.txHash = n;
21
+ class x extends Error {
22
+ constructor(e) {
23
+ super(e), this.name = "CustomFeeError";
24
24
  }
25
25
  }
26
- const I = {
26
+ class H extends Error {
27
+ constructor(e, t, o) {
28
+ super(e), this.name = "ExecuteTimeoutError", this.stage = t, this.txHash = o;
29
+ }
30
+ }
31
+ const k = {
27
32
  /** Default route search depth */
28
33
  depth: 3,
29
34
  /** Default trade split count */
30
35
  splitCount: 20,
31
36
  /** Default DEX providers */
32
- providers: ["PANCAKEV2", "PANCAKEV3", "PANCAKE_INFINITY_CL", "UNISWAPV3", "UNISWAPV4", "DODO", "THENA"],
37
+ providers: ["PANCAKEV2", "PANCAKEV3", "PANCAKE_INFINITY_CL", "UNISWAPV3", "UNISWAPV4", "DODO", "THENA", "NOMISWAP_STABLE", "BISWAP", "APESWAP", "BABYDOGESWAP", "BABYSWAP"],
33
38
  /** Default client version for V3 API */
34
39
  clientVersion: 1001500
35
- }, B = 1e4;
36
- class M {
37
- constructor(t = {}) {
38
- this.baseUrl = t.baseUrl || V, this.timeout = t.timeout || B;
40
+ }, z = 1e4;
41
+ function J(w) {
42
+ const e = {};
43
+ return w.forEach((t, o) => {
44
+ e[o] = t;
45
+ }), e;
46
+ }
47
+ class X {
48
+ constructor(e = {}) {
49
+ this.baseUrl = e.baseUrl || q, this.timeout = e.timeout || z, this.extraHeaders = e.headers ? { ...e.headers } : {};
39
50
  }
40
- /**
41
- * Find optimal routes via API
42
- */
43
- async findRoutes(t) {
51
+ async findRoutes(e) {
44
52
  const {
45
- from: e,
46
- target: n,
47
- amount: o,
53
+ from: t,
54
+ target: o,
55
+ amount: n,
48
56
  byAmountIn: s = !0,
49
- depth: r = I.depth,
50
- splitCount: a = I.splitCount,
51
- providers: i = I.providers
52
- } = t, c = new URLSearchParams({
53
- from: e,
54
- target: n,
55
- amount: o.toString(),
57
+ depth: r = k.depth,
58
+ splitCount: a = k.splitCount,
59
+ providers: i = k.providers,
60
+ includeResponseHeaders: c = !1
61
+ } = e, u = new URLSearchParams({
62
+ from: t,
63
+ target: o,
64
+ amount: n.toString(),
56
65
  by_amount_in: s.toString(),
57
66
  depth: r.toString(),
58
67
  split_count: a.toString(),
59
68
  providers: i.join(","),
60
- v: I.clientVersion.toString()
61
- }), u = `${this.baseUrl}/router/find_routes?${c}`, d = new AbortController(), l = setTimeout(() => d.abort(), this.timeout);
69
+ v: k.clientVersion.toString()
70
+ }), d = `${this.baseUrl}/router/find_routes?${u}`, p = new AbortController(), g = setTimeout(() => p.abort(), this.timeout);
62
71
  try {
63
- const f = await fetch(u, {
72
+ const m = await fetch(d, {
64
73
  method: "GET",
65
74
  headers: {
66
- Accept: "application/json"
75
+ Accept: "application/json",
76
+ ...this.extraHeaders
67
77
  },
68
- signal: d.signal
78
+ signal: p.signal
69
79
  });
70
- if (clearTimeout(l), !f.ok)
71
- throw new v(
72
- `API request failed: ${f.status} ${f.statusText}`,
73
- f.status
80
+ if (clearTimeout(g), !m.ok)
81
+ throw new A(
82
+ `API request failed: ${m.status} ${m.statusText}`,
83
+ m.status
74
84
  );
75
- const g = await f.json();
76
- if (g.code !== 200)
77
- throw new v(g.msg || "Route not found", g.code);
78
- if (!g.data || !g.data.paths || g.data.paths.length === 0)
79
- throw new v("No routes found", 404);
80
- return g.data;
81
- } catch (f) {
82
- throw clearTimeout(l), f instanceof v ? f : f instanceof Error ? f.name === "AbortError" ? new v("API request timeout", 408) : new v(`API request failed: ${f.message}`, 0) : new v("Unknown API error", 0);
85
+ const v = await m.json();
86
+ if (v.code !== 200)
87
+ throw new A(v.msg || "Route not found", v.code);
88
+ if (!v.data || !v.data.paths || v.data.paths.length === 0)
89
+ throw new A("No routes found", 404);
90
+ return c ? {
91
+ data: v.data,
92
+ responseHeaders: J(m.headers)
93
+ } : v.data;
94
+ } catch (m) {
95
+ throw clearTimeout(g), m instanceof A ? m : m instanceof Error ? m.name === "AbortError" ? new A("API request timeout", 408) : new A(`API request failed: ${m.message}`, 0) : new A("Unknown API error", 0);
83
96
  }
84
97
  }
85
98
  /**
86
99
  * Get service status including available providers
87
100
  */
88
101
  async getStatus() {
89
- const t = `${this.baseUrl}/router/status`, e = new AbortController(), n = setTimeout(() => e.abort(), this.timeout);
102
+ const e = `${this.baseUrl}/router/status`, t = new AbortController(), o = setTimeout(() => t.abort(), this.timeout);
90
103
  try {
91
- const o = await fetch(t, {
104
+ const n = await fetch(e, {
92
105
  method: "GET",
93
106
  headers: {
94
- Accept: "application/json"
107
+ Accept: "application/json",
108
+ ...this.extraHeaders
95
109
  },
96
- signal: e.signal
110
+ signal: t.signal
97
111
  });
98
- if (clearTimeout(n), !o.ok)
99
- throw new v(
100
- `API request failed: ${o.status} ${o.statusText}`,
101
- o.status
112
+ if (clearTimeout(o), !n.ok)
113
+ throw new A(
114
+ `API request failed: ${n.status} ${n.statusText}`,
115
+ n.status
102
116
  );
103
- const s = await o.json();
117
+ const s = await n.json();
104
118
  if (s.code !== 200)
105
- throw new v(s.msg || "Failed to get status", s.code);
119
+ throw new A(s.msg || "Failed to get status", s.code);
106
120
  return s.data;
107
- } catch (o) {
108
- throw clearTimeout(n), o instanceof v ? o : o instanceof Error ? o.name === "AbortError" ? new v("API request timeout", 408) : new v(`API request failed: ${o.message}`, 0) : new v("Unknown API error", 0);
121
+ } catch (n) {
122
+ throw clearTimeout(o), n instanceof A ? n : n instanceof Error ? n.name === "AbortError" ? new A("API request timeout", 408) : new A(`API request failed: ${n.message}`, 0) : new A("Unknown API error", 0);
109
123
  }
110
124
  }
111
125
  /**
@@ -117,8 +131,8 @@ class M {
117
131
  /**
118
132
  * Update API base URL
119
133
  */
120
- setBaseUrl(t) {
121
- this.baseUrl = t;
134
+ setBaseUrl(e) {
135
+ this.baseUrl = e;
122
136
  }
123
137
  /**
124
138
  * Get current API base URL
@@ -127,93 +141,106 @@ class M {
127
141
  return this.baseUrl;
128
142
  }
129
143
  }
130
- class v extends Error {
131
- constructor(t, e) {
132
- super(t), this.name = "ApiError", this.code = e;
144
+ class A extends Error {
145
+ constructor(e, t) {
146
+ super(e), this.name = "ApiError", this.code = t;
133
147
  }
134
148
  }
135
- async function b(m, t = D) {
136
- if (t <= 0)
137
- return m;
138
- let e;
149
+ async function U(w, e = W) {
150
+ if (e <= 0)
151
+ return w;
152
+ let t;
139
153
  try {
140
154
  return await Promise.race([
141
- m,
142
- new Promise((n, o) => {
143
- e = setTimeout(() => {
144
- o(
145
- new N(
146
- `Wallet did not settle sendTransaction within ${t}ms.`,
155
+ w,
156
+ new Promise((o, n) => {
157
+ t = setTimeout(() => {
158
+ n(
159
+ new H(
160
+ `Wallet did not settle sendTransaction within ${e}ms.`,
147
161
  "wallet_send"
148
162
  )
149
163
  );
150
- }, t);
164
+ }, e);
151
165
  })
152
166
  ]);
153
167
  } finally {
154
- e && clearTimeout(e);
168
+ t && clearTimeout(t);
155
169
  }
156
170
  }
157
- const K = [
158
- "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) params) external returns (uint256 amountOut)",
159
- "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) params) external payable returns (uint256 amountOut)",
171
+ const B = [
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
+ "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)",
160
174
  "function isAdapterRegistered(address adapter) external view returns (bool)",
161
- "function WETH() external view returns (address)"
162
- ], C = [
175
+ "function getAdapterProtocolId(address adapter) external view returns (bytes32)",
176
+ "function WETH() external view returns (address)",
177
+ "function owner() external view returns (address)",
178
+ "function pendingOwner() external view returns (address)",
179
+ "function paused() external view returns (bool)",
180
+ "function maxCustomFeeBps() external view returns (uint16)",
181
+ "function maxProtocolCutBps() external view returns (uint16)",
182
+ "function protocolFeeReceiver() external view returns (address)",
183
+ "function protocolCutBps() external view returns (uint16)"
184
+ ], y = [
163
185
  "function approve(address spender, uint256 amount) external returns (bool)",
164
186
  "function allowance(address owner, address spender) external view returns (uint256)",
165
187
  "function balanceOf(address account) external view returns (uint256)",
166
188
  "function decimals() external view returns (uint8)",
167
189
  "function symbol() external view returns (string)"
168
- ], W = "0xa0FfB9c1CE1Fe56963B0321B32E7A0302114058b", R = {
169
- PANCAKEV3: w.PancakeV3,
170
- PANCAKEV2: w.PancakeV2,
171
- PANCAKE_INFINITY_CL: w.PancakeInfinityCl,
172
- UNISWAPV3: w.UniswapV3,
173
- UNISWAPV4: w.UniswapV4,
174
- DODO: w.Dodo,
175
- THENA: w.Thena
190
+ ], ee = "0xa0FfB9c1CE1Fe56963B0321B32E7A0302114058b", V = {
191
+ PANCAKEV3: f.PancakeV3,
192
+ PANCAKEV2: f.PancakeV2,
193
+ PANCAKE_INFINITY_CL: f.PancakeInfinityCl,
194
+ UNISWAPV3: f.UniswapV3,
195
+ UNISWAPV4: f.UniswapV4,
196
+ DODO: f.Dodo,
197
+ THENA: f.Thena,
198
+ NOMISWAP_STABLE: f.NomiswapStable,
199
+ BISWAP: f.Biswap,
200
+ APESWAP: f.Apeswap,
201
+ BABYDOGESWAP: f.BabyDogeSwap,
202
+ BABYSWAP: f.BabySwap
176
203
  };
177
- class st {
178
- constructor(t, e, n) {
179
- this.config = t, this.provider = e || new h.JsonRpcProvider(t.rpcUrl), this.routerContract = new h.Contract(
180
- t.routerAddress || h.ZeroAddress,
181
- K,
204
+ class K {
205
+ constructor(e, t, o) {
206
+ this.config = e, this.provider = t || new l.JsonRpcProvider(e.rpcUrl), this.routerContract = new l.Contract(
207
+ e.routerAddress || l.ZeroAddress,
208
+ B,
182
209
  this.provider
183
- ), this.apiClient = new M(n?.api);
210
+ ), this.apiClient = new X(o?.api);
184
211
  }
185
212
  /**
186
213
  * Get the effective router address for a quote.
187
214
  */
188
- getRouterAddress(t) {
189
- const e = t.routerAddress || this.config.routerAddress;
190
- if (!e || e === h.ZeroAddress)
215
+ getRouterAddress(e) {
216
+ const t = e.routerAddress || this.config.routerAddress;
217
+ if (!t || t === l.ZeroAddress)
191
218
  throw new Error("No router address available. Provide routerAddress in config or use API-based getQuote.");
192
- return e;
219
+ return t;
193
220
  }
194
221
  /**
195
222
  * Apply slippage to swap params, returning a new SwapParams with adjusted amountOutMin
196
223
  */
197
- applySlippage(t, e) {
198
- if (e < 0 || e > 1e4)
224
+ applySlippage(e, t) {
225
+ if (t < 0 || t > 1e4)
199
226
  throw new Error("slippageBps must be between 0 and 10000");
200
- const n = t.amountOutMin * (O - BigInt(e)) / O;
201
- return { ...t, amountOutMin: n };
227
+ const o = e.amountOutMin * (b - BigInt(t)) / b;
228
+ return { ...e, amountOutMin: o };
202
229
  }
203
230
  /**
204
231
  * Build transaction requests for an approval (if needed) and the swap itself.
205
232
  */
206
- async swap(t, e, n) {
207
- const o = this.getRouterAddress(t), { tx: s, method: r } = this.buildSwapTransactionRequest(t, n);
233
+ async swap(e, t, o) {
234
+ const n = this.getRouterAddress(e), { tx: s, method: r } = this.buildSwapTransactionRequest(e, o);
208
235
  let a;
209
- return t.srcNative || (a = await this.buildApprovalRequest(
210
- t.srcToken,
211
- e,
212
- t.amountIn,
213
- o,
214
- n
236
+ return e.srcNative || (a = await this.buildApprovalRequest(
237
+ e.srcToken,
238
+ t,
239
+ e.amountIn,
240
+ n,
241
+ o
215
242
  )), {
216
- routerAddress: o,
243
+ routerAddress: n,
217
244
  method: r,
218
245
  tx: s,
219
246
  approval: a
@@ -224,14 +251,14 @@ class st {
224
251
  *
225
252
  * @deprecated Prefer swap(), then send the returned tx request with your wallet/client.
226
253
  */
227
- async execute(t, e, n) {
228
- const o = await e.getAddress(), s = await this.swap(t, o, n);
254
+ async execute(e, t, o) {
255
+ const n = await t.getAddress(), s = await this.swap(e, n, o);
229
256
  try {
230
257
  return s.approval && await (await this.sendTransactionWithTimeout(
231
- e,
258
+ t,
232
259
  s.approval.tx,
233
- n
234
- )).wait(), await this.sendTransactionWithTimeout(e, s.tx, n);
260
+ o
261
+ )).wait(), await this.sendTransactionWithTimeout(t, s.tx, o);
235
262
  } catch (r) {
236
263
  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");
237
264
  if (i && (c || /reason=null|data=null/.test(a))) {
@@ -244,30 +271,32 @@ class st {
244
271
  /**
245
272
  * Encode parameters to contract format
246
273
  */
247
- encodeParams(t) {
274
+ encodeParams(e) {
248
275
  return {
249
- srcToken: t.srcToken,
250
- dstToken: t.dstToken,
251
- amountIn: t.amountIn,
252
- amountOutMin: t.amountOutMin,
253
- steps: t.steps.map((e) => ({
254
- adapter: e.adapter,
255
- pool: e.pool,
256
- tokenIn: e.tokenIn,
257
- tokenOut: e.tokenOut,
258
- amountIn: e.amountIn,
259
- extraData: e.extraData
276
+ srcToken: e.srcToken,
277
+ dstToken: e.dstToken,
278
+ amountIn: e.amountIn,
279
+ amountOutMin: e.amountOutMin,
280
+ steps: e.steps.map((t) => ({
281
+ adapter: t.adapter,
282
+ pool: t.pool,
283
+ tokenIn: t.tokenIn,
284
+ tokenOut: t.tokenOut,
285
+ amountIn: t.amountIn,
286
+ extraData: t.extraData
260
287
  })),
261
- intermediateTokens: t.intermediateTokens,
262
- deadline: t.deadline,
263
- quoteId: t.quoteId,
264
- expectAmountOut: t.expectAmountOut
288
+ intermediateTokens: e.intermediateTokens,
289
+ deadline: e.deadline,
290
+ quoteId: e.quoteId,
291
+ expectAmountOut: e.expectAmountOut,
292
+ feeReceiver: e.feeReceiver,
293
+ feeBps: e.feeBps
265
294
  };
266
295
  }
267
- getProtocolForProvider(t) {
268
- if (t in R)
269
- return R[t];
270
- throw new Error(`Unsupported provider: ${t}`);
296
+ getProtocolForProvider(e) {
297
+ if (e in V)
298
+ return V[e];
299
+ throw new Error(`Unsupported provider: ${e}`);
271
300
  }
272
301
  /**
273
302
  * Encode swap calldata for the Peach Aggregator contract
@@ -277,172 +306,322 @@ class st {
277
306
  * @param slippageBps - Slippage tolerance in basis points (e.g. 50 = 0.5%). Required.
278
307
  * @returns Encoded calldata and transaction info (to address, value)
279
308
  */
280
- encodeSwapCalldata(t, e) {
281
- const n = t.routerAddress ?? this.config.routerAddress ?? this.routerContract.target, o = this.applySlippage(t.params, e), s = t.srcNative === !0 || t.dstNative === !0, r = this.encodeParams(o);
309
+ encodeSwapCalldata(e, t) {
310
+ const o = e.routerAddress ?? this.config.routerAddress ?? this.routerContract.target, n = this.applySlippage(e.params, t), s = e.srcNative === !0 || e.dstNative === !0, r = this.encodeParams(n);
282
311
  if (s) {
283
312
  const a = this.routerContract.interface.encodeFunctionData("swapETH", [r]);
284
313
  return {
285
- to: n,
314
+ to: o,
286
315
  data: a,
287
- value: t.srcNative ? t.amountIn : 0n,
316
+ value: e.srcNative ? e.amountIn : 0n,
288
317
  method: "swapETH"
289
318
  };
290
319
  } else {
291
320
  const a = this.routerContract.interface.encodeFunctionData("swap", [r]);
292
321
  return {
293
- to: n,
322
+ to: o,
294
323
  data: a,
295
324
  value: 0n,
296
325
  method: "swap"
297
326
  };
298
327
  }
299
328
  }
300
- buildSwapTransactionRequest(t, e) {
301
- const { to: n, data: o, value: s, method: r } = this.encodeSwapCalldata(t, e.slippageBps);
329
+ buildSwapTransactionRequest(e, t) {
330
+ const { to: o, data: n, value: s, method: r } = this.encodeSwapCalldata(e, t.slippageBps);
302
331
  return {
303
332
  method: r,
304
- tx: this.applyTxOverrides({ to: n, data: o, value: s }, e, !0)
333
+ tx: this.applyTxOverrides({ to: o, data: n, value: s }, t, !0)
305
334
  };
306
335
  }
307
- async buildApprovalRequest(t, e, n, o, s) {
308
- const r = await this.getAllowance(t, e, o);
309
- if (!(r >= n))
336
+ async buildApprovalRequest(e, t, o, n, s) {
337
+ const r = await this.getAllowance(e, t, n);
338
+ if (!(r >= o))
310
339
  return {
311
- token: t,
312
- owner: e,
313
- spender: o,
340
+ token: e,
341
+ owner: t,
342
+ spender: n,
314
343
  currentAllowance: r,
315
- requiredAmount: n,
316
- approveAmount: h.MaxUint256,
317
- tx: this.buildApprovalTransactionRequest(t, o, s)
344
+ requiredAmount: o,
345
+ approveAmount: l.MaxUint256,
346
+ tx: this.buildApprovalTransactionRequest(e, n, s)
318
347
  };
319
348
  }
320
- buildApprovalTransactionRequest(t, e, n) {
321
- const s = new h.Interface(C).encodeFunctionData("approve", [e, h.MaxUint256]);
322
- return this.applyTxOverrides({ to: t, data: s, value: 0n }, n, !1);
349
+ buildApprovalTransactionRequest(e, t, o) {
350
+ const s = new l.Interface(y).encodeFunctionData("approve", [t, l.MaxUint256]);
351
+ return this.applyTxOverrides({ to: e, data: s, value: 0n }, o, !1);
323
352
  }
324
- async getAllowance(t, e, n) {
325
- return new h.Contract(t, C, this.provider).allowance(e, n);
353
+ async getAllowance(e, t, o) {
354
+ return new l.Contract(e, y, this.provider).allowance(t, o);
326
355
  }
327
- applyTxOverrides(t, e, n) {
328
- const o = { ...t };
329
- return e.gasPrice && (o.gasPrice = e.gasPrice), n && e.gasLimit && (o.gasLimit = e.gasLimit), o;
356
+ applyTxOverrides(e, t, o) {
357
+ const n = { ...e };
358
+ return t.gasPrice && (n.gasPrice = t.gasPrice), o && t.gasLimit && (n.gasLimit = t.gasLimit), n;
330
359
  }
331
- async sendTransactionWithTimeout(t, e, n) {
332
- const o = n.timeoutMs ?? D;
333
- if (o <= 0)
334
- return t.sendTransaction(e);
335
- const s = t;
360
+ async sendTransactionWithTimeout(e, t, o) {
361
+ const n = o.timeoutMs ?? W;
362
+ if (n <= 0)
363
+ return e.sendTransaction(t);
364
+ const s = e;
336
365
  if (typeof s.sendUncheckedTransaction == "function" && s.provider) {
337
- const r = await b(
338
- s.sendUncheckedTransaction(e),
339
- o
366
+ const r = await U(
367
+ s.sendUncheckedTransaction(t),
368
+ n
340
369
  ), a = await this.waitForTransactionResponse(
341
370
  s.provider,
342
371
  r,
343
- o,
344
- n.transactionResponsePollingIntervalsMs
372
+ n,
373
+ o.transactionResponsePollingIntervalsMs
345
374
  );
346
375
  if (a.response)
347
376
  return a.response;
348
377
  const i = a.rpcErrors > 0 ? `${a.rpcErrors} transient provider error(s) and ${a.nullResponses} null response(s)` : `${a.nullResponses} null response(s)`;
349
- throw new N(
350
- `Transaction was broadcast but provider did not return TransactionResponse within ${o}ms (${i}).`,
378
+ throw new H(
379
+ `Transaction was broadcast but provider did not return TransactionResponse within ${n}ms (${i}).`,
351
380
  "provider_index",
352
381
  r
353
382
  );
354
383
  }
355
- return b(t.sendTransaction(e), o);
384
+ return U(e.sendTransaction(t), n);
356
385
  }
357
- async waitForTransactionResponse(t, e, n, o = x) {
358
- const s = Date.now() + n;
386
+ async waitForTransactionResponse(e, t, o, n = $) {
387
+ const s = Date.now() + o;
359
388
  let r = 0, a = 0, i = 0;
360
389
  for (; Date.now() < s; ) {
361
390
  try {
362
- const u = await t.getTransaction(e);
391
+ const u = await e.getTransaction(t);
363
392
  if (u)
364
393
  return { response: u, nullResponses: a, rpcErrors: i };
365
394
  a++;
366
395
  } catch {
367
396
  i++;
368
397
  }
369
- const c = this.getNextPollingDelay(o, r);
398
+ const c = this.getNextPollingDelay(n, r);
370
399
  r++, await this.delay(Math.min(c, Math.max(25, s - Date.now())));
371
400
  }
372
401
  return { response: null, nullResponses: a, rpcErrors: i };
373
402
  }
374
- async delay(t) {
375
- t <= 0 || await new Promise((e) => {
376
- setTimeout(e, t);
403
+ async delay(e) {
404
+ e <= 0 || await new Promise((t) => {
405
+ setTimeout(t, e);
377
406
  });
378
407
  }
379
- getNextPollingDelay(t, e) {
380
- return t.length === 0 ? x.at(-1) ?? 1200 : t[Math.min(e, t.length - 1)] ?? 1200;
408
+ getNextPollingDelay(e, t) {
409
+ return e.length === 0 ? $.at(-1) ?? 1200 : e[Math.min(t, e.length - 1)] ?? 1200;
381
410
  }
382
411
  /**
383
412
  * Get token metadata and, optionally, the balance for a specific owner.
384
413
  */
385
- async getTokenInfo(t, e) {
386
- const n = new h.Contract(t, C, this.provider), [o, s, r] = await Promise.all([
387
- n.symbol(),
388
- n.decimals(),
389
- e ? n.balanceOf(e) : Promise.resolve(void 0)
414
+ async getTokenInfo(e, t) {
415
+ const o = new l.Contract(e, y, this.provider), [n, s, r] = await Promise.all([
416
+ o.symbol(),
417
+ o.decimals(),
418
+ t ? o.balanceOf(t) : Promise.resolve(void 0)
390
419
  ]);
391
- return r === void 0 ? { symbol: o, decimals: s } : { symbol: o, decimals: s, balance: r };
420
+ return r === void 0 ? { symbol: n, decimals: s } : { symbol: n, decimals: s, balance: r };
392
421
  }
393
422
  /**
394
423
  * Get user token balance
395
424
  */
396
- async getBalance(t, e) {
397
- return new h.Contract(t, C, this.provider).balanceOf(e);
425
+ async getBalance(e, t) {
426
+ return new l.Contract(e, y, this.provider).balanceOf(t);
398
427
  }
399
428
  /**
400
429
  * Get quote via API
401
430
  * @throws Error if API client is not configured
431
+ * @throws CustomFeeError if `options.customFee` is malformed
402
432
  */
403
- async getQuote(t) {
404
- const { srcToken: e, dstToken: n, amountIn: o, options: s = {} } = t, {
433
+ async getQuote(e) {
434
+ const { srcToken: t, dstToken: o, amountIn: n, options: s = {} } = e, {
405
435
  byAmountIn: r = !0,
406
- depth: a = I.depth,
407
- splitCount: i = I.splitCount,
408
- providers: c = I.providers,
409
- deadlineSeconds: u = y
410
- } = s, d = _(e), l = _(n), f = d ? this.config.weth : e, g = l ? this.config.weth : n, k = await this.apiClient.findRoutes({
411
- from: f,
412
- target: g,
413
- amount: o,
436
+ depth: a = k.depth,
437
+ splitCount: i = k.splitCount,
438
+ providers: c = k.providers,
439
+ deadlineSeconds: u = T,
440
+ includeResponseHeaders: d = !1,
441
+ customFee: p
442
+ } = s;
443
+ K.validateCustomFee(p);
444
+ const g = _(t), m = _(o), v = g ? this.config.weth : t, C = m ? this.config.weth : o;
445
+ if (d) {
446
+ const { data: P, responseHeaders: S } = await this.apiClient.findRoutes({
447
+ from: v,
448
+ target: C,
449
+ amount: n,
450
+ byAmountIn: r,
451
+ depth: a,
452
+ splitCount: i,
453
+ providers: c,
454
+ includeResponseHeaders: !0
455
+ });
456
+ return this.buildQuoteFromApi(
457
+ P,
458
+ v,
459
+ C,
460
+ u,
461
+ c,
462
+ g,
463
+ m,
464
+ S,
465
+ p
466
+ );
467
+ }
468
+ const E = await this.apiClient.findRoutes({
469
+ from: v,
470
+ target: C,
471
+ amount: n,
414
472
  byAmountIn: r,
415
473
  depth: a,
416
474
  splitCount: i,
417
475
  providers: c
418
476
  });
419
- return this.buildQuoteFromApi(k, f, g, u, c, d, l);
477
+ return this.buildQuoteFromApi(
478
+ E,
479
+ v,
480
+ C,
481
+ u,
482
+ c,
483
+ g,
484
+ m,
485
+ void 0,
486
+ p
487
+ );
488
+ }
489
+ /**
490
+ * Validate custom-fee configuration. Pure / static so callers (tests, custom flows)
491
+ * can reuse it. Throws CustomFeeError on any violation; returns silently for valid input.
492
+ */
493
+ static validateCustomFee(e) {
494
+ if (!e) return;
495
+ const { feeAccount: t, feeBps: o } = e;
496
+ if (!Number.isInteger(o) || o < 1 || o > L)
497
+ throw new x(
498
+ `customFee.feeBps must be an integer in [1, ${L}] (5%), got ${o}`
499
+ );
500
+ if (!t || !l.isAddress(t))
501
+ throw new x(
502
+ `customFee.feeAccount must be a valid address, got ${t}`
503
+ );
504
+ if (t === l.ZeroAddress)
505
+ throw new x("customFee.feeAccount must not be the zero address");
506
+ }
507
+ /**
508
+ * Resolve the router address for read methods: argument → quote.routerAddress →
509
+ * config.routerAddress. Throws when none is available so callers never silently
510
+ * read from the zero address.
511
+ */
512
+ resolveRouterAddress(e) {
513
+ const t = e ?? this.config.routerAddress;
514
+ if (!t || t === l.ZeroAddress)
515
+ throw new Error(
516
+ "No router address available. Pass one explicitly or set config.routerAddress."
517
+ );
518
+ return t;
519
+ }
520
+ /**
521
+ * Read the protocol-cut configuration from a deployed PeachRouter. Useful for
522
+ * displaying "X bps integrator / Y bps protocol" before the user signs.
523
+ *
524
+ * Values are mutable on-chain — the router owner (Safe) can change them at any
525
+ * time. Re-read before each swap if your UI needs exact numbers on the signing
526
+ * screen.
527
+ *
528
+ * @param routerAddress Optional router address. Defaults to `config.routerAddress`.
529
+ * Pass an explicit address when reading from a different deployment.
530
+ */
531
+ async getProtocolFeeConfig(e) {
532
+ const t = this.resolveRouterAddress(e), o = new l.Contract(t, B, this.provider), [n, s] = await Promise.all([
533
+ o.protocolFeeReceiver(),
534
+ o.protocolCutBps()
535
+ ]);
536
+ return {
537
+ protocolFeeReceiver: n,
538
+ protocolCutBps: Number(s)
539
+ };
540
+ }
541
+ /**
542
+ * @deprecated Use {@link getProtocolFeeConfig}. Kept as an alias for the pre-v2 name.
543
+ * The returned object now uses the `ProtocolFeeConfig` field names
544
+ * (`protocolFeeReceiver` / `protocolCutBps`).
545
+ */
546
+ async getPlatformConfig(e) {
547
+ return this.getProtocolFeeConfig(e);
548
+ }
549
+ /**
550
+ * Read the full PeachRouter configuration in a single batched call: identity
551
+ * (WETH / owner / pendingOwner), emergency state (`paused`), fee caps
552
+ * (`maxCustomFeeBps`, `maxProtocolCutBps`), and protocol-cut split
553
+ * (`protocolFeeReceiver`, `protocolCutBps`).
554
+ *
555
+ * Intended for:
556
+ * - Verifying a deployment before the UI surfaces swap flows.
557
+ * - Pre-swap checks: reject quotes when `paused == true` or when the requested
558
+ * `customFee.feeBps` exceeds the live `maxCustomFeeBps`.
559
+ * - Showing the integrator / protocol fee split on the signing screen.
560
+ *
561
+ * All fields reflect on-chain state AT READ TIME — the owner (Safe) can mutate
562
+ * caps, the pause flag, and protocol-fee configuration at any time.
563
+ *
564
+ * @param routerAddress Optional router address. Defaults to `config.routerAddress`.
565
+ */
566
+ async getRouterConfig(e) {
567
+ const t = this.resolveRouterAddress(e), o = new l.Contract(t, B, this.provider), [
568
+ n,
569
+ s,
570
+ r,
571
+ a,
572
+ i,
573
+ c,
574
+ u,
575
+ d
576
+ ] = await Promise.all([
577
+ o.WETH(),
578
+ o.owner(),
579
+ o.pendingOwner(),
580
+ o.paused(),
581
+ o.maxCustomFeeBps(),
582
+ o.maxProtocolCutBps(),
583
+ o.protocolFeeReceiver(),
584
+ o.protocolCutBps()
585
+ ]);
586
+ return {
587
+ address: t,
588
+ weth: n,
589
+ owner: s,
590
+ pendingOwner: r,
591
+ paused: !!a,
592
+ maxCustomFeeBps: Number(i),
593
+ maxProtocolCutBps: Number(c),
594
+ protocolFee: {
595
+ protocolFeeReceiver: u,
596
+ protocolCutBps: Number(d)
597
+ }
598
+ };
420
599
  }
421
600
  /**
422
601
  * Filter paths by allowed providers, removing paths with disallowed providers
423
602
  * and cascade-removing orphaned paths that depend on removed paths.
424
603
  */
425
- filterPathsByProviders(t, e, n, o) {
426
- const s = new Set(e.map((l) => l.toUpperCase()));
427
- let r = t.filter((l) => s.has(l.provider.toUpperCase()));
428
- if (r.length === t.length)
604
+ filterPathsByProviders(e, t, o, n) {
605
+ const s = new Set(t.map((p) => p.toUpperCase()));
606
+ let r = e.filter((p) => s.has(p.provider.toUpperCase()));
607
+ if (r.length === e.length)
429
608
  return r;
430
- const a = n.toLowerCase(), i = o.toLowerCase(), c = /* @__PURE__ */ new Set();
609
+ const a = o.toLowerCase(), i = n.toLowerCase(), c = /* @__PURE__ */ new Set();
431
610
  c.add(a);
432
611
  let u = !0;
433
612
  for (; u; ) {
434
613
  u = !1;
435
- for (const l of r)
436
- c.has(l.token_in.toLowerCase()) && !c.has(l.token_out.toLowerCase()) && (c.add(l.token_out.toLowerCase()), u = !0);
614
+ for (const p of r)
615
+ c.has(p.token_in.toLowerCase()) && !c.has(p.token_out.toLowerCase()) && (c.add(p.token_out.toLowerCase()), u = !0);
437
616
  }
438
617
  const d = /* @__PURE__ */ new Set();
439
618
  for (d.add(i), u = !0; u; ) {
440
619
  u = !1;
441
- for (const l of r)
442
- d.has(l.token_out.toLowerCase()) && !d.has(l.token_in.toLowerCase()) && (d.add(l.token_in.toLowerCase()), u = !0);
620
+ for (const p of r)
621
+ d.has(p.token_out.toLowerCase()) && !d.has(p.token_in.toLowerCase()) && (d.add(p.token_in.toLowerCase()), u = !0);
443
622
  }
444
623
  return r.length, r = r.filter(
445
- (l) => c.has(l.token_in.toLowerCase()) && d.has(l.token_out.toLowerCase())
624
+ (p) => c.has(p.token_in.toLowerCase()) && d.has(p.token_out.toLowerCase())
446
625
  ), r;
447
626
  }
448
627
  /**
@@ -454,12 +633,12 @@ class st {
454
633
  * @param dstToken - Destination token address (last path token_out)
455
634
  * @param deadlineSeconds - Optional deadline in seconds from now (default: 20 min)
456
635
  */
457
- buildQuoteFromRouteData(t, e, n, o, s) {
636
+ buildQuoteFromRouteData(e, t, o, n, s) {
458
637
  const r = this.buildQuoteFromRouteDataInternal(
459
- t,
460
638
  e,
461
- n,
462
- o ?? y,
639
+ t,
640
+ o,
641
+ n ?? T,
463
642
  void 0
464
643
  );
465
644
  return s?.srcNative && (r.srcNative = !0), s?.dstNative && (r.dstNative = !0), r;
@@ -467,98 +646,108 @@ class st {
467
646
  /**
468
647
  * Build Quote from API response
469
648
  */
470
- buildQuoteFromApi(t, e, n, o, s, r, a) {
471
- const i = this.buildQuoteFromRouteDataInternal(
472
- t,
649
+ buildQuoteFromApi(e, t, o, n, s, r, a, i, c) {
650
+ const u = this.buildQuoteFromRouteDataInternal(
473
651
  e,
474
- n,
652
+ t,
475
653
  o,
476
- s
654
+ n,
655
+ s,
656
+ c
477
657
  );
478
- return r && (i.srcNative = !0), a && (i.dstNative = !0), i;
479
- }
480
- buildQuoteFromRouteDataInternal(t, e, n, o, s) {
481
- const r = e.toLowerCase();
482
- t.paths.length;
483
- let a = t.paths.filter((p) => !(!(p.token_in.toLowerCase() === r) && BigInt(p.amount_in) === 0n && BigInt(p.amount_out) === 0n));
484
- if (a.length === 0)
485
- throw new v("All route paths have zero amounts", 4001);
486
- if (s && s.length > 0 && (a = this.filterPathsByProviders(a, s, e, n), a.length === 0))
487
- throw new v("No valid route paths remaining after provider filtering", 4001);
488
- const i = n.toLowerCase();
489
- let c = 0n, u = 0n;
490
- for (const p of a)
491
- p.token_in.toLowerCase() === r && (c += BigInt(p.amount_in)), p.token_out.toLowerCase() === i && (u += BigInt(p.amount_out));
492
- const d = BigInt(
493
- Math.floor(Date.now() / 1e3) + o
494
- ), l = /* @__PURE__ */ new Map();
495
- for (const p of a) {
496
- const A = p.token_in.toLowerCase();
497
- l.set(A, (l.get(A) ?? 0) + 1);
658
+ return r && (u.srcNative = !0), a && (u.dstNative = !0), i && (u.responseHeaders = i), u;
659
+ }
660
+ buildQuoteFromRouteDataInternal(e, t, o, n, s, r) {
661
+ const a = t.toLowerCase();
662
+ e.paths.length;
663
+ let i = e.paths.filter((h) => !(!(h.token_in.toLowerCase() === a) && BigInt(h.amount_in) === 0n && BigInt(h.amount_out) === 0n));
664
+ if (i.length === 0)
665
+ throw new A("All route paths have zero amounts", 4001);
666
+ if (s && s.length > 0 && (i = this.filterPathsByProviders(i, s, t, o), i.length === 0))
667
+ throw new A("No valid route paths remaining after provider filtering", 4001);
668
+ const c = o.toLowerCase();
669
+ let u = 0n, d = 0n;
670
+ for (const h of i)
671
+ h.token_in.toLowerCase() === a && (u += BigInt(h.amount_in)), h.token_out.toLowerCase() === c && (d += BigInt(h.amount_out));
672
+ const p = BigInt(
673
+ Math.floor(Date.now() / 1e3) + n
674
+ ), g = /* @__PURE__ */ new Map();
675
+ for (const h of i) {
676
+ const I = h.token_in.toLowerCase();
677
+ g.set(I, (g.get(I) ?? 0) + 1);
498
678
  }
499
- const f = /* @__PURE__ */ new Map(), g = a.map((p) => {
500
- const A = p.token_in.toLowerCase(), T = (f.get(A) ?? 0) + 1;
501
- f.set(A, T);
502
- const S = l.get(A), L = S > 1 && T < S, U = A === r;
679
+ const m = /* @__PURE__ */ new Map(), v = i.map((h) => {
680
+ const I = h.token_in.toLowerCase(), N = (m.get(I) ?? 0) + 1;
681
+ m.set(I, N);
682
+ const D = g.get(I), Z = D > 1 && N < D, j = I === a;
503
683
  return {
504
- adapter: p.adapter,
505
- pool: p.provider.toUpperCase() === "PANCAKE_INFINITY_CL" ? W : p.provider.toUpperCase() === "UNISWAPV4" ? h.ZeroAddress : p.pool,
506
- tokenIn: p.token_in,
507
- tokenOut: p.token_out,
508
- amountIn: U || L ? BigInt(p.amount_in) : 0n,
509
- extraData: p.extra_data || "0x"
684
+ adapter: h.adapter,
685
+ pool: h.provider.toUpperCase() === "PANCAKE_INFINITY_CL" ? ee : h.provider.toUpperCase() === "UNISWAPV4" ? l.ZeroAddress : h.pool,
686
+ tokenIn: h.token_in,
687
+ tokenOut: h.token_out,
688
+ amountIn: j || Z ? BigInt(h.amount_in) : 0n,
689
+ extraData: h.extra_data || "0x"
510
690
  };
511
- }), k = /* @__PURE__ */ new Set();
512
- for (const p of a)
513
- p.token_out.toLowerCase() !== i && k.add(p.token_out);
514
- const E = Array.from(k), P = {
515
- srcToken: e,
516
- dstToken: n,
517
- amountIn: c,
518
- amountOutMin: u,
519
- steps: g,
691
+ }), C = /* @__PURE__ */ new Set();
692
+ for (const h of i)
693
+ h.token_out.toLowerCase() !== c && C.add(h.token_out);
694
+ const E = Array.from(C), P = r?.feeBps ?? 0, S = r?.feeAccount ?? l.ZeroAddress, R = d, F = P > 0 ? R * BigInt(P) / b : 0n, O = R - F, G = {
695
+ srcToken: t,
696
+ dstToken: o,
697
+ amountIn: u,
698
+ amountOutMin: O,
699
+ steps: v,
520
700
  intermediateTokens: E,
521
- deadline: d,
522
- quoteId: t.request_id ? h.id(t.request_id).slice(0, 66) : h.ZeroHash,
523
- expectAmountOut: u
524
- }, F = {
701
+ deadline: p,
702
+ quoteId: e.request_id ? l.id(e.request_id).slice(0, 66) : l.ZeroHash,
703
+ expectAmountOut: O,
704
+ feeReceiver: S,
705
+ feeBps: P
706
+ }, Y = {
525
707
  routes: [
526
708
  {
527
- steps: a.map((p) => ({
709
+ steps: i.map((h) => ({
528
710
  pool: {
529
- address: p.pool,
530
- token0: p.token_in,
531
- token1: p.token_out,
532
- protocol: this.getProtocolForProvider(p.provider),
533
- fee: p.fee_rate ? Math.round(parseFloat(p.fee_rate) * 1e6) : void 0
711
+ address: h.pool,
712
+ token0: h.token_in,
713
+ token1: h.token_out,
714
+ protocol: this.getProtocolForProvider(h.provider),
715
+ fee: h.fee_rate ? Math.round(parseFloat(h.fee_rate) * 1e6) : void 0
534
716
  },
535
- tokenIn: p.token_in,
536
- tokenOut: p.token_out,
537
- amountIn: BigInt(p.amount_in),
538
- amountOut: BigInt(p.amount_out)
717
+ tokenIn: h.token_in,
718
+ tokenOut: h.token_out,
719
+ amountIn: BigInt(h.amount_in),
720
+ amountOut: BigInt(h.amount_out)
539
721
  })),
540
- amountIn: c,
541
- amountOut: u,
542
- gasEstimate: BigInt(t.gas)
722
+ amountIn: u,
723
+ amountOut: d,
724
+ gasEstimate: BigInt(e.gas)
543
725
  }
544
726
  ],
545
727
  percentages: [1e4],
546
- totalAmountIn: c,
547
- totalAmountOut: u,
548
- totalGasEstimate: BigInt(t.gas)
728
+ totalAmountIn: u,
729
+ totalAmountOut: d,
730
+ totalGasEstimate: BigInt(e.gas)
549
731
  };
550
- if (!t.contracts?.router)
551
- throw new v("API response missing contracts.router address", 4002);
732
+ if (!e.contracts?.router)
733
+ throw new A("API response missing contracts.router address", 4002);
552
734
  return {
553
- srcToken: e,
554
- dstToken: n,
555
- amountIn: c,
556
- amountOut: u,
557
- priceImpact: parseFloat(t.deviation_ratio || "0"),
558
- route: F,
559
- params: P,
560
- gasEstimate: BigInt(t.gas),
561
- routerAddress: t.contracts?.router
735
+ srcToken: t,
736
+ dstToken: o,
737
+ amountIn: u,
738
+ // Quote.amountOut reflects the user-perceived output (post custom fee).
739
+ // Wallets / UIs should display this number; the gross figure is at route.totalAmountOut.
740
+ amountOut: O,
741
+ priceImpact: parseFloat(e.deviation_ratio || "0"),
742
+ route: Y,
743
+ params: G,
744
+ gasEstimate: BigInt(e.gas),
745
+ routerAddress: e.contracts?.router,
746
+ customFee: P > 0 ? {
747
+ feeAccount: S,
748
+ feeBps: P,
749
+ feeAmount: F
750
+ } : void 0
562
751
  };
563
752
  }
564
753
  /**
@@ -578,15 +767,15 @@ class st {
578
767
  * @param stateOverrides - Optional state overrides for ERC20 balance/allowance
579
768
  * @returns Simulated amountOut and method used
580
769
  */
581
- async simulate(t, e, n, o) {
582
- const s = n || h.ZeroAddress, { to: r, data: a, value: i, method: c } = this.encodeSwapCalldata(t, e);
583
- if (console.log("[PeachClient] simulate using router:", r), o) {
584
- const u = this.getJsonRpcProviderForStateOverrides(), d = i > 0n ? "0x" + i.toString(16) : void 0, l = await u.send("eth_call", [
770
+ async simulate(e, t, o, n) {
771
+ const s = o || l.ZeroAddress, { to: r, data: a, value: i, method: c } = this.encodeSwapCalldata(e, t);
772
+ if (n) {
773
+ const u = this.getJsonRpcProviderForStateOverrides(), d = i > 0n ? "0x" + i.toString(16) : void 0, p = await u.send("eth_call", [
585
774
  { from: s, to: r, data: a, value: d },
586
775
  "latest",
587
- o
588
- ]), [f] = this.routerContract.interface.decodeFunctionResult(c, l);
589
- return { amountOut: f, method: c };
776
+ n
777
+ ]), [g] = this.routerContract.interface.decodeFunctionResult(c, p);
778
+ return { amountOut: g, method: c };
590
779
  } else {
591
780
  const u = await this.provider.call({
592
781
  from: s,
@@ -607,8 +796,8 @@ class st {
607
796
  /**
608
797
  * Format simulate error with human-readable details
609
798
  */
610
- formatSimulateError(t, e, n, o) {
611
- const s = t instanceof Error ? t : new Error(String(t)), r = t;
799
+ formatSimulateError(e, t, o, n) {
800
+ const s = e instanceof Error ? e : new Error(String(e)), r = e;
612
801
  let a = "unknown";
613
802
  if (r.reason && typeof r.reason == "string")
614
803
  a = r.reason;
@@ -616,17 +805,17 @@ class st {
616
805
  const d = r.revert;
617
806
  d.args && Array.isArray(d.args) && (a = d.args.join(", "));
618
807
  } else s.message && (a = s.message);
619
- const i = e.params.steps.map(
620
- (d, l) => ` Step ${l}: ${d.tokenIn.slice(0, 10)}→${d.tokenOut.slice(0, 10)} via adapter ${d.adapter.slice(0, 10)} pool ${d.pool.slice(0, 10)}`
808
+ const i = t.params.steps.map(
809
+ (d, p) => ` Step ${p}: ${d.tokenIn.slice(0, 10)}→${d.tokenOut.slice(0, 10)} via adapter ${d.adapter.slice(0, 10)} pool ${d.pool.slice(0, 10)}`
621
810
  ).join(`
622
811
  `), c = [
623
- `Simulate ${n} failed: ${a}`,
624
- ` Route: ${e.srcToken} → ${e.dstToken}`,
625
- ` AmountIn: ${e.amountIn}`,
626
- ` AmountOutMin: ${e.params.amountOutMin}`,
627
- ` Router: ${e.routerAddress}`,
628
- ` Caller: ${o}`,
629
- ` Steps (${e.params.steps.length}):`,
812
+ `Simulate ${o} failed: ${a}`,
813
+ ` Route: ${t.srcToken} → ${t.dstToken}`,
814
+ ` AmountIn: ${t.amountIn}`,
815
+ ` AmountOutMin: ${t.params.amountOutMin}`,
816
+ ` Router: ${t.routerAddress}`,
817
+ ` Caller: ${n}`,
818
+ ` Steps (${t.params.steps.length}):`,
630
819
  i
631
820
  ].join(`
632
821
  `), u = new Error(c);
@@ -644,22 +833,22 @@ class st {
644
833
  * @param fullRouteError - The error from simulating the full route. Required so we match by revert reason (e.g. "MUL_ERROR"); only the step that produces the same reason is returned.
645
834
  * @returns The step index and step details whose revert matches fullRouteError, or null if none match or full route succeeds
646
835
  */
647
- async findFailingStep(t, e, n, o, s) {
648
- const r = t.params.steps;
836
+ async findFailingStep(e, t, o, n, s) {
837
+ const r = e.params.steps;
649
838
  if (!r.length) return null;
650
839
  const a = s != null ? this.normalizeRevertReason(s) : void 0;
651
840
  for (let i = 1; i <= r.length; i++) {
652
- const c = this.quoteWithFirstNSteps(t, i);
841
+ const c = this.quoteWithFirstNSteps(e, i);
653
842
  try {
654
- await this.simulate(c, e, n, o);
843
+ await this.simulate(c, t, o, n);
655
844
  } catch (u) {
656
- const d = this.normalizeRevertReason(u), l = u?.message ?? u?.reason ?? u?.shortMessage;
845
+ const d = this.normalizeRevertReason(u), p = u?.message ?? u?.reason ?? u?.shortMessage;
657
846
  if (a != null ? d === a : !0)
658
847
  return {
659
848
  stepIndex: i - 1,
660
849
  step: r[i - 1],
661
850
  error: u,
662
- revertMessage: typeof l == "string" ? l : void 0,
851
+ revertMessage: typeof p == "string" ? p : void 0,
663
852
  fullRouteRevertMessage: a ?? void 0
664
853
  };
665
854
  }
@@ -667,31 +856,31 @@ class st {
667
856
  return null;
668
857
  }
669
858
  /** Extract a comparable revert reason (e.g. "MUL_ERROR") from an error for findFailingStep matching. */
670
- normalizeRevertReason(t) {
671
- if (t == null) return;
672
- const e = t;
673
- if (typeof e.reason == "string" && e.reason.length > 0) return e.reason;
674
- const n = e.shortMessage ?? e.message;
675
- if (typeof n != "string") return;
676
- const o = n.match(/reason="([^"]+)"/);
677
- if (o) return o[1];
678
- const s = n.match(/reverted:\s*"([^"]+)"/);
859
+ normalizeRevertReason(e) {
860
+ if (e == null) return;
861
+ const t = e;
862
+ if (typeof t.reason == "string" && t.reason.length > 0) return t.reason;
863
+ const o = t.shortMessage ?? t.message;
864
+ if (typeof o != "string") return;
865
+ const n = o.match(/reason="([^"]+)"/);
866
+ if (n) return n[1];
867
+ const s = o.match(/reverted:\s*"([^"]+)"/);
679
868
  if (s) return s[1];
680
- const r = n.match(/execution reverted:\s*"([^"]+)"/);
869
+ const r = o.match(/execution reverted:\s*"([^"]+)"/);
681
870
  if (r) return r[1];
682
871
  }
683
872
  /** Build a quote that only includes the first stepCount steps (for findFailingStep). */
684
- quoteWithFirstNSteps(t, e) {
685
- const n = t.params.steps.slice(0, e), o = t.dstToken.toLowerCase(), s = /* @__PURE__ */ new Set(), r = [];
686
- for (const a of n) {
873
+ quoteWithFirstNSteps(e, t) {
874
+ const o = e.params.steps.slice(0, t), n = e.dstToken.toLowerCase(), s = /* @__PURE__ */ new Set(), r = [];
875
+ for (const a of o) {
687
876
  const i = a.tokenOut.toLowerCase();
688
- i !== o && !s.has(i) && (s.add(i), r.push(a.tokenOut));
877
+ i !== n && !s.has(i) && (s.add(i), r.push(a.tokenOut));
689
878
  }
690
879
  return {
691
- ...t,
880
+ ...e,
692
881
  params: {
693
- ...t.params,
694
- steps: n,
882
+ ...e.params,
883
+ steps: o,
695
884
  intermediateTokens: r
696
885
  }
697
886
  };
@@ -713,62 +902,68 @@ class st {
713
902
  * @param balance - Balance to inject (default: 1M tokens with 18 decimals)
714
903
  * @param spenderAddress - Spender to approve (default: routerAddress). Pass quote.routerAddress when simulating API quotes.
715
904
  */
716
- buildStateOverrides(t, e, n, o, s, r) {
717
- if (r?.isNative || _(t))
905
+ buildStateOverrides(e, t, o, n, s, r) {
906
+ if (r?.isNative || _(e))
718
907
  return {};
719
- if (!n || n === h.ZeroAddress)
908
+ if (!o || o === l.ZeroAddress)
720
909
  throw new Error("buildStateOverrides requires a non-zero routerAddress.");
721
- const a = h.AbiCoder.defaultAbiCoder(), i = o || h.parseUnits("1000000", 18), c = s ?? n, u = h.zeroPadValue(h.toBeHex(i), 32), d = h.zeroPadValue(h.toBeHex(h.MaxUint256), 32), l = {}, f = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 50, 51, 52, 100, 101, 102];
722
- for (const g of f) {
723
- const k = h.keccak256(a.encode(["address", "uint256"], [e, g]));
724
- l[k] = u;
725
- const E = h.keccak256(a.encode(["address", "uint256"], [e, g])), P = h.keccak256(a.encode(["address", "bytes32"], [c, E]));
726
- l[P] = d;
910
+ const a = l.AbiCoder.defaultAbiCoder(), i = n || l.parseUnits("1000000", 18), c = s ?? o, u = l.zeroPadValue(l.toBeHex(i), 32), d = l.zeroPadValue(l.toBeHex(l.MaxUint256), 32), p = {}, g = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 50, 51, 52, 100, 101, 102];
911
+ for (const m of g) {
912
+ const v = l.keccak256(a.encode(["address", "uint256"], [t, m]));
913
+ p[v] = u;
914
+ const C = l.keccak256(a.encode(["address", "uint256"], [t, m])), E = l.keccak256(a.encode(["address", "bytes32"], [c, C]));
915
+ p[E] = d;
727
916
  }
728
917
  return {
729
- [t.toLowerCase()]: { stateDiff: l }
918
+ [e.toLowerCase()]: { stateDiff: p }
730
919
  };
731
920
  }
732
921
  }
733
- const H = [
922
+ const M = [
734
923
  "function token0() external view returns (address)",
735
924
  "function token1() external view returns (address)",
736
925
  "function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast)"
737
- ], G = [
926
+ ], te = [
738
927
  "function token0() external view returns (address)",
739
928
  "function token1() external view returns (address)",
740
929
  "function fee() external view returns (uint24)",
741
930
  "function liquidity() external view returns (uint128)",
742
931
  "function slot0() external view returns (uint160 sqrtPriceX96, int24 tick, uint16 observationIndex, uint16 observationCardinality, uint16 observationCardinalityNext, uint32 feeProtocol, bool unlocked)"
743
- ], j = "0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73", q = [
932
+ ], oe = "0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73", ne = [
744
933
  "function getPair(address tokenA, address tokenB) external view returns (address pair)"
745
- ], Z = "0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865", Q = [
934
+ ], re = "0x86407bEa2078ea5f5EB5A52B2caA963bC1F889Da", se = [
935
+ "function getPair(address tokenA, address tokenB) external view returns (address pair)"
936
+ ], ae = "0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865", ie = [
746
937
  "function getPool(address tokenA, address tokenB, uint24 fee) external view returns (address pool)"
747
- ], Y = [100, 500, 2500, 1e4], z = 60000n, J = 120000n, X = 100000n;
748
- class at {
749
- constructor(t, e) {
750
- this.poolCache = /* @__PURE__ */ new Map(), this.provider = t, this.config = e, this.v2Factory = new h.Contract(
751
- j,
752
- q,
753
- t
754
- ), this.v3Factory = new h.Contract(
755
- Z,
756
- Q,
757
- t
938
+ ], ce = [100, 500, 2500, 1e4], ue = 60000n, de = 120000n, le = 100000n;
939
+ class Ae {
940
+ constructor(e, t) {
941
+ this.poolCache = /* @__PURE__ */ new Map(), this.provider = e, this.v2Factory = new l.Contract(
942
+ oe,
943
+ ne,
944
+ e
945
+ ), this.v3Factory = new l.Contract(
946
+ ae,
947
+ ie,
948
+ e
949
+ ), this.babySwapFactory = new l.Contract(
950
+ re,
951
+ se,
952
+ e
758
953
  );
759
954
  }
760
955
  /**
761
956
  * Discover optimal route
762
957
  */
763
- async findBestRoute(t, e, n) {
764
- const o = await this.discoverPools(t, e);
765
- if (o.length === 0)
766
- throw new Error(`No pools found for ${t} -> ${e}`);
958
+ async findBestRoute(e, t, o) {
959
+ const n = await this.discoverPools(e, t);
960
+ if (n.length === 0)
961
+ throw new Error(`No pools found for ${e} -> ${t}`);
767
962
  const r = (await this.calculateRoutes(
768
- o,
769
- t,
963
+ n,
770
964
  e,
771
- n
965
+ t,
966
+ o
772
967
  )).reduce(
773
968
  (a, i) => i.amountOut > a.amountOut ? i : a
774
969
  );
@@ -776,7 +971,7 @@ class at {
776
971
  routes: [r],
777
972
  percentages: [1e4],
778
973
  // 100%
779
- totalAmountIn: n,
974
+ totalAmountIn: o,
780
975
  totalAmountOut: r.amountOut,
781
976
  totalGasEstimate: r.gasEstimate
782
977
  };
@@ -784,56 +979,61 @@ class at {
784
979
  /**
785
980
  * Discover available pools (direct path)
786
981
  */
787
- async discoverPools(t, e) {
788
- const n = [];
982
+ async discoverPools(e, t) {
983
+ const o = [];
789
984
  try {
790
- const o = await this.findV2Pool(t, e);
791
- o && n.push(o);
985
+ const n = await this.findV2Pool(e, t);
986
+ n && o.push(n);
792
987
  } catch {
793
988
  }
794
- for (const o of Y)
989
+ for (const n of ce)
795
990
  try {
796
- const s = await this.findV3Pool(t, e, o);
797
- s && n.push(s);
991
+ const s = await this.findV3Pool(e, t, n);
992
+ s && o.push(s);
798
993
  } catch {
799
994
  }
800
- return n;
995
+ try {
996
+ const n = await this.findBabySwapPool(e, t);
997
+ n && o.push(n);
998
+ } catch {
999
+ }
1000
+ return o;
801
1001
  }
802
1002
  /**
803
1003
  * Find V2 pool
804
1004
  */
805
- async findV2Pool(t, e) {
806
- const n = `v2-${t}-${e}`;
807
- if (this.poolCache.has(n))
808
- return this.poolCache.get(n);
809
- const o = await this.v2Factory.getPair(t, e);
810
- if (o === h.ZeroAddress)
1005
+ async findV2Pool(e, t) {
1006
+ const o = `v2-${e}-${t}`;
1007
+ if (this.poolCache.has(o))
1008
+ return this.poolCache.get(o);
1009
+ const n = await this.v2Factory.getPair(e, t);
1010
+ if (n === l.ZeroAddress)
811
1011
  return null;
812
- const s = new h.Contract(o, H, this.provider), [r, a, i] = await Promise.all([
1012
+ const s = new l.Contract(n, M, this.provider), [r, a, i] = await Promise.all([
813
1013
  s.token0(),
814
1014
  s.token1(),
815
1015
  s.getReserves()
816
1016
  ]), c = {
817
- address: o,
1017
+ address: n,
818
1018
  token0: r,
819
1019
  token1: a,
820
- protocol: w.PancakeV2,
1020
+ protocol: f.PancakeV2,
821
1021
  reserve0: i.reserve0,
822
1022
  reserve1: i.reserve1
823
1023
  };
824
- return this.poolCache.set(n, c), c;
1024
+ return this.poolCache.set(o, c), c;
825
1025
  }
826
1026
  /**
827
1027
  * Find V3 pool
828
1028
  */
829
- async findV3Pool(t, e, n) {
830
- const o = `v3-${t}-${e}-${n}`;
831
- if (this.poolCache.has(o))
832
- return this.poolCache.get(o);
833
- const s = await this.v3Factory.getPool(t, e, n);
834
- if (s === h.ZeroAddress)
1029
+ async findV3Pool(e, t, o) {
1030
+ const n = `v3-${e}-${t}-${o}`;
1031
+ if (this.poolCache.has(n))
1032
+ return this.poolCache.get(n);
1033
+ const s = await this.v3Factory.getPool(e, t, o);
1034
+ if (s === l.ZeroAddress)
835
1035
  return null;
836
- const r = new h.Contract(s, G, this.provider), [a, i, c] = await Promise.all([
1036
+ const r = new l.Contract(s, te, this.provider), [a, i, c] = await Promise.all([
837
1037
  r.token0(),
838
1038
  r.token1(),
839
1039
  r.liquidity()
@@ -844,38 +1044,62 @@ class at {
844
1044
  address: s,
845
1045
  token0: a,
846
1046
  token1: i,
847
- protocol: w.PancakeV3,
848
- fee: n,
1047
+ protocol: f.PancakeV3,
1048
+ fee: o,
849
1049
  liquidity: c
850
1050
  };
851
- return this.poolCache.set(o, u), u;
1051
+ return this.poolCache.set(n, u), u;
1052
+ }
1053
+ /**
1054
+ * Find BabySwap pool (V2 fork, 0.2% fee)
1055
+ */
1056
+ async findBabySwapPool(e, t) {
1057
+ const o = `babyswap-${e}-${t}`;
1058
+ if (this.poolCache.has(o))
1059
+ return this.poolCache.get(o);
1060
+ const n = await this.babySwapFactory.getPair(e, t);
1061
+ if (n === l.ZeroAddress)
1062
+ return null;
1063
+ const s = new l.Contract(n, M, this.provider), [r, a, i] = await Promise.all([
1064
+ s.token0(),
1065
+ s.token1(),
1066
+ s.getReserves()
1067
+ ]), c = {
1068
+ address: n,
1069
+ token0: r,
1070
+ token1: a,
1071
+ protocol: f.BabySwap,
1072
+ reserve0: i.reserve0,
1073
+ reserve1: i.reserve1
1074
+ };
1075
+ return this.poolCache.set(o, c), c;
852
1076
  }
853
1077
  /**
854
1078
  * Calculate route quotes
855
1079
  */
856
- async calculateRoutes(t, e, n, o) {
1080
+ async calculateRoutes(e, t, o, n) {
857
1081
  const s = [];
858
- for (const r of t)
1082
+ for (const r of e)
859
1083
  try {
860
1084
  const a = await this.getAmountOut(
861
1085
  r,
862
- e,
863
- n,
864
- o
1086
+ t,
1087
+ o,
1088
+ n
865
1089
  );
866
1090
  a > 0n && s.push({
867
1091
  steps: [
868
1092
  {
869
1093
  pool: r,
870
- tokenIn: e,
871
- tokenOut: n,
872
- amountIn: o,
1094
+ tokenIn: t,
1095
+ tokenOut: o,
1096
+ amountIn: n,
873
1097
  amountOut: a
874
1098
  }
875
1099
  ],
876
- amountIn: o,
1100
+ amountIn: n,
877
1101
  amountOut: a,
878
- gasEstimate: r.protocol === w.PancakeV2 ? z : r.protocol === w.Dodo ? X : J
1102
+ gasEstimate: r.protocol === f.PancakeV2 || r.protocol === f.BabySwap ? ue : r.protocol === f.Dodo ? le : de
879
1103
  });
880
1104
  } catch {
881
1105
  }
@@ -884,26 +1108,35 @@ class at {
884
1108
  /**
885
1109
  * Get output for a single pool
886
1110
  */
887
- async getAmountOut(t, e, n, o) {
888
- if (t.protocol === w.PancakeV2)
889
- return this.getV2AmountOut(t, e, o);
890
- if (t.protocol === w.Dodo)
1111
+ async getAmountOut(e, t, o, n) {
1112
+ if (e.protocol === f.PancakeV2)
1113
+ return this.getV2AmountOut(e, t, n);
1114
+ if (e.protocol === f.BabySwap)
1115
+ return this.getBabySwapAmountOut(e, t, n);
1116
+ if (e.protocol === f.Dodo)
891
1117
  throw new Error("DODO amount out not supported in local route discovery");
892
- return this.estimateV3AmountOut(t, e, o);
1118
+ return this.estimateV3AmountOut(e, t, n);
893
1119
  }
894
1120
  /**
895
1121
  * V2 output calculation
896
1122
  */
897
- getV2AmountOut(t, e, n) {
898
- const o = e.toLowerCase() === t.token0.toLowerCase(), [s, r] = o ? [t.reserve0, t.reserve1] : [t.reserve1, t.reserve0], a = n * 9975n, i = a * r, c = s * 10000n + a;
1123
+ getV2AmountOut(e, t, o) {
1124
+ const n = t.toLowerCase() === e.token0.toLowerCase(), [s, r] = n ? [e.reserve0, e.reserve1] : [e.reserve1, e.reserve0], a = o * 9975n, i = a * r, c = s * 10000n + a;
1125
+ return i / c;
1126
+ }
1127
+ /**
1128
+ * BabySwap output calculation (V2 fork, 0.2% fee — coefficient 2 in 1000-scale)
1129
+ */
1130
+ getBabySwapAmountOut(e, t, o) {
1131
+ const n = t.toLowerCase() === e.token0.toLowerCase(), [s, r] = n ? [e.reserve0, e.reserve1] : [e.reserve1, e.reserve0], a = o * 998n, i = a * r, c = s * 1000n + a;
899
1132
  return i / c;
900
1133
  }
901
1134
  /**
902
1135
  * V3 output estimation (simplified)
903
1136
  */
904
- estimateV3AmountOut(t, e, n) {
905
- const s = 1000000n - BigInt(t.fee || 2500);
906
- return n * s / 1000000n;
1137
+ estimateV3AmountOut(e, t, o) {
1138
+ const s = 1000000n - BigInt(e.fee || 2500);
1139
+ return o * s / 1000000n;
907
1140
  }
908
1141
  /**
909
1142
  * Clear cache
@@ -912,143 +1145,158 @@ class at {
912
1145
  this.poolCache.clear();
913
1146
  }
914
1147
  }
915
- class it {
916
- constructor(t) {
917
- this.adapters = t;
1148
+ class ge {
1149
+ constructor(e) {
1150
+ this.adapters = e;
918
1151
  }
919
1152
  /**
920
1153
  * Build SwapParams from split route
921
1154
  */
922
- build(t, e, n, o, s = y) {
923
- const r = this.flattenRoutes(t), a = this.mergeIdenticalPools(r), i = this.topologicalSort(a, e), c = this.convertToSwapSteps(i), u = this.extractIntermediates(
1155
+ build(e, t, o, n, s = T) {
1156
+ const r = this.flattenRoutes(e), a = this.mergeIdenticalPools(r), i = this.topologicalSort(a, t), c = this.convertToSwapSteps(i), u = this.extractIntermediates(
924
1157
  i,
925
- e,
926
- n
1158
+ t,
1159
+ o
927
1160
  ), d = BigInt(Math.floor(Date.now() / 1e3) + s);
928
1161
  return {
929
- srcToken: e,
930
- dstToken: n,
931
- amountIn: t.totalAmountIn,
932
- amountOutMin: o,
1162
+ srcToken: t,
1163
+ dstToken: o,
1164
+ amountIn: e.totalAmountIn,
1165
+ amountOutMin: n,
933
1166
  steps: c,
934
1167
  intermediateTokens: u,
935
1168
  deadline: d,
936
- quoteId: h.ZeroHash,
937
- expectAmountOut: t.totalAmountOut
1169
+ quoteId: l.ZeroHash,
1170
+ expectAmountOut: e.totalAmountOut,
1171
+ // SwapBuilder is the legacy direct-build path that does not know about custom fees.
1172
+ // Integrators that want custom fees should use PeachClient.getQuote with options.customFee
1173
+ // instead, which sets these fields and adjusts amountOutMin accordingly.
1174
+ feeReceiver: l.ZeroAddress,
1175
+ feeBps: 0
938
1176
  };
939
1177
  }
940
1178
  /**
941
1179
  * Flatten split route
942
1180
  */
943
- flattenRoutes(t) {
944
- const e = [];
945
- for (let n = 0; n < t.routes.length; n++) {
946
- const o = t.routes[n], s = t.percentages[n], r = t.totalAmountIn * BigInt(s) / O;
947
- for (let a = 0; a < o.steps.length; a++) {
948
- const i = o.steps[a];
949
- e.push({
1181
+ flattenRoutes(e) {
1182
+ const t = [];
1183
+ for (let o = 0; o < e.routes.length; o++) {
1184
+ const n = e.routes[o], s = e.percentages[o], r = e.totalAmountIn * BigInt(s) / b;
1185
+ for (let a = 0; a < n.steps.length; a++) {
1186
+ const i = n.steps[a];
1187
+ t.push({
950
1188
  pool: i.pool,
951
1189
  tokenIn: i.tokenIn,
952
1190
  tokenOut: i.tokenOut,
953
1191
  // Only first step has fixed amount, subsequent steps depend on previous output
954
1192
  amountIn: a === 0 ? r : 0n,
955
- routeIndex: n,
1193
+ routeIndex: o,
956
1194
  stepIndex: a
957
1195
  });
958
1196
  }
959
1197
  }
960
- return e;
1198
+ return t;
961
1199
  }
962
1200
  /**
963
1201
  * Merge identical pools
964
1202
  * Key: pool + tokenIn + tokenOut
965
1203
  */
966
- mergeIdenticalPools(t) {
967
- const e = /* @__PURE__ */ new Map(), n = [];
968
- for (const o of t) {
969
- const s = `${o.pool.address}-${o.tokenIn}-${o.tokenOut}`;
970
- if (e.has(s)) {
971
- const r = e.get(s);
972
- o.amountIn > 0n && r.amountIn > 0n && (r.amountIn = 0n);
1204
+ mergeIdenticalPools(e) {
1205
+ const t = /* @__PURE__ */ new Map(), o = [];
1206
+ for (const n of e) {
1207
+ const s = `${n.pool.address}-${n.tokenIn}-${n.tokenOut}`;
1208
+ if (t.has(s)) {
1209
+ const r = t.get(s);
1210
+ n.amountIn > 0n && r.amountIn > 0n && (r.amountIn = 0n);
973
1211
  } else {
974
- const r = { ...o };
975
- e.set(s, r), n.push(r);
1212
+ const r = { ...n };
1213
+ t.set(s, r), o.push(r);
976
1214
  }
977
1215
  }
978
- for (const o of n) {
979
- const s = `${o.pool.address}-${o.tokenIn}-${o.tokenOut}`;
980
- t.filter(
1216
+ for (const n of o) {
1217
+ const s = `${n.pool.address}-${n.tokenIn}-${n.tokenOut}`;
1218
+ e.filter(
981
1219
  (a) => `${a.pool.address}-${a.tokenIn}-${a.tokenOut}` === s
982
- ).length > 1 && (o.amountIn = 0n);
1220
+ ).length > 1 && (n.amountIn = 0n);
983
1221
  }
984
- return n;
1222
+ return o;
985
1223
  }
986
1224
  /**
987
1225
  * Topological sort (Kahn's Algorithm)
988
1226
  */
989
- topologicalSort(t, e) {
990
- const n = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map();
991
- for (const i of t) {
1227
+ topologicalSort(e, t) {
1228
+ const o = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map();
1229
+ for (const i of e) {
992
1230
  const c = this.stepKey(i);
993
- o.set(c, i), n.set(c, 0), s.set(c, []);
1231
+ n.set(c, i), o.set(c, 0), s.set(c, []);
994
1232
  }
995
- for (const i of t) {
1233
+ for (const i of e) {
996
1234
  const c = this.stepKey(i);
997
- if (i.tokenIn !== e) {
998
- for (const u of t)
1235
+ if (i.tokenIn !== t) {
1236
+ for (const u of e)
999
1237
  if (u.tokenOut === i.tokenIn) {
1000
1238
  const d = this.stepKey(u);
1001
- d !== c && (s.get(d).push(c), n.set(c, (n.get(c) || 0) + 1));
1239
+ d !== c && (s.get(d).push(c), o.set(c, (o.get(c) || 0) + 1));
1002
1240
  }
1003
1241
  }
1004
1242
  }
1005
1243
  const r = [];
1006
- for (const [i, c] of n)
1244
+ for (const [i, c] of o)
1007
1245
  c === 0 && r.push(i);
1008
1246
  const a = [];
1009
1247
  for (; r.length > 0; ) {
1010
- const i = r.shift(), c = o.get(i);
1248
+ const i = r.shift(), c = n.get(i);
1011
1249
  a.push(c);
1012
1250
  for (const u of s.get(i) || []) {
1013
- const d = (n.get(u) || 0) - 1;
1014
- n.set(u, d), d === 0 && r.push(u);
1251
+ const d = (o.get(u) || 0) - 1;
1252
+ o.set(u, d), d === 0 && r.push(u);
1015
1253
  }
1016
1254
  }
1017
- if (a.length !== t.length)
1255
+ if (a.length !== e.length)
1018
1256
  throw new Error("Circular dependency detected in route");
1019
1257
  return a;
1020
1258
  }
1021
1259
  /**
1022
1260
  * Convert to contract SwapStep format
1023
1261
  */
1024
- convertToSwapSteps(t) {
1025
- return t.map((e) => {
1026
- const n = this.adapters.get(e.pool.protocol);
1027
- if (!n)
1028
- throw new Error(`No adapter for protocol: ${e.pool.protocol}`);
1262
+ convertToSwapSteps(e) {
1263
+ return e.map((t) => {
1264
+ const o = this.adapters.get(t.pool.protocol);
1265
+ if (!o)
1266
+ throw new Error(`No adapter for protocol: ${t.pool.protocol}`);
1029
1267
  return {
1030
- adapter: n,
1031
- pool: e.pool.address,
1032
- tokenIn: e.tokenIn,
1033
- tokenOut: e.tokenOut,
1034
- amountIn: e.amountIn,
1035
- extraData: this.encodeExtraData(e.pool)
1268
+ adapter: o,
1269
+ pool: t.pool.address,
1270
+ tokenIn: t.tokenIn,
1271
+ tokenOut: t.tokenOut,
1272
+ amountIn: t.amountIn,
1273
+ extraData: this.encodeExtraData(t.pool)
1036
1274
  };
1037
1275
  });
1038
1276
  }
1039
1277
  /**
1040
1278
  * Encode protocol-specific parameters
1041
1279
  */
1042
- encodeExtraData(t) {
1043
- switch (t.protocol) {
1044
- case w.PancakeV2:
1280
+ encodeExtraData(e) {
1281
+ switch (e.protocol) {
1282
+ case f.PancakeV2:
1045
1283
  return "0x";
1046
1284
  // V2 doesn't need extra parameters
1047
- case w.PancakeV3:
1048
- case w.UniswapV3:
1049
- case w.UniswapV4:
1285
+ case f.PancakeV3:
1286
+ case f.UniswapV3:
1287
+ case f.UniswapV4:
1288
+ return "0x";
1289
+ case f.Dodo:
1290
+ return "0x";
1291
+ case f.NomiswapStable:
1292
+ return "0x";
1293
+ case f.Biswap:
1294
+ return "0x";
1295
+ case f.Apeswap:
1296
+ return "0x";
1297
+ case f.BabyDogeSwap:
1050
1298
  return "0x";
1051
- case w.Dodo:
1299
+ case f.BabySwap:
1052
1300
  return "0x";
1053
1301
  default:
1054
1302
  return "0x";
@@ -1057,39 +1305,42 @@ class it {
1057
1305
  /**
1058
1306
  * Extract intermediate tokens
1059
1307
  */
1060
- extractIntermediates(t, e, n) {
1061
- const o = /* @__PURE__ */ new Set();
1062
- for (const s of t)
1063
- s.tokenOut !== n && o.add(s.tokenOut);
1064
- return o.delete(e), o.delete(n), Array.from(o);
1308
+ extractIntermediates(e, t, o) {
1309
+ const n = /* @__PURE__ */ new Set();
1310
+ for (const s of e)
1311
+ s.tokenOut !== o && n.add(s.tokenOut);
1312
+ return n.delete(t), n.delete(o), Array.from(n);
1065
1313
  }
1066
1314
  /**
1067
1315
  * Generate unique step key
1068
1316
  */
1069
- stepKey(t) {
1070
- return `${t.pool.address}-${t.tokenIn}-${t.tokenOut}`;
1317
+ stepKey(e) {
1318
+ return `${e.pool.address}-${e.tokenIn}-${e.tokenOut}`;
1071
1319
  }
1072
1320
  }
1073
1321
  export {
1074
- I as API_DEFAULTS,
1075
- M as ApiClient,
1076
- v as ApiError,
1077
- O as BPS_DENOMINATOR,
1078
- ot as BSC_MAINNET_CONFIG,
1079
- rt as BSC_TESTNET_CONFIG,
1080
- V as DEFAULT_API_URL,
1081
- y as DEFAULT_DEADLINE_SECONDS,
1082
- D as DEFAULT_EXECUTE_TIMEOUT_MS,
1083
- et as DEFAULT_SLIPPAGE_BPS,
1084
- x as DEFAULT_TRANSACTION_RESPONSE_POLL_INTERVALS_MS,
1085
- nt as ERR_ZERO_AMOUNT_PATHS,
1086
- N as ExecuteTimeoutError,
1087
- $ as NATIVE_TOKEN_ADDRESS,
1088
- st as PeachClient,
1089
- w as ProtocolType,
1090
- at as RouteDiscovery,
1091
- it as SwapBuilder,
1322
+ k as API_DEFAULTS,
1323
+ X as ApiClient,
1324
+ A as ApiError,
1325
+ b as BPS_DENOMINATOR,
1326
+ me as BSC_MAINNET_CONFIG,
1327
+ ve as BSC_TESTNET_CONFIG,
1328
+ x as CustomFeeError,
1329
+ q as DEFAULT_API_URL,
1330
+ T as DEFAULT_DEADLINE_SECONDS,
1331
+ W as DEFAULT_EXECUTE_TIMEOUT_MS,
1332
+ he as DEFAULT_SLIPPAGE_BPS,
1333
+ $ as DEFAULT_TRANSACTION_RESPONSE_POLL_INTERVALS_MS,
1334
+ we as ERR_ZERO_AMOUNT_PATHS,
1335
+ H as ExecuteTimeoutError,
1336
+ L as MAX_FEE_BPS,
1337
+ fe as MAX_PLATFORM_CUT_BPS,
1338
+ Q as NATIVE_TOKEN_ADDRESS,
1339
+ K as PeachClient,
1340
+ f as ProtocolType,
1341
+ Ae as RouteDiscovery,
1342
+ ge as SwapBuilder,
1092
1343
  _ as isNativeTokenAddress,
1093
- b as withWalletSendTimeout
1344
+ U as withWalletSendTimeout
1094
1345
  };
1095
1346
  //# sourceMappingURL=index.mjs.map