feat: dynamic FOT tax fetching (#7252)
* feat: disable exact_output FOT swaps * fix: pr comments * test: update snapshots * feat: dynamically fetch tax rates * remove tax constants file * test: update useRoutingAPITrade expected args * fix: useSwapTaxes nits * lint: useSwapTaxes dependency array
This commit is contained in:
parent
45a138dec1
commit
b6e388c68c
133
src/abis/fee-on-transfer-detector.json
Normal file
133
src/abis/fee-on-transfer-detector.json
Normal file
@ -0,0 +1,133 @@
|
||||
[
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_factoryV2",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "PairLookupFailed",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "SameToken",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address[]",
|
||||
"name": "tokens",
|
||||
"type": "address[]"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "baseToken",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amountToBorrow",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "batchValidate",
|
||||
"outputs": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "buyFeeBps",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "sellFeeBps",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"internalType": "struct TokenFees[]",
|
||||
"name": "fotResults",
|
||||
"type": "tuple[]"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount0",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes",
|
||||
"name": "data",
|
||||
"type": "bytes"
|
||||
}
|
||||
],
|
||||
"name": "uniswapV2Call",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "token",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "baseToken",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amountToBorrow",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "validate",
|
||||
"outputs": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "buyFeeBps",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "sellFeeBps",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"internalType": "struct TokenFees",
|
||||
"name": "fotResult",
|
||||
"type": "tuple"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
@ -1,75 +0,0 @@
|
||||
import { ChainId, Currency, Percent } from '@uniswap/sdk-core'
|
||||
|
||||
import { ZERO_PERCENT } from './misc'
|
||||
|
||||
interface TokenTaxMetadata {
|
||||
buyFee?: Percent
|
||||
sellFee?: Percent
|
||||
}
|
||||
|
||||
const CHAIN_TOKEN_TAX_MAP: { [chainId in number]?: { [address in string]?: TokenTaxMetadata } } = {
|
||||
[ChainId.MAINNET]: {
|
||||
// BULLET
|
||||
'0x8ef32a03784c8fd63bbf027251b9620865bd54b6': {
|
||||
buyFee: new Percent(5, 100), // 5%
|
||||
sellFee: new Percent(5, 100), // 5%
|
||||
},
|
||||
// X
|
||||
'0xabec00542d141bddf58649bfe860c6449807237c': {
|
||||
buyFee: new Percent(1, 100), // 1%
|
||||
sellFee: new Percent(1, 100), // 1%
|
||||
},
|
||||
// HarryPotterObamaKnuckles9Inu
|
||||
'0x2577944fd4b556a99cc5aa0f072e4b944aa088df': {
|
||||
buyFee: new Percent(1, 100), // 1%
|
||||
sellFee: new Percent(11, 1000), // 1.1%
|
||||
},
|
||||
// QWN
|
||||
'0xb354b5da5ea39dadb1cea8140bf242eb24b1821a': {
|
||||
buyFee: new Percent(5, 100), // 5%
|
||||
sellFee: new Percent(5, 100), // 5%
|
||||
},
|
||||
// HarryPotterObamaPacMan8Inu
|
||||
'0x07e0edf8ce600fb51d44f51e3348d77d67f298ae': {
|
||||
buyFee: new Percent(2, 100), // 2%
|
||||
sellFee: new Percent(2, 100), // 2%
|
||||
},
|
||||
// KUKU
|
||||
'0x27206f5a9afd0c51da95f20972885545d3b33647': {
|
||||
buyFee: new Percent(2, 100), // 2%
|
||||
sellFee: new Percent(21, 1000), // 2.1%
|
||||
},
|
||||
// AIMBOT
|
||||
'0x0c48250eb1f29491f1efbeec0261eb556f0973c7': {
|
||||
buyFee: new Percent(5, 100), // 5%
|
||||
sellFee: new Percent(5, 100), // 5%
|
||||
},
|
||||
// PYUSD
|
||||
'0xe0a8ed732658832fac18141aa5ad3542e2eb503b': {
|
||||
buyFee: new Percent(1, 100), // 1%
|
||||
sellFee: new Percent(13, 1000), // 1.3%
|
||||
},
|
||||
// ND4
|
||||
'0x4f849c55180ddf8185c5cc495ed58c3aea9c9a28': {
|
||||
buyFee: new Percent(1, 100), // 1%
|
||||
sellFee: new Percent(1, 100), // 1%
|
||||
},
|
||||
// COCO
|
||||
'0xcb50350ab555ed5d56265e096288536e8cac41eb': {
|
||||
buyFee: new Percent(2, 100), // 2%
|
||||
sellFee: new Percent(26, 1000), // 2.6%
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export function getInputTax(currency: Currency): Percent {
|
||||
if (currency.isNative) return ZERO_PERCENT
|
||||
|
||||
return CHAIN_TOKEN_TAX_MAP[currency.chainId]?.[currency.address.toLowerCase()]?.sellFee ?? ZERO_PERCENT
|
||||
}
|
||||
|
||||
export function getOutputTax(currency: Currency): Percent {
|
||||
if (currency.isNative) return ZERO_PERCENT
|
||||
|
||||
return CHAIN_TOKEN_TAX_MAP[currency.chainId]?.[currency.address.toLowerCase()]?.buyFee ?? ZERO_PERCENT
|
||||
}
|
@ -46,8 +46,10 @@ describe('#useBestV3Trade ExactIn', () => {
|
||||
USDCAmount,
|
||||
DAI,
|
||||
RouterPreference.CLIENT,
|
||||
true, // skipFetch
|
||||
undefined
|
||||
/* skipFetch = */ true,
|
||||
/* account = */ undefined,
|
||||
/* inputTax = */ undefined,
|
||||
/* outputTax = */ undefined
|
||||
)
|
||||
expect(result.current).toEqual({ state: TradeState.NO_ROUTE_FOUND, trade: undefined })
|
||||
})
|
||||
@ -64,8 +66,10 @@ describe('#useDebouncedTrade ExactOut', () => {
|
||||
DAIAmount,
|
||||
USDC_MAINNET,
|
||||
RouterPreference.CLIENT,
|
||||
true, // skipFetch
|
||||
undefined
|
||||
/* skipFetch = */ true,
|
||||
/* account = */ undefined,
|
||||
/* inputTax = */ undefined,
|
||||
/* outputTax = */ undefined
|
||||
)
|
||||
expect(result.current).toEqual({ state: TradeState.NO_ROUTE_FOUND, trade: undefined })
|
||||
})
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core'
|
||||
import { Currency, CurrencyAmount, Percent, TradeType } from '@uniswap/sdk-core'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import { WRAPPED_NATIVE_CURRENCY } from 'constants/tokens'
|
||||
import { DebounceSwapQuoteVariant, useDebounceSwapQuoteFlag } from 'featureFlags/flags/debounceSwapQuote'
|
||||
@ -22,7 +22,9 @@ export function useDebouncedTrade(
|
||||
amountSpecified?: CurrencyAmount<Currency>,
|
||||
otherCurrency?: Currency,
|
||||
routerPreferenceOverride?: RouterPreference.X,
|
||||
account?: string
|
||||
account?: string,
|
||||
inputTax?: Percent,
|
||||
outputTax?: Percent
|
||||
): {
|
||||
state: TradeState
|
||||
trade?: InterfaceTrade
|
||||
@ -34,7 +36,9 @@ export function useDebouncedTrade(
|
||||
amountSpecified?: CurrencyAmount<Currency>,
|
||||
otherCurrency?: Currency,
|
||||
routerPreferenceOverride?: RouterPreference.API | RouterPreference.CLIENT,
|
||||
account?: string
|
||||
account?: string,
|
||||
inputTax?: Percent,
|
||||
outputTax?: Percent
|
||||
): {
|
||||
state: TradeState
|
||||
trade?: ClassicTrade
|
||||
@ -54,7 +58,9 @@ export function useDebouncedTrade(
|
||||
amountSpecified?: CurrencyAmount<Currency>,
|
||||
otherCurrency?: Currency,
|
||||
routerPreferenceOverride?: RouterPreference,
|
||||
account?: string
|
||||
account?: string,
|
||||
inputTax?: Percent,
|
||||
outputTax?: Percent
|
||||
): {
|
||||
state: TradeState
|
||||
trade?: InterfaceTrade
|
||||
@ -91,6 +97,8 @@ export function useDebouncedTrade(
|
||||
otherCurrency,
|
||||
routerPreferenceOverride ?? routerPreference,
|
||||
skipFetch,
|
||||
account
|
||||
account,
|
||||
inputTax,
|
||||
outputTax
|
||||
)
|
||||
}
|
||||
|
88
src/hooks/useSwapTaxes.ts
Normal file
88
src/hooks/useSwapTaxes.ts
Normal file
@ -0,0 +1,88 @@
|
||||
import * as Sentry from '@sentry/react'
|
||||
import { InterfaceEventName } from '@uniswap/analytics-events'
|
||||
import { ChainId, Percent } from '@uniswap/sdk-core'
|
||||
import { WETH_ADDRESS as getWethAddress } from '@uniswap/universal-router-sdk'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import FOT_DETECTOR_ABI from 'abis/fee-on-transfer-detector.json'
|
||||
import { FeeOnTransferDetector } from 'abis/types'
|
||||
import { sendAnalyticsEvent } from 'analytics'
|
||||
import { ZERO_PERCENT } from 'constants/misc'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
import { useContract } from './useContract'
|
||||
|
||||
const FEE_ON_TRANSFER_DETECTOR_ADDRESS = '0x19C97dc2a25845C7f9d1d519c8C2d4809c58b43f'
|
||||
|
||||
function useFeeOnTransferDetectorContract(): FeeOnTransferDetector | null {
|
||||
const { account } = useWeb3React()
|
||||
const contract = useContract<FeeOnTransferDetector>(FEE_ON_TRANSFER_DETECTOR_ADDRESS, FOT_DETECTOR_ABI)
|
||||
|
||||
useEffect(() => {
|
||||
if (contract && account) {
|
||||
sendAnalyticsEvent(InterfaceEventName.WALLET_PROVIDER_USED, {
|
||||
source: 'useFeeOnTransferDetectorContract',
|
||||
contract,
|
||||
})
|
||||
}
|
||||
}, [account, contract])
|
||||
return contract
|
||||
}
|
||||
|
||||
// TODO(WEB-2787): add tax-fetching for other chains
|
||||
const WETH_ADDRESS = getWethAddress(ChainId.MAINNET)
|
||||
const AMOUNT_TO_BORROW = 10000 // smallest amount that has full precision over bps
|
||||
|
||||
const FEE_CACHE: { [address in string]?: { sellTax?: Percent; buyTax?: Percent } } = {}
|
||||
|
||||
async function getSwapTaxes(
|
||||
fotDetector: FeeOnTransferDetector,
|
||||
inputTokenAddress: string | undefined,
|
||||
outputTokenAddress: string | undefined
|
||||
) {
|
||||
const addresses = []
|
||||
if (inputTokenAddress && FEE_CACHE[inputTokenAddress] === undefined) {
|
||||
addresses.push(inputTokenAddress)
|
||||
}
|
||||
|
||||
if (outputTokenAddress && FEE_CACHE[outputTokenAddress] === undefined) {
|
||||
addresses.push(outputTokenAddress)
|
||||
}
|
||||
|
||||
try {
|
||||
if (addresses.length) {
|
||||
const data = await fotDetector.callStatic.batchValidate(addresses, WETH_ADDRESS, AMOUNT_TO_BORROW)
|
||||
|
||||
addresses.forEach((address, index) => {
|
||||
const { sellFeeBps, buyFeeBps } = data[index]
|
||||
const sellTax = new Percent(sellFeeBps.toNumber(), 10000)
|
||||
const buyTax = new Percent(buyFeeBps.toNumber(), 10000)
|
||||
|
||||
FEE_CACHE[address] = { sellTax, buyTax }
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
Sentry.withScope(function (scope) {
|
||||
scope.setTag('method', 'getSwapTaxes')
|
||||
scope.setLevel('warning')
|
||||
Sentry.captureException(e)
|
||||
})
|
||||
}
|
||||
|
||||
const inputTax = (inputTokenAddress ? FEE_CACHE[inputTokenAddress]?.sellTax : ZERO_PERCENT) ?? ZERO_PERCENT
|
||||
const outputTax = (outputTokenAddress ? FEE_CACHE[outputTokenAddress]?.buyTax : ZERO_PERCENT) ?? ZERO_PERCENT
|
||||
|
||||
return { inputTax, outputTax }
|
||||
}
|
||||
|
||||
export function useSwapTaxes(inputTokenAddress: string | undefined, outputTokenAddress: string | undefined) {
|
||||
const fotDetector = useFeeOnTransferDetectorContract()
|
||||
const [{ inputTax, outputTax }, setTaxes] = useState({ inputTax: ZERO_PERCENT, outputTax: ZERO_PERCENT })
|
||||
const { chainId } = useWeb3React()
|
||||
|
||||
useEffect(() => {
|
||||
if (!fotDetector || chainId !== ChainId.MAINNET) return
|
||||
getSwapTaxes(fotDetector, inputTokenAddress, outputTokenAddress).then(setTaxes)
|
||||
}, [fotDetector, inputTokenAddress, outputTokenAddress, chainId])
|
||||
|
||||
return { inputTax, outputTax }
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import { SkipToken, skipToken } from '@reduxjs/toolkit/query/react'
|
||||
import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core'
|
||||
import { Currency, CurrencyAmount, Percent, TradeType } from '@uniswap/sdk-core'
|
||||
import { useFotAdjustmentsEnabled } from 'featureFlags/flags/fotAdjustments'
|
||||
import { useUniswapXEthOutputEnabled } from 'featureFlags/flags/uniswapXEthOutput'
|
||||
import { useUniswapXExactOutputEnabled } from 'featureFlags/flags/uniswapXExactOutput'
|
||||
@ -21,6 +21,8 @@ export function useRoutingAPIArguments({
|
||||
amount,
|
||||
tradeType,
|
||||
routerPreference,
|
||||
inputTax,
|
||||
outputTax,
|
||||
}: {
|
||||
account?: string
|
||||
tokenIn?: Currency
|
||||
@ -28,6 +30,8 @@ export function useRoutingAPIArguments({
|
||||
amount?: CurrencyAmount<Currency>
|
||||
tradeType: TradeType
|
||||
routerPreference: RouterPreference | typeof INTERNAL_ROUTER_PREFERENCE_PRICE
|
||||
inputTax: Percent
|
||||
outputTax: Percent
|
||||
}): GetQuoteArgs | SkipToken {
|
||||
const uniswapXForceSyntheticQuotes = useUniswapXSyntheticQuoteEnabled()
|
||||
const userDisabledUniswapX = useUserDisabledUniswapX()
|
||||
@ -58,6 +62,8 @@ export function useRoutingAPIArguments({
|
||||
uniswapXEthOutputEnabled,
|
||||
uniswapXExactOutputEnabled,
|
||||
fotAdjustmentsEnabled,
|
||||
inputTax,
|
||||
outputTax,
|
||||
},
|
||||
[
|
||||
account,
|
||||
@ -71,6 +77,8 @@ export function useRoutingAPIArguments({
|
||||
userDisabledUniswapX,
|
||||
uniswapXEthOutputEnabled,
|
||||
fotAdjustmentsEnabled,
|
||||
inputTax,
|
||||
outputTax,
|
||||
]
|
||||
)
|
||||
}
|
||||
|
@ -31,7 +31,6 @@ import { SwitchLocaleLink } from 'components/SwitchLocaleLink'
|
||||
import TokenSafetyModal from 'components/TokenSafety/TokenSafetyModal'
|
||||
import { getChainInfo } from 'constants/chainInfo'
|
||||
import { asSupportedChain, isSupportedChain } from 'constants/chains'
|
||||
import { getInputTax, getOutputTax } from 'constants/tax'
|
||||
import { getSwapCurrencyId, TOKEN_SHORTHANDS } from 'constants/tokens'
|
||||
import { useCurrency, useDefaultActiveTokens } from 'hooks/Tokens'
|
||||
import { useIsSwapUnsupported } from 'hooks/useIsSwapUnsupported'
|
||||
@ -279,14 +278,13 @@ export function Swap({
|
||||
parsedAmount,
|
||||
currencies,
|
||||
inputError: swapInputError,
|
||||
inputTax,
|
||||
outputTax,
|
||||
} = swapInfo
|
||||
|
||||
const [inputTokenHasTax, outputTokenHasTax] = useMemo(
|
||||
() => [
|
||||
!!currencies[Field.INPUT] && !getInputTax(currencies[Field.INPUT]).equalTo(0),
|
||||
!!currencies[Field.OUTPUT] && !getOutputTax(currencies[Field.OUTPUT]).equalTo(0),
|
||||
],
|
||||
[currencies]
|
||||
() => [!inputTax.equalTo(0), !outputTax.equalTo(0)],
|
||||
[inputTax, outputTax]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -47,6 +47,8 @@ export interface GetQuoteArgs {
|
||||
uniswapXExactOutputEnabled: boolean
|
||||
userDisabledUniswapX: boolean
|
||||
fotAdjustmentsEnabled: boolean
|
||||
inputTax: Percent
|
||||
outputTax: Percent
|
||||
}
|
||||
|
||||
// from https://github.com/Uniswap/routing-api/blob/main/lib/handlers/schema.ts
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { skipToken } from '@reduxjs/toolkit/query/react'
|
||||
import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core'
|
||||
import { Currency, CurrencyAmount, Percent, TradeType } from '@uniswap/sdk-core'
|
||||
import { IMetric, MetricLoggerUnit, setGlobalMetric } from '@uniswap/smart-order-router'
|
||||
import { sendTiming } from 'components/analytics'
|
||||
import { AVERAGE_L1_BLOCK_TIME } from 'constants/chainInfo'
|
||||
import { ZERO_PERCENT } from 'constants/misc'
|
||||
import { useRoutingAPIArguments } from 'lib/hooks/routing/useRoutingAPIArguments'
|
||||
import ms from 'ms'
|
||||
import { useMemo } from 'react'
|
||||
@ -27,7 +28,9 @@ export function useRoutingAPITrade<TTradeType extends TradeType>(
|
||||
otherCurrency: Currency | undefined,
|
||||
routerPreference: typeof INTERNAL_ROUTER_PREFERENCE_PRICE,
|
||||
skipFetch?: boolean,
|
||||
account?: string
|
||||
account?: string,
|
||||
inputTax?: Percent,
|
||||
outputTax?: Percent
|
||||
): {
|
||||
state: TradeState
|
||||
trade?: ClassicTrade
|
||||
@ -40,7 +43,9 @@ export function useRoutingAPITrade<TTradeType extends TradeType>(
|
||||
otherCurrency: Currency | undefined,
|
||||
routerPreference: RouterPreference,
|
||||
skipFetch?: boolean,
|
||||
account?: string
|
||||
account?: string,
|
||||
inputTax?: Percent,
|
||||
outputTax?: Percent
|
||||
): {
|
||||
state: TradeState
|
||||
trade?: InterfaceTrade
|
||||
@ -59,7 +64,9 @@ export function useRoutingAPITrade<TTradeType extends TradeType>(
|
||||
otherCurrency: Currency | undefined,
|
||||
routerPreference: RouterPreference | typeof INTERNAL_ROUTER_PREFERENCE_PRICE,
|
||||
skipFetch = false,
|
||||
account?: string
|
||||
account?: string,
|
||||
inputTax = ZERO_PERCENT,
|
||||
outputTax = ZERO_PERCENT
|
||||
): {
|
||||
state: TradeState
|
||||
trade?: InterfaceTrade
|
||||
@ -81,6 +88,8 @@ export function useRoutingAPITrade<TTradeType extends TradeType>(
|
||||
amount: amountSpecified,
|
||||
tradeType,
|
||||
routerPreference,
|
||||
inputTax,
|
||||
outputTax,
|
||||
})
|
||||
|
||||
const { isError, data: tradeResult, error, currentData } = useGetQuoteQueryState(queryArgs)
|
||||
|
@ -6,9 +6,7 @@ import { DutchOrderInfo, DutchOrderInfoJSON } from '@uniswap/uniswapx-sdk'
|
||||
import { Pair, Route as V2Route } from '@uniswap/v2-sdk'
|
||||
import { FeeAmount, Pool, Route as V3Route } from '@uniswap/v3-sdk'
|
||||
import { asSupportedChain } from 'constants/chains'
|
||||
import { ZERO_PERCENT } from 'constants/misc'
|
||||
import { RPC_PROVIDERS } from 'constants/providers'
|
||||
import { getInputTax, getOutputTax } from 'constants/tax'
|
||||
import { isAvalanche, isBsc, isMatic, nativeOnChain } from 'constants/tokens'
|
||||
import { toSlippagePercent } from 'utils/slippage'
|
||||
|
||||
@ -215,9 +213,6 @@ export async function transformRoutesToTrade(
|
||||
|
||||
const approveInfo = await getApproveInfo(account, currencyIn, amount, usdCostPerGas)
|
||||
|
||||
const inputTax = args.fotAdjustmentsEnabled ? getInputTax(currencyIn) : ZERO_PERCENT
|
||||
const outputTax = args.fotAdjustmentsEnabled ? getOutputTax(currencyOut) : ZERO_PERCENT
|
||||
|
||||
const classicTrade = new ClassicTrade({
|
||||
v2Routes:
|
||||
routes
|
||||
@ -252,8 +247,8 @@ export async function transformRoutesToTrade(
|
||||
isUniswapXBetter,
|
||||
requestId: data.quote.requestId,
|
||||
quoteMethod,
|
||||
inputTax,
|
||||
outputTax,
|
||||
inputTax: args.inputTax,
|
||||
outputTax: args.outputTax,
|
||||
})
|
||||
|
||||
// During the opt-in period, only return UniswapX quotes if the user has turned on the setting,
|
||||
|
@ -3,6 +3,7 @@ import { ChainId, Currency, CurrencyAmount, Percent, TradeType } from '@uniswap/
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import useAutoSlippageTolerance from 'hooks/useAutoSlippageTolerance'
|
||||
import { useDebouncedTrade } from 'hooks/useDebouncedTrade'
|
||||
import { useSwapTaxes } from 'hooks/useSwapTaxes'
|
||||
import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount'
|
||||
import { ParsedQs } from 'qs'
|
||||
import { ReactNode, useCallback, useEffect, useMemo } from 'react'
|
||||
@ -77,6 +78,8 @@ const BAD_RECIPIENT_ADDRESSES: { [address: string]: true } = {
|
||||
export type SwapInfo = {
|
||||
currencies: { [field in Field]?: Currency | null }
|
||||
currencyBalances: { [field in Field]?: CurrencyAmount<Currency> }
|
||||
inputTax: Percent
|
||||
outputTax: Percent
|
||||
parsedAmount?: CurrencyAmount<Currency>
|
||||
inputError?: ReactNode
|
||||
trade: {
|
||||
@ -104,6 +107,12 @@ export function useDerivedSwapInfo(state: SwapState, chainId: ChainId | undefine
|
||||
|
||||
const inputCurrency = useCurrency(inputCurrencyId, chainId)
|
||||
const outputCurrency = useCurrency(outputCurrencyId, chainId)
|
||||
|
||||
const { inputTax, outputTax } = useSwapTaxes(
|
||||
inputCurrency?.isToken ? inputCurrency.address : undefined,
|
||||
outputCurrency?.isToken ? outputCurrency.address : undefined
|
||||
)
|
||||
|
||||
const recipientLookup = useENS(recipient ?? undefined)
|
||||
const to: string | null = (recipient === null ? account : recipientLookup.address) ?? null
|
||||
|
||||
@ -123,7 +132,9 @@ export function useDerivedSwapInfo(state: SwapState, chainId: ChainId | undefine
|
||||
parsedAmount,
|
||||
(isExactIn ? outputCurrency : inputCurrency) ?? undefined,
|
||||
undefined,
|
||||
account
|
||||
account,
|
||||
inputTax,
|
||||
outputTax
|
||||
)
|
||||
|
||||
const currencyBalances = useMemo(
|
||||
@ -198,8 +209,10 @@ export function useDerivedSwapInfo(state: SwapState, chainId: ChainId | undefine
|
||||
trade,
|
||||
autoSlippage,
|
||||
allowedSlippage,
|
||||
inputTax,
|
||||
outputTax,
|
||||
}),
|
||||
[allowedSlippage, autoSlippage, currencies, currencyBalances, inputError, parsedAmount, trade]
|
||||
[allowedSlippage, autoSlippage, currencies, currencyBalances, inputError, inputTax, outputTax, parsedAmount, trade]
|
||||
)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user