From 6c908b545fd96579ce09616289bb32d6187e6a8c Mon Sep 17 00:00:00 2001 From: liu Date: Tue, 28 Jun 2022 11:11:58 +0800 Subject: [PATCH 01/20] Fix token decimals for usdc, usdt --- .gitignore | 2 ++ src/common/tokens/usdc.ts | 2 +- src/common/tokens/usdt.ts | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 6704566..91d083a 100644 --- a/.gitignore +++ b/.gitignore @@ -102,3 +102,5 @@ dist # TernJS port file .tern-port + +.prettierignore \ No newline at end of file diff --git a/src/common/tokens/usdc.ts b/src/common/tokens/usdc.ts index 5e525d7..bb67389 100644 --- a/src/common/tokens/usdc.ts +++ b/src/common/tokens/usdc.ts @@ -11,7 +11,7 @@ export class USDC { return { chainId: ChainId.MAINNET, contractAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', - decimals: 18, + decimals: 6, symbol: 'USDC', name: 'USD Coin', }; diff --git a/src/common/tokens/usdt.ts b/src/common/tokens/usdt.ts index dce2695..56a46b3 100644 --- a/src/common/tokens/usdt.ts +++ b/src/common/tokens/usdt.ts @@ -11,7 +11,7 @@ export class USDT { return { chainId: ChainId.MAINNET, contractAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7', - decimals: 18, + decimals: 6, symbol: 'USDT', name: 'Tether USD', }; From fe19516de724d756ea5f36db875c27b05583e1d3 Mon Sep 17 00:00:00 2001 From: liu Date: Tue, 28 Jun 2022 11:23:46 +0800 Subject: [PATCH 02/20] add customized route abi to the settings --- .../models/clone-uniswap-contract-details.ts | 3 ++ .../v2/uniswap-router-contract.factory.v2.ts | 6 ++-- .../v3/uniswap-router-contract.factory.v3.ts | 6 ++-- .../get-uniswap-contracts.ts | 28 +++++++++++++++++++ 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/factories/pair/models/clone-uniswap-contract-details.ts b/src/factories/pair/models/clone-uniswap-contract-details.ts index 1dfb198..0915947 100644 --- a/src/factories/pair/models/clone-uniswap-contract-details.ts +++ b/src/factories/pair/models/clone-uniswap-contract-details.ts @@ -1,13 +1,16 @@ +import { JsonFragment } from '@ethersproject/abi'; export interface CloneUniswapContractDetailsV2 { routerAddress: string; factoryAddress: string; pairAddress: string; + routerAbi?: JsonFragment[]; } export interface CloneUniswapContractDetailsV3 { routerAddress: string; factoryAddress: string; quoterAddress: string; + routerAbi?: JsonFragment[]; } export interface CloneUniswapContractDetails { diff --git a/src/factories/router/v2/uniswap-router-contract.factory.v2.ts b/src/factories/router/v2/uniswap-router-contract.factory.v2.ts index e55726c..b490cde 100644 --- a/src/factories/router/v2/uniswap-router-contract.factory.v2.ts +++ b/src/factories/router/v2/uniswap-router-contract.factory.v2.ts @@ -1,4 +1,5 @@ import { BigNumberish, BytesLike } from 'ethers'; +import { JsonFragment } from '@ethersproject/abi'; import { ContractContext as RouterContractContext } from '../../../ABI/types/uniswap-router-v2'; import { EthersProvider } from '../../../ethers-provider'; import { UniswapContractContextV2 } from '../../../uniswap-contract-context/uniswap-contract-context-v2'; @@ -6,13 +7,14 @@ import { UniswapContractContextV2 } from '../../../uniswap-contract-context/unis export class UniswapRouterContractFactoryV2 { private _uniswapRouterContract = this._ethersProvider.getContract( - JSON.stringify(UniswapContractContextV2.routerAbi), + JSON.stringify(this._routerAbi), this._routerAddress ); constructor( private _ethersProvider: EthersProvider, - private _routerAddress: string = UniswapContractContextV2.routerAddress + private _routerAddress: string = UniswapContractContextV2.routerAddress, + private _routerAbi: JsonFragment[] = UniswapContractContextV2.routerAbi ) {} public addLiquidity( diff --git a/src/factories/router/v3/uniswap-router-contract.factory.v3.ts b/src/factories/router/v3/uniswap-router-contract.factory.v3.ts index b7c477b..7beb6bd 100644 --- a/src/factories/router/v3/uniswap-router-contract.factory.v3.ts +++ b/src/factories/router/v3/uniswap-router-contract.factory.v3.ts @@ -1,4 +1,5 @@ import { BigNumberish, BytesLike } from 'ethers'; +import { JsonFragment } from '@ethersproject/abi'; import { ContractContext as RouterContractContext, ExactInputSingleRequest, @@ -10,13 +11,14 @@ import { UniswapContractContextV3 } from '../../../uniswap-contract-context/unis export class UniswapRouterContractFactoryV3 { private _uniswapRouterContract = this._ethersProvider.getContract( - JSON.stringify(UniswapContractContextV3.routerAbi), + JSON.stringify(this._routerAbi), this._routerAddress ); constructor( private _ethersProvider: EthersProvider, - private _routerAddress: string = UniswapContractContextV3.routerAddress + private _routerAddress: string = UniswapContractContextV3.routerAddress, + private _routerAbi: JsonFragment[] = UniswapContractContextV3.routerAbi ) {} /** diff --git a/src/uniswap-contract-context/get-uniswap-contracts.ts b/src/uniswap-contract-context/get-uniswap-contracts.ts index e6e42a9..a80bbf6 100644 --- a/src/uniswap-contract-context/get-uniswap-contracts.ts +++ b/src/uniswap-contract-context/get-uniswap-contracts.ts @@ -42,6 +42,20 @@ export const uniswapContracts = { return UniswapContractContextV2.pairAddress; }, + + getRouterAbi: ( + cloneUniswapContractDetails: CloneUniswapContractDetails | undefined + ) => { + if ( + cloneUniswapContractDetails && + cloneUniswapContractDetails.v2Override && + cloneUniswapContractDetails.v2Override.routerAbi + ) { + return cloneUniswapContractDetails.v2Override.routerAbi; + } + + return UniswapContractContextV2.routerAbi; + }, }, v3: { getRouterAddress: ( @@ -82,5 +96,19 @@ export const uniswapContracts = { return UniswapContractContextV3.quoterAddress; }, + + getRouterAbi: ( + cloneUniswapContractDetails: CloneUniswapContractDetails | undefined + ) => { + if ( + cloneUniswapContractDetails && + cloneUniswapContractDetails.v3Override && + cloneUniswapContractDetails.v3Override.routerAbi + ) { + return cloneUniswapContractDetails.v3Override.routerAbi; + } + + return UniswapContractContextV3.routerAbi; + }, }, }; From fdedbc1bbc00d6d8d2ebc9cf64d6b499ca625693 Mon Sep 17 00:00:00 2001 From: liu Date: Tue, 28 Jun 2022 11:33:55 +0800 Subject: [PATCH 03/20] add customized router methods --- .../models/clone-uniswap-contract-details.ts | 3 + src/factories/router/models/route-methods.ts | 62 +++++++++++++++++ .../v2/uniswap-router-contract.factory.v2.ts | 67 ++++++++++++------- .../get-uniswap-contracts.ts | 14 ++++ .../uniswap-contract-context-v2.ts | 9 +++ 5 files changed, 129 insertions(+), 26 deletions(-) create mode 100644 src/factories/router/models/route-methods.ts diff --git a/src/factories/pair/models/clone-uniswap-contract-details.ts b/src/factories/pair/models/clone-uniswap-contract-details.ts index 0915947..1bf0412 100644 --- a/src/factories/pair/models/clone-uniswap-contract-details.ts +++ b/src/factories/pair/models/clone-uniswap-contract-details.ts @@ -1,9 +1,12 @@ import { JsonFragment } from '@ethersproject/abi'; +import { IRouterMethods } from '../../router/models/route-methods'; + export interface CloneUniswapContractDetailsV2 { routerAddress: string; factoryAddress: string; pairAddress: string; routerAbi?: JsonFragment[]; + routerMethods?: Partial; } export interface CloneUniswapContractDetailsV3 { diff --git a/src/factories/router/models/route-methods.ts b/src/factories/router/models/route-methods.ts new file mode 100644 index 0000000..2f2261d --- /dev/null +++ b/src/factories/router/models/route-methods.ts @@ -0,0 +1,62 @@ + +export type IRouterMethodName = +| 'WETH' +| 'addLiquidity' +| 'addLiquidityETH' +| 'factory' +| 'getAmountIn' +| 'getAmountOut' +| 'getAmountsIn' +| 'getAmountsOut' +| 'quote' +| 'removeLiquidity' +| 'removeLiquidityETH' +| 'removeLiquidityETHSupportingFeeOnTransferTokens' +| 'removeLiquidityETHWithPermit' +| 'removeLiquidityETHWithPermitSupportingFeeOnTransferTokens' +| 'removeLiquidityWithPermit' +| 'swapETHForExactTokens' +| 'swapExactETHForTokens' +| 'swapExactETHForTokensSupportingFeeOnTransferTokens' +| 'swapExactTokensForETH' +| 'swapExactTokensForETHSupportingFeeOnTransferTokens' +| 'swapExactTokensForTokens' +| 'swapExactTokensForTokensSupportingFeeOnTransferTokens' +| 'swapTokensForExactETH' +| 'swapTokensForExactTokens'; + +export type IRouterMethods = { +[key in IRouterMethodName]: string; +}; + +export const DEFAULT_ROUTER_METHOD: IRouterMethods = { +WETH: 'WETH', +addLiquidity: 'addLiquidity', +addLiquidityETH: 'addLiquidityETH', +factory: 'factory', +getAmountIn: 'getAmountIn', +getAmountOut: 'getAmountOut', +getAmountsIn: 'getAmountsIn', +getAmountsOut: 'getAmountsOut', +quote: 'quote', +removeLiquidity: 'removeLiquidity', +removeLiquidityETH: 'removeLiquidityETH', +removeLiquidityETHSupportingFeeOnTransferTokens: + 'removeLiquidityETHSupportingFeeOnTransferTokens', +removeLiquidityETHWithPermit: 'removeLiquidityETHWithPermit', +removeLiquidityETHWithPermitSupportingFeeOnTransferTokens: + 'removeLiquidityETHWithPermitSupportingFeeOnTransferTokens', +removeLiquidityWithPermit: 'removeLiquidityWithPermit', +swapETHForExactTokens: 'swapETHForExactTokens', +swapExactETHForTokens: 'swapExactETHForTokens', +swapExactETHForTokensSupportingFeeOnTransferTokens: + 'swapExactETHForTokensSupportingFeeOnTransferTokens', +swapExactTokensForETH: 'swapExactTokensForETH', +swapExactTokensForETHSupportingFeeOnTransferTokens: + 'swapExactTokensForETHSupportingFeeOnTransferTokens', +swapExactTokensForTokens: 'swapExactTokensForTokens', +swapExactTokensForTokensSupportingFeeOnTransferTokens: + 'swapExactTokensForTokensSupportingFeeOnTransferTokens', +swapTokensForExactETH: 'swapTokensForExactETH', +swapTokensForExactTokens: 'swapTokensForExactTokens', +}; \ No newline at end of file diff --git a/src/factories/router/v2/uniswap-router-contract.factory.v2.ts b/src/factories/router/v2/uniswap-router-contract.factory.v2.ts index b490cde..1160a22 100644 --- a/src/factories/router/v2/uniswap-router-contract.factory.v2.ts +++ b/src/factories/router/v2/uniswap-router-contract.factory.v2.ts @@ -1,20 +1,25 @@ -import { BigNumberish, BytesLike } from 'ethers'; +import { BigNumber, BigNumberish, BytesLike, Contract } from 'ethers'; import { JsonFragment } from '@ethersproject/abi'; -import { ContractContext as RouterContractContext } from '../../../ABI/types/uniswap-router-v2'; import { EthersProvider } from '../../../ethers-provider'; import { UniswapContractContextV2 } from '../../../uniswap-contract-context/uniswap-contract-context-v2'; +import { DEFAULT_ROUTER_METHOD, IRouterMethods } from '../models/route-methods'; export class UniswapRouterContractFactoryV2 { - private _uniswapRouterContract = - this._ethersProvider.getContract( - JSON.stringify(this._routerAbi), - this._routerAddress - ); + private _uniswapRouterContract = this._ethersProvider.getContract( + JSON.stringify(this._routerAbi), + this._routerAddress + ); + + private _uniswapRouterNames: IRouterMethods = { + ...DEFAULT_ROUTER_METHOD, + ...this._routerMethods, + }; constructor( private _ethersProvider: EthersProvider, private _routerAddress: string = UniswapContractContextV2.routerAddress, - private _routerAbi: JsonFragment[] = UniswapContractContextV2.routerAbi + private _routerAbi: JsonFragment[] = UniswapContractContextV2.routerAbi, + private _routerMethods: Partial = DEFAULT_ROUTER_METHOD ) {} public addLiquidity( @@ -28,7 +33,7 @@ export class UniswapRouterContractFactoryV2 { deadline: BigNumberish ): string { return this._uniswapRouterContract.interface.encodeFunctionData( - 'addLiquidity', + this._uniswapRouterNames['addLiquidity'], [ tokenA, tokenB, @@ -51,7 +56,7 @@ export class UniswapRouterContractFactoryV2 { deadline: BigNumberish ): string { return this._uniswapRouterContract.interface.encodeFunctionData( - 'addLiquidityETH', + this._uniswapRouterNames['addLiquidityETH'], [token, amountTokenDesired, amountTokenMin, amountETHMin, to, deadline] ); } @@ -68,7 +73,7 @@ export class UniswapRouterContractFactoryV2 { amountIn, path ); - return amounts.map((c) => c.toHexString()); + return amounts.map((c: BigNumber) => c.toHexString()); } public async quote( @@ -91,7 +96,7 @@ export class UniswapRouterContractFactoryV2 { deadline: BigNumberish ): string { return this._uniswapRouterContract.interface.encodeFunctionData( - 'removeLiquidity', + this._uniswapRouterNames['removeLiquidity'], [tokenA, tokenB, liquidity, amountAMin, amountBMin, to, deadline] ); } @@ -105,7 +110,7 @@ export class UniswapRouterContractFactoryV2 { deadline: BigNumberish ): string { return this._uniswapRouterContract.interface.encodeFunctionData( - 'removeLiquidity', + this._uniswapRouterNames['removeLiquidity'], [token, liquidity, amountTokenMin, amountETHMin, to, deadline] ); } @@ -119,7 +124,9 @@ export class UniswapRouterContractFactoryV2 { deadline: BigNumberish ): string { return this._uniswapRouterContract.interface.encodeFunctionData( - 'removeLiquidityETHSupportingFeeOnTransferTokens', + this._uniswapRouterNames[ + 'removeLiquidityETHSupportingFeeOnTransferTokens' + ], [token, liquidity, amountTokenMin, amountETHMin, to, deadline] ); } @@ -137,7 +144,7 @@ export class UniswapRouterContractFactoryV2 { s: BytesLike ): string { return this._uniswapRouterContract.interface.encodeFunctionData( - 'removeLiquidityETHWithPermit', + this._uniswapRouterNames['removeLiquidityETHWithPermit'], [ token, liquidity, @@ -166,7 +173,9 @@ export class UniswapRouterContractFactoryV2 { s: BytesLike ): string { return this._uniswapRouterContract.interface.encodeFunctionData( - 'removeLiquidityETHWithPermitSupportingFeeOnTransferTokens', + this._uniswapRouterNames[ + 'removeLiquidityETHWithPermitSupportingFeeOnTransferTokens' + ], [ token, liquidity, @@ -196,7 +205,7 @@ export class UniswapRouterContractFactoryV2 { s: BytesLike ): string { return this._uniswapRouterContract.interface.encodeFunctionData( - 'removeLiquidityWithPermit', + this._uniswapRouterNames['removeLiquidityWithPermit'], [ tokenA, tokenB, @@ -220,7 +229,7 @@ export class UniswapRouterContractFactoryV2 { deadline: BigNumberish ): string { return this._uniswapRouterContract.interface.encodeFunctionData( - 'swapExactETHForTokens', + this._uniswapRouterNames['swapExactETHForTokens'], [amountOutMin, path, to, deadline] ); } @@ -232,7 +241,7 @@ export class UniswapRouterContractFactoryV2 { deadline: BigNumberish ): string { return this._uniswapRouterContract.interface.encodeFunctionData( - 'swapETHForExactTokens', + this._uniswapRouterNames['swapETHForExactTokens'], [amountOut, path, to, deadline] ); } @@ -245,7 +254,9 @@ export class UniswapRouterContractFactoryV2 { deadline: BigNumberish ): string { return this._uniswapRouterContract.interface.encodeFunctionData( - 'swapExactETHForTokensSupportingFeeOnTransferTokens', + this._uniswapRouterNames[ + 'swapExactETHForTokensSupportingFeeOnTransferTokens' + ], [amountIn, amountOutMin, path, to, deadline] ); } @@ -258,7 +269,7 @@ export class UniswapRouterContractFactoryV2 { deadline: BigNumberish ): string { return this._uniswapRouterContract.interface.encodeFunctionData( - 'swapExactTokensForETH', + this._uniswapRouterNames['swapExactTokensForETH'], [amountIn, amountOutMin, path, to, deadline] ); } @@ -271,7 +282,7 @@ export class UniswapRouterContractFactoryV2 { deadline: BigNumberish ): string { return this._uniswapRouterContract.interface.encodeFunctionData( - 'swapTokensForExactETH', + this._uniswapRouterNames['swapTokensForExactETH'], [amountOut, amountInMax, path, to, deadline] ); } @@ -284,7 +295,9 @@ export class UniswapRouterContractFactoryV2 { deadline: BigNumberish ): string { return this._uniswapRouterContract.interface.encodeFunctionData( - 'swapExactTokensForETHSupportingFeeOnTransferTokens', + this._uniswapRouterNames[ + 'swapExactTokensForETHSupportingFeeOnTransferTokens' + ], [amountIn, amountOutMin, path, to, deadline] ); } @@ -297,7 +310,7 @@ export class UniswapRouterContractFactoryV2 { deadline: BigNumberish ): string { return this._uniswapRouterContract.interface.encodeFunctionData( - 'swapExactTokensForTokens', + this._uniswapRouterNames['swapExactTokensForTokens'], [amountIn, amountOutMin, path, to, deadline] ); } @@ -310,7 +323,7 @@ export class UniswapRouterContractFactoryV2 { deadline: BigNumberish ): string { return this._uniswapRouterContract.interface.encodeFunctionData( - 'swapTokensForExactTokens', + this._uniswapRouterNames['swapTokensForExactTokens'], [amountOut, amountInMax, path, to, deadline] ); } @@ -323,7 +336,9 @@ export class UniswapRouterContractFactoryV2 { deadline: BigNumberish ): string { return this._uniswapRouterContract.interface.encodeFunctionData( - 'swapExactTokensForTokensSupportingFeeOnTransferTokens', + this._uniswapRouterNames[ + 'swapExactTokensForTokensSupportingFeeOnTransferTokens' + ], [amountIn, amountOutMin, path, to, deadline] ); } diff --git a/src/uniswap-contract-context/get-uniswap-contracts.ts b/src/uniswap-contract-context/get-uniswap-contracts.ts index a80bbf6..1e7b129 100644 --- a/src/uniswap-contract-context/get-uniswap-contracts.ts +++ b/src/uniswap-contract-context/get-uniswap-contracts.ts @@ -56,6 +56,20 @@ export const uniswapContracts = { return UniswapContractContextV2.routerAbi; }, + + getRouterMethods: ( + cloneUniswapContractDetails: CloneUniswapContractDetails | undefined + ) => { + if ( + cloneUniswapContractDetails && + cloneUniswapContractDetails.v2Override && + cloneUniswapContractDetails.v2Override.routerMethods + ) { + return cloneUniswapContractDetails.v2Override.routerMethods; + } + + return UniswapContractContextV2.routerMethods; + }, }, v3: { getRouterAddress: ( diff --git a/src/uniswap-contract-context/uniswap-contract-context-v2.ts b/src/uniswap-contract-context/uniswap-contract-context-v2.ts index 43c2d9d..0f286b6 100644 --- a/src/uniswap-contract-context/uniswap-contract-context-v2.ts +++ b/src/uniswap-contract-context/uniswap-contract-context-v2.ts @@ -1,4 +1,8 @@ import { JsonFragment } from '@ethersproject/abi'; +import { + DEFAULT_ROUTER_METHOD, + IRouterMethods, +} from "../factories/router/models/route-methods"; export class UniswapContractContextV2 { /** @@ -30,4 +34,9 @@ export class UniswapContractContextV2 { * Uniswap v2 pair */ public static pairAbi: JsonFragment[] = require('../ABI/uniswap-pair-v2.json'); + + /** + * Router Methods + */ + public static routerMethods: IRouterMethods = DEFAULT_ROUTER_METHOD; } From 4df4ffe74f10b2fe2a888da106f839edbb44a0f8 Mon Sep 17 00:00:00 2001 From: liu Date: Wed, 29 Jun 2022 10:51:00 +0800 Subject: [PATCH 04/20] add isSameAddress utils func --- src/common/utils/is-same-address.spec.ts | 20 ++++++++++++++++++++ src/common/utils/is-same-address.ts | 10 ++++++++++ 2 files changed, 30 insertions(+) create mode 100644 src/common/utils/is-same-address.spec.ts create mode 100644 src/common/utils/is-same-address.ts diff --git a/src/common/utils/is-same-address.spec.ts b/src/common/utils/is-same-address.spec.ts new file mode 100644 index 0000000..79441f4 --- /dev/null +++ b/src/common/utils/is-same-address.spec.ts @@ -0,0 +1,20 @@ +import { ETH } from '../tokens'; +import { isSameAddress } from './is-same-address'; + +describe('isSameAddress', () => { + it('should return true if its a valid ethereum address type', () => { + expect(isSameAddress('0x45Cd08334aeedd8a06265B2Ae302E3597d8fAA28', '0x45cd08334aeedd8a06265b2ae302e3597d8faa28')).toEqual( + true + ); + }); + + it('should return false when one of them is a invalid address', () => { + expect(isSameAddress('0xC1912fEE45d61C87Cc5EA59DaE31190FFFFf232d', '0xaaaaa')).toEqual( + false + ); + }); + + it('should return false when both of them are invalid address', () => { + expect(isSameAddress('0x0', '0x1')).toEqual(false); + }); +}); diff --git a/src/common/utils/is-same-address.ts b/src/common/utils/is-same-address.ts new file mode 100644 index 0000000..718678c --- /dev/null +++ b/src/common/utils/is-same-address.ts @@ -0,0 +1,10 @@ +import { ethers } from "ethers"; +import { removeEthFromContractAddress } from "../tokens/eth"; + +export function isSameAddress(address1: string, address2: string): boolean { + return ( + ethers.utils.isAddress(removeEthFromContractAddress(address1)) && + ethers.utils.isAddress(removeEthFromContractAddress(address2)) && + address1.toLowerCase() === address2.toLowerCase() + ); +} \ No newline at end of file From 0a0cb0be688d574c7617731ac695f72f7e091641 Mon Sep 17 00:00:00 2001 From: liu Date: Wed, 29 Jun 2022 10:54:13 +0800 Subject: [PATCH 05/20] update FUN token totalSupply --- src/factories/token/token.factory.public.spec.ts | 2 +- src/factories/token/token.factory.spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/factories/token/token.factory.public.spec.ts b/src/factories/token/token.factory.public.spec.ts index f20ca26..3b83f2e 100644 --- a/src/factories/token/token.factory.public.spec.ts +++ b/src/factories/token/token.factory.public.spec.ts @@ -168,7 +168,7 @@ describe('TokenFactoryPublic', () => { describe('erc20', () => { it('totalSupply', async () => { const result = await tokenFactory.totalSupply(); - expect(result).toEqual('0x0f4229ebe353e7b6'); + expect(result).toEqual('0x0f3be988963624b6'); }); }); diff --git a/src/factories/token/token.factory.spec.ts b/src/factories/token/token.factory.spec.ts index bb06706..188720a 100644 --- a/src/factories/token/token.factory.spec.ts +++ b/src/factories/token/token.factory.spec.ts @@ -164,7 +164,7 @@ describe('TokenFactory', () => { describe('erc20', () => { it('totalSupply', async () => { const result = await tokenFactory.totalSupply(); - expect(result).toEqual('0x0f4229ebe353e7b6'); + expect(result).toEqual('0x0f3be988963624b6'); }); }); From 699125d655e088ac1d46a3ca0cbd75f4c509315f Mon Sep 17 00:00:00 2001 From: liu Date: Wed, 29 Jun 2022 11:01:02 +0800 Subject: [PATCH 06/20] update models for uniswap v3 --- src/factories/pair/models/current-trade-context.ts | 2 +- src/factories/pair/models/trade-context.ts | 4 ++-- src/factories/router/models/route-context.ts | 2 +- src/factories/router/models/route-quote-trade-context.ts | 2 +- src/factories/router/models/route-quote.ts | 2 +- src/factories/router/models/token-routes.ts | 6 +++--- src/factories/token/models/token.ts | 6 ++++++ 7 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/factories/pair/models/current-trade-context.ts b/src/factories/pair/models/current-trade-context.ts index 815a66c..1a546a0 100644 --- a/src/factories/pair/models/current-trade-context.ts +++ b/src/factories/pair/models/current-trade-context.ts @@ -8,7 +8,7 @@ export interface CurrentTradeContext { quoteDirection: TradeDirection; fromToken: Token; toToken: Token; - liquidityProviderFee: string; + liquidityProviderFee: string[]; transaction: Transaction; routeText: string; tradeExpires: number; diff --git a/src/factories/pair/models/trade-context.ts b/src/factories/pair/models/trade-context.ts index cb48b72..3fb733e 100644 --- a/src/factories/pair/models/trade-context.ts +++ b/src/factories/pair/models/trade-context.ts @@ -12,8 +12,8 @@ export interface TradeContext { minAmountConvertQuote: string | null; maximumSent: string | null; expectedConvertQuote: string; - liquidityProviderFee: string; - liquidityProviderFeePercent: number; + liquidityProviderFee: string[]; + liquidityProviderFeePercent: number[]; tradeExpires: number; routePathTokenMap: Token[]; routeText: string; diff --git a/src/factories/router/models/route-context.ts b/src/factories/router/models/route-context.ts index e5d73fa..b57fb49 100644 --- a/src/factories/router/models/route-context.ts +++ b/src/factories/router/models/route-context.ts @@ -2,5 +2,5 @@ import { Token } from '../../token/models/token'; export interface RouteContext { route: Token[]; - liquidityProviderFee: number; + liquidityProviderFee: number[]; } diff --git a/src/factories/router/models/route-quote-trade-context.ts b/src/factories/router/models/route-quote-trade-context.ts index f5c921b..8f3a5d5 100644 --- a/src/factories/router/models/route-quote-trade-context.ts +++ b/src/factories/router/models/route-quote-trade-context.ts @@ -3,5 +3,5 @@ import { UniswapVersion } from '../../../enums/uniswap-version'; export interface RouteQuoteTradeContext { uniswapVersion: UniswapVersion; routePathArray: string[]; - liquidityProviderFee: number; + liquidityProviderFee: number[]; } diff --git a/src/factories/router/models/route-quote.ts b/src/factories/router/models/route-quote.ts index a0ca140..7ca1ecc 100644 --- a/src/factories/router/models/route-quote.ts +++ b/src/factories/router/models/route-quote.ts @@ -12,7 +12,7 @@ export interface RouteQuote { routeText: string; routePathArray: string[]; uniswapVersion: UniswapVersion; - liquidityProviderFee: number; + liquidityProviderFee: number[]; quoteDirection: TradeDirection; gasPriceEstimatedBy?: string | undefined; } diff --git a/src/factories/router/models/token-routes.ts b/src/factories/router/models/token-routes.ts index e84787c..3c2a397 100644 --- a/src/factories/router/models/token-routes.ts +++ b/src/factories/router/models/token-routes.ts @@ -1,9 +1,9 @@ -import { Token } from '../../token/models/token'; +import { Pool, Token } from "../../token/models/token"; export interface TokenRoutes { token: Token; pairs: { - fromTokenPairs?: Token[] | undefined; - toTokenPairs?: Token[] | undefined; + fromTokenPairs?: Pool[] | undefined; + toTokenPairs?: Pool[] | undefined; }; } diff --git a/src/factories/token/models/token.ts b/src/factories/token/models/token.ts index 2f4d4bd..f39f1c4 100644 --- a/src/factories/token/models/token.ts +++ b/src/factories/token/models/token.ts @@ -1,4 +1,5 @@ import { ChainId } from '../../../enums/chain-id'; +import { FeeAmount } from '../../router/v3/enums/fee-amount-v3'; export interface Token { chainId: ChainId; @@ -7,3 +8,8 @@ export interface Token { symbol: string; name: string; } + +export interface Pool { + token: Token; + fee?: FeeAmount | undefined; +} From 6097a0f91cbf09aeee945ce4f5f876ca5aa8138d Mon Sep 17 00:00:00 2001 From: liu Date: Wed, 29 Jun 2022 22:01:23 +0800 Subject: [PATCH 07/20] uniswap v3 quote works --- src/factories/pair/uniswap-pair.factory.ts | 35 +- .../router/uniswap-router.factory.ts | 726 +++++++++++++----- .../v3/uniswap-router-contract.factory.v3.ts | 24 + 3 files changed, 585 insertions(+), 200 deletions(-) diff --git a/src/factories/pair/uniswap-pair.factory.ts b/src/factories/pair/uniswap-pair.factory.ts index ab8f32e..454f2f5 100644 --- a/src/factories/pair/uniswap-pair.factory.ts +++ b/src/factories/pair/uniswap-pair.factory.ts @@ -333,14 +333,13 @@ export class UniswapPairFactory { ? null : bestRouteQuote.expectedConvertQuoteOrTokenAmountInMaxWithSlippage, expectedConvertQuote: bestRouteQuote.expectedConvertQuote, - liquidityProviderFee: + liquidityProviderFee: bestRouteQuote.liquidityProviderFee.map((f) => direction === TradeDirection.input - ? baseConvertRequest - .times(bestRouteQuote.liquidityProviderFee) - .toFixed(this.fromToken.decimals) + ? baseConvertRequest.times(f).toFixed(this.fromToken.decimals) : new BigNumber(bestRouteQuote.expectedConvertQuote) - .times(bestRouteQuote.liquidityProviderFee) - .toFixed(this.fromToken.decimals), + .times(f) + .toFixed(this.fromToken.decimals) + ), liquidityProviderFeePercent: bestRouteQuote.liquidityProviderFee, tradeExpires: bestRouteQuote.tradeExpires, routePathTokenMap: bestRouteQuote.routePathArrayTokenMap, @@ -404,14 +403,13 @@ export class UniswapPairFactory { ? null : bestRouteQuote.expectedConvertQuoteOrTokenAmountInMaxWithSlippage, expectedConvertQuote: bestRouteQuote.expectedConvertQuote, - liquidityProviderFee: + liquidityProviderFee: bestRouteQuote.liquidityProviderFee.map((f) => direction === TradeDirection.input - ? baseConvertRequest - .times(bestRouteQuote.liquidityProviderFee) - .toFixed(this.fromToken.decimals) + ? baseConvertRequest.times(f).toFixed(this.fromToken.decimals) : new BigNumber(bestRouteQuote.expectedConvertQuote) - .times(bestRouteQuote.liquidityProviderFee) - .toFixed(this.fromToken.decimals), + .times(f) + .toFixed(this.fromToken.decimals) + ), liquidityProviderFeePercent: bestRouteQuote.liquidityProviderFee, tradeExpires: bestRouteQuote.tradeExpires, routePathTokenMap: bestRouteQuote.routePathArrayTokenMap, @@ -470,14 +468,13 @@ export class UniswapPairFactory { ? null : bestRouteQuote.expectedConvertQuoteOrTokenAmountInMaxWithSlippage, expectedConvertQuote: bestRouteQuote.expectedConvertQuote, - liquidityProviderFee: + liquidityProviderFee: bestRouteQuote.liquidityProviderFee.map((f) => direction === TradeDirection.input - ? baseConvertRequest - .times(bestRouteQuote.liquidityProviderFee) - .toFixed(this.fromToken.decimals) + ? baseConvertRequest.times(f).toFixed(this.fromToken.decimals) : new BigNumber(bestRouteQuote.expectedConvertQuote) - .times(bestRouteQuote.liquidityProviderFee) - .toFixed(this.fromToken.decimals), + .times(f) + .toFixed(this.fromToken.decimals) + ), liquidityProviderFeePercent: bestRouteQuote.liquidityProviderFee, tradeExpires: bestRouteQuote.tradeExpires, routePathTokenMap: bestRouteQuote.routePathArrayTokenMap, @@ -580,4 +577,4 @@ export class UniswapPairFactory { } } } -} +} \ No newline at end of file diff --git a/src/factories/router/uniswap-router.factory.ts b/src/factories/router/uniswap-router.factory.ts index c4ffbb7..9df909f 100644 --- a/src/factories/router/uniswap-router.factory.ts +++ b/src/factories/router/uniswap-router.factory.ts @@ -5,7 +5,9 @@ import { ContractCallResults, } from 'ethereum-multicall'; import { + ExactInputRequest, ExactInputSingleRequest, + ExactOutputRequest, ExactOutputSingleRequest, } from '../../ABI/types/uniswap-router-v3'; import { CoinGecko } from '../../coin-gecko'; @@ -27,6 +29,7 @@ import { WETHContract } from '../../common/tokens/weth'; import { deepClone } from '../../common/utils/deep-clone'; import { formatEther } from '../../common/utils/format-ether'; import { hexlify } from '../../common/utils/hexlify'; +import { isSameAddress } from '../../common/utils/is-same-address'; import { onlyUnique } from '../../common/utils/only-unique'; import { parseEther } from '../../common/utils/parse-ether'; import { toEthersBigNumber } from '../../common/utils/to-ethers-big-number'; @@ -43,7 +46,7 @@ import { TradeDirection } from '../pair/models/trade-direction'; import { Transaction } from '../pair/models/transaction'; import { UniswapPairSettings } from '../pair/models/uniswap-pair-settings'; import { AllowanceAndBalanceOf } from '../token/models/allowance-balance-of'; -import { Token } from '../token/models/token'; +import { Pool, Token } from '../token/models/token'; import { TokensFactory } from '../token/tokens.factory'; import { RouterDirection } from './enums/router-direction'; import { AllPossibleRoutes } from './models/all-possible-routes'; @@ -70,14 +73,16 @@ export class UniswapRouterFactory { this._ethersProvider, uniswapContracts.v2.getRouterAddress( this._settings.cloneUniswapContractDetails - ) + ), + uniswapContracts.v2.getRouterAbi(this._settings.cloneUniswapContractDetails) ); private _uniswapRouterContractFactoryV3 = new UniswapRouterContractFactoryV3( this._ethersProvider, uniswapContracts.v3.getRouterAddress( this._settings.cloneUniswapContractDetails - ) + ), + uniswapContracts.v3.getRouterAbi(this._settings.cloneUniswapContractDetails) ); private _tokensFactory = new TokensFactory( @@ -121,7 +126,7 @@ export class UniswapRouterFactory { findPairs = [[[this._fromToken, this._toToken]]]; } - // console.log(JSON.stringify(findPairs, null, 4)); + // console.log('find Pairts', JSON.stringify(findPairs, null, 4)); const contractCallContext: ContractCallContext[] = []; @@ -143,6 +148,8 @@ export class UniswapRouterFactory { ) { const fromToken = findPairs[pairs][tokenPairs][0]; const toToken = findPairs[pairs][tokenPairs][1]; + if (isSameAddress(fromToken.contractAddress, toToken.contractAddress)) + continue; contractCallContext[0].calls.push({ reference: `${fromToken.contractAddress}-${toToken.contractAddress}-${fromToken.symbol}/${toToken.symbol}`, @@ -158,41 +165,43 @@ export class UniswapRouterFactory { // for now v3 quotes will just be direct aka UNI > AAVE etc! if (this._settings.uniswapVersions.includes(UniswapVersion.v3)) { + let v3Calls = []; + for (let pairs = 0; pairs < findPairs.length; pairs++) { + for ( + let tokenPairs = 0; + tokenPairs < findPairs[pairs].length; + tokenPairs++ + ) { + const fromToken = findPairs[pairs][tokenPairs][0]; + const toToken = findPairs[pairs][tokenPairs][1]; + + if (isSameAddress(fromToken.contractAddress, toToken.contractAddress)) + continue; + + for (let fee = 0; fee < 3; fee++) { + const feeAmount = [FeeAmount.LOW, FeeAmount.MEDIUM, FeeAmount.HIGH][ + fee + ]; + v3Calls.push({ + reference: `${fromToken.contractAddress}-${toToken.contractAddress}-${fromToken.symbol}/${toToken.symbol}-${feeAmount}`, + methodName: 'getPool', + methodParameters: [ + removeEthFromContractAddress(fromToken.contractAddress), + removeEthFromContractAddress(toToken.contractAddress), + feeAmount, + ], + }); + } + } + } + contractCallContext.push({ reference: UniswapVersion.v3, contractAddress: uniswapContracts.v3.getFactoryAddress( this._settings.cloneUniswapContractDetails ), abi: UniswapContractContextV3.factoryAbi, - calls: [ - { - reference: `${this._fromToken.contractAddress}-${this._toToken.contractAddress}-${this._fromToken.symbol}/${this._toToken.symbol}`, - methodName: 'getPool', - methodParameters: [ - removeEthFromContractAddress(this._fromToken.contractAddress), - removeEthFromContractAddress(this._toToken.contractAddress), - FeeAmount.LOW, - ], - }, - { - reference: `${this._fromToken.contractAddress}-${this._toToken.contractAddress}-${this._fromToken.symbol}/${this._toToken.symbol}`, - methodName: 'getPool', - methodParameters: [ - removeEthFromContractAddress(this._fromToken.contractAddress), - removeEthFromContractAddress(this._toToken.contractAddress), - FeeAmount.MEDIUM, - ], - }, - { - reference: `${this._fromToken.contractAddress}-${this._toToken.contractAddress}-${this._fromToken.symbol}/${this._toToken.symbol}`, - methodName: 'getPool', - methodParameters: [ - removeEthFromContractAddress(this._fromToken.contractAddress), - removeEthFromContractAddress(this._toToken.contractAddress), - FeeAmount.HIGH, - ], - }, - ], + calls: v3Calls, }); } @@ -208,8 +217,6 @@ export class UniswapRouterFactory { c.returnValues[0] !== '0x0000000000000000000000000000000000000000' ); - // console.log(JSON.stringify(results.callsReturnContext, null, 4)); - const fromTokenRoutes: TokenRoutes = { token: this._fromToken, pairs: { @@ -258,6 +265,7 @@ export class UniswapRouterFactory { }); } + // console.log('allMainRoutes'); // console.log(JSON.stringify(allMainRoutes, null, 4)); allPossibleRoutes.v2 = this.workOutAllPossibleRoutes( @@ -270,30 +278,70 @@ export class UniswapRouterFactory { if (this._settings.uniswapVersions.includes(UniswapVersion.v3)) { const results = contractCallResults.results[UniswapVersion.v3]; - for (let i = 0; i < results.callsReturnContext.length; i++) { - if ( - results.callsReturnContext[i].returnValues[0] !== - '0x0000000000000000000000000000000000000000' - ) { - let liquidityProviderFee!: FeeAmount; - switch (i) { - case 0: - liquidityProviderFee = FeeAmount.LOW; - break; - case 1: - liquidityProviderFee = FeeAmount.MEDIUM; - break; - case 2: - liquidityProviderFee = FeeAmount.HIGH; - break; - } + const availablePairs = results.callsReturnContext.filter( + (c) => + c.returnValues[0] !== '0x0000000000000000000000000000000000000000' + ); + // console.log('available pairs', availablePairs); - allPossibleRoutes.v3.push({ - route: [this._fromToken, this._toToken], - liquidityProviderFee: feeToPercent(liquidityProviderFee), - }); - } + const fromTokenRoutes: TokenRoutes = { + token: this._fromToken, + pairs: { + fromTokenPairs: this.getTokenAvailablePairsV3( + this._fromToken, + availablePairs, + RouterDirection.from + ), + }, + }; + + const toTokenRoutes: TokenRoutes = { + token: this._toToken, + pairs: { + toTokenPairs: this.getTokenAvailablePairsV3( + this._toToken, + availablePairs, + RouterDirection.to + ), + }, + }; + + // console.log('fromTokenRoutes'); + // console.log(JSON.stringify(fromTokenRoutes, null, 4)); + // console.log('break'); + // console.log('toTokenRoutes'); + // console.log(JSON.stringify(toTokenRoutes, null, 4)); + // console.log('break'); + + const allMainRoutes: TokenRoutes[] = []; + + for (let i = 0; i < this.allMainTokens.length; i++) { + const fromTokenPairs = this.getTokenAvailablePairsV3( + this.allMainTokens[i], + availablePairs, + RouterDirection.from + ); + + const toTokenPairs = this.getTokenAvailablePairsV3( + this.allMainTokens[i], + availablePairs, + RouterDirection.to + ); + + allMainRoutes.push({ + token: this.allMainTokens[i], + pairs: { fromTokenPairs, toTokenPairs }, + }); } + + // console.log('allMainRoutes'); + // console.log(JSON.stringify(allMainRoutes, null, 4)); + + allPossibleRoutes.v3 = this.workOutAllPossibleRoutesV3( + fromTokenRoutes, + toTokenRoutes, + allMainRoutes + ); } // console.log(JSON.stringify(allPossibleRoutes, null, 4)); @@ -321,7 +369,9 @@ export class UniswapRouterFactory { contractAddress: uniswapContracts.v2.getRouterAddress( this._settings.cloneUniswapContractDetails ), - abi: UniswapContractContextV2.routerAbi, + abi: uniswapContracts.v2.getRouterAbi( + this._settings.cloneUniswapContractDetails + ), calls: [], context: routes.v2, }); @@ -358,25 +408,49 @@ export class UniswapRouterFactory { return removeEthFromContractAddress(c.contractAddress); }); - contractCallContext[ - this._settings.uniswapVersions.includes(UniswapVersion.v2) ? 1 : 0 - ].calls.push({ - reference: `route${i}`, - methodName: - direction === TradeDirection.input - ? 'quoteExactInputSingle' - : 'quoteExactOutputSingle', - methodParameters: [ - routeCombo[0], - routeCombo[1], - percentToFeeAmount(routes.v3[i].liquidityProviderFee), - tradeAmount, - 0, - ], - }); + if (routeCombo.length == 2) { + contractCallContext[ + this._settings.uniswapVersions.includes(UniswapVersion.v2) ? 1 : 0 + ].calls.push({ + reference: `route${i}`, + methodName: + direction === TradeDirection.input + ? 'quoteExactInputSingle' + : 'quoteExactOutputSingle', + methodParameters: [ + routeCombo[0], + routeCombo[1], + percentToFeeAmount(routes.v3[i].liquidityProviderFee[0]), + tradeAmount, + 0, + ], + }); + } else if (routeCombo.length > 2) { + contractCallContext[ + this._settings.uniswapVersions.includes(UniswapVersion.v2) ? 1 : 0 + ].calls.push({ + reference: `route${i}`, + methodName: + direction === TradeDirection.input + ? 'quoteExactInput' + : 'quoteExactOutput', + methodParameters: [ + this.getEncodedPoolsPath( + routeCombo, + routes.v3[i].liquidityProviderFee, + direction + ), + tradeAmount, + ], + }); + } else { + continue; + } } } + // console.log('contractCallContext', contractCallContext); + const contractCallResults = await this._multicall.call(contractCallContext); return this.buildRouteQuotesFromResults( @@ -505,7 +579,7 @@ export class UniswapRouterFactory { return this.generateTradeDataForV3Input( parseEther(ethAmountIn), convertedMinTokens, - routeQuoteTradeContext.liquidityProviderFee, + routeQuoteTradeContext, deadline ); default: @@ -547,7 +621,7 @@ export class UniswapRouterFactory { return this.generateTradeDataForV3Output( amountOut, parseEther(ethAmountInMax), - routeQuoteTradeContext.liquidityProviderFee, + routeQuoteTradeContext, deadline ); default: @@ -591,7 +665,7 @@ export class UniswapRouterFactory { return this.generateTradeDataForV3Input( amountIn, parseEther(ethAmountOutMin), - routeQuoteTradeContext.liquidityProviderFee, + routeQuoteTradeContext, deadline ); default: @@ -635,7 +709,7 @@ export class UniswapRouterFactory { return this.generateTradeDataForV3Output( parseEther(ethAmountOut), amountInMax, - routeQuoteTradeContext.liquidityProviderFee, + routeQuoteTradeContext, deadline ); default: @@ -680,7 +754,7 @@ export class UniswapRouterFactory { return this.generateTradeDataForV3Input( amountIn, amountMin, - routeQuoteTradeContext.liquidityProviderFee, + routeQuoteTradeContext, deadline ); default: @@ -726,7 +800,7 @@ export class UniswapRouterFactory { return this.generateTradeDataForV3Output( amountOut, amountInMax, - routeQuoteTradeContext.liquidityProviderFee, + routeQuoteTradeContext, deadline ); default: @@ -740,38 +814,61 @@ export class UniswapRouterFactory { /** * Generate trade data for v3 * @param tokenAmount The token amount - * @param tokenAmountOut The min token amount out - * @param liquidityProviderFee The liquidity provider fee + * @param tokenAmountMin The min token amount out + * @param routeQuoteTradeContext The route quote trade context * @param deadline The deadline it expiries unix time */ private generateTradeDataForV3Input( tokenAmount: BigNumber, tokenAmountMin: BigNumber, - liquidityProviderFee: number, + routeQuoteTradeContext: RouteQuoteTradeContext, deadline: string ): string { const isNativeReceivingNativeEth = isNativeEth( this._toToken.contractAddress ); - const params: ExactInputSingleRequest = { - tokenIn: removeEthFromContractAddress(this._fromToken.contractAddress), - tokenOut: removeEthFromContractAddress(this._toToken.contractAddress), - fee: percentToFeeAmount(liquidityProviderFee), - recipient: - isNativeReceivingNativeEth === true - ? '0x0000000000000000000000000000000000000000' - : this._ethereumAddress, - deadline, - amountIn: hexlify(tokenAmount), - amountOutMinimum: hexlify(tokenAmountMin), - sqrtPriceLimitX96: 0, - }; + const isSingle = routeQuoteTradeContext.routePathArray.length == 2; const multicallData: string[] = []; + if (isSingle) { + const params: ExactInputSingleRequest = { + tokenIn: removeEthFromContractAddress(this._fromToken.contractAddress), + tokenOut: removeEthFromContractAddress(this._toToken.contractAddress), + fee: percentToFeeAmount(routeQuoteTradeContext.liquidityProviderFee[0]), + recipient: + isNativeReceivingNativeEth === true + ? '0x0000000000000000000000000000000000000000' + : this._ethereumAddress, + deadline, + amountIn: hexlify(tokenAmount), + amountOutMinimum: hexlify(tokenAmountMin), + sqrtPriceLimitX96: 0, + }; + + multicallData.push( + this._uniswapRouterContractFactoryV3.exactInputSingle(params) + ); + } else { + const params: ExactInputRequest = { + path: this.getEncodedPoolsPath( + routeQuoteTradeContext.routePathArray, + routeQuoteTradeContext.liquidityProviderFee, + TradeDirection.input + ), + recipient: + isNativeReceivingNativeEth === true + ? '0x0000000000000000000000000000000000000000' + : this._ethereumAddress, + deadline, + amountIn: hexlify(tokenAmount), + amountOutMinimum: hexlify(tokenAmountMin), + }; + + multicallData.push( + this._uniswapRouterContractFactoryV3.exactInput(params) + ); + } - multicallData.push( - this._uniswapRouterContractFactoryV3.exactInputSingle(params) - ); if (isNativeEth(this._toToken.contractAddress)) { multicallData.push( this._uniswapRouterContractFactoryV3.unwrapWETH9( @@ -786,40 +883,62 @@ export class UniswapRouterFactory { /** * Generate trade data for v3 - * @param tokenAmountInMax The amount in max - * @param ethAmountOut The amount to receive - * @param liquidityProviderFee The liquidity provider fee + * @param amountOut The amount in max + * @param amountInMaximum The amount to receive + * @param routeQuoteTradeContext The route quote trade context * @param deadline The deadline it expiries unix time */ private generateTradeDataForV3Output( amountOut: BigNumber, amountInMaximum: BigNumber, - liquidityProviderFee: number, + routeQuoteTradeContext: RouteQuoteTradeContext, deadline: string ): string { const isNativeReceivingNativeEth = isNativeEth( this._toToken.contractAddress ); - const params: ExactOutputSingleRequest = { - tokenIn: removeEthFromContractAddress(this._fromToken.contractAddress), - tokenOut: removeEthFromContractAddress(this._toToken.contractAddress), - fee: percentToFeeAmount(liquidityProviderFee), - recipient: - isNativeReceivingNativeEth === true - ? '0x0000000000000000000000000000000000000000' - : this._ethereumAddress, - deadline, - amountOut: hexlify(amountOut), - amountInMaximum: hexlify(amountInMaximum), - sqrtPriceLimitX96: 0, - }; - + const isSingle = routeQuoteTradeContext.routePathArray.length == 2; const multicallData: string[] = []; + if (isSingle) { + const params: ExactOutputSingleRequest = { + tokenIn: removeEthFromContractAddress(this._fromToken.contractAddress), + tokenOut: removeEthFromContractAddress(this._toToken.contractAddress), + fee: percentToFeeAmount(routeQuoteTradeContext.liquidityProviderFee[0]), + recipient: + isNativeReceivingNativeEth === true + ? '0x0000000000000000000000000000000000000000' + : this._ethereumAddress, + deadline, + amountOut: hexlify(amountOut), + amountInMaximum: hexlify(amountInMaximum), + sqrtPriceLimitX96: 0, + }; + + multicallData.push( + this._uniswapRouterContractFactoryV3.exactOutputSingle(params) + ); + } else { + const params: ExactOutputRequest = { + path: this.getEncodedPoolsPath( + routeQuoteTradeContext.routePathArray, + routeQuoteTradeContext.liquidityProviderFee, + TradeDirection.output + ), + recipient: + isNativeReceivingNativeEth === true + ? '0x0000000000000000000000000000000000000000' + : this._ethereumAddress, + deadline, + amountOut: hexlify(amountOut), + amountInMaximum: hexlify(amountInMaximum), + }; + + multicallData.push( + this._uniswapRouterContractFactoryV3.exactOutput(params) + ); + } - multicallData.push( - this._uniswapRouterContractFactoryV3.exactOutputSingle(params) - ); if (isNativeEth(this._toToken.contractAddress)) { multicallData.push( this._uniswapRouterContractFactoryV3.unwrapWETH9( @@ -1250,7 +1369,8 @@ export class UniswapRouterFactory { (t) => fromTokenRoutes.pairs.fromTokenPairs!.find( (f) => - f.contractAddress.toLowerCase() === t.contractAddress.toLowerCase() + f.token.contractAddress.toLowerCase() === + t.token.contractAddress.toLowerCase() ) ); @@ -1258,13 +1378,13 @@ export class UniswapRouterFactory { if ( fromTokenRoutes.pairs.fromTokenPairs!.find( (t) => - t.contractAddress.toLowerCase() === + t.token.contractAddress.toLowerCase() === toTokenRoutes.token.contractAddress.toLowerCase() ) ) { routes.push({ route: [fromTokenRoutes.token, toTokenRoutes.token], - liquidityProviderFee: this.LIQUIDITY_PROVIDER_FEE_V2, + liquidityProviderFee: [this.LIQUIDITY_PROVIDER_FEE_V2], }); } @@ -1273,21 +1393,22 @@ export class UniswapRouterFactory { if ( jointCompatibleRoutes.find( (c) => - c.contractAddress.toLowerCase() === + c.token.contractAddress.toLowerCase() === tokenRoute.token.contractAddress.toLowerCase() ) ) { routes.push({ route: [fromTokenRoutes.token, tokenRoute.token, toTokenRoutes.token], - liquidityProviderFee: this.LIQUIDITY_PROVIDER_FEE_V2, + liquidityProviderFee: [this.LIQUIDITY_PROVIDER_FEE_V2], }); for (let f = 0; f < fromTokenRoutes.pairs.fromTokenPairs!.length; f++) { - const fromSupportedToken = fromTokenRoutes.pairs.fromTokenPairs![f]; + const fromSupportedToken = + fromTokenRoutes.pairs.fromTokenPairs![f].token; if ( tokenRoute.pairs.toTokenPairs!.find( (pair) => - pair.contractAddress.toLowerCase() === + pair.token.contractAddress.toLowerCase() === fromSupportedToken.contractAddress.toLowerCase() ) ) { @@ -1303,18 +1424,18 @@ export class UniswapRouterFactory { ) { routes.push({ route: workedOutFromRoute, - liquidityProviderFee: this.LIQUIDITY_PROVIDER_FEE_V2, + liquidityProviderFee: [this.LIQUIDITY_PROVIDER_FEE_V2], }); } } } for (let f = 0; f < toTokenRoutes.pairs.toTokenPairs!.length; f++) { - const toSupportedToken = toTokenRoutes.pairs.toTokenPairs![f]; + const toSupportedToken = toTokenRoutes.pairs.toTokenPairs![f].token; if ( tokenRoute.pairs.fromTokenPairs!.find( (pair) => - pair.contractAddress.toLowerCase() === + pair.token.contractAddress.toLowerCase() === toSupportedToken.contractAddress.toLowerCase() ) ) { @@ -1331,7 +1452,7 @@ export class UniswapRouterFactory { ) { routes.push({ route: workedOutToRoute, - liquidityProviderFee: this.LIQUIDITY_PROVIDER_FEE_V2, + liquidityProviderFee: [this.LIQUIDITY_PROVIDER_FEE_V2], }); } } @@ -1364,43 +1485,259 @@ export class UniswapRouterFactory { private getFromRouterDirectionAvailablePairs( token: Token, allAvailablePairs: CallReturnContext[] - ): Token[] { - const fromRouterDirection = allAvailablePairs.filter( - (c) => c.reference.split('-')[0] === token.contractAddress + ): Pool[] { + const fromRouterDirection = allAvailablePairs.filter((c) => + isSameAddress(token.contractAddress, c.reference.split('-')[0]) ); - const tokens: Token[] = []; + const pools: Pool[] = []; for (let index = 0; index < fromRouterDirection.length; index++) { const context = fromRouterDirection[index]; - tokens.push( - this.allTokens.find( - (t) => t.contractAddress === context.reference.split('-')[1] - )! - ); + pools.push({ + token: this.allTokens.find((t) => + isSameAddress(t.contractAddress, context.reference.split('-')[1]) + )!, + }); } - return tokens; + return pools; } private getToRouterDirectionAvailablePairs( token: Token, allAvailablePairs: CallReturnContext[] - ): Token[] { - const toRouterDirection = allAvailablePairs.filter( - (c) => c.reference.split('-')[1] === token.contractAddress + ): Pool[] { + const fromRouterDirection = allAvailablePairs.filter((c) => + isSameAddress(token.contractAddress, c.reference.split('-')[1]) ); - const tokens: Token[] = []; - - for (let index = 0; index < toRouterDirection.length; index++) { - const context = toRouterDirection[index]; - tokens.push( - this.allTokens.find( - (t) => t.contractAddress === context.reference.split('-')[0] - )! - ); + const pools: Pool[] = []; + + for (let index = 0; index < fromRouterDirection.length; index++) { + const context = fromRouterDirection[index]; + pools.push({ + token: this.allTokens.find((t) => + isSameAddress(t.contractAddress, context.reference.split('-')[0]) + )!, + }); + } + + return pools; + } + + /** + * Works out every possible route it can take - v2 only + * @param fromTokenRoutes The from token routes + * @param toTokenRoutes The to token routes + * @param allMainRoutes All the main routes + */ + private workOutAllPossibleRoutesV3( + fromTokenRoutes: TokenRoutes, + toTokenRoutes: TokenRoutes, + allMainRoutes: TokenRoutes[] + ): RouteContext[] { + const jointCompatibleRoutes = toTokenRoutes.pairs.toTokenPairs!.filter( + (t) => + fromTokenRoutes.pairs.fromTokenPairs!.find((f) => + isSameAddress(f.token.contractAddress, t.token.contractAddress) + ) + ); + + const routes: RouteContext[] = []; + const directRoute = fromTokenRoutes.pairs.fromTokenPairs!.find((t) => + isSameAddress( + t.token.contractAddress, + toTokenRoutes.token.contractAddress + ) + ); + if (directRoute) { + routes.push({ + route: [fromTokenRoutes.token, toTokenRoutes.token], + liquidityProviderFee: [feeToPercent(directRoute.fee!)], + }); } - return tokens; + for (let i = 0; i < allMainRoutes.length; i++) { + const tokenRoute = allMainRoutes[i]; + if ( + jointCompatibleRoutes.find((c) => + isSameAddress( + c.token.contractAddress, + tokenRoute.token.contractAddress + ) + ) + ) { + const feeFrom2Main = fromTokenRoutes.pairs.fromTokenPairs!.find((t) => + isSameAddress( + t.token.contractAddress, + tokenRoute.token.contractAddress + ) + )!.fee; + + const feeMain2To = toTokenRoutes.pairs.toTokenPairs!.find((t) => + isSameAddress( + t.token.contractAddress, + tokenRoute.token.contractAddress + ) + )!.fee; + + routes.push({ + route: [fromTokenRoutes.token, tokenRoute.token, toTokenRoutes.token], + liquidityProviderFee: [ + feeToPercent(feeFrom2Main!), + feeToPercent(feeMain2To!), + ], + }); + + for (let f = 0; f < fromTokenRoutes.pairs.fromTokenPairs!.length; f++) { + const fromSupportedToken = + fromTokenRoutes.pairs.fromTokenPairs![f].token; + if ( + tokenRoute.pairs.toTokenPairs!.find((pair) => + isSameAddress( + pair.token.contractAddress, + fromSupportedToken.contractAddress + ) + ) + ) { + const workedOutFromRoute = [ + fromTokenRoutes.token, + fromSupportedToken, + tokenRoute.token, + toTokenRoutes.token, + ]; + if ( + workedOutFromRoute.filter(onlyUnique).length === + workedOutFromRoute.length + ) { + const feeFrom2Support = + fromTokenRoutes.pairs.fromTokenPairs![f].fee; + const feeSupport2Main = tokenRoute.pairs.toTokenPairs!.find( + (pair) => + isSameAddress( + pair.token.contractAddress, + fromSupportedToken.contractAddress + ) + )!.fee; + + routes.push({ + route: workedOutFromRoute, + liquidityProviderFee: [ + feeToPercent(feeFrom2Support!), + feeToPercent(feeSupport2Main!), + feeToPercent(feeMain2To!), + ], + }); + } + } + } + + for (let f = 0; f < toTokenRoutes.pairs.toTokenPairs!.length; f++) { + const toSupportedToken = toTokenRoutes.pairs.toTokenPairs![f].token!; + if ( + tokenRoute.pairs.fromTokenPairs!.find( + (pair) => + pair.token.contractAddress.toLowerCase() === + toSupportedToken.contractAddress.toLowerCase() + ) + ) { + const workedOutToRoute = [ + fromTokenRoutes.token, + tokenRoute.token, + toSupportedToken, + toTokenRoutes.token, + ]; + + if ( + workedOutToRoute.filter(onlyUnique).length === + workedOutToRoute.length + ) { + const feeMain2Support = tokenRoute.pairs.fromTokenPairs!.find( + (pair) => + pair.token.contractAddress.toLowerCase() === + toSupportedToken.contractAddress.toLowerCase() + )!.fee; + const feeSupport2To = toTokenRoutes.pairs.toTokenPairs![f].fee; + + routes.push({ + route: workedOutToRoute, + liquidityProviderFee: [ + feeToPercent(feeFrom2Main!), + feeToPercent(feeMain2Support!), + feeToPercent(feeSupport2To!), + ], + }); + } + } + } + } + } + + return routes; + } + + private getTokenAvailablePairsV3( + token: Token, + allAvailablePairs: CallReturnContext[], + direction: RouterDirection + ) { + switch (direction) { + case RouterDirection.from: + return this.getFromRouterDirectionAvailablePairsV3( + token, + allAvailablePairs + ); + case RouterDirection.to: + return this.getToRouterDirectionAvailablePairsV3( + token, + allAvailablePairs + ); + } + } + + private getFromRouterDirectionAvailablePairsV3( + token: Token, + allAvailablePairs: CallReturnContext[] + ): Pool[] { + const pools: Pool[] = []; + + for (let index = 0; index < allAvailablePairs.length; index++) { + const context = allAvailablePairs[index]; + if ( + isSameAddress(context.reference.split('-')[0], token.contractAddress) + ) { + pools.push({ + token: this.allTokens.find((t) => + isSameAddress(t.contractAddress, context.reference.split('-')[1]) + )!, + fee: parseInt(context.reference.split('-')[3]) as FeeAmount, + }); + } + } + + return pools; + } + + private getToRouterDirectionAvailablePairsV3( + token: Token, + allAvailablePairs: CallReturnContext[] + ): Pool[] { + const pools: Pool[] = []; + + for (let index = 0; index < allAvailablePairs.length; index++) { + const context = allAvailablePairs[index]; + if ( + isSameAddress(context.reference.split('-')[1], token.contractAddress) + ) { + pools.push({ + token: this.allTokens.find((t) => + isSameAddress(t.contractAddress, context.reference.split('-')[0]) + )!, + fee: parseInt(context.reference.split('-')[3]) as FeeAmount, + }); + } + } + + return pools; } /** @@ -1557,11 +1894,15 @@ export class UniswapRouterFactory { ); const tradeExpires = this.generateTradeDeadlineUnixTime(); + const routePathArray = + uniswapVersion === UniswapVersion.v2 + ? callReturnContext.methodParameters[1] + : routeContext.route.map((r) => r.contractAddress); const routeQuoteTradeContext: RouteQuoteTradeContext = { uniswapVersion, liquidityProviderFee: routeContext.liquidityProviderFee, - routePathArray: callReturnContext.methodParameters[1], + routePathArray: routePathArray, }; const data = direction === TradeDirection.input @@ -1582,40 +1923,22 @@ export class UniswapRouterFactory { switch (uniswapVersion) { case UniswapVersion.v2: + case UniswapVersion.v3: return { expectedConvertQuote, expectedConvertQuoteOrTokenAmountInMaxWithSlippage, transaction, tradeExpires, - routePathArrayTokenMap: callReturnContext.methodParameters[1].map( - (c: string) => { - return this.allTokens.find((t) => t.contractAddress === c); - } - ), - routeText: callReturnContext.methodParameters[1] + routePathArrayTokenMap: routePathArray.map((c: string) => { + return this.allTokens.find((t) => t.contractAddress === c); + }), + routeText: routePathArray .map((c: string) => { return this.allTokens.find((t) => t.contractAddress === c)! .symbol; }) .join(' > '), - // route array is always in the 1 index of the method parameters - routePathArray: callReturnContext.methodParameters[1], - uniswapVersion, - liquidityProviderFee: routeContext.liquidityProviderFee, - quoteDirection: direction, - }; - case UniswapVersion.v3: - return { - expectedConvertQuote, - expectedConvertQuoteOrTokenAmountInMaxWithSlippage, - transaction, - tradeExpires, - routePathArrayTokenMap: [this._fromToken, this._toToken], - routeText: `${this._fromToken.symbol} > ${this._toToken.symbol}`, - routePathArray: [ - this._fromToken.contractAddress, - this._toToken.contractAddress, - ], + routePathArray: routePathArray, uniswapVersion, liquidityProviderFee: routeContext.liquidityProviderFee, quoteDirection: direction, @@ -1662,10 +1985,15 @@ export class UniswapRouterFactory { ); const tradeExpires = this.generateTradeDeadlineUnixTime(); + const routePathArray = + uniswapVersion === UniswapVersion.v2 + ? callReturnContext.methodParameters[1] + : routeContext.route.map((r) => r.contractAddress); + const routeQuoteTradeContext: RouteQuoteTradeContext = { uniswapVersion, liquidityProviderFee: routeContext.liquidityProviderFee, - routePathArray: callReturnContext.methodParameters[1], + routePathArray: routePathArray, }; const data = direction === TradeDirection.input @@ -1990,6 +2318,42 @@ export class UniswapRouterFactory { } } + /** + * Converts uni v3 route to encoded bytes string to pass it to contract. + * Structure of encoded string: '0x${tokenAddress_0}${toHex(fee_0)}${tokenAddress_1}${toHex(fee_1)}...${tokenAddress_n}. + * toHex(fee_i) must be of length 6, so leading zeroes are added. + * @param tokens Tokens, included in route. + * @return string Encoded string. + */ + private getEncodedPoolsPath( + tokens: string[], + fees: number[], + direction: TradeDirection + ): string { + if (tokens.length < 2 || tokens.length - fees.length != 1) { + throw new UniswapError( + 'Invalid V3 Route', + ErrorCodes.tradePathIsNotSupported + ); + } + const convertedTokens = + direction == TradeDirection.input ? tokens : deepClone(tokens).reverse(); + const convertedFees = + direction == TradeDirection.input ? fees : deepClone(fees).reverse(); + + const initialTokenAddress = convertedTokens[0]; + let contractPath = initialTokenAddress.slice(2).toLowerCase(); + + for (let i = 0; i < convertedFees.length; i++) { + contractPath += percentToFeeAmount(convertedFees[i]) + .toString(16) + .padStart(6, '0'); + contractPath += convertedTokens[i + 1].slice(2).toLowerCase(); + } + + return `0x${contractPath}`; + } + /** * Get the trade path */ @@ -2297,4 +2661,4 @@ export class UniswapRouterFactory { return ETH_SYMBOL; } -} +} \ No newline at end of file diff --git a/src/factories/router/v3/uniswap-router-contract.factory.v3.ts b/src/factories/router/v3/uniswap-router-contract.factory.v3.ts index 7beb6bd..0736db6 100644 --- a/src/factories/router/v3/uniswap-router-contract.factory.v3.ts +++ b/src/factories/router/v3/uniswap-router-contract.factory.v3.ts @@ -2,7 +2,9 @@ import { BigNumberish, BytesLike } from 'ethers'; import { JsonFragment } from '@ethersproject/abi'; import { ContractContext as RouterContractContext, + ExactInputRequest, ExactInputSingleRequest, + ExactOutputRequest, ExactOutputSingleRequest, } from '../../../ABI/types/uniswap-router-v3'; import { EthersProvider } from '../../../ethers-provider'; @@ -43,6 +45,28 @@ export class UniswapRouterContractFactoryV3 { ); } + /** + * Exact input + * @param params The parameters + */ + public exactInput(params: ExactInputRequest): string { + return this._uniswapRouterContract.interface.encodeFunctionData( + 'exactInput', + [params] + ); + } + + /** + * The exact output + * @param params The parameters + */ + public exactOutput(params: ExactOutputRequest): string { + return this._uniswapRouterContract.interface.encodeFunctionData( + 'exactOutput', + [params] + ); + } + /** * Unwrap eth * @param amountMinimum The amount min From 5ce261c1ac6edf5347c357d5f8a0212ebddc7e8f Mon Sep 17 00:00:00 2001 From: liu Date: Thu, 30 Jun 2022 02:19:36 +0800 Subject: [PATCH 08/20] formatting --- src/factories/router/models/route-methods.ts | 108 +++++++++---------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/src/factories/router/models/route-methods.ts b/src/factories/router/models/route-methods.ts index 2f2261d..f19d96d 100644 --- a/src/factories/router/models/route-methods.ts +++ b/src/factories/router/models/route-methods.ts @@ -1,62 +1,62 @@ export type IRouterMethodName = -| 'WETH' -| 'addLiquidity' -| 'addLiquidityETH' -| 'factory' -| 'getAmountIn' -| 'getAmountOut' -| 'getAmountsIn' -| 'getAmountsOut' -| 'quote' -| 'removeLiquidity' -| 'removeLiquidityETH' -| 'removeLiquidityETHSupportingFeeOnTransferTokens' -| 'removeLiquidityETHWithPermit' -| 'removeLiquidityETHWithPermitSupportingFeeOnTransferTokens' -| 'removeLiquidityWithPermit' -| 'swapETHForExactTokens' -| 'swapExactETHForTokens' -| 'swapExactETHForTokensSupportingFeeOnTransferTokens' -| 'swapExactTokensForETH' -| 'swapExactTokensForETHSupportingFeeOnTransferTokens' -| 'swapExactTokensForTokens' -| 'swapExactTokensForTokensSupportingFeeOnTransferTokens' -| 'swapTokensForExactETH' -| 'swapTokensForExactTokens'; + | 'WETH' + | 'addLiquidity' + | 'addLiquidityETH' + | 'factory' + | 'getAmountIn' + | 'getAmountOut' + | 'getAmountsIn' + | 'getAmountsOut' + | 'quote' + | 'removeLiquidity' + | 'removeLiquidityETH' + | 'removeLiquidityETHSupportingFeeOnTransferTokens' + | 'removeLiquidityETHWithPermit' + | 'removeLiquidityETHWithPermitSupportingFeeOnTransferTokens' + | 'removeLiquidityWithPermit' + | 'swapETHForExactTokens' + | 'swapExactETHForTokens' + | 'swapExactETHForTokensSupportingFeeOnTransferTokens' + | 'swapExactTokensForETH' + | 'swapExactTokensForETHSupportingFeeOnTransferTokens' + | 'swapExactTokensForTokens' + | 'swapExactTokensForTokensSupportingFeeOnTransferTokens' + | 'swapTokensForExactETH' + | 'swapTokensForExactTokens'; export type IRouterMethods = { -[key in IRouterMethodName]: string; + [key in IRouterMethodName]: string; }; export const DEFAULT_ROUTER_METHOD: IRouterMethods = { -WETH: 'WETH', -addLiquidity: 'addLiquidity', -addLiquidityETH: 'addLiquidityETH', -factory: 'factory', -getAmountIn: 'getAmountIn', -getAmountOut: 'getAmountOut', -getAmountsIn: 'getAmountsIn', -getAmountsOut: 'getAmountsOut', -quote: 'quote', -removeLiquidity: 'removeLiquidity', -removeLiquidityETH: 'removeLiquidityETH', -removeLiquidityETHSupportingFeeOnTransferTokens: - 'removeLiquidityETHSupportingFeeOnTransferTokens', -removeLiquidityETHWithPermit: 'removeLiquidityETHWithPermit', -removeLiquidityETHWithPermitSupportingFeeOnTransferTokens: - 'removeLiquidityETHWithPermitSupportingFeeOnTransferTokens', -removeLiquidityWithPermit: 'removeLiquidityWithPermit', -swapETHForExactTokens: 'swapETHForExactTokens', -swapExactETHForTokens: 'swapExactETHForTokens', -swapExactETHForTokensSupportingFeeOnTransferTokens: - 'swapExactETHForTokensSupportingFeeOnTransferTokens', -swapExactTokensForETH: 'swapExactTokensForETH', -swapExactTokensForETHSupportingFeeOnTransferTokens: - 'swapExactTokensForETHSupportingFeeOnTransferTokens', -swapExactTokensForTokens: 'swapExactTokensForTokens', -swapExactTokensForTokensSupportingFeeOnTransferTokens: - 'swapExactTokensForTokensSupportingFeeOnTransferTokens', -swapTokensForExactETH: 'swapTokensForExactETH', -swapTokensForExactTokens: 'swapTokensForExactTokens', + WETH: 'WETH', + addLiquidity: 'addLiquidity', + addLiquidityETH: 'addLiquidityETH', + factory: 'factory', + getAmountIn: 'getAmountIn', + getAmountOut: 'getAmountOut', + getAmountsIn: 'getAmountsIn', + getAmountsOut: 'getAmountsOut', + quote: 'quote', + removeLiquidity: 'removeLiquidity', + removeLiquidityETH: 'removeLiquidityETH', + removeLiquidityETHSupportingFeeOnTransferTokens: + 'removeLiquidityETHSupportingFeeOnTransferTokens', + removeLiquidityETHWithPermit: 'removeLiquidityETHWithPermit', + removeLiquidityETHWithPermitSupportingFeeOnTransferTokens: + 'removeLiquidityETHWithPermitSupportingFeeOnTransferTokens', + removeLiquidityWithPermit: 'removeLiquidityWithPermit', + swapETHForExactTokens: 'swapETHForExactTokens', + swapExactETHForTokens: 'swapExactETHForTokens', + swapExactETHForTokensSupportingFeeOnTransferTokens: + 'swapExactETHForTokensSupportingFeeOnTransferTokens', + swapExactTokensForETH: 'swapExactTokensForETH', + swapExactTokensForETHSupportingFeeOnTransferTokens: + 'swapExactTokensForETHSupportingFeeOnTransferTokens', + swapExactTokensForTokens: 'swapExactTokensForTokens', + swapExactTokensForTokensSupportingFeeOnTransferTokens: + 'swapExactTokensForTokensSupportingFeeOnTransferTokens', + swapTokensForExactETH: 'swapTokensForExactETH', + swapTokensForExactTokens: 'swapTokensForExactTokens', }; \ No newline at end of file From 50b8098e9bead430b40e041e59fbfbe3e58a32de Mon Sep 17 00:00:00 2001 From: liu Date: Thu, 30 Jun 2022 03:01:58 +0800 Subject: [PATCH 09/20] Update README.md --- README.md | 162 +++++++++++++++++++++++++++++------------------------- 1 file changed, 86 insertions(+), 76 deletions(-) diff --git a/README.md b/README.md index 83b16c2..b70abbf 100644 --- a/README.md +++ b/README.md @@ -113,10 +113,16 @@ export interface GasSettings { getGasPrice: () => Promise; } +export type IRouterMethods = { + [key in IRouterMethodName]: string; +}; + export interface CloneUniswapContractDetailsV2 { routerAddress: string; factoryAddress: string; pairAddress: string; + routerAbi?: JsonFragment[]; + routerMethods?: Partial; } export interface CloneUniswapContractDetailsV3 { @@ -420,12 +426,16 @@ export interface TradeContext { expectedConvertQuote: string; // A portion of each trade goes to // liquidity providers as a protocol of incentive - // v2 always = (0.3%) + // length must be routePath.length - 1 + // v2 always = (0.3%) ex [0.03, 0.03] // v3 depends on the fee amount sent on that pool // - low = 0.05% // - medium = 0.3% // - high = 1% - liquidityProviderFee: string; + // For multihop swap + // Sequence of Fees + // ex: USDC>USDT>WETH>WBTC => [(USDC-USDT fee), (USDT-WETH fee), (WETH-WBTC fee)] + liquidityProviderFee: string[]; // A portion of each trade goes to // liquidity providers as a protocol of incentive // v2 always = (0.3%) @@ -437,7 +447,7 @@ export interface TradeContext { // aka 0.05% = 0.0005 // 0.3% = 0.003 // 1% = 0.01 - liquidityProviderFeePercent: number; + liquidityProviderFeePercent: number[]; // A unix datestamp in when this trade expires // if it does expiry while looking at it as long // as you are hooked onto `quoteChanged$` that will @@ -464,7 +474,7 @@ export interface TradeContext { routeText: string; routePathArray: string[]; uniswapVersion: UniswapVersion; - liquidityProviderFee: number; + liquidityProviderFee: number[]; quoteDirection: TradeDirection; }[]; // if the allowance approved for moving tokens is below the amount sending to the @@ -891,8 +901,8 @@ console.log(trade); minAmountConvertQuote: '0.014400465273974444', maximumSent: null, expectedConvertQuote: '0.014730394044348867', - liquidityProviderFee: '0.030000000000000000', - liquidityProviderFeePercent: 0.003, + liquidityProviderFee: ['0.030000000000000000','0.050000000000000000','0.030000000000000000'], + liquidityProviderFeePercent: [0.003, 0.005, 0.003], tradeExpires: 1612189240, routePathTokenMap: [ { @@ -959,7 +969,7 @@ console.log(trade); '0x1985365e9f78359a9B6AD760e32412f4a445E862', ], uniswapVersion: 'v2', - liquidityProviderFee: 0.003 + liquidityProviderFee: [0.003, 0.003], }, { expectedConvertQuote: '0.014606303273323544', @@ -1001,7 +1011,7 @@ console.log(trade); '0x1985365e9f78359a9B6AD760e32412f4a445E862', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.003, 0.005, 0.003], }, { expectedConvertQuote: '0.013997397994408657', @@ -1043,7 +1053,7 @@ console.log(trade); '0x1985365e9f78359a9B6AD760e32412f4a445E862', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.005, 0.005, 0.003], }, { expectedConvertQuote: '0.000000298264906505', @@ -1085,7 +1095,7 @@ console.log(trade); '0x1985365e9f78359a9B6AD760e32412f4a445E862', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.003, 0.005, 0.005], }, ], hasEnoughAllowance: true, @@ -1165,8 +1175,8 @@ console.log(trade); minAmountConvertQuote: '446878.20758208', maximumSent: null, expectedConvertQuote: '449123.82671566', - liquidityProviderFee: '0.030000000000000000', - liquidityProviderFeePercent: 0.003, + liquidityProviderFee: ['0.030000000000000000'], + liquidityProviderFeePercent: [0.003], tradeExpires: 1612189240, routePathTokenMap: [ { @@ -1242,7 +1252,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v2', - liquidityProviderFee: 0.003 + liquidityProviderFee: [0.003] }, { expectedConvertQuote: '446400.4834047', @@ -1276,7 +1286,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.01] }, { expectedConvertQuote: '446400.4834047', @@ -1310,7 +1320,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.01] }, { expectedConvertQuote: '446356.68778218', @@ -1344,7 +1354,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.0005] }, { expectedConvertQuote: '446356.68778218', @@ -1378,7 +1388,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.0005] }, { expectedConvertQuote: '446345.24608428', @@ -1412,7 +1422,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003] }, { expectedConvertQuote: '446345.24608428', @@ -1446,7 +1456,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003] }, { expectedConvertQuote: '347402.73288796', @@ -1480,7 +1490,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003] }, { expectedConvertQuote: '346246.52439964', @@ -1522,7 +1532,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '346246.52439964', @@ -1564,7 +1574,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '346246.52439964', @@ -1606,7 +1616,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '345845.48248206', @@ -1648,7 +1658,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '345845.48248206', @@ -1690,7 +1700,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '345845.48248206', @@ -1732,7 +1742,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '153353.27776886', @@ -1766,7 +1776,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.01] }, { expectedConvertQuote: '153171.51955671', @@ -1808,7 +1818,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.0005, 0.0005] }, { expectedConvertQuote: '153171.51955671', @@ -1850,7 +1860,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.0005, 0.0005] }, { expectedConvertQuote: '153171.51955671', @@ -1892,7 +1902,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.0005, 0.0005] }, { expectedConvertQuote: '153099.84287111', @@ -1934,7 +1944,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '153099.84287111', @@ -1976,7 +1986,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '153099.84287111', @@ -2018,7 +2028,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '10090.42827381', @@ -2060,7 +2070,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '10090.42827381', @@ -2102,7 +2112,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '176.25846115', @@ -2144,7 +2154,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '176.25846115', @@ -2186,7 +2196,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.00167195', @@ -2228,7 +2238,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '0.00167195', @@ -2270,7 +2280,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.0005, 0.003] }, { expectedConvertQuote: '0.00167195', @@ -2312,7 +2322,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '0.00167195', @@ -2346,7 +2356,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.0005] }, { expectedConvertQuote: '0.00167195', @@ -2388,7 +2398,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '0.00167195', @@ -2430,7 +2440,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.0005, 0.003] }, { expectedConvertQuote: '0.00167195', @@ -2472,7 +2482,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.0005, 0.003] }, { expectedConvertQuote: '0.00167195', @@ -2514,7 +2524,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '0.00167195', @@ -2556,7 +2566,7 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.003] }, ], } @@ -2609,8 +2619,8 @@ console.log(trade); minAmountConvertQuote: '0.00022040807282109', maximumSent: null, expectedConvertQuote: '0.00022151807282109', - liquidityProviderFee: '0.03000000', - liquidityProviderFeePercent: 0.003, + liquidityProviderFee: ['0.03000000', '0.00500000', '0.03000000'], + liquidityProviderFeePercent: [0.003, 0.0005, 0.003], tradeExpires: 1612189240, routePathTokenMap: [ { @@ -2690,7 +2700,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v2', - liquidityProviderFee: 0.003 + liquidityProviderFee: [0.003, 0.003, 0.003] }, { expectedConvertQuote: '0.00022151807282109', @@ -2732,7 +2742,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.003, 0.003, 0.003] }, { expectedConvertQuote: '0.000217400884509221', @@ -2758,7 +2768,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005] }, { expectedConvertQuote: '0.000216692105524981', @@ -2792,7 +2802,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003] }, { expectedConvertQuote: '0.000216165414503092', @@ -2834,7 +2844,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.0005, 0.0005] }, { expectedConvertQuote: '0.000216165414503092', @@ -2876,7 +2886,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.0005, 0.0005] }, { expectedConvertQuote: '0.000216165414503092', @@ -2918,7 +2928,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.0005, 0.0005] }, { expectedConvertQuote: '0.000216113740987982', @@ -2960,7 +2970,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '0.000216113740987982', @@ -3002,7 +3012,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '0.000216113740987982', @@ -3044,7 +3054,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '0.000207416610491746', @@ -3078,7 +3088,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.0005] }, { expectedConvertQuote: '0.000206879660311982', @@ -3120,7 +3130,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.000206879660311982', @@ -3162,7 +3172,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.000206879660311982', @@ -3204,7 +3214,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.000206675889551395', @@ -3246,7 +3256,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.000206675889551395', @@ -3288,7 +3298,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.000206675889551395', @@ -3330,7 +3340,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.000201332888879835', @@ -3372,7 +3382,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.000201332888879835', @@ -3414,7 +3424,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.00000000454541448', @@ -3456,7 +3466,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.00000000454541448', @@ -3498,7 +3508,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.000000004421040886', @@ -3532,7 +3542,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003] }, { expectedConvertQuote: '0.000000004406314787', @@ -3574,7 +3584,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '0.000000004406314787', @@ -3616,7 +3626,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '0.000000004406314787', @@ -3658,7 +3668,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '0.000000003689610342', @@ -3700,7 +3710,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.000000003689610342', @@ -3742,7 +3752,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.000000003689610342', @@ -3784,7 +3794,7 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: 0.0005 + liquidityProviderFee: [0.0005, 0.003, 0.0005] }, ], hasEnoughAllowance: true, From 98b9ecdf9f8039d37ded9f2cb81e0d01417a71fa Mon Sep 17 00:00:00 2001 From: liu Date: Fri, 1 Jul 2022 01:42:53 +0800 Subject: [PATCH 10/20] fix uniswap v2 provider fee --- .gitignore | 2 -- .prettierignore | 1 + src/factories/router/uniswap-router.factory.ts | 6 +++--- 3 files changed, 4 insertions(+), 5 deletions(-) create mode 100644 .prettierignore diff --git a/.gitignore b/.gitignore index 91d083a..6704566 100644 --- a/.gitignore +++ b/.gitignore @@ -102,5 +102,3 @@ dist # TernJS port file .tern-port - -.prettierignore \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..fa29cdf --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +** \ No newline at end of file diff --git a/src/factories/router/uniswap-router.factory.ts b/src/factories/router/uniswap-router.factory.ts index 9df909f..2e0fb00 100644 --- a/src/factories/router/uniswap-router.factory.ts +++ b/src/factories/router/uniswap-router.factory.ts @@ -1399,7 +1399,7 @@ export class UniswapRouterFactory { ) { routes.push({ route: [fromTokenRoutes.token, tokenRoute.token, toTokenRoutes.token], - liquidityProviderFee: [this.LIQUIDITY_PROVIDER_FEE_V2], + liquidityProviderFee: new Array(2).fill(this.LIQUIDITY_PROVIDER_FEE_V2), }); for (let f = 0; f < fromTokenRoutes.pairs.fromTokenPairs!.length; f++) { @@ -1424,7 +1424,7 @@ export class UniswapRouterFactory { ) { routes.push({ route: workedOutFromRoute, - liquidityProviderFee: [this.LIQUIDITY_PROVIDER_FEE_V2], + liquidityProviderFee: new Array(3).fill(this.LIQUIDITY_PROVIDER_FEE_V2), }); } } @@ -1452,7 +1452,7 @@ export class UniswapRouterFactory { ) { routes.push({ route: workedOutToRoute, - liquidityProviderFee: [this.LIQUIDITY_PROVIDER_FEE_V2], + liquidityProviderFee: new Array(3).fill(this.LIQUIDITY_PROVIDER_FEE_V2), }); } } From ebc3fa156f1bbaa8c81bd7dd8d8bbb45f96899e1 Mon Sep 17 00:00:00 2001 From: liu Date: Fri, 1 Jul 2022 01:51:06 +0800 Subject: [PATCH 11/20] fix test description --- src/common/utils/is-same-address.spec.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/common/utils/is-same-address.spec.ts b/src/common/utils/is-same-address.spec.ts index 79441f4..c519442 100644 --- a/src/common/utils/is-same-address.spec.ts +++ b/src/common/utils/is-same-address.spec.ts @@ -1,8 +1,7 @@ -import { ETH } from '../tokens'; import { isSameAddress } from './is-same-address'; describe('isSameAddress', () => { - it('should return true if its a valid ethereum address type', () => { + it('should return true if they are all valid ethereum addresses', () => { expect(isSameAddress('0x45Cd08334aeedd8a06265B2Ae302E3597d8fAA28', '0x45cd08334aeedd8a06265b2ae302e3597d8faa28')).toEqual( true ); From 594fcb7d9da934d75f3abcd0a7da36974bec7a90 Mon Sep 17 00:00:00 2001 From: liu Date: Fri, 1 Jul 2022 02:30:42 +0800 Subject: [PATCH 12/20] fix percent examples --- README.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index b70abbf..502a3d6 100644 --- a/README.md +++ b/README.md @@ -184,7 +184,7 @@ export class UniswapPairSettings { cloneUniswapContractDetails?: CloneUniswapContractDetails | undefined; customNetwork?: CustomNetwork | undefined; }) { - this.slippage = settings?.slippage || 0.005; + this.slippage = settings?.slippage || 0.0005; this.deadlineMinutes = settings?.deadlineMinutes || 20; this.disableMultihops = settings?.disableMultihops || false; this.gasSettings = settings?.gasSettings; @@ -228,10 +228,10 @@ const uniswapPair = new UniswapPair({ ethereumAddress: '0xB1E6079212888f0bE0cf55874B2EB9d7a5e02cD9', chainId: ChainId.MAINNET, settings: new UniswapPairSettings({ - // if not supplied it will use `0.005` which is 0.5% + // if not supplied it will use `0.0005` which is 0.5% // please pass it in as a full number decimal so 0.7% // would be 0.007 - slippage: 0.005, + slippage: 0.0005, // if not supplied it will use 20 a deadline minutes deadlineMinutes: 20, // if not supplied it will try to use multihops @@ -266,10 +266,10 @@ const uniswapPair = new UniswapPair({ chainId: ChainId.MAINNET, providerUrl: YOUR_PROVIDER_URL, settings: new UniswapPairSettings({ - // if not supplied it will use `0.005` which is 0.5% + // if not supplied it will use `0.0005` which is 0.5% // please pass it in as a full number decimal so 0.7% // would be 0.007 - slippage: 0.005, + slippage: 0.0005, // if not supplied it will use 20 a deadline minutes deadlineMinutes: 20, // if not supplied it will try to use multihops @@ -303,10 +303,10 @@ const uniswapPair = new UniswapPair({ ethereumAddress: '0xB1E6079212888f0bE0cf55874B2EB9d7a5e02cD9', ethereumProvider: YOUR_WEB3_ETHERS_OR_CUSTOM_ETHEREUM_PROVIDER, settings: new UniswapPairSettings({ - // if not supplied it will use `0.005` which is 0.5% + // if not supplied it will use `0.0005` which is 0.5% // please pass it in as a full number decimal so 0.7% // would be 0.007 - slippage: 0.005, + slippage: 0.0005, // if not supplied it will use 20 a deadline minutes deadlineMinutes: 20, // if not supplied it will try to use multihops @@ -427,7 +427,7 @@ export interface TradeContext { // A portion of each trade goes to // liquidity providers as a protocol of incentive // length must be routePath.length - 1 - // v2 always = (0.3%) ex [0.03, 0.03] + // v2 always = (0.3%) ex [0.003, 0.003] // v3 depends on the fee amount sent on that pool // - low = 0.05% // - medium = 0.3% @@ -901,8 +901,8 @@ console.log(trade); minAmountConvertQuote: '0.014400465273974444', maximumSent: null, expectedConvertQuote: '0.014730394044348867', - liquidityProviderFee: ['0.030000000000000000','0.050000000000000000','0.030000000000000000'], - liquidityProviderFeePercent: [0.003, 0.005, 0.003], + liquidityProviderFee: ['0.030000000000000000','0.0000500000000000000','0.030000000000000000'], + liquidityProviderFeePercent: [0.003, 0.0005, 0.003], tradeExpires: 1612189240, routePathTokenMap: [ { @@ -1011,7 +1011,7 @@ console.log(trade); '0x1985365e9f78359a9B6AD760e32412f4a445E862', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.003, 0.005, 0.003], + liquidityProviderFee: [0.003, 0.0005, 0.003], }, { expectedConvertQuote: '0.013997397994408657', @@ -1053,7 +1053,7 @@ console.log(trade); '0x1985365e9f78359a9B6AD760e32412f4a445E862', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.005, 0.005, 0.003], + liquidityProviderFee: [0.0005, 0.0005, 0.003], }, { expectedConvertQuote: '0.000000298264906505', @@ -1095,7 +1095,7 @@ console.log(trade); '0x1985365e9f78359a9B6AD760e32412f4a445E862', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.003, 0.005, 0.005], + liquidityProviderFee: [0.003, 0.0005, 0.0005], }, ], hasEnoughAllowance: true, @@ -2619,7 +2619,7 @@ console.log(trade); minAmountConvertQuote: '0.00022040807282109', maximumSent: null, expectedConvertQuote: '0.00022151807282109', - liquidityProviderFee: ['0.03000000', '0.00500000', '0.03000000'], + liquidityProviderFee: ['0.03000000', '0.000500000', '0.03000000'], liquidityProviderFeePercent: [0.003, 0.0005, 0.003], tradeExpires: 1612189240, routePathTokenMap: [ From 1e6cedc1ee21904065dd0e457b020f781039dead Mon Sep 17 00:00:00 2001 From: liu Date: Tue, 5 Jul 2022 09:29:20 +0800 Subject: [PATCH 13/20] EthToErc20, Erc20ToEth working for v3 --- .../router/uniswap-router.factory.ts | 80 ++++--------------- 1 file changed, 17 insertions(+), 63 deletions(-) diff --git a/src/factories/router/uniswap-router.factory.ts b/src/factories/router/uniswap-router.factory.ts index 2e0fb00..27fd273 100644 --- a/src/factories/router/uniswap-router.factory.ts +++ b/src/factories/router/uniswap-router.factory.ts @@ -2020,12 +2020,13 @@ export class UniswapRouterFactory { switch (uniswapVersion) { case UniswapVersion.v2: + case UniswapVersion.v3: return { expectedConvertQuote, expectedConvertQuoteOrTokenAmountInMaxWithSlippage, transaction, tradeExpires, - routePathArrayTokenMap: callReturnContext.methodParameters[1].map( + routePathArrayTokenMap: routePathArray.map( (c: string, index: number) => { const token = deepClone( this.allTokens.find((t) => t.contractAddress === c)! @@ -2040,7 +2041,7 @@ export class UniswapRouterFactory { return token; } ), - routeText: callReturnContext.methodParameters[1] + routeText: routePathArray .map((c: string, index: number) => { if (index === 0) { return this.getNativeTokenSymbol(); @@ -2050,34 +2051,7 @@ export class UniswapRouterFactory { }) .join(' > '), // route array is always in the 1 index of the method parameters - routePathArray: callReturnContext.methodParameters[1], - uniswapVersion, - liquidityProviderFee: routeContext.liquidityProviderFee, - quoteDirection: direction, - }; - case UniswapVersion.v3: - return { - expectedConvertQuote, - expectedConvertQuoteOrTokenAmountInMaxWithSlippage, - transaction, - tradeExpires, - routePathArrayTokenMap: [ - turnTokenIntoEthForResponse( - this._fromToken, - this._settings?.customNetwork?.nativeCurrency - ), - this._toToken, - ], - routeText: `${ - turnTokenIntoEthForResponse( - this._fromToken, - this._settings?.customNetwork?.nativeCurrency - ).symbol - } > ${this._toToken.symbol}`, - routePathArray: [ - this._fromToken.contractAddress, - this._toToken.contractAddress, - ], + routePathArray: routePathArray, uniswapVersion, liquidityProviderFee: routeContext.liquidityProviderFee, quoteDirection: direction, @@ -2124,11 +2098,17 @@ export class UniswapRouterFactory { ); const tradeExpires = this.generateTradeDeadlineUnixTime(); + const routePathArray = + uniswapVersion === UniswapVersion.v2 + ? callReturnContext.methodParameters[1] + : routeContext.route.map((r) => r.contractAddress); + const routeQuoteTradeContext: RouteQuoteTradeContext = { uniswapVersion, liquidityProviderFee: routeContext.liquidityProviderFee, - routePathArray: callReturnContext.methodParameters[1], + routePathArray: routePathArray, }; + const data = direction === TradeDirection.input ? this.generateTradeDataErc20ToEthInput( @@ -2148,17 +2128,18 @@ export class UniswapRouterFactory { switch (uniswapVersion) { case UniswapVersion.v2: + case UniswapVersion.v3: return { expectedConvertQuote, expectedConvertQuoteOrTokenAmountInMaxWithSlippage, transaction, tradeExpires, - routePathArrayTokenMap: callReturnContext.methodParameters[1].map( + routePathArrayTokenMap: routePathArray.map( (c: string, index: number) => { const token = deepClone( this.allTokens.find((t) => t.contractAddress === c)! ); - if (index === callReturnContext.methodParameters[1].length - 1) { + if (index === routePathArray.length - 1) { return turnTokenIntoEthForResponse( token, this._settings?.customNetwork?.nativeCurrency @@ -2168,9 +2149,9 @@ export class UniswapRouterFactory { return token; } ), - routeText: callReturnContext.methodParameters[1] + routeText: routePathArray .map((c: string, index: number) => { - if (index === callReturnContext.methodParameters[1].length - 1) { + if (index === routePathArray.length - 1) { return this.getNativeTokenSymbol(); } return this.allTokens.find((t) => t.contractAddress === c)! @@ -2178,34 +2159,7 @@ export class UniswapRouterFactory { }) .join(' > '), // route array is always in the 1 index of the method parameters - routePathArray: callReturnContext.methodParameters[1], - uniswapVersion, - liquidityProviderFee: routeContext.liquidityProviderFee, - quoteDirection: direction, - }; - case UniswapVersion.v3: - return { - expectedConvertQuote, - expectedConvertQuoteOrTokenAmountInMaxWithSlippage, - transaction, - tradeExpires, - routePathArrayTokenMap: [ - this._fromToken, - turnTokenIntoEthForResponse( - this._toToken, - this._settings?.customNetwork?.nativeCurrency - ), - ], - routeText: `${this._fromToken.symbol} > ${ - turnTokenIntoEthForResponse( - this._toToken, - this._settings?.customNetwork?.nativeCurrency - ).symbol - }`, - routePathArray: [ - this._fromToken.contractAddress, - this._toToken.contractAddress, - ], + routePathArray: routePathArray, uniswapVersion, liquidityProviderFee: routeContext.liquidityProviderFee, quoteDirection: direction, From db9ce96a601b5abcf0c4a24dd73543d1fbd83222 Mon Sep 17 00:00:00 2001 From: liu Date: Wed, 6 Jul 2022 01:36:09 +0800 Subject: [PATCH 14/20] fix generateTradeDataForV3Input remove eth --- src/factories/router/uniswap-router.factory.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/factories/router/uniswap-router.factory.ts b/src/factories/router/uniswap-router.factory.ts index 27fd273..41431ac 100644 --- a/src/factories/router/uniswap-router.factory.ts +++ b/src/factories/router/uniswap-router.factory.ts @@ -851,7 +851,9 @@ export class UniswapRouterFactory { } else { const params: ExactInputRequest = { path: this.getEncodedPoolsPath( - routeQuoteTradeContext.routePathArray, + routeQuoteTradeContext.routePathArray.map((r) => + removeEthFromContractAddress(r) + ), routeQuoteTradeContext.liquidityProviderFee, TradeDirection.input ), From 26aa246b855ec53b62665ef324251bfd148e9e7b Mon Sep 17 00:00:00 2001 From: liu Date: Wed, 6 Jul 2022 22:12:50 +0800 Subject: [PATCH 15/20] fixed customized router methods --- src/factories/router/uniswap-router.factory.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/factories/router/uniswap-router.factory.ts b/src/factories/router/uniswap-router.factory.ts index 41431ac..847d81f 100644 --- a/src/factories/router/uniswap-router.factory.ts +++ b/src/factories/router/uniswap-router.factory.ts @@ -74,7 +74,8 @@ export class UniswapRouterFactory { uniswapContracts.v2.getRouterAddress( this._settings.cloneUniswapContractDetails ), - uniswapContracts.v2.getRouterAbi(this._settings.cloneUniswapContractDetails) + uniswapContracts.v2.getRouterAbi(this._settings.cloneUniswapContractDetails), + uniswapContracts.v2.getRouterMethods(this._settings.cloneUniswapContractDetails) ); private _uniswapRouterContractFactoryV3 = new UniswapRouterContractFactoryV3( From e0432b1f8515118d2aabd28770ba8d0975550f9a Mon Sep 17 00:00:00 2001 From: liu Date: Wed, 13 Jul 2022 22:35:22 +0800 Subject: [PATCH 16/20] bug fix on hexlify --- src/common/utils/hexlify.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/utils/hexlify.ts b/src/common/utils/hexlify.ts index e84fae5..ff1605d 100644 --- a/src/common/utils/hexlify.ts +++ b/src/common/utils/hexlify.ts @@ -7,5 +7,5 @@ import { hexlify as EthersHexlify } from 'ethers/lib/utils'; * @param value The value */ export function hexlify(value: BigNumber): string { - return EthersHexlify(EthersBigNumber.from(value.toFixed())); + return EthersHexlify(EthersBigNumber.from(value.toFixed(0))); } From 1c166b961c1cb7874ff16cb12069687ee641ccff Mon Sep 17 00:00:00 2001 From: liu Date: Tue, 2 Aug 2022 09:15:20 +0800 Subject: [PATCH 17/20] add new fields for uniswap v3 liquidity fee --- src/factories/pair/models/current-trade-context.ts | 3 ++- src/factories/pair/models/trade-context.ts | 6 ++++-- src/factories/router/models/route-context.ts | 3 ++- src/factories/router/models/route-quote-trade-context.ts | 3 ++- src/factories/router/models/route-quote.ts | 3 ++- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/factories/pair/models/current-trade-context.ts b/src/factories/pair/models/current-trade-context.ts index 1a546a0..656f64c 100644 --- a/src/factories/pair/models/current-trade-context.ts +++ b/src/factories/pair/models/current-trade-context.ts @@ -8,7 +8,8 @@ export interface CurrentTradeContext { quoteDirection: TradeDirection; fromToken: Token; toToken: Token; - liquidityProviderFee: string[]; + liquidityProviderFee: string; + liquidityProviderFeesV3: string[]; transaction: Transaction; routeText: string; tradeExpires: number; diff --git a/src/factories/pair/models/trade-context.ts b/src/factories/pair/models/trade-context.ts index 3fb733e..a8ac562 100644 --- a/src/factories/pair/models/trade-context.ts +++ b/src/factories/pair/models/trade-context.ts @@ -12,8 +12,10 @@ export interface TradeContext { minAmountConvertQuote: string | null; maximumSent: string | null; expectedConvertQuote: string; - liquidityProviderFee: string[]; - liquidityProviderFeePercent: number[]; + liquidityProviderFee: string; + liquidityProviderFeePercent: number; + liquidityProviderFeesV3: string[]; + liquidityProviderFeePercentsV3: number[]; tradeExpires: number; routePathTokenMap: Token[]; routeText: string; diff --git a/src/factories/router/models/route-context.ts b/src/factories/router/models/route-context.ts index b57fb49..9295c6a 100644 --- a/src/factories/router/models/route-context.ts +++ b/src/factories/router/models/route-context.ts @@ -2,5 +2,6 @@ import { Token } from '../../token/models/token'; export interface RouteContext { route: Token[]; - liquidityProviderFee: number[]; + liquidityProviderFee: number; + liquidityProviderFeesV3: number[]; } diff --git a/src/factories/router/models/route-quote-trade-context.ts b/src/factories/router/models/route-quote-trade-context.ts index 8f3a5d5..8ef45a3 100644 --- a/src/factories/router/models/route-quote-trade-context.ts +++ b/src/factories/router/models/route-quote-trade-context.ts @@ -3,5 +3,6 @@ import { UniswapVersion } from '../../../enums/uniswap-version'; export interface RouteQuoteTradeContext { uniswapVersion: UniswapVersion; routePathArray: string[]; - liquidityProviderFee: number[]; + liquidityProviderFee: number; + liquidityProviderFeesV3: number[]; } diff --git a/src/factories/router/models/route-quote.ts b/src/factories/router/models/route-quote.ts index 7ca1ecc..59ff242 100644 --- a/src/factories/router/models/route-quote.ts +++ b/src/factories/router/models/route-quote.ts @@ -12,7 +12,8 @@ export interface RouteQuote { routeText: string; routePathArray: string[]; uniswapVersion: UniswapVersion; - liquidityProviderFee: number[]; + liquidityProviderFee: number; + liquidityProviderFeesV3: number[]; quoteDirection: TradeDirection; gasPriceEstimatedBy?: string | undefined; } From 501e5d64f08b82cb971e99b49768764d02ff56c0 Mon Sep 17 00:00:00 2001 From: liu Date: Tue, 2 Aug 2022 09:36:03 +0800 Subject: [PATCH 18/20] fix router & factory --- src/factories/pair/uniswap-pair.factory.ts | 33 ++++++++++--- .../router/uniswap-router.factory.ts | 47 ++++++++++++------- 2 files changed, 57 insertions(+), 23 deletions(-) diff --git a/src/factories/pair/uniswap-pair.factory.ts b/src/factories/pair/uniswap-pair.factory.ts index 454f2f5..7615b32 100644 --- a/src/factories/pair/uniswap-pair.factory.ts +++ b/src/factories/pair/uniswap-pair.factory.ts @@ -298,6 +298,7 @@ export class UniswapPairFactory { fromToken: trade.fromToken, toToken: trade.toToken, liquidityProviderFee: trade.liquidityProviderFee, + liquidityProviderFeesV3: trade.liquidityProviderFeesV3, transaction: trade.transaction, routeText: trade.routeText, tradeExpires: trade.tradeExpires, @@ -319,7 +320,7 @@ export class UniswapPairFactory { ); const bestRouteQuote = bestRouteQuotes.bestRouteQuote; - + const tradeContext: TradeContext = { uniswapVersion: bestRouteQuote.uniswapVersion, quoteDirection: direction, @@ -333,14 +334,20 @@ export class UniswapPairFactory { ? null : bestRouteQuote.expectedConvertQuoteOrTokenAmountInMaxWithSlippage, expectedConvertQuote: bestRouteQuote.expectedConvertQuote, - liquidityProviderFee: bestRouteQuote.liquidityProviderFee.map((f) => + liquidityProviderFee: direction === TradeDirection.input + ? baseConvertRequest.times(bestRouteQuote.uniswapVersion === UniswapVersion.v3 ? 0 : bestRouteQuote.liquidityProviderFee).toFixed(this.fromToken.decimals) + : new BigNumber(bestRouteQuote.expectedConvertQuote) + .times(bestRouteQuote.uniswapVersion === UniswapVersion.v3 ? 0 : bestRouteQuote.liquidityProviderFee) + .toFixed(this.fromToken.decimals), + liquidityProviderFeePercent: bestRouteQuote.liquidityProviderFee, + liquidityProviderFeesV3: bestRouteQuote.liquidityProviderFeesV3.map((f) => direction === TradeDirection.input ? baseConvertRequest.times(f).toFixed(this.fromToken.decimals) : new BigNumber(bestRouteQuote.expectedConvertQuote) .times(f) .toFixed(this.fromToken.decimals) ), - liquidityProviderFeePercent: bestRouteQuote.liquidityProviderFee, + liquidityProviderFeePercentsV3: bestRouteQuote.liquidityProviderFeesV3, tradeExpires: bestRouteQuote.tradeExpires, routePathTokenMap: bestRouteQuote.routePathArrayTokenMap, routeText: bestRouteQuote.routeText, @@ -403,14 +410,20 @@ export class UniswapPairFactory { ? null : bestRouteQuote.expectedConvertQuoteOrTokenAmountInMaxWithSlippage, expectedConvertQuote: bestRouteQuote.expectedConvertQuote, - liquidityProviderFee: bestRouteQuote.liquidityProviderFee.map((f) => + liquidityProviderFee: direction === TradeDirection.input + ? baseConvertRequest.times(bestRouteQuote.uniswapVersion === UniswapVersion.v3 ? 0 : bestRouteQuote.liquidityProviderFee).toFixed(this.fromToken.decimals) + : new BigNumber(bestRouteQuote.expectedConvertQuote) + .times(bestRouteQuote.uniswapVersion === UniswapVersion.v3 ? 0 : bestRouteQuote.liquidityProviderFee) + .toFixed(this.fromToken.decimals), + liquidityProviderFeePercent: bestRouteQuote.liquidityProviderFee, + liquidityProviderFeesV3: bestRouteQuote.liquidityProviderFeesV3.map((f) => direction === TradeDirection.input ? baseConvertRequest.times(f).toFixed(this.fromToken.decimals) : new BigNumber(bestRouteQuote.expectedConvertQuote) .times(f) .toFixed(this.fromToken.decimals) ), - liquidityProviderFeePercent: bestRouteQuote.liquidityProviderFee, + liquidityProviderFeePercentsV3: bestRouteQuote.liquidityProviderFeesV3, tradeExpires: bestRouteQuote.tradeExpires, routePathTokenMap: bestRouteQuote.routePathArrayTokenMap, routeText: bestRouteQuote.routeText, @@ -468,14 +481,20 @@ export class UniswapPairFactory { ? null : bestRouteQuote.expectedConvertQuoteOrTokenAmountInMaxWithSlippage, expectedConvertQuote: bestRouteQuote.expectedConvertQuote, - liquidityProviderFee: bestRouteQuote.liquidityProviderFee.map((f) => + liquidityProviderFee: direction === TradeDirection.input + ? baseConvertRequest.times(bestRouteQuote.uniswapVersion === UniswapVersion.v3 ? 0 : bestRouteQuote.liquidityProviderFee).toFixed(this.fromToken.decimals) + : new BigNumber(bestRouteQuote.expectedConvertQuote) + .times(bestRouteQuote.uniswapVersion === UniswapVersion.v3 ? 0 : bestRouteQuote.liquidityProviderFee) + .toFixed(this.fromToken.decimals), + liquidityProviderFeePercent: bestRouteQuote.liquidityProviderFee, + liquidityProviderFeesV3: bestRouteQuote.liquidityProviderFeesV3.map((f) => direction === TradeDirection.input ? baseConvertRequest.times(f).toFixed(this.fromToken.decimals) : new BigNumber(bestRouteQuote.expectedConvertQuote) .times(f) .toFixed(this.fromToken.decimals) ), - liquidityProviderFeePercent: bestRouteQuote.liquidityProviderFee, + liquidityProviderFeePercentsV3: bestRouteQuote.liquidityProviderFeesV3, tradeExpires: bestRouteQuote.tradeExpires, routePathTokenMap: bestRouteQuote.routePathArrayTokenMap, routeText: bestRouteQuote.routeText, diff --git a/src/factories/router/uniswap-router.factory.ts b/src/factories/router/uniswap-router.factory.ts index 847d81f..e460f9a 100644 --- a/src/factories/router/uniswap-router.factory.ts +++ b/src/factories/router/uniswap-router.factory.ts @@ -421,7 +421,7 @@ export class UniswapRouterFactory { methodParameters: [ routeCombo[0], routeCombo[1], - percentToFeeAmount(routes.v3[i].liquidityProviderFee[0]), + percentToFeeAmount(routes.v3[i].liquidityProviderFeesV3[0]), tradeAmount, 0, ], @@ -438,7 +438,7 @@ export class UniswapRouterFactory { methodParameters: [ this.getEncodedPoolsPath( routeCombo, - routes.v3[i].liquidityProviderFee, + routes.v3[i].liquidityProviderFeesV3, direction ), tradeAmount, @@ -514,6 +514,7 @@ export class UniswapRouterFactory { routePathArray: route.routePathArray, uniswapVersion: route.uniswapVersion, liquidityProviderFee: route.liquidityProviderFee, + liquidityProviderFeesV3: route.liquidityProviderFeesV3, quoteDirection: route.quoteDirection, gasPriceEstimatedBy: route.gasPriceEstimatedBy, }; @@ -835,7 +836,7 @@ export class UniswapRouterFactory { const params: ExactInputSingleRequest = { tokenIn: removeEthFromContractAddress(this._fromToken.contractAddress), tokenOut: removeEthFromContractAddress(this._toToken.contractAddress), - fee: percentToFeeAmount(routeQuoteTradeContext.liquidityProviderFee[0]), + fee: percentToFeeAmount(routeQuoteTradeContext.liquidityProviderFeesV3[0]), recipient: isNativeReceivingNativeEth === true ? '0x0000000000000000000000000000000000000000' @@ -855,7 +856,7 @@ export class UniswapRouterFactory { routeQuoteTradeContext.routePathArray.map((r) => removeEthFromContractAddress(r) ), - routeQuoteTradeContext.liquidityProviderFee, + routeQuoteTradeContext.liquidityProviderFeesV3, TradeDirection.input ), recipient: @@ -925,7 +926,7 @@ export class UniswapRouterFactory { const params: ExactOutputRequest = { path: this.getEncodedPoolsPath( routeQuoteTradeContext.routePathArray, - routeQuoteTradeContext.liquidityProviderFee, + routeQuoteTradeContext.liquidityProviderFeesV3, TradeDirection.output ), recipient: @@ -1387,7 +1388,8 @@ export class UniswapRouterFactory { ) { routes.push({ route: [fromTokenRoutes.token, toTokenRoutes.token], - liquidityProviderFee: [this.LIQUIDITY_PROVIDER_FEE_V2], + liquidityProviderFee: this.LIQUIDITY_PROVIDER_FEE_V2, + liquidityProviderFeesV3: [this.LIQUIDITY_PROVIDER_FEE_V2], }); } @@ -1402,7 +1404,8 @@ export class UniswapRouterFactory { ) { routes.push({ route: [fromTokenRoutes.token, tokenRoute.token, toTokenRoutes.token], - liquidityProviderFee: new Array(2).fill(this.LIQUIDITY_PROVIDER_FEE_V2), + liquidityProviderFee: this.LIQUIDITY_PROVIDER_FEE_V2, + liquidityProviderFeesV3: new Array(2).fill(this.LIQUIDITY_PROVIDER_FEE_V2), }); for (let f = 0; f < fromTokenRoutes.pairs.fromTokenPairs!.length; f++) { @@ -1427,7 +1430,8 @@ export class UniswapRouterFactory { ) { routes.push({ route: workedOutFromRoute, - liquidityProviderFee: new Array(3).fill(this.LIQUIDITY_PROVIDER_FEE_V2), + liquidityProviderFee: this.LIQUIDITY_PROVIDER_FEE_V2, + liquidityProviderFeesV3: new Array(3).fill(this.LIQUIDITY_PROVIDER_FEE_V2), }); } } @@ -1455,7 +1459,8 @@ export class UniswapRouterFactory { ) { routes.push({ route: workedOutToRoute, - liquidityProviderFee: new Array(3).fill(this.LIQUIDITY_PROVIDER_FEE_V2), + liquidityProviderFee: this.LIQUIDITY_PROVIDER_FEE_V2, + liquidityProviderFeesV3: new Array(3).fill(this.LIQUIDITY_PROVIDER_FEE_V2), }); } } @@ -1555,7 +1560,8 @@ export class UniswapRouterFactory { if (directRoute) { routes.push({ route: [fromTokenRoutes.token, toTokenRoutes.token], - liquidityProviderFee: [feeToPercent(directRoute.fee!)], + liquidityProviderFee: 0, + liquidityProviderFeesV3: [feeToPercent(directRoute.fee!)], }); } @@ -1585,7 +1591,8 @@ export class UniswapRouterFactory { routes.push({ route: [fromTokenRoutes.token, tokenRoute.token, toTokenRoutes.token], - liquidityProviderFee: [ + liquidityProviderFee: 0, + liquidityProviderFeesV3: [ feeToPercent(feeFrom2Main!), feeToPercent(feeMain2To!), ], @@ -1624,7 +1631,8 @@ export class UniswapRouterFactory { routes.push({ route: workedOutFromRoute, - liquidityProviderFee: [ + liquidityProviderFee: 0, + liquidityProviderFeesV3: [ feeToPercent(feeFrom2Support!), feeToPercent(feeSupport2Main!), feeToPercent(feeMain2To!), @@ -1663,7 +1671,8 @@ export class UniswapRouterFactory { routes.push({ route: workedOutToRoute, - liquidityProviderFee: [ + liquidityProviderFee: 0, + liquidityProviderFeesV3: [ feeToPercent(feeFrom2Main!), feeToPercent(feeMain2Support!), feeToPercent(feeSupport2To!), @@ -1905,6 +1914,7 @@ export class UniswapRouterFactory { const routeQuoteTradeContext: RouteQuoteTradeContext = { uniswapVersion, liquidityProviderFee: routeContext.liquidityProviderFee, + liquidityProviderFeesV3: routeContext.liquidityProviderFeesV3, routePathArray: routePathArray, }; const data = @@ -1943,7 +1953,8 @@ export class UniswapRouterFactory { .join(' > '), routePathArray: routePathArray, uniswapVersion, - liquidityProviderFee: routeContext.liquidityProviderFee, + liquidityProviderFee: uniswapVersion === UniswapVersion.v2 ? routeContext.liquidityProviderFee : 0, + liquidityProviderFeesV3: routeContext.liquidityProviderFeesV3, quoteDirection: direction, }; default: @@ -1996,6 +2007,7 @@ export class UniswapRouterFactory { const routeQuoteTradeContext: RouteQuoteTradeContext = { uniswapVersion, liquidityProviderFee: routeContext.liquidityProviderFee, + liquidityProviderFeesV3: routeContext.liquidityProviderFeesV3, routePathArray: routePathArray, }; const data = @@ -2056,7 +2068,8 @@ export class UniswapRouterFactory { // route array is always in the 1 index of the method parameters routePathArray: routePathArray, uniswapVersion, - liquidityProviderFee: routeContext.liquidityProviderFee, + liquidityProviderFee: uniswapVersion === UniswapVersion.v2 ? routeContext.liquidityProviderFee : 0, + liquidityProviderFeesV3: routeContext.liquidityProviderFeesV3, quoteDirection: direction, }; default: @@ -2109,6 +2122,7 @@ export class UniswapRouterFactory { const routeQuoteTradeContext: RouteQuoteTradeContext = { uniswapVersion, liquidityProviderFee: routeContext.liquidityProviderFee, + liquidityProviderFeesV3: routeContext.liquidityProviderFeesV3, routePathArray: routePathArray, }; @@ -2164,7 +2178,8 @@ export class UniswapRouterFactory { // route array is always in the 1 index of the method parameters routePathArray: routePathArray, uniswapVersion, - liquidityProviderFee: routeContext.liquidityProviderFee, + liquidityProviderFee: uniswapVersion === UniswapVersion.v2 ? routeContext.liquidityProviderFee : 0, + liquidityProviderFeesV3: routeContext.liquidityProviderFeesV3, quoteDirection: direction, }; default: From 7a178a7e9618ef32258b2e6daaa8d076189f183d Mon Sep 17 00:00:00 2001 From: liu Date: Tue, 2 Aug 2022 11:44:46 +0800 Subject: [PATCH 19/20] update Readme --- README.md | 233 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 158 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index 502a3d6..846fdd2 100644 --- a/README.md +++ b/README.md @@ -424,6 +424,16 @@ export interface TradeContext { // this will be formatted in readable number // so you can render straight out the box expectedConvertQuote: string; + // A portion of each trade goes to + // liquidity providers as a protocol of incentive + // v2 always = (0.3%) + // v3 always = (0.0%) for v3, use `liquidityProviderFeesV3` + liquidityProviderFee: string; + // A portion of each trade goes to + // liquidity providers as a protocol of incentive + // v2 always = (0.3%) + // v3 always = (0.0%) for v3, use `liquidityProviderFeePercentsV3` + liquidityProviderFeePercent: number; // A portion of each trade goes to // liquidity providers as a protocol of incentive // length must be routePath.length - 1 @@ -435,7 +445,7 @@ export interface TradeContext { // For multihop swap // Sequence of Fees // ex: USDC>USDT>WETH>WBTC => [(USDC-USDT fee), (USDT-WETH fee), (WETH-WBTC fee)] - liquidityProviderFee: string[]; + liquidityProviderFeesV3: string[]; // A portion of each trade goes to // liquidity providers as a protocol of incentive // v2 always = (0.3%) @@ -447,7 +457,7 @@ export interface TradeContext { // aka 0.05% = 0.0005 // 0.3% = 0.003 // 1% = 0.01 - liquidityProviderFeePercent: number[]; + liquidityProviderFeePercentsV3: number[]; // A unix datestamp in when this trade expires // if it does expiry while looking at it as long // as you are hooked onto `quoteChanged$` that will @@ -474,7 +484,8 @@ export interface TradeContext { routeText: string; routePathArray: string[]; uniswapVersion: UniswapVersion; - liquidityProviderFee: number[]; + liquidityProviderFee: number; + liquidityProviderFeesV3: number[]; quoteDirection: TradeDirection; }[]; // if the allowance approved for moving tokens is below the amount sending to the @@ -901,8 +912,10 @@ console.log(trade); minAmountConvertQuote: '0.014400465273974444', maximumSent: null, expectedConvertQuote: '0.014730394044348867', - liquidityProviderFee: ['0.030000000000000000','0.0000500000000000000','0.030000000000000000'], - liquidityProviderFeePercent: [0.003, 0.0005, 0.003], + liquidityProviderFee: 0, + liquidityProviderFeePercent: 0, + liquidityProviderFeesV3: ['0.030000000000000000','0.0000500000000000000','0.030000000000000000'], + liquidityProviderFeePercentsV3: [0.003, 0.0005, 0.003], tradeExpires: 1612189240, routePathTokenMap: [ { @@ -969,7 +982,8 @@ console.log(trade); '0x1985365e9f78359a9B6AD760e32412f4a445E862', ], uniswapVersion: 'v2', - liquidityProviderFee: [0.003, 0.003], + liquidityProviderFee: 0.003, + liquidityProviderFeesV3: [0.003, 0.003], }, { expectedConvertQuote: '0.014606303273323544', @@ -1011,7 +1025,8 @@ console.log(trade); '0x1985365e9f78359a9B6AD760e32412f4a445E862', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.003, 0.0005, 0.003], + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.003, 0.0005, 0.003], }, { expectedConvertQuote: '0.013997397994408657', @@ -1053,7 +1068,8 @@ console.log(trade); '0x1985365e9f78359a9B6AD760e32412f4a445E862', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.0005, 0.003], + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.0005, 0.003], }, { expectedConvertQuote: '0.000000298264906505', @@ -1095,7 +1111,8 @@ console.log(trade); '0x1985365e9f78359a9B6AD760e32412f4a445E862', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.003, 0.0005, 0.0005], + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.003, 0.0005, 0.0005], }, ], hasEnoughAllowance: true, @@ -1175,8 +1192,10 @@ console.log(trade); minAmountConvertQuote: '446878.20758208', maximumSent: null, expectedConvertQuote: '449123.82671566', - liquidityProviderFee: ['0.030000000000000000'], - liquidityProviderFeePercent: [0.003], + liquidityProviderFee: 0, + liquidityProviderFeePercent: 0, + liquidityProviderFeesV3: ['0.030000000000000000'], + liquidityProviderFeePercentsV3: [0.003], tradeExpires: 1612189240, routePathTokenMap: [ { @@ -1252,7 +1271,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v2', - liquidityProviderFee: [0.003] + liquidityProviderFee: 0.003, + liquidityProviderFeesV3: [0.003] }, { expectedConvertQuote: '446400.4834047', @@ -1286,7 +1306,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.01] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.01] }, { expectedConvertQuote: '446400.4834047', @@ -1320,7 +1341,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.01] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.01] }, { expectedConvertQuote: '446356.68778218', @@ -1354,7 +1376,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.0005] }, { expectedConvertQuote: '446356.68778218', @@ -1388,7 +1411,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.0005] }, { expectedConvertQuote: '446345.24608428', @@ -1422,7 +1446,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003] }, { expectedConvertQuote: '446345.24608428', @@ -1456,7 +1481,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003] }, { expectedConvertQuote: '347402.73288796', @@ -1490,7 +1516,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003] }, { expectedConvertQuote: '346246.52439964', @@ -1532,7 +1559,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '346246.52439964', @@ -1574,7 +1602,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '346246.52439964', @@ -1616,7 +1645,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '345845.48248206', @@ -1658,7 +1688,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '345845.48248206', @@ -1700,7 +1731,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '345845.48248206', @@ -1742,7 +1774,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '153353.27776886', @@ -1776,7 +1809,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.01] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.01] }, { expectedConvertQuote: '153171.51955671', @@ -1818,7 +1852,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.0005, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.0005, 0.0005] }, { expectedConvertQuote: '153171.51955671', @@ -1860,7 +1895,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.0005, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.0005, 0.0005] }, { expectedConvertQuote: '153171.51955671', @@ -1902,7 +1938,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.0005, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.0005, 0.0005] }, { expectedConvertQuote: '153099.84287111', @@ -1944,7 +1981,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '153099.84287111', @@ -1986,7 +2024,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '153099.84287111', @@ -2028,7 +2067,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '10090.42827381', @@ -2070,7 +2110,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '10090.42827381', @@ -2112,7 +2153,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '176.25846115', @@ -2154,7 +2196,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '176.25846115', @@ -2196,7 +2239,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.00167195', @@ -2238,7 +2282,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '0.00167195', @@ -2280,7 +2325,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.0005, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.0005, 0.003] }, { expectedConvertQuote: '0.00167195', @@ -2322,7 +2368,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '0.00167195', @@ -2356,7 +2403,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.0005] }, { expectedConvertQuote: '0.00167195', @@ -2398,7 +2446,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '0.00167195', @@ -2440,7 +2489,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.0005, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.0005, 0.003] }, { expectedConvertQuote: '0.00167195', @@ -2482,7 +2532,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.0005, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.0005, 0.003] }, { expectedConvertQuote: '0.00167195', @@ -2524,7 +2575,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '0.00167195', @@ -2566,7 +2618,8 @@ console.log(trade); '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.003] }, ], } @@ -2619,8 +2672,10 @@ console.log(trade); minAmountConvertQuote: '0.00022040807282109', maximumSent: null, expectedConvertQuote: '0.00022151807282109', - liquidityProviderFee: ['0.03000000', '0.000500000', '0.03000000'], - liquidityProviderFeePercent: [0.003, 0.0005, 0.003], + liquidityProviderFee: 0, + liquidityProviderFeePercent: 0, + liquidityProviderFeesV3: ['0.03000000', '0.000500000', '0.03000000'], + liquidityProviderFeePercentsV3: [0.003, 0.0005, 0.003], tradeExpires: 1612189240, routePathTokenMap: [ { @@ -2700,7 +2755,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v2', - liquidityProviderFee: [0.003, 0.003, 0.003] + liquidityProviderFee: 0.003, + liquidityProviderFeesV3: [0.003, 0.003, 0.003] }, { expectedConvertQuote: '0.00022151807282109', @@ -2742,7 +2798,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.003, 0.003, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.003, 0.003, 0.003] }, { expectedConvertQuote: '0.000217400884509221', @@ -2768,7 +2825,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005] }, { expectedConvertQuote: '0.000216692105524981', @@ -2802,7 +2860,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003] }, { expectedConvertQuote: '0.000216165414503092', @@ -2844,7 +2903,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.0005, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.0005, 0.0005] }, { expectedConvertQuote: '0.000216165414503092', @@ -2886,7 +2946,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.0005, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.0005, 0.0005] }, { expectedConvertQuote: '0.000216165414503092', @@ -2928,7 +2989,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.0005, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.0005, 0.0005] }, { expectedConvertQuote: '0.000216113740987982', @@ -2970,7 +3032,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '0.000216113740987982', @@ -3012,7 +3075,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '0.000216113740987982', @@ -3054,7 +3118,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '0.000207416610491746', @@ -3088,7 +3153,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.0005] }, { expectedConvertQuote: '0.000206879660311982', @@ -3130,7 +3196,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.000206879660311982', @@ -3172,7 +3239,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.000206879660311982', @@ -3214,7 +3282,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.000206675889551395', @@ -3256,7 +3325,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.000206675889551395', @@ -3298,7 +3368,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.000206675889551395', @@ -3340,7 +3411,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.000201332888879835', @@ -3382,7 +3454,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.000201332888879835', @@ -3424,7 +3497,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.00000000454541448', @@ -3466,7 +3540,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.00000000454541448', @@ -3508,7 +3583,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.000000004421040886', @@ -3542,7 +3618,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003] }, { expectedConvertQuote: '0.000000004406314787', @@ -3584,7 +3661,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '0.000000004406314787', @@ -3626,7 +3704,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '0.000000004406314787', @@ -3668,7 +3747,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.003] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.003] }, { expectedConvertQuote: '0.000000003689610342', @@ -3710,7 +3790,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.000000003689610342', @@ -3752,7 +3833,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.0005] }, { expectedConvertQuote: '0.000000003689610342', @@ -3794,7 +3876,8 @@ console.log(trade); '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', ], uniswapVersion: 'v3', - liquidityProviderFee: [0.0005, 0.003, 0.0005] + liquidityProviderFee: 0, + liquidityProviderFeesV3: [0.0005, 0.003, 0.0005] }, ], hasEnoughAllowance: true, From 6a9aab443afb2bad372b747626135a35a430cb3e Mon Sep 17 00:00:00 2001 From: liu Date: Thu, 4 Aug 2022 08:53:50 +0800 Subject: [PATCH 20/20] empty liquidityProviderFeesV3 for v2 --- README.md | 10 +++++----- src/factories/router/uniswap-router.factory.ts | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 846fdd2..603279d 100644 --- a/README.md +++ b/README.md @@ -437,7 +437,7 @@ export interface TradeContext { // A portion of each trade goes to // liquidity providers as a protocol of incentive // length must be routePath.length - 1 - // v2 always = (0.3%) ex [0.003, 0.003] + // v2 always = [] // v3 depends on the fee amount sent on that pool // - low = 0.05% // - medium = 0.3% @@ -448,7 +448,7 @@ export interface TradeContext { liquidityProviderFeesV3: string[]; // A portion of each trade goes to // liquidity providers as a protocol of incentive - // v2 always = (0.3%) + // v2 always = [] // v3 depends on the fee amount sent on that pool // - low = 0.05% // - medium = 0.3% @@ -983,7 +983,7 @@ console.log(trade); ], uniswapVersion: 'v2', liquidityProviderFee: 0.003, - liquidityProviderFeesV3: [0.003, 0.003], + liquidityProviderFeesV3: [], }, { expectedConvertQuote: '0.014606303273323544', @@ -1272,7 +1272,7 @@ console.log(trade); ], uniswapVersion: 'v2', liquidityProviderFee: 0.003, - liquidityProviderFeesV3: [0.003] + liquidityProviderFeesV3: [] }, { expectedConvertQuote: '446400.4834047', @@ -2756,7 +2756,7 @@ console.log(trade); ], uniswapVersion: 'v2', liquidityProviderFee: 0.003, - liquidityProviderFeesV3: [0.003, 0.003, 0.003] + liquidityProviderFeesV3: [] }, { expectedConvertQuote: '0.00022151807282109', diff --git a/src/factories/router/uniswap-router.factory.ts b/src/factories/router/uniswap-router.factory.ts index e460f9a..ef487f9 100644 --- a/src/factories/router/uniswap-router.factory.ts +++ b/src/factories/router/uniswap-router.factory.ts @@ -1389,7 +1389,7 @@ export class UniswapRouterFactory { routes.push({ route: [fromTokenRoutes.token, toTokenRoutes.token], liquidityProviderFee: this.LIQUIDITY_PROVIDER_FEE_V2, - liquidityProviderFeesV3: [this.LIQUIDITY_PROVIDER_FEE_V2], + liquidityProviderFeesV3: [], }); } @@ -1405,7 +1405,7 @@ export class UniswapRouterFactory { routes.push({ route: [fromTokenRoutes.token, tokenRoute.token, toTokenRoutes.token], liquidityProviderFee: this.LIQUIDITY_PROVIDER_FEE_V2, - liquidityProviderFeesV3: new Array(2).fill(this.LIQUIDITY_PROVIDER_FEE_V2), + liquidityProviderFeesV3: [], }); for (let f = 0; f < fromTokenRoutes.pairs.fromTokenPairs!.length; f++) { @@ -1431,7 +1431,7 @@ export class UniswapRouterFactory { routes.push({ route: workedOutFromRoute, liquidityProviderFee: this.LIQUIDITY_PROVIDER_FEE_V2, - liquidityProviderFeesV3: new Array(3).fill(this.LIQUIDITY_PROVIDER_FEE_V2), + liquidityProviderFeesV3: [], }); } } @@ -1460,7 +1460,7 @@ export class UniswapRouterFactory { routes.push({ route: workedOutToRoute, liquidityProviderFee: this.LIQUIDITY_PROVIDER_FEE_V2, - liquidityProviderFeesV3: new Array(3).fill(this.LIQUIDITY_PROVIDER_FEE_V2), + liquidityProviderFeesV3: [], }); } }