Commit fe6324f8 authored by Vignesh Mohankumar's avatar Vignesh Mohankumar Committed by GitHub

feat: remove v2, v3 swap router (#4372)

* remove v3 router

* rm v2

* unused

* remove anytrade

* unused

* rm shared

* remove optimized trade

* celo fix
parent 4a70eb59
......@@ -13,7 +13,7 @@ export const V2_ROUTER_ADDRESS: AddressMap = constructSameAddressMap('0x7a250d56
// celo v3 addresses
const CELO_V3_CORE_FACTORY_ADDRESSES = '0xAfE208a311B21f13EF87E33A90049fC17A7acDEc'
const CELO_V3_ROUTER_ADDRESS = '0x5615CDAb10dc425a742d643d949a7F474C01abc4'
const CELO_ROUTER_ADDRESS = '0x5615CDAb10dc425a742d643d949a7F474C01abc4'
const CELO_V3_MIGRATOR_ADDRESSES = '0x3cFd4d48EDfDCC53D3f173F596f621064614C582'
const CELO_MULTICALL_ADDRESS = '0x633987602DE5C4F337e3DbF265303A1080324204'
const CELO_QUOTER_ADDRESSES = '0x82825d0554fA07f7FC52Ab63c961F330fdEFa8E8'
......@@ -34,19 +34,6 @@ export const V3_CORE_FACTORY_ADDRESSES: AddressMap = {
[SupportedChainId.CELO_ALFAJORES]: CELO_V3_CORE_FACTORY_ADDRESSES,
}
export const V3_ROUTER_ADDRESS: AddressMap = {
...constructSameAddressMap('0xE592427A0AEce92De3Edee1F18E0157C05861564', [
SupportedChainId.OPTIMISM,
SupportedChainId.OPTIMISTIC_KOVAN,
SupportedChainId.ARBITRUM_ONE,
SupportedChainId.ARBITRUM_RINKEBY,
SupportedChainId.POLYGON,
SupportedChainId.POLYGON_MUMBAI,
]),
[SupportedChainId.CELO]: CELO_V3_ROUTER_ADDRESS,
[SupportedChainId.CELO_ALFAJORES]: CELO_V3_ROUTER_ADDRESS,
}
export const V3_MIGRATOR_ADDRESSES: AddressMap = {
...constructSameAddressMap('0xA5644E29708357803b5A882D272c41cC0dF92B34', [
SupportedChainId.ARBITRUM_ONE,
......@@ -80,8 +67,8 @@ export const SWAP_ROUTER_ADDRESSES: AddressMap = {
SupportedChainId.POLYGON,
SupportedChainId.POLYGON_MUMBAI,
]),
[SupportedChainId.CELO]: CELO_V3_ROUTER_ADDRESS,
[SupportedChainId.CELO_ALFAJORES]: CELO_V3_ROUTER_ADDRESS,
[SupportedChainId.CELO]: CELO_ROUTER_ADDRESS,
[SupportedChainId.CELO_ALFAJORES]: CELO_ROUTER_ADDRESS,
}
/**
......
import { Trade } from '@uniswap/router-sdk'
import { Currency, CurrencyAmount, Percent, TradeType } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import useSwapApproval, { useSwapApprovalOptimizedTrade } from 'lib/hooks/swap/useSwapApproval'
import useSwapApproval from 'lib/hooks/swap/useSwapApproval'
import { ApprovalState, useApproval } from 'lib/hooks/useApproval'
import { useCallback } from 'react'
......@@ -31,19 +29,8 @@ export function useApproveCallback(
return [approval, useGetAndTrackApproval(getApproval)]
}
export function useApprovalOptimizedTrade(
trade: Trade<Currency, Currency, TradeType> | undefined,
allowedSlippage: Percent
) {
return useSwapApprovalOptimizedTrade(trade, allowedSlippage, useHasPendingApproval)
}
export function useApproveCallbackFromTrade(
trade:
| V2Trade<Currency, Currency, TradeType>
| V3Trade<Currency, Currency, TradeType>
| Trade<Currency, Currency, TradeType>
| undefined,
trade: Trade<Currency, Currency, TradeType> | undefined,
allowedSlippage: Percent
): [ApprovalState, () => Promise<void>] {
const [approval, getApproval] = useSwapApproval(trade, allowedSlippage, useHasPendingApproval)
......
......@@ -2,14 +2,12 @@ import { BigNumber } from '@ethersproject/bignumber'
import { splitSignature } from '@ethersproject/bytes'
import { Trade } from '@uniswap/router-sdk'
import { Currency, CurrencyAmount, Percent, TradeType } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import { useWeb3React } from '@web3-react/core'
import JSBI from 'jsbi'
import { useSingleCallResult } from 'lib/hooks/multicall'
import { useMemo, useState } from 'react'
import { SWAP_ROUTER_ADDRESSES, V3_ROUTER_ADDRESS } from '../constants/addresses'
import { SWAP_ROUTER_ADDRESSES } from '../constants/addresses'
import { DAI, UNI, USDC_MAINNET } from '../constants/tokens'
import { useEIP2612Contract } from './useContract'
import useIsArgentWallet from './useIsArgentWallet'
......@@ -260,23 +258,12 @@ export function useERC20Permit(
}
export function useERC20PermitFromTrade(
trade:
| V2Trade<Currency, Currency, TradeType>
| V3Trade<Currency, Currency, TradeType>
| Trade<Currency, Currency, TradeType>
| undefined,
trade: Trade<Currency, Currency, TradeType> | undefined,
allowedSlippage: Percent,
transactionDeadline: BigNumber | undefined
) {
const { chainId } = useWeb3React()
const swapRouterAddress = chainId
? // v2 router does not support
trade instanceof V2Trade
? undefined
: trade instanceof V3Trade
? V3_ROUTER_ADDRESS[chainId]
: SWAP_ROUTER_ADDRESSES[chainId]
: undefined
const swapRouterAddress = chainId ? SWAP_ROUTER_ADDRESSES[chainId] : undefined
const amountToApprove = useMemo(
() => (trade ? trade.maximumAmountIn(allowedSlippage) : undefined),
[trade, allowedSlippage]
......
import { BigNumber } from '@ethersproject/bignumber'
import { SwapRouter, Trade } from '@uniswap/router-sdk'
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
import { Router as V2SwapRouter, Trade as V2Trade } from '@uniswap/v2-sdk'
import { FeeOptions, SwapRouter as V3SwapRouter, Trade as V3Trade } from '@uniswap/v3-sdk'
import { FeeOptions } from '@uniswap/v3-sdk'
import { useWeb3React } from '@web3-react/core'
import { SWAP_ROUTER_ADDRESSES, V3_ROUTER_ADDRESS } from 'constants/addresses'
import { SWAP_ROUTER_ADDRESSES } from 'constants/addresses'
import { useMemo } from 'react'
import approveAmountCalldata from 'utils/approveAmountCalldata'
import { useArgentWalletContract } from './useArgentWalletContract'
import { useV2RouterContract } from './useContract'
import useENS from './useENS'
import { SignatureData } from './useERC20Permit'
export type AnyTrade =
| V2Trade<Currency, Currency, TradeType>
| V3Trade<Currency, Currency, TradeType>
| Trade<Currency, Currency, TradeType>
interface SwapCall {
address: string
calldata: string
......@@ -32,7 +25,7 @@ interface SwapCall {
* @param signatureData the signature data of the permit of the input token amount, if available
*/
export function useSwapCallArguments(
trade: AnyTrade | undefined,
trade: Trade<Currency, Currency, TradeType> | undefined,
allowedSlippage: Percent,
recipientAddressOrName: string | null | undefined,
signatureData: SignatureData | null | undefined,
......@@ -43,131 +36,67 @@ export function useSwapCallArguments(
const { address: recipientAddress } = useENS(recipientAddressOrName)
const recipient = recipientAddressOrName === null ? account : recipientAddress
const routerContract = useV2RouterContract()
const argentWalletContract = useArgentWalletContract()
return useMemo(() => {
if (!trade || !recipient || !provider || !account || !chainId || !deadline) return []
if (trade instanceof V2Trade) {
if (!routerContract) return []
const swapMethods = []
swapMethods.push(
V2SwapRouter.swapCallParameters(trade, {
feeOnTransfer: false,
allowedSlippage,
recipient,
deadline: deadline.toNumber(),
})
)
const swapRouterAddress = chainId ? SWAP_ROUTER_ADDRESSES[chainId] : undefined
if (!swapRouterAddress) return []
if (trade.tradeType === TradeType.EXACT_INPUT) {
swapMethods.push(
V2SwapRouter.swapCallParameters(trade, {
feeOnTransfer: true,
allowedSlippage,
recipient,
deadline: deadline.toNumber(),
})
)
}
return swapMethods.map(({ methodName, args, value }) => {
if (argentWalletContract && trade.inputAmount.currency.isToken) {
return {
address: argentWalletContract.address,
calldata: argentWalletContract.interface.encodeFunctionData('wc_multiCall', [
[
approveAmountCalldata(trade.maximumAmountIn(allowedSlippage), routerContract.address),
{
to: routerContract.address,
value,
data: routerContract.interface.encodeFunctionData(methodName, args),
},
],
]),
value: '0x0',
const { value, calldata } = SwapRouter.swapCallParameters(trade, {
fee: feeOptions,
recipient,
slippageTolerance: allowedSlippage,
...(signatureData
? {
inputTokenPermit:
'allowed' in signatureData
? {
expiry: signatureData.deadline,
nonce: signatureData.nonce,
s: signatureData.s,
r: signatureData.r,
v: signatureData.v as any,
}
: {
deadline: signatureData.deadline,
amount: signatureData.amount,
s: signatureData.s,
r: signatureData.r,
v: signatureData.v as any,
},
}
} else {
return {
address: routerContract.address,
calldata: routerContract.interface.encodeFunctionData(methodName, args),
value,
}
}
})
} else {
// swap options shared by v3 and v2+v3 swap routers
const sharedSwapOptions = {
fee: feeOptions,
recipient,
slippageTolerance: allowedSlippage,
...(signatureData
? {
inputTokenPermit:
'allowed' in signatureData
? {
expiry: signatureData.deadline,
nonce: signatureData.nonce,
s: signatureData.s,
r: signatureData.r,
v: signatureData.v as any,
}
: {
deadline: signatureData.deadline,
amount: signatureData.amount,
s: signatureData.s,
r: signatureData.r,
v: signatureData.v as any,
},
}
: {}),
}
const swapRouterAddress = chainId
? trade instanceof V3Trade
? V3_ROUTER_ADDRESS[chainId]
: SWAP_ROUTER_ADDRESSES[chainId]
: undefined
if (!swapRouterAddress) return []
: {}),
const { value, calldata } =
trade instanceof V3Trade
? V3SwapRouter.swapCallParameters(trade, {
...sharedSwapOptions,
deadline: deadline.toString(),
})
: SwapRouter.swapCallParameters(trade, {
...sharedSwapOptions,
deadlineOrPreviousBlockhash: deadline.toString(),
})
deadlineOrPreviousBlockhash: deadline.toString(),
})
if (argentWalletContract && trade.inputAmount.currency.isToken) {
return [
{
address: argentWalletContract.address,
calldata: argentWalletContract.interface.encodeFunctionData('wc_multiCall', [
[
approveAmountCalldata(trade.maximumAmountIn(allowedSlippage), swapRouterAddress),
{
to: swapRouterAddress,
value,
data: calldata,
},
],
]),
value: '0x0',
},
]
}
if (argentWalletContract && trade.inputAmount.currency.isToken) {
return [
{
address: swapRouterAddress,
calldata,
value,
address: argentWalletContract.address,
calldata: argentWalletContract.interface.encodeFunctionData('wc_multiCall', [
[
approveAmountCalldata(trade.maximumAmountIn(allowedSlippage), swapRouterAddress),
{
to: swapRouterAddress,
value,
data: calldata,
},
],
]),
value: '0x0',
},
]
}
return [
{
address: swapRouterAddress,
calldata,
value,
},
]
}, [
account,
allowedSlippage,
......@@ -177,7 +106,6 @@ export function useSwapCallArguments(
feeOptions,
provider,
recipient,
routerContract,
signatureData,
trade,
])
......
// eslint-disable-next-line no-restricted-imports
import { Percent, TradeType } from '@uniswap/sdk-core'
import { Trade } from '@uniswap/router-sdk'
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { SwapCallbackState, useSwapCallback as useLibSwapCallBack } from 'lib/hooks/swap/useSwapCallback'
import { ReactNode, useMemo } from 'react'
......@@ -9,13 +10,12 @@ import { TransactionType } from '../state/transactions/types'
import { currencyId } from '../utils/currencyId'
import useENS from './useENS'
import { SignatureData } from './useERC20Permit'
import { AnyTrade } from './useSwapCallArguments'
import useTransactionDeadline from './useTransactionDeadline'
// returns a function that will execute a swap, if the parameters are all valid
// and the user has approved the slippage adjusted input amount for the trade
export function useSwapCallback(
trade: AnyTrade | undefined, // trade to execute, required
trade: Trade<Currency, Currency, TradeType> | undefined, // trade to execute, required
allowedSlippage: Percent, // in bips
recipientAddressOrName: string | null, // the ENS name or address of the recipient of the trade, or null if swap should be returned to sender
signatureData: SignatureData | undefined | null
......
......@@ -4,18 +4,11 @@ import { JsonRpcProvider, TransactionResponse } from '@ethersproject/providers'
import { t, Trans } from '@lingui/macro'
import { Trade } from '@uniswap/router-sdk'
import { Currency, TradeType } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import { useMemo } from 'react'
import { calculateGasMargin } from 'utils/calculateGasMargin'
import isZero from 'utils/isZero'
import { swapErrorToUserReadableMessage } from 'utils/swapErrorToUserReadableMessage'
type AnyTrade =
| V2Trade<Currency, Currency, TradeType>
| V3Trade<Currency, Currency, TradeType>
| Trade<Currency, Currency, TradeType>
interface SwapCall {
address: string
calldata: string
......@@ -41,7 +34,7 @@ export default function useSendSwapTransaction(
account: string | null | undefined,
chainId: number | undefined,
provider: JsonRpcProvider | undefined,
trade: AnyTrade | undefined, // trade to execute, required
trade: Trade<Currency, Currency, TradeType> | undefined, // trade to execute, required
swapCalls: SwapCall[]
): { callback: null | (() => Promise<TransactionResponse>) } {
return useMemo(() => {
......
import { Protocol, Trade } from '@uniswap/router-sdk'
import { Trade } from '@uniswap/router-sdk'
import { Currency, CurrencyAmount, Percent, Token, TradeType } from '@uniswap/sdk-core'
import { Pair, Route as V2Route, Trade as V2Trade } from '@uniswap/v2-sdk'
import { Pool, Route as V3Route, Trade as V3Trade } from '@uniswap/v3-sdk'
import { useWeb3React } from '@web3-react/core'
import { SWAP_ROUTER_ADDRESSES, V2_ROUTER_ADDRESS, V3_ROUTER_ADDRESS } from 'constants/addresses'
import { SWAP_ROUTER_ADDRESSES } from 'constants/addresses'
import { useMemo } from 'react'
import { getTxOptimizedSwapRouter, SwapRouterVersion } from 'utils/getTxOptimizedSwapRouter'
import { ApprovalState, useApproval, useApprovalStateForSpender } from '../useApproval'
import { useApproval } from '../useApproval'
export { ApprovalState } from '../useApproval'
/** Returns approval state for all known swap routers */
function useSwapApprovalStates(
trade: Trade<Currency, Currency, TradeType> | undefined,
allowedSlippage: Percent,
useIsPendingApproval: (token?: Token, spender?: string) => boolean
): { v2: ApprovalState; v3: ApprovalState; v2V3: ApprovalState } {
const { chainId } = useWeb3React()
const amountToApprove = useMemo(
() => (trade && trade.inputAmount.currency.isToken ? trade.maximumAmountIn(allowedSlippage) : undefined),
[trade, allowedSlippage]
)
const v2RouterAddress = chainId ? V2_ROUTER_ADDRESS[chainId] : undefined
const v3RouterAddress = chainId ? V3_ROUTER_ADDRESS[chainId] : undefined
const swapRouterAddress = chainId ? SWAP_ROUTER_ADDRESSES[chainId] : undefined
const v2 = useApprovalStateForSpender(amountToApprove, v2RouterAddress, useIsPendingApproval)
const v3 = useApprovalStateForSpender(amountToApprove, v3RouterAddress, useIsPendingApproval)
const v2V3 = useApprovalStateForSpender(amountToApprove, swapRouterAddress, useIsPendingApproval)
return useMemo(() => ({ v2, v3, v2V3 }), [v2, v2V3, v3])
}
export function useSwapRouterAddress(
trade:
| V2Trade<Currency, Currency, TradeType>
| V3Trade<Currency, Currency, TradeType>
| Trade<Currency, Currency, TradeType>
| undefined
) {
const { chainId } = useWeb3React()
return useMemo(
() =>
chainId
? trade instanceof V2Trade
? V2_ROUTER_ADDRESS[chainId]
: trade instanceof V3Trade
? V3_ROUTER_ADDRESS[chainId]
: SWAP_ROUTER_ADDRESSES[chainId]
: undefined,
[chainId, trade]
)
}
// wraps useApproveCallback in the context of a swap
export default function useSwapApproval(
trade:
| V2Trade<Currency, Currency, TradeType>
| V3Trade<Currency, Currency, TradeType>
| Trade<Currency, Currency, TradeType>
| undefined,
trade: Trade<Currency, Currency, TradeType> | undefined,
allowedSlippage: Percent,
useIsPendingApproval: (token?: Token, spender?: string) => boolean,
amount?: CurrencyAmount<Currency> // defaults to trade.maximumAmountIn(allowedSlippage)
) {
const { chainId } = useWeb3React()
const amountToApprove = useMemo(
() => amount || (trade && trade.inputAmount.currency.isToken ? trade.maximumAmountIn(allowedSlippage) : undefined),
[amount, trade, allowedSlippage]
)
const spender = useSwapRouterAddress(trade)
const spender = chainId ? SWAP_ROUTER_ADDRESSES[chainId] : undefined
return useApproval(amountToApprove, spender, useIsPendingApproval)
}
export function useSwapApprovalOptimizedTrade(
trade: Trade<Currency, Currency, TradeType> | undefined,
allowedSlippage: Percent,
useIsPendingApproval: (token?: Token, spender?: string) => boolean
):
| V2Trade<Currency, Currency, TradeType>
| V3Trade<Currency, Currency, TradeType>
| Trade<Currency, Currency, TradeType>
| undefined {
const onlyV2Routes = trade?.routes.every((route) => route.protocol === Protocol.V2)
const onlyV3Routes = trade?.routes.every((route) => route.protocol === Protocol.V3)
const tradeHasSplits = (trade?.routes.length ?? 0) > 1
const approvalStates = useSwapApprovalStates(trade, allowedSlippage, useIsPendingApproval)
const optimizedSwapRouter = useMemo(
() => getTxOptimizedSwapRouter({ onlyV2Routes, onlyV3Routes, tradeHasSplits, approvalStates }),
[approvalStates, tradeHasSplits, onlyV2Routes, onlyV3Routes]
)
return useMemo(() => {
if (!trade) return undefined
try {
switch (optimizedSwapRouter) {
case SwapRouterVersion.V2V3:
return trade
case SwapRouterVersion.V2:
const pairs = trade.swaps[0].route.pools.filter((pool) => pool instanceof Pair) as Pair[]
const v2Route = new V2Route(pairs, trade.inputAmount.currency, trade.outputAmount.currency)
return new V2Trade(v2Route, trade.inputAmount, trade.tradeType)
case SwapRouterVersion.V3:
return V3Trade.createUncheckedTradeWithMultipleRoutes({
routes: trade.swaps.map(({ route, inputAmount, outputAmount }) => ({
route: new V3Route(
route.pools.filter((p): p is Pool => p instanceof Pool),
inputAmount.currency,
outputAmount.currency
),
inputAmount,
outputAmount,
})),
tradeType: trade.tradeType,
})
default:
return undefined
}
} catch (e) {
// TODO(#2989): remove try-catch
console.debug(e)
return undefined
}
}, [trade, optimizedSwapRouter])
}
......@@ -2,12 +2,13 @@
import { BigNumber } from '@ethersproject/bignumber'
import { TransactionResponse } from '@ethersproject/providers'
import { Trans } from '@lingui/macro'
import { Percent } from '@uniswap/sdk-core'
import { Trade } from '@uniswap/router-sdk'
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
import { FeeOptions } from '@uniswap/v3-sdk'
import { useWeb3React } from '@web3-react/core'
import useENS from 'hooks/useENS'
import { SignatureData } from 'hooks/useERC20Permit'
import { AnyTrade, useSwapCallArguments } from 'hooks/useSwapCallArguments'
import { useSwapCallArguments } from 'hooks/useSwapCallArguments'
import { ReactNode, useMemo } from 'react'
import useSendSwapTransaction from './useSendSwapTransaction'
......@@ -24,7 +25,7 @@ interface UseSwapCallbackReturns {
error?: ReactNode
}
interface UseSwapCallbackArgs {
trade: AnyTrade | undefined // trade to execute, required
trade: Trade<Currency, Currency, TradeType> | undefined // trade to execute, required
allowedSlippage: Percent // in bips
recipientAddressOrName: string | null | undefined // the ENS name or address of the recipient of the trade, or null if swap should be returned to sender
signatureData: SignatureData | null | undefined
......
......@@ -17,7 +17,7 @@ export enum ApprovalState {
APPROVED = 'APPROVED',
}
export function useApprovalStateForSpender(
function useApprovalStateForSpender(
amountToApprove: CurrencyAmount<Currency> | undefined,
spender: string | undefined,
useIsPendingApproval: (token?: Token, spender?: string) => boolean
......
import { Trans } from '@lingui/macro'
import { Trade } from '@uniswap/router-sdk'
import { Currency, CurrencyAmount, Percent, Token, TradeType } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import { useWeb3React } from '@web3-react/core'
import { sendAnalyticsEvent } from 'components/AmplitudeAnalytics'
import { ElementName, Event, EventName, PageName, SectionName } from 'components/AmplitudeAnalytics/constants'
......@@ -52,7 +50,7 @@ import { SwitchLocaleLink } from '../../components/SwitchLocaleLink'
import TokenWarningModal from '../../components/TokenWarningModal'
import { TOKEN_SHORTHANDS } from '../../constants/tokens'
import { useAllTokens, useCurrency } from '../../hooks/Tokens'
import { ApprovalState, useApprovalOptimizedTrade, useApproveCallbackFromTrade } from '../../hooks/useApproveCallback'
import { ApprovalState, useApproveCallbackFromTrade } from '../../hooks/useApproveCallback'
import useENSAddress from '../../hooks/useENSAddress'
import { useERC20PermitFromTrade, UseERC20PermitState } from '../../hooks/useERC20Permit'
import useIsArgentWallet from '../../hooks/useIsArgentWallet'
......@@ -153,6 +151,8 @@ const formatSwapQuoteReceivedEventProperties = (
}
}
const TRADE_STRING = 'SwapRouter'
export default function Swap() {
const navigate = useNavigate()
const redesignFlag = useRedesignFlag()
......@@ -305,22 +305,14 @@ export default function Swap() {
currencies[Field.INPUT] && currencies[Field.OUTPUT] && parsedAmounts[independentField]?.greaterThan(JSBI.BigInt(0))
)
const approvalOptimizedTrade = useApprovalOptimizedTrade(trade, allowedSlippage)
const approvalOptimizedTradeString =
approvalOptimizedTrade instanceof V2Trade
? 'V2SwapRouter'
: approvalOptimizedTrade instanceof V3Trade
? 'V3SwapRouter'
: 'SwapRouter'
// check whether the user has approved the router on the input token
const [approvalState, approveCallback] = useApproveCallbackFromTrade(approvalOptimizedTrade, allowedSlippage)
const [approvalState, approveCallback] = useApproveCallbackFromTrade(trade, allowedSlippage)
const transactionDeadline = useTransactionDeadline()
const {
state: signatureState,
signatureData,
gatherPermitSignature,
} = useERC20PermitFromTrade(approvalOptimizedTrade, allowedSlippage, transactionDeadline)
} = useERC20PermitFromTrade(trade, allowedSlippage, transactionDeadline)
const handleApprove = useCallback(async () => {
if (signatureState === UseERC20PermitState.NOT_SIGNED && gatherPermitSignature) {
......@@ -338,16 +330,10 @@ export default function Swap() {
sendEvent({
category: 'Swap',
action: 'Approve',
label: [approvalOptimizedTradeString, approvalOptimizedTrade?.inputAmount?.currency.symbol].join('/'),
label: [TRADE_STRING, trade?.inputAmount?.currency.symbol].join('/'),
})
}
}, [
signatureState,
gatherPermitSignature,
approveCallback,
approvalOptimizedTradeString,
approvalOptimizedTrade?.inputAmount?.currency.symbol,
])
}, [signatureState, gatherPermitSignature, approveCallback, trade?.inputAmount?.currency.symbol])
// check if user has gone through approval process, used to show two step buttons, reset on token change
const [approvalSubmitted, setApprovalSubmitted] = useState<boolean>(false)
......@@ -367,7 +353,7 @@ export default function Swap() {
// the callback to execute the swap
const { callback: swapCallback, error: swapCallbackError } = useSwapCallback(
approvalOptimizedTrade,
trade,
allowedSlippage,
recipient,
signatureData
......@@ -397,12 +383,9 @@ export default function Swap() {
: (recipientAddress ?? recipient) === account
? 'Swap w/o Send + recipient'
: 'Swap w/ Send',
label: [
approvalOptimizedTradeString,
approvalOptimizedTrade?.inputAmount?.currency?.symbol,
approvalOptimizedTrade?.outputAmount?.currency?.symbol,
'MH',
].join('/'),
label: [TRADE_STRING, trade?.inputAmount?.currency?.symbol, trade?.outputAmount?.currency?.symbol, 'MH'].join(
'/'
),
})
})
.catch((error) => {
......@@ -422,9 +405,8 @@ export default function Swap() {
recipient,
recipientAddress,
account,
approvalOptimizedTradeString,
approvalOptimizedTrade?.inputAmount?.currency?.symbol,
approvalOptimizedTrade?.outputAmount?.currency?.symbol,
trade?.inputAmount?.currency?.symbol,
trade?.outputAmount?.currency?.symbol,
])
// errors
......
import { ApprovalState } from 'lib/hooks/useApproval'
import { getTxOptimizedSwapRouter, SwapRouterVersion } from './getTxOptimizedSwapRouter'
const getApprovalState = (approved: SwapRouterVersion[]) => ({
v2: approved.includes(SwapRouterVersion.V2) ? ApprovalState.APPROVED : ApprovalState.NOT_APPROVED,
v3: approved.includes(SwapRouterVersion.V3) ? ApprovalState.APPROVED : ApprovalState.NOT_APPROVED,
v2V3: approved.includes(SwapRouterVersion.V2V3) ? ApprovalState.APPROVED : ApprovalState.NOT_APPROVED,
})
describe(getTxOptimizedSwapRouter, () => {
it('always selects v2v3 when approved', () => {
expect(
getTxOptimizedSwapRouter({
onlyV2Routes: true,
onlyV3Routes: false,
tradeHasSplits: false,
approvalStates: getApprovalState([SwapRouterVersion.V2V3]),
})
).toEqual(SwapRouterVersion.V2V3)
expect(
getTxOptimizedSwapRouter({
onlyV2Routes: false,
onlyV3Routes: true,
tradeHasSplits: false,
approvalStates: getApprovalState([SwapRouterVersion.V2V3]),
})
).toEqual(SwapRouterVersion.V2V3)
expect(
getTxOptimizedSwapRouter({
onlyV2Routes: false,
onlyV3Routes: true,
tradeHasSplits: false,
approvalStates: getApprovalState([SwapRouterVersion.V2, SwapRouterVersion.V3, SwapRouterVersion.V2V3]),
})
).toEqual(SwapRouterVersion.V2V3)
})
it('selects the right router when only v2 routes', () => {
const base = { onlyV3Routes: false }
// selects v2
expect(
getTxOptimizedSwapRouter({
...base,
onlyV2Routes: true,
tradeHasSplits: false,
approvalStates: getApprovalState([SwapRouterVersion.V2, SwapRouterVersion.V3]),
})
).toEqual(SwapRouterVersion.V2)
// selects v2V3
expect(
getTxOptimizedSwapRouter({
...base,
onlyV2Routes: true,
tradeHasSplits: true,
approvalStates: getApprovalState([SwapRouterVersion.V2]),
})
).toEqual(SwapRouterVersion.V2V3)
expect(
getTxOptimizedSwapRouter({
...base,
onlyV2Routes: true,
tradeHasSplits: true,
approvalStates: getApprovalState([SwapRouterVersion.V2, SwapRouterVersion.V2V3]),
})
).toEqual(SwapRouterVersion.V2V3)
})
it('selects the right router when only v3 routes', () => {
const base = { onlyV2Routes: false }
// select v3
expect(
getTxOptimizedSwapRouter({
...base,
onlyV3Routes: true,
tradeHasSplits: false,
approvalStates: getApprovalState([SwapRouterVersion.V2, SwapRouterVersion.V3]),
})
).toEqual(SwapRouterVersion.V3)
expect(
getTxOptimizedSwapRouter({
...base,
onlyV3Routes: true,
tradeHasSplits: true,
approvalStates: getApprovalState([SwapRouterVersion.V3]),
})
).toEqual(SwapRouterVersion.V3)
// selects v2V3
expect(
getTxOptimizedSwapRouter({
...base,
onlyV3Routes: true,
tradeHasSplits: true,
approvalStates: getApprovalState([SwapRouterVersion.V2, SwapRouterVersion.V2V3]),
})
).toEqual(SwapRouterVersion.V2V3)
})
})
import { ApprovalState } from 'lib/hooks/useApproval'
export enum SwapRouterVersion {
V2,
V3,
V2V3,
}
/**
* Returns the swap router that will result in the least amount of txs (less gas) for a given swap.
* Heuristic:
* - if trade contains a single v2-only trade & V2 SwapRouter is approved: use V2 SwapRouter
* - if trade contains only v3 & V3 SwapRouter is approved: use V3 SwapRouter
* - else: approve and use V2+V3 SwapRouter
*/
export function getTxOptimizedSwapRouter({
onlyV2Routes,
onlyV3Routes,
tradeHasSplits,
approvalStates,
}: {
onlyV2Routes: boolean | undefined
onlyV3Routes: boolean | undefined
tradeHasSplits: boolean | undefined
approvalStates: { v2: ApprovalState; v3: ApprovalState; v2V3: ApprovalState }
}): SwapRouterVersion | undefined {
if ([approvalStates.v2, approvalStates.v3, approvalStates.v2V3].includes(ApprovalState.PENDING)) return undefined
if (approvalStates.v2V3 === ApprovalState.APPROVED) return SwapRouterVersion.V2V3
if (approvalStates.v2 === ApprovalState.APPROVED && onlyV2Routes && !tradeHasSplits) return SwapRouterVersion.V2
if (approvalStates.v3 === ApprovalState.APPROVED && onlyV3Routes) return SwapRouterVersion.V3
return SwapRouterVersion.V2V3
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment