@@ -14,6 +14,7 @@ import {
14
14
type Hex ,
15
15
encodeAbiParameters ,
16
16
parseAbiParameters ,
17
+ parseUnits ,
17
18
} from "viem"
18
19
import { SwapperMode } from "../interface"
19
20
import type { StrategyResult , SwapParams , SwapQuote } from "../types"
@@ -24,6 +25,7 @@ import {
24
25
buildApiResponseExactInputFromQuote ,
25
26
buildApiResponseSwap ,
26
27
buildApiResponseVerifyDebtMax ,
28
+ calculateEstimatedAmountFrom ,
27
29
encodeSwapMulticallItem ,
28
30
isExactInRepay ,
29
31
matchParams ,
@@ -239,13 +241,6 @@ export class StrategyBalmySDK {
239
241
}
240
242
}
241
243
242
- const reverseSwapParams = {
243
- ...swapParams ,
244
- tokenIn : swapParams . tokenOut ,
245
- tokenOut : swapParams . tokenIn ,
246
- swapperMode : SwapperMode . EXACT_IN ,
247
- }
248
-
249
244
let sourcesFilter
250
245
if ( this . config . sourcesFilter ?. includeSources ) {
251
246
sourcesFilter = {
@@ -263,12 +258,28 @@ export class StrategyBalmySDK {
263
258
} else {
264
259
sourcesFilter = { excludeSources : BINARY_SEARCH_EXCLUDE_SOURCES }
265
260
}
261
+ const swapParamsExactIn = {
262
+ ...swapParams ,
263
+ swapperMode : SwapperMode . EXACT_IN ,
264
+ receiver : swapParams . from ,
265
+ isRepay : false ,
266
+ }
267
+ const { amountTo : unitAmountTo } = await fetchQuote (
268
+ {
269
+ ...swapParamsExactIn ,
270
+ amount : parseUnits ( "1" , swapParams . tokenIn . decimals ) ,
271
+ } ,
272
+ sourcesFilter ,
273
+ )
266
274
267
- const reverseQuote = await fetchQuote ( reverseSwapParams , sourcesFilter )
268
- const estimatedAmountIn = reverseQuote . amountTo
269
- if ( estimatedAmountIn === 0n ) throw new Error ( "quote not found" )
275
+ const estimatedAmountIn = calculateEstimatedAmountFrom (
276
+ unitAmountTo ,
277
+ swapParamsExactIn . amount ,
278
+ swapParamsExactIn . tokenIn . decimals ,
279
+ swapParamsExactIn . tokenOut . decimals ,
280
+ )
270
281
271
- const bestSourceId = reverseQuote . quote . source . id
282
+ if ( estimatedAmountIn === 0n ) throw new Error ( " quote not found" )
272
283
273
284
const overSwapTarget = adjustForInterest ( swapParams . amount )
274
285
@@ -277,10 +288,19 @@ export class StrategyBalmySDK {
277
288
currentAmountTo < overSwapTarget ||
278
289
( currentAmountTo * 1000n ) / overSwapTarget > 1005n
279
290
291
+ let bestSourceId : string
292
+
280
293
const quote = await binarySearchQuote (
281
294
swapParams ,
282
- ( swapParams : SwapParams ) =>
283
- fetchQuote ( swapParams , { includeSources : [ bestSourceId ] } ) , // preselect single source to avoid oscilations
295
+ async ( swapParams : SwapParams ) => {
296
+ let bestSourceConfig
297
+ if ( bestSourceId ) {
298
+ bestSourceConfig = { includeSources : [ bestSourceId ] }
299
+ }
300
+ const q = await fetchQuote ( swapParams , bestSourceConfig ) // preselect single source to avoid oscilations
301
+ if ( ! bestSourceId ) bestSourceId = q . quote . source . id
302
+ return q
303
+ } ,
284
304
overSwapTarget ,
285
305
estimatedAmountIn ,
286
306
shouldContinue ,
@@ -293,6 +313,73 @@ export class StrategyBalmySDK {
293
313
return this . #getSwapQuoteFromSDKQuoteWithTx( swapParams , quoteWithTx )
294
314
}
295
315
316
+ // async #binarySearchOverswapQuote(swapParams: SwapParams) {
317
+ // const fetchQuote = async (
318
+ // sp: SwapParams,
319
+ // sourcesFilter?: SourcesFilter,
320
+ // ) => {
321
+ // const quote = await this.#getBestSDKQuote(sp, sourcesFilter)
322
+ // return {
323
+ // quote,
324
+ // amountTo: quote.buyAmount.amount,
325
+ // }
326
+ // }
327
+
328
+ // const reverseSwapParams = {
329
+ // ...swapParams,
330
+ // tokenIn: swapParams.tokenOut,
331
+ // tokenOut: swapParams.tokenIn,
332
+ // swapperMode: SwapperMode.EXACT_IN,
333
+ // }
334
+
335
+ // let sourcesFilter
336
+ // if (this.config.sourcesFilter?.includeSources) {
337
+ // sourcesFilter = {
338
+ // includeSources: this.config.sourcesFilter.includeSources.filter(
339
+ // (s) => !BINARY_SEARCH_EXCLUDE_SOURCES.includes(s),
340
+ // ),
341
+ // }
342
+ // } else if (this.config.sourcesFilter?.excludeSources) {
343
+ // sourcesFilter = {
344
+ // excludeSources: [
345
+ // ...this.config.sourcesFilter.excludeSources,
346
+ // ...BINARY_SEARCH_EXCLUDE_SOURCES,
347
+ // ],
348
+ // }
349
+ // } else {
350
+ // sourcesFilter = { excludeSources: BINARY_SEARCH_EXCLUDE_SOURCES }
351
+ // }
352
+ // console.log(11);
353
+ // const reverseQuote = await fetchQuote(reverseSwapParams, sourcesFilter)
354
+ // console.log(22);
355
+ // const estimatedAmountIn = reverseQuote.amountTo
356
+ // if (estimatedAmountIn === 0n) throw new Error("quote not found")
357
+
358
+ // const bestSourceId = reverseQuote.quote.source.id
359
+
360
+ // const overSwapTarget = adjustForInterest(swapParams.amount)
361
+
362
+ // const shouldContinue = (currentAmountTo: bigint): boolean =>
363
+ // // search until quote is 100 - 100.5% target
364
+ // currentAmountTo < overSwapTarget ||
365
+ // (currentAmountTo * 1000n) / overSwapTarget > 1005n
366
+
367
+ // const quote = await binarySearchQuote(
368
+ // swapParams,
369
+ // (swapParams: SwapParams) =>
370
+ // fetchQuote(swapParams, { includeSources: [bestSourceId] }), // preselect single source to avoid oscilations
371
+ // overSwapTarget,
372
+ // estimatedAmountIn,
373
+ // shouldContinue,
374
+ // )
375
+ // const quoteWithTx = {
376
+ // ...quote,
377
+ // tx: await this.#getTxForQuote(quote),
378
+ // }
379
+
380
+ // return this.#getSwapQuoteFromSDKQuoteWithTx(swapParams, quoteWithTx)
381
+ // }
382
+
296
383
async #getBestSDKQuote(
297
384
swapParams : SwapParams ,
298
385
sourcesFilter ?: SourcesFilter ,
0 commit comments