diff --git a/packages/cli/source/commands/convert.tsx b/packages/cli/source/commands/convert.tsx index f9e181a..897acc9 100644 --- a/packages/cli/source/commands/convert.tsx +++ b/packages/cli/source/commands/convert.tsx @@ -96,6 +96,16 @@ export const options = zod.object({ ) .optional() .default(false), + fixedPairs: zod + .boolean() + .describe( + option({ + description: "Use fixed pairs to query available pools", + alias: "f", + }), + ) + .optional() + .default(false), minIncomeBp: zod .number() .describe( @@ -116,8 +126,19 @@ interface Props { * Command to search for and execute token conversions based on parameters */ export default function Convert({ options }: Props) { - const { minTradeUsd, maxTradeUsd, simulate, assetIn, assetOut, converter, profitable, loop, debug, minIncomeBp } = - options; + const { + minTradeUsd, + maxTradeUsd, + simulate, + assetIn, + assetOut, + converter, + profitable, + loop, + debug, + minIncomeBp, + fixedPairs, + } = options; const { exit } = useApp(); const { write: writeStdErr } = useStderr(); @@ -127,25 +148,25 @@ export default function Convert({ options }: Props) { useEffect(() => { const network = getEnvValue("NETWORK"); + const tokenConverter = new TokenConverter({ + subscriber: dispatch, + simulate: !!simulate, + swapProvider: network?.includes("bsc") ? PancakeSwapProvider : UniswapProvider, + }); + const convert = async () => { - const tokenConverter = new TokenConverter({ - subscriber: dispatch, - simulate: !!simulate, - swapProvider: network?.includes("bsc") ? PancakeSwapProvider : UniswapProvider, + const potentialConversions = await tokenConverter.queryConversions({ + assetIn, + assetOut, + converter, + releaseFunds: false, }); - do { - const potentialConversions = await tokenConverter.queryConversions({ - assetIn, - assetOut, - converter, - releaseFunds: false, - }); - - if (potentialConversions.length === 0) { - setError("No Potential Trades Found"); - } + if (potentialConversions.length === 0) { + setError("No Potential Trades Found"); + } + do { for (const t of potentialConversions) { let amountOut = t.assetOut.balance; @@ -166,6 +187,7 @@ export default function Convert({ options }: Props) { t.assetOut.address, t.assetIn.address, amountOut, + fixedPairs, ); const { trade, amount, minIncome } = arbitrageArgs || { diff --git a/packages/keeper-bots/src/converter-bot/TokenConverter.test.ts b/packages/keeper-bots/src/converter-bot/TokenConverter.test.ts index 7c3e3c9..62db992 100644 --- a/packages/keeper-bots/src/converter-bot/TokenConverter.test.ts +++ b/packages/keeper-bots/src/converter-bot/TokenConverter.test.ts @@ -185,6 +185,7 @@ describe("Token Converter", () => { addresses.WBNB, addresses.USDC, 1000000000000000000000n, + false, ); expect(trade.inputToken).toEqual({ @@ -205,6 +206,7 @@ describe("Token Converter", () => { numerator: 8904975230019520420n, }, }); + expect(trade.outputToken).toEqual({ address: "0xcf6bb5389c92bdda8a3747ddb454cb7a64626c63", amount: { @@ -233,6 +235,7 @@ describe("Token Converter", () => { addresses.WBNB, addresses.USDC, 750000000000000000n, + false, ); expect(subscriberMock).toHaveBeenCalledWith({ type: "GetBestTrade", diff --git a/packages/keeper-bots/src/converter-bot/TokenConverter.ts b/packages/keeper-bots/src/converter-bot/TokenConverter.ts index 0882116..b07fa22 100644 --- a/packages/keeper-bots/src/converter-bot/TokenConverter.ts +++ b/packages/keeper-bots/src/converter-bot/TokenConverter.ts @@ -54,8 +54,9 @@ export class TokenConverter extends BotBase { swapFrom: Address, swapTo: Address, amount: bigint, + fixedPairs?: boolean, ): Promise<[TradeRoute, bigint]> { - return this.swapProvider.getBestTrade(tokenConverter, swapFrom, swapTo, amount); + return this.swapProvider.getBestTrade(tokenConverter, swapFrom, swapTo, amount, fixedPairs); } /** @@ -385,13 +386,19 @@ export class TokenConverter extends BotBase { * @param amountOut Amount of asset out to receive from the token converter * @returns {trade: SmartRouterTrade, amount: bigint, minIncome: bigint } */ - async prepareConversion(tokenConverter: Address, assetOut: Address, assetIn: Address, amountOut: bigint) { + async prepareConversion( + tokenConverter: Address, + assetOut: Address, + assetIn: Address, + amountOut: bigint, + fixedPairs?: boolean, + ) { let error; let trade; let amount; try { - [trade, amount] = await this.getBestTrade(tokenConverter, assetOut, assetIn, amountOut); + [trade, amount] = await this.getBestTrade(tokenConverter, assetOut, assetIn, amountOut, fixedPairs); } catch (e) { error = (e as Error).message; } finally { diff --git a/packages/keeper-bots/src/providers/pancake-swap.ts b/packages/keeper-bots/src/providers/pancake-swap.ts index 3cee9ae..c6b9afd 100644 --- a/packages/keeper-bots/src/providers/pancake-swap.ts +++ b/packages/keeper-bots/src/providers/pancake-swap.ts @@ -80,7 +80,7 @@ class PancakeSwapProvider extends SwapProvider { * @param swapFromToken * @param swapToToken */ - getCandidatePools = async (swapFromToken: Token, swapToToken: Token) => { + getCandidatePools = async (swapFromToken: Token, swapToToken: Token, fixedPairs: boolean) => { const now = new Date(); if (!this._candidatePools.data.length || this._candidatePools.expirationTimestamp < now) { const candidatePools = await SmartRouter.getV3CandidatePools({ @@ -88,6 +88,12 @@ class PancakeSwapProvider extends SwapProvider { subgraphProvider: () => this.v3PancakeSubgraphClient, currencyA: swapFromToken, currencyB: swapToToken, + pairs: fixedPairs + ? [ + [swapFromToken, swapToToken], + [swapToToken, swapFromToken], + ] + : undefined, }); now.setMinutes(15 + new Date().getMinutes()); @@ -105,6 +111,7 @@ class PancakeSwapProvider extends SwapProvider { swapFrom: Address, swapTo: Address, amount: bigint, + fixedPairs: boolean = false, ): Promise<[TradeRoute, bigint]> { const swapFromToken = await this.getToken(swapFrom); const swapToToken = await this.getToken(swapTo); @@ -122,7 +129,7 @@ class PancakeSwapProvider extends SwapProvider { }); try { - const candidatePools = await this.getCandidatePools(swapFromToken, swapToToken); + const candidatePools = await this.getCandidatePools(swapFromToken, swapToToken, fixedPairs); const response = await SmartRouter.getBestTrade( CurrencyAmount.fromRawAmount(swapToToken, updatedAmountIn[1]), @@ -179,7 +186,7 @@ class PancakeSwapProvider extends SwapProvider { }, }); - return this.getBestTrade(tokenConverter, swapFrom, swapTo, (updatedAmountIn[1] * 75n) / 100n); + return this.getBestTrade(tokenConverter, swapFrom, swapTo, (updatedAmountIn[1] * 75n) / 100n, fixedPairs); } return [trade, updatedAmountIn[0]]; } diff --git a/packages/keeper-bots/src/providers/swap-provider.ts b/packages/keeper-bots/src/providers/swap-provider.ts index 714795b..75664cc 100644 --- a/packages/keeper-bots/src/providers/swap-provider.ts +++ b/packages/keeper-bots/src/providers/swap-provider.ts @@ -53,6 +53,8 @@ class SwapProvider { swapTo: Address, // eslint-disable-next-line amount: bigint, + // eslint-disable-next-line + fixedPairs?: boolean, ): Promise<[TradeRoute, bigint]> { throw new Error("Not Implemented Error"); }