Skip to content

Commit

Permalink
fix: refactor get best trade to query amount again
Browse files Browse the repository at this point in the history
  • Loading branch information
coreyar committed Aug 26, 2024
1 parent 8fd86f2 commit 79ddbc9
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 29 deletions.
36 changes: 28 additions & 8 deletions packages/keeper-bots/src/converter-bot/TokenConverter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,14 @@ describe("Token Converter", () => {
(SmartRouter.getBestTrade as jest.Mock).mockImplementationOnce(() => null);

// eslint-disable-next-line @typescript-eslint/no-floating-promises
expect(tokenConverter.getBestTrade(addresses.WBNB, addresses.USDC, 1000000000000000000000n)).rejects.toThrow(
"No trade found",
);
expect(
tokenConverter.getBestTrade(
addresses.USDCPrimeConverter,
addresses.WBNB,
addresses.USDC,
1000000000000000000000n,
),
).rejects.toThrow("No trade found");
});

test("should handle thrown error", async () => {
Expand All @@ -96,9 +101,14 @@ describe("Token Converter", () => {
throw new Error("Cannot find a valid swap route");
});
// eslint-disable-next-line @typescript-eslint/no-floating-promises
expect(tokenConverter.getBestTrade(addresses.WBNB, addresses.USDC, 1000000000000000000000n)).rejects.toThrow(
"Error getting best trade - Cannot find a valid swap route",
);
expect(
tokenConverter.getBestTrade(
addresses.USDCPrimeConverter,
addresses.WBNB,
addresses.USDC,
1000000000000000000000n,
),
).rejects.toThrow("Error getting best trade - Cannot find a valid swap route");
});

test("should return trade with low price impact", async () => {
Expand All @@ -110,7 +120,12 @@ describe("Token Converter", () => {
(tokenConverter.publicClient.simulateContract as jest.Mock).mockImplementation(() => ({
result: [1000000000000000000n, 1000000000000000000n],
}));
const trade = await tokenConverter.getBestTrade(addresses.WBNB, addresses.USDC, 1000000000000000000000n);
const [trade] = await tokenConverter.getBestTrade(
addresses.USDCPrimeConverter,
addresses.WBNB,
addresses.USDC,
1000000000000000000000n,
);

expect(trade.inputToken).toEqual({
address: "0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c",
Expand Down Expand Up @@ -176,7 +191,12 @@ describe("Token Converter", () => {
return new Percent(9n, 1000n);
});

const trade = await pancakeSwapProvider.getBestTrade(addresses.WBNB, addresses.USDC, 1000000000000000000000n);
const [trade] = await pancakeSwapProvider.getBestTrade(
addresses.USDCPrimeConverter,
addresses.WBNB,
addresses.USDC,
1000000000000000000000n,
);

expect(trade.inputToken).toEqual({
address: "0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c",
Expand Down
26 changes: 15 additions & 11 deletions packages/keeper-bots/src/converter-bot/TokenConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,13 @@ export class TokenConverter extends BotBase {
* @param amount The amount we will receive from the converter of swapFrom
* @returns [SmartRouterTrade, [amount transferred out of converter, amount transferred in]]
*/
async getBestTrade(swapFrom: Address, swapTo: Address, amount: bigint): Promise<TradeRoute> {
return this.swapProvider.getBestTrade(swapFrom, swapTo, amount);
async getBestTrade(
tokenConverter: Address,
swapFrom: Address,
swapTo: Address,
amount: bigint,
): Promise<[TradeRoute, bigint]> {
return this.swapProvider.getBestTrade(tokenConverter, swapFrom, swapTo, amount);
}

/**
Expand Down Expand Up @@ -384,7 +389,7 @@ export class TokenConverter extends BotBase {
async prepareConversion(tokenConverter: Address, assetOut: Address, assetIn: Address, amountOut: bigint) {
let error;
let trade;
let tradeAmount;
let amount;

// [amount transferred out of converter, amount transferred in]
const { result: updatedAmountIn } = await this.publicClient.simulateContract({
Expand All @@ -395,14 +400,13 @@ export class TokenConverter extends BotBase {
});

try {
trade = await this.getBestTrade(assetOut, assetIn, updatedAmountIn[1]);
[trade, amount] = await this.getBestTrade(tokenConverter, assetOut, assetIn, updatedAmountIn[0]);
} catch (e) {
error = (e as Error).message;
} finally {
let tradeContext: Pick<GetBestTradeMessage["context"], "tradeAmount" | "swap"> = {};
if (trade && tradeAmount) {
let tradeContext: Pick<GetBestTradeMessage["context"], "swap"> = {};
if (trade) {
tradeContext = {
tradeAmount: { amountOut: tradeAmount && tradeAmount[0], amountIn: tradeAmount && tradeAmount[1] },
swap: {
inputToken: {
amount: trade.inputToken.amount.toFixed(0),
Expand All @@ -428,13 +432,13 @@ export class TokenConverter extends BotBase {
});
}

if (trade && tradeAmount) {
if (trade && amount) {
// the difference between the token you get from TokenConverter and the token you pay to the MM
const minIncome = new Fraction(tradeAmount[0], 1).subtract(trade.inputToken.amount);
const minIncome = new Fraction(amount).subtract(trade.inputToken.amount);
return {
trade,
amount: tradeAmount[0],
minIncome: BigInt(minIncome.toFixed(0, { groupSeparator: "" })),
amount: trade.inputToken.amount.quotient,
minIncome: minIncome.quotient,
};
}
}
Expand Down
23 changes: 19 additions & 4 deletions packages/keeper-bots/src/providers/pancake-swap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Client as UrqlClient, createClient } from "urql/core";
import { Address, Hex, encodePacked, erc20Abi } from "viem";

import getConfig from "../config";
import { tokenConverterAbi } from "../config/abis/generated";
import type { SUPPORTED_CHAINS } from "../config/chains";
import { chains } from "../config/chains";
import { ConverterBotMessage } from "../converter-bot/types";
Expand Down Expand Up @@ -66,10 +67,23 @@ class PancakeSwapProvider extends SwapProvider {
throw new Error(`Unable to fetch token details for ${address}`);
}

async getBestTrade(swapFrom: Address, swapTo: Address, amount: bigint): Promise<TradeRoute> {
async getBestTrade(
tokenConverter: Address,
swapFrom: Address,
swapTo: Address,
amount: bigint,
): Promise<[TradeRoute, bigint]> {
const swapFromToken = await this.getToken(swapFrom);
const swapToToken = await this.getToken(swapTo);

// [amount transferred out of converter, amount transferred in]
const { result: updatedAmountIn } = await this.publicClient.simulateContract({
address: tokenConverter,
abi: tokenConverterAbi,
functionName: "getUpdatedAmountIn",
args: [amount, swapTo, swapFrom],
});

const candidatePools = await SmartRouter.getV3CandidatePools({
onChainProvider: () => this.publicClient,
subgraphProvider: () => this.v3PancakeSubgraphClient,
Expand All @@ -82,7 +96,7 @@ class PancakeSwapProvider extends SwapProvider {

try {
const response = await SmartRouter.getBestTrade(
CurrencyAmount.fromRawAmount(swapToToken, amount),
CurrencyAmount.fromRawAmount(swapToToken, updatedAmountIn[1]),
swapFromToken,
TradeType.EXACT_OUTPUT,
{
Expand All @@ -94,6 +108,7 @@ class PancakeSwapProvider extends SwapProvider {
quoterOptimization: true,
},
);

if (response) {
trade = {
inputToken: {
Expand Down Expand Up @@ -128,9 +143,9 @@ class PancakeSwapProvider extends SwapProvider {
},
});

return this.getBestTrade(swapFrom, swapTo, (amount * 75n) / 100n);
return this.getBestTrade(tokenConverter, swapFrom, swapTo, (updatedAmountIn[1] * 75n) / 100n);
}
return trade;
return [trade, amount];
}

/**
Expand Down
4 changes: 2 additions & 2 deletions packages/keeper-bots/src/providers/swap-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ class SwapProvider {

async getBestTrade(
// eslint-disable-next-line
// tokenConverter: Address,
tokenConverter: Address,
// eslint-disable-next-line
swapFrom: Address,
// eslint-disable-next-line
swapTo: Address,
// eslint-disable-next-line
amount: bigint,
): Promise<TradeRoute> {
): Promise<[TradeRoute, bigint]> {
throw new Error("Not Implemented Error");
}
}
Expand Down
17 changes: 13 additions & 4 deletions packages/keeper-bots/src/providers/uniswap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import JSBI from "jsbi";
import { Address, Hex, encodePacked, erc20Abi } from "viem";

import getConfig from "../config";
import { tokenConverterAbi } from "../config/abis/generated";
import type { SUPPORTED_CHAINS } from "../config/chains";
import { chains } from "../config/chains";
import { ConverterBotMessage } from "../converter-bot/types";
Expand Down Expand Up @@ -61,14 +62,22 @@ class UniswapProvider extends SwapProvider {
}

async getBestTrade(
// tokenConverter: Address,
tokenConverter: Address,
swapFrom: Address,
swapTo: Address,
amount: bigint,
): Promise<TradeRoute> {
): Promise<[TradeRoute, bigint]> {
const swapFromToken = await this.getToken(swapFrom);
const swapToToken = await this.getToken(swapTo);

// [amount transferred out of converter, amount transferred in]
const { result: updatedAmountIn } = await this.publicClient.simulateContract({
address: tokenConverter,
abi: tokenConverterAbi,
functionName: "getUpdatedAmountIn",
args: [amount, swapTo, swapFrom],
});

const provider = new ethers.providers.JsonRpcProvider(config.rpcUrl);
const router = new AlphaRouter({
chainId: config.network.id as ChainId,
Expand All @@ -84,7 +93,7 @@ class UniswapProvider extends SwapProvider {
let trade;
try {
const response = await router.route(
CurrencyAmount.fromRawAmount(swapToToken, JSBI.BigInt(amount.toString())),
CurrencyAmount.fromRawAmount(swapToToken, JSBI.BigInt(updatedAmountIn[1].toString())),
swapFromToken,
TradeType.EXACT_OUTPUT,
options,
Expand Down Expand Up @@ -125,7 +134,7 @@ class UniswapProvider extends SwapProvider {
throw new Error("No trade found");
}

return trade;
return [trade, amount];
}

/**
Expand Down

0 comments on commit 79ddbc9

Please sign in to comment.