feat: read token taxes from backend response (#7532)

* read token taxes from backend

* revert env changes

* upgrade router-sdk for updated price impact logic

* add tax information to trade currencies instead of directly on trade object

* consolidate getTradeCurrencies with getSwapCurrenciesWithTaxInfo

* delete feature flag for token taxes!

* run yarn dedupe again

* fix unit tests

* update logic for disabling inputs

* update snapshot again

* fix return value for uniswapx

* remove unused constants and update comment

* pr review

* re-add useSwapTaxes for token descriptor page

* add in client-side tax fetching on currency level

* revert removing newline

* typecheck....

* typecheck...

* remove inputTax, outputTax from routing-api arguments because they are now unused

* dont pass in tax info to preview trade
This commit is contained in:
Tina 2023-11-15 09:57:43 -05:00 committed by GitHub
parent 76157c057e
commit ff6d1cc510
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 259 additions and 297 deletions

@ -202,7 +202,7 @@
"@uniswap/merkle-distributor": "^1.0.1",
"@uniswap/permit2-sdk": "^1.2.0",
"@uniswap/redux-multicall": "^1.1.8",
"@uniswap/router-sdk": "^1.6.0",
"@uniswap/router-sdk": "^1.7.1",
"@uniswap/sdk-core": "4.0.7",
"@uniswap/smart-order-router": "^3.15.0",
"@uniswap/token-lists": "^1.0.0-beta.33",

@ -90,7 +90,7 @@ const DescriptionText = styled(ThemedText.LabelMicro)`
function useOrderAmounts(
orderDetails?: UniswapXOrderDetails
): Pick<InterfaceTrade, 'inputAmount' | 'postTaxOutputAmount'> | undefined {
): Pick<InterfaceTrade, 'inputAmount' | 'outputAmount'> | undefined {
const inputCurrency = useCurrency(orderDetails?.swapInfo?.inputCurrencyId, orderDetails?.chainId)
const outputCurrency = useCurrency(orderDetails?.swapInfo?.outputCurrencyId, orderDetails?.chainId)
@ -106,7 +106,7 @@ function useOrderAmounts(
if (swapInfo.tradeType === TradeType.EXACT_INPUT) {
return {
inputAmount: CurrencyAmount.fromRawAmount(inputCurrency, swapInfo.inputCurrencyAmountRaw),
postTaxOutputAmount: CurrencyAmount.fromRawAmount(
outputAmount: CurrencyAmount.fromRawAmount(
outputCurrency,
swapInfo.settledOutputCurrencyAmountRaw ?? swapInfo.expectedOutputCurrencyAmountRaw
),
@ -114,7 +114,7 @@ function useOrderAmounts(
} else {
return {
inputAmount: CurrencyAmount.fromRawAmount(inputCurrency, swapInfo.expectedInputCurrencyAmountRaw),
postTaxOutputAmount: CurrencyAmount.fromRawAmount(outputCurrency, swapInfo.outputCurrencyAmountRaw),
outputAmount: CurrencyAmount.fromRawAmount(outputCurrency, swapInfo.outputCurrencyAmountRaw),
}
}
}

@ -6,7 +6,6 @@ import { useQuickRouteChains } from 'featureFlags/dynamicConfig/quickRouteChains
import { useAndroidGALaunchFlag } from 'featureFlags/flags/androidGALaunch'
import { useCurrencyConversionFlag } from 'featureFlags/flags/currencyConversion'
import { useFallbackProviderEnabledFlag } from 'featureFlags/flags/fallbackProvider'
import { useFotAdjustmentsFlag } from 'featureFlags/flags/fotAdjustments'
import { useInfoExploreFlag } from 'featureFlags/flags/infoExplore'
import { useInfoLiveViewsFlag } from 'featureFlags/flags/infoLiveViews'
import { useInfoPoolPageFlag } from 'featureFlags/flags/infoPoolPage'
@ -293,12 +292,6 @@ export default function FeatureFlagModal() {
featureFlag={FeatureFlag.multichainUX}
label="Updated Multichain UX"
/>
<FeatureFlagOption
variant={BaseVariant}
value={useFotAdjustmentsFlag()}
featureFlag={FeatureFlag.fotAdjustedmentsEnabled}
label="Enable fee-on-transfer UI and slippage adjustments"
/>
<FeatureFlagOption
variant={BaseVariant}
value={useProgressIndicatorV2Flag()}

@ -6,7 +6,7 @@ import { useTheme } from 'styled-components'
import { ThemedText } from 'theme/components'
import { useFormatter } from 'utils/formatNumbers'
export function TradeSummary({ trade }: { trade: Pick<InterfaceTrade, 'inputAmount' | 'postTaxOutputAmount'> }) {
export function TradeSummary({ trade }: { trade: Pick<InterfaceTrade, 'inputAmount' | 'outputAmount'> }) {
const theme = useTheme()
const { formatReviewSwapCurrencyAmount } = useFormatter()
@ -17,9 +17,9 @@ export function TradeSummary({ trade }: { trade: Pick<InterfaceTrade, 'inputAmou
{formatReviewSwapCurrencyAmount(trade.inputAmount)} {trade.inputAmount.currency.symbol}
</ThemedText.LabelSmall>
<ArrowRight color={theme.neutral1} size="12px" />
<CurrencyLogo currency={trade.postTaxOutputAmount.currency} size="16px" />
<CurrencyLogo currency={trade.outputAmount.currency} size="16px" />
<ThemedText.LabelSmall color="neutral1">
{formatReviewSwapCurrencyAmount(trade.postTaxOutputAmount)} {trade.postTaxOutputAmount.currency.symbol}
{formatReviewSwapCurrencyAmount(trade.outputAmount)} {trade.outputAmount.currency.symbol}
</ThemedText.LabelSmall>
</Row>
)

@ -24,7 +24,7 @@ export default function SwapModalHeader({
allowedSlippage: Percent
}) {
const fiatValueInput = useUSDPrice(trade.inputAmount)
const fiatValueOutput = useUSDPrice(trade.postTaxOutputAmount)
const fiatValueOutput = useUSDPrice(trade.outputAmount)
return (
<HeaderContainer gap="sm">
@ -40,7 +40,7 @@ export default function SwapModalHeader({
<SwapModalHeaderAmount
field={Field.OUTPUT}
label={<Trans>You receive</Trans>}
amount={trade.postTaxOutputAmount}
amount={trade.outputAmount}
currency={trade.outputAmount.currency}
usdAmount={fiatValueOutput.data}
isLoading={isPreviewTrade(trade) && trade.tradeType === TradeType.EXACT_INPUT}

@ -6882,7 +6882,7 @@ exports[`SwapLineItem.tsx fee on buy 1`] = `
<span
class=""
>
~-105566.373%
~-108834.406%
</span>
</div>
</div>
@ -7165,14 +7165,14 @@ exports[`SwapLineItem.tsx fee on buy 1`] = `
<div
class="c3 css-obwv3p"
>
0.000000000000000952 DEF
0.00000000000000098 DEF
</div>
</div>
<div
class="c13"
/>
<div>
If the price moves so that you will receive less than 0.000000000000000952 DEF, your transaction will be reverted. This is the minimum amount you are guaranteed to receive.
If the price moves so that you will receive less than 0.00000000000000098 DEF, your transaction will be reverted. This is the minimum amount you are guaranteed to receive.
<a
class="c14"
href="https://support.uniswap.org/hc/en-us/articles/8643879653261-What-is-Price-Slippage-"
@ -7549,7 +7549,7 @@ exports[`SwapLineItem.tsx fee on buy 1`] = `
<div
class="c3 c6 css-142zc9n"
>
0.000000000000000952 DEF
0.00000000000000098 DEF
</div>
</div>
</div>
@ -8761,7 +8761,7 @@ exports[`SwapLineItem.tsx fee on sell 1`] = `
<span
class=""
>
~-105566.373%
~-108834.406%
</span>
</div>
</div>
@ -9044,14 +9044,14 @@ exports[`SwapLineItem.tsx fee on sell 1`] = `
<div
class="c3 css-obwv3p"
>
0.000000000000000952 DEF
0.00000000000000098 DEF
</div>
</div>
<div
class="c13"
/>
<div>
If the price moves so that you will receive less than 0.000000000000000952 DEF, your transaction will be reverted. This is the minimum amount you are guaranteed to receive.
If the price moves so that you will receive less than 0.00000000000000098 DEF, your transaction will be reverted. This is the minimum amount you are guaranteed to receive.
<a
class="c14"
href="https://support.uniswap.org/hc/en-us/articles/8643879653261-What-is-Price-Slippage-"
@ -9428,7 +9428,7 @@ exports[`SwapLineItem.tsx fee on sell 1`] = `
<div
class="c3 c6 css-142zc9n"
>
0.000000000000000952 DEF
0.00000000000000098 DEF
</div>
</div>
</div>

@ -1,9 +0,0 @@
import { BaseVariant, FeatureFlag, useBaseFlag } from '../index'
export function useFotAdjustmentsFlag(): BaseVariant {
return useBaseFlag(FeatureFlag.fotAdjustedmentsEnabled)
}
export function useFotAdjustmentsEnabled(): boolean {
return useFotAdjustmentsFlag() === BaseVariant.Enabled
}

@ -14,7 +14,6 @@ export enum FeatureFlag {
uniswapXExactOutputEnabled = 'uniswapx_exact_output_enabled',
multichainUX = 'multichain_ux',
currencyConversion = 'currency_conversion',
fotAdjustedmentsEnabled = 'fot_dynamic_adjustments_enabled',
infoExplore = 'info_explore',
infoTDP = 'info_tdp',
infoPoolPage = 'info_pool_page',

@ -84,13 +84,13 @@ export function useSwapCallback(
? {
tradeType: TradeType.EXACT_INPUT,
inputCurrencyAmountRaw: trade.inputAmount.quotient.toString(),
expectedOutputCurrencyAmountRaw: trade.postTaxOutputAmount.quotient.toString(),
expectedOutputCurrencyAmountRaw: trade.outputAmount.quotient.toString(),
minimumOutputCurrencyAmountRaw: trade.minimumAmountOut(allowedSlippage).quotient.toString(),
}
: {
tradeType: TradeType.EXACT_OUTPUT,
maximumInputCurrencyAmountRaw: trade.maximumAmountIn(allowedSlippage).quotient.toString(),
outputCurrencyAmountRaw: trade.postTaxOutputAmount.quotient.toString(),
outputCurrencyAmountRaw: trade.outputAmount.quotient.toString(),
expectedInputCurrencyAmountRaw: trade.inputAmount.quotient.toString(),
}),
}

@ -73,12 +73,8 @@ export function useUniversalRouterSwapCallback(
setTraceData('slippageTolerance', options.slippageTolerance.toFixed(2))
// universal-router-sdk reconstructs V2Trade objects, so rather than updating the trade amounts to account for tax, we adjust the slippage tolerance as a workaround
// TODO(WEB-2725): update universal-router-sdk to not reconstruct trades
const taxAdjustedSlippageTolerance = options.slippageTolerance.add(trade.totalTaxRate)
const { calldata: data, value } = SwapRouter.swapERC20CallParameters(trade, {
slippageTolerance: taxAdjustedSlippageTolerance,
slippageTolerance: options.slippageTolerance,
deadlineOrPreviousBlockhash: options.deadline?.toString(),
inputTokenPermit: options.permit,
fee: options.feeOptions,

@ -1,5 +1,5 @@
import { SkipToken, skipToken } from '@reduxjs/toolkit/query/react'
import { Currency, CurrencyAmount, Percent, TradeType } from '@uniswap/sdk-core'
import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core'
import { useUniswapXDefaultEnabled } from 'featureFlags/flags/uniswapXDefault'
import { useUniswapXEthOutputEnabled } from 'featureFlags/flags/uniswapXEthOutput'
import { useUniswapXExactOutputEnabled } from 'featureFlags/flags/uniswapXExactOutput'
@ -22,8 +22,6 @@ export function useRoutingAPIArguments({
amount,
tradeType,
routerPreference,
inputTax,
outputTax,
}: {
account?: string
tokenIn?: Currency
@ -31,8 +29,6 @@ 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()
@ -70,8 +66,6 @@ export function useRoutingAPIArguments({
uniswapXExactOutputEnabled,
isUniswapXDefaultEnabled,
sendPortionEnabled,
inputTax,
outputTax,
},
[
account,
@ -87,8 +81,6 @@ export function useRoutingAPIArguments({
uniswapXEthOutputEnabled,
isUniswapXDefaultEnabled,
sendPortionEnabled,
inputTax,
outputTax,
]
)
}

@ -51,7 +51,7 @@ export function formatCommonPropertiesForTrade(
token_in_symbol: trade.inputAmount.currency.symbol,
token_out_symbol: trade.outputAmount.currency.symbol,
token_in_amount: formatToDecimal(trade.inputAmount, trade.inputAmount.currency.decimals),
token_out_amount: formatToDecimal(trade.postTaxOutputAmount, trade.outputAmount.currency.decimals),
token_out_amount: formatToDecimal(trade.outputAmount, trade.outputAmount.currency.decimals),
price_impact_basis_points: isClassicTrade(trade)
? formatPercentInBasisPointsNumber(computeRealizedPriceImpact(trade))
: undefined,
@ -64,6 +64,8 @@ export function formatCommonPropertiesForTrade(
allowed_slippage: formatPercentNumber(allowedSlippage),
method: getQuoteMethod(trade),
fee_usd: outputFeeFiatValue,
token_out_detected_tax: formatPercentNumber(trade.outputTax),
token_in_detected_tax: formatPercentNumber(trade.inputTax),
}
}
@ -101,8 +103,6 @@ export const formatSwapQuoteReceivedEventProperties = (
trade: InterfaceTrade,
allowedSlippage: Percent,
swapQuoteLatencyMs: number | undefined,
inputTax: Percent,
outputTax: Percent,
outputFeeFiatValue: number | undefined
) => {
return {
@ -112,7 +112,5 @@ export const formatSwapQuoteReceivedEventProperties = (
token_in_amount_max: trade.maximumAmountIn(allowedSlippage).toExact(),
token_out_amount_min: trade.minimumAmountOut(allowedSlippage).toExact(),
quote_latency_milliseconds: swapQuoteLatencyMs,
token_out_detected_tax: formatPercentNumber(outputTax),
token_in_detected_tax: formatPercentNumber(inputTax),
}
}

@ -292,9 +292,9 @@ export function Swap({
parsedAmount,
currencies,
inputError: swapInputError,
outputFeeFiatValue,
inputTax,
outputTax,
outputFeeFiatValue,
} = swapInfo
const [inputTokenHasTax, outputTokenHasTax] = useMemo(
@ -323,7 +323,7 @@ export function Swap({
}
: {
[Field.INPUT]: independentField === Field.INPUT ? parsedAmount : trade?.inputAmount,
[Field.OUTPUT]: independentField === Field.OUTPUT ? parsedAmount : trade?.postTaxOutputAmount,
[Field.OUTPUT]: independentField === Field.OUTPUT ? parsedAmount : trade?.outputAmount,
},
[independentField, parsedAmount, showWrap, trade]
)
@ -354,7 +354,7 @@ export function Swap({
)
const fiatValueTradeInput = useUSDPrice(trade?.inputAmount)
const fiatValueTradeOutput = useUSDPrice(trade?.postTaxOutputAmount)
const fiatValueTradeOutput = useUSDPrice(trade?.outputAmount)
const preTaxFiatValueTradeOutput = useUSDPrice(trade?.outputAmount)
const [stablecoinPriceImpact, preTaxStablecoinPriceImpact] = useMemo(
() =>
@ -585,17 +585,10 @@ export function Swap({
if (!trade || prevTrade === trade) return // no new swap quote to log
sendAnalyticsEvent(SwapEventName.SWAP_QUOTE_RECEIVED, {
...formatSwapQuoteReceivedEventProperties(
trade,
allowedSlippage,
swapQuoteLatency,
inputTax,
outputTax,
outputFeeFiatValue
),
...formatSwapQuoteReceivedEventProperties(trade, allowedSlippage, swapQuoteLatency, outputFeeFiatValue),
...trace,
})
}, [prevTrade, trade, trace, allowedSlippage, swapQuoteLatency, inputTax, outputTax, outputFeeFiatValue])
}, [prevTrade, trade, trace, allowedSlippage, swapQuoteLatency, outputFeeFiatValue])
const showDetailsDropdown = Boolean(
!showWrap && userHasSpecifiedInputOutput && (trade || routeIsLoading || routeIsSyncing)

@ -19,7 +19,7 @@ import {
URAQuoteResponse,
URAQuoteType,
} from './types'
import { isExactInput, transformRoutesToTrade } from './utils'
import { isExactInput, transformQuoteToTrade } from './utils'
const UNISWAP_API_URL = process.env.REACT_APP_UNISWAP_API_URL
if (UNISWAP_API_URL === undefined) {
@ -69,6 +69,7 @@ function getRoutingAPIConfig(args: GetQuoteArgs): RoutingConfig {
...DEFAULT_QUERY_PARAMS,
routingType: URAQuoteType.CLASSIC,
recipient: account,
enableFeeOnTransferFeeFetching: true,
}
const tokenOutIsNative = Object.values(SwapRouterNativeAssets).includes(tokenOutAddress as SwapRouterNativeAssets)
@ -179,7 +180,7 @@ export const routingApi = createApi({
}
const uraQuoteResponse = response.data as URAQuoteResponse
const tradeResult = await transformRoutesToTrade(args, uraQuoteResponse, QuoteMethod.ROUTING_API)
const tradeResult = await transformQuoteToTrade(args, uraQuoteResponse, QuoteMethod.ROUTING_API)
return { data: { ...tradeResult, latencyMs: getQuoteLatencyMeasure(quoteStartMark).duration } }
} catch (error: any) {
console.warn(
@ -194,7 +195,7 @@ export const routingApi = createApi({
const router = getRouter(args.tokenInChainId)
const quoteResult = await getClientSideQuote(args, router, CLIENT_PARAMS)
if (quoteResult.state === QuoteState.SUCCESS) {
const trade = await transformRoutesToTrade(args, quoteResult.data, QuoteMethod.CLIENT_SIDE_FALLBACK)
const trade = await transformQuoteToTrade(args, quoteResult.data, QuoteMethod.CLIENT_SIDE_FALLBACK)
return {
data: { ...trade, latencyMs: getQuoteLatencyMeasure(quoteStartMark).duration },
}

@ -51,8 +51,6 @@ export interface GetQuoteArgs {
userOptedOutOfUniswapX: boolean
isUniswapXDefaultEnabled: boolean
sendPortionEnabled: boolean
inputTax: Percent
outputTax: Percent
}
export type GetQuickQuoteArgs = {
@ -69,9 +67,12 @@ export type GetQuickQuoteArgs = {
inputTax: Percent
outputTax: Percent
}
// from https://github.com/Uniswap/routing-api/blob/main/lib/handlers/schema.ts
type TokenInRoute = Pick<Token, 'address' | 'chainId' | 'symbol' | 'decimals'>
// from https://github.com/Uniswap/routing-api/blob/main/lib/handlers/schema.ts
export type TokenInRoute = Pick<Token, 'address' | 'chainId' | 'symbol' | 'decimals'> & {
buyFeeBps?: string
sellFeeBps?: string
}
export type V3PoolInRoute = {
type: 'v3-pool'
@ -201,8 +202,6 @@ export class ClassicTrade extends Trade<Currency, Currency, TradeType> {
isUniswapXBetter: boolean | undefined
requestId: string | undefined
quoteMethod: QuoteMethod
inputTax: Percent
outputTax: Percent
swapFee: SwapFeeInfo | undefined
constructor({
@ -212,8 +211,6 @@ export class ClassicTrade extends Trade<Currency, Currency, TradeType> {
requestId,
quoteMethod,
approveInfo,
inputTax,
outputTax,
swapFee,
...routes
}: {
@ -224,8 +221,6 @@ export class ClassicTrade extends Trade<Currency, Currency, TradeType> {
requestId?: string
quoteMethod: QuoteMethod
approveInfo: ApproveInfo
inputTax: Percent
outputTax: Percent
swapFee?: SwapFeeInfo
v2Routes: {
routev2: V2Route<Currency, Currency>
@ -251,8 +246,6 @@ export class ClassicTrade extends Trade<Currency, Currency, TradeType> {
this.requestId = requestId
this.quoteMethod = quoteMethod
this.approveInfo = approveInfo
this.inputTax = inputTax
this.outputTax = outputTax
this.swapFee = swapFee
}
@ -263,10 +256,6 @@ export class ClassicTrade extends Trade<Currency, Currency, TradeType> {
return new Price({ baseAmount: this.inputAmount, quoteAmount: this.postSwapFeeOutputAmount })
}
public get totalTaxRate(): Percent {
return this.inputTax.add(this.outputTax)
}
public get postSwapFeeOutputAmount(): CurrencyAmount<Currency> {
// Routing api already applies the swap fee to the output amount for exact-in
if (this.tradeType === TradeType.EXACT_INPUT) return this.outputAmount
@ -275,20 +264,6 @@ export class ClassicTrade extends Trade<Currency, Currency, TradeType> {
return this.outputAmount.subtract(swapFeeAmount)
}
public get postTaxOutputAmount() {
// Ideally we should calculate the final output amount by ammending the inputAmount based on the input tax and then applying the output tax,
// but this isn't currently possible because V2Trade reconstructs the total inputAmount based on the swap routes
// TODO(WEB-2761): Amend V2Trade objects in the v2-sdk to have a separate field for post-input tax routes
return this.postSwapFeeOutputAmount.multiply(new Fraction(ONE).subtract(this.totalTaxRate))
}
public minimumAmountOut(slippageTolerance: Percent, amountOut = this.outputAmount): CurrencyAmount<Currency> {
// Since universal-router-sdk reconstructs V2Trade objects, overriding this method does not actually change the minimumAmountOut that gets submitted on-chain
// Our current workaround is to add tax rate to slippage tolerance before we submit the trade to universal-router-sdk in useUniversalRouter.ts
// So the purpose of this override is so the UI displays the same minimum amount out as what is submitted on-chain
return super.minimumAmountOut(slippageTolerance.add(this.totalTaxRate), amountOut)
}
// gas estimate for maybe approve + swap
public get totalGasUseEstimateUSD(): number | undefined {
if (this.approveInfo.needsApprove && this.gasUseEstimateUSD) {
@ -370,11 +345,6 @@ export class DutchOrderTrade extends IDutchOrderTrade<Currency, Currency, TradeT
return 0
}
/** For UniswapX, handling token taxes in the output amount is outsourced to quoters */
public get postTaxOutputAmount() {
return this.outputAmount
}
}
export class PreviewTrade {
@ -383,38 +353,19 @@ export class PreviewTrade {
public readonly tradeType: TradeType
public readonly inputAmount: CurrencyAmount<Currency>
public readonly outputAmount: CurrencyAmount<Currency>
inputTax: Percent
outputTax: Percent
constructor({
inputAmount,
outputAmount,
tradeType,
inputTax,
outputTax,
}: {
inputAmount: CurrencyAmount<Currency>
outputAmount: CurrencyAmount<Currency>
tradeType: TradeType
inputTax: Percent
outputTax: Percent
}) {
this.inputAmount = inputAmount
this.outputAmount = outputAmount
this.tradeType = tradeType
this.inputTax = inputTax
this.outputTax = outputTax
}
public get totalTaxRate(): Percent {
return this.inputTax.add(this.outputTax)
}
public get postTaxOutputAmount() {
// Ideally we should calculate the final output amount by ammending the inputAmount based on the input tax and then applying the output tax,
// but this isn't currently possible because V2Trade reconstructs the total inputAmount based on the swap routes
// TODO(WEB-2761): Amend V2Trade objects in the v2-sdk to have a separate field for post-input tax routes
return this.outputAmount.multiply(new Fraction(ONE).subtract(this.totalTaxRate))
}
// below methods are copied from router-sdk
@ -440,6 +391,26 @@ export class PreviewTrade {
}
}
/**
* Returns the sell tax of the input token
*/
public get inputTax(): Percent {
const inputCurrency = this.inputAmount.currency
if (inputCurrency.isNative || !inputCurrency.wrapped.sellFeeBps) return ZERO_PERCENT
return new Percent(inputCurrency.wrapped.sellFeeBps.toNumber(), 10000)
}
/**
* Returns the buy tax of the output token
*/
public get outputTax(): Percent {
const outputCurrency = this.outputAmount.currency
if (outputCurrency.isNative || !outputCurrency.wrapped.buyFeeBps) return ZERO_PERCENT
return new Percent(outputCurrency.wrapped.buyFeeBps.toNumber(), 10000)
}
private _executionPrice: Price<Currency, Currency> | undefined
/**
* The price expressed in terms of output amount/input amount.

@ -2,7 +2,6 @@ import { skipToken } from '@reduxjs/toolkit/query/react'
import { renderHook } from '@testing-library/react'
import { CurrencyAmount, TradeType } from '@uniswap/sdk-core'
import { AVERAGE_L1_BLOCK_TIME } from 'constants/chainInfo'
import { ZERO_PERCENT } from 'constants/misc'
import { USDC_MAINNET } from 'constants/tokens'
import { useUniswapXDefaultEnabled } from 'featureFlags/flags/uniswapXDefault'
import { useUniswapXEthOutputEnabled } from 'featureFlags/flags/uniswapXEthOutput'
@ -79,8 +78,6 @@ const MOCK_ARGS: GetQuoteArgs = {
uniswapXExactOutputEnabled: false,
isUniswapXDefaultEnabled: false,
sendPortionEnabled: true,
inputTax: ZERO_PERCENT,
outputTax: ZERO_PERCENT,
}
describe('#useRoutingAPITrade ExactIn', () => {

@ -1,7 +1,6 @@
import { skipToken } from '@reduxjs/toolkit/query/react'
import { Currency, CurrencyAmount, Percent, TradeType } from '@uniswap/sdk-core'
import { AVERAGE_L1_BLOCK_TIME } from 'constants/chainInfo'
import { ZERO_PERCENT } from 'constants/misc'
import useIsWindowVisible from 'hooks/useIsWindowVisible'
import { useRoutingAPIArguments } from 'lib/hooks/routing/useRoutingAPIArguments'
import ms from 'ms'
@ -65,9 +64,7 @@ export function useRoutingAPITrade<TTradeType extends TradeType>(
amountSpecified: CurrencyAmount<Currency> | undefined,
otherCurrency: Currency | undefined,
routerPreference: RouterPreference | typeof INTERNAL_ROUTER_PREFERENCE_PRICE,
account?: string,
inputTax = ZERO_PERCENT,
outputTax = ZERO_PERCENT
account?: string
): {
state: TradeState
trade?: SubmittableTrade
@ -90,8 +87,6 @@ export function useRoutingAPITrade<TTradeType extends TradeType>(
amount: amountSpecified,
tradeType,
routerPreference,
inputTax,
outputTax,
})
// skip all pricing and quote requests if the window is not focused
const isWindowVisible = useIsWindowVisible()

@ -1,26 +1,69 @@
import { ChainId, Token } from '@uniswap/sdk-core'
import { ChainId, Currency, Token, TradeType } from '@uniswap/sdk-core'
import { nativeOnChain } from 'constants/tokens'
import { PoolType } from './types'
import { GetQuoteArgs, PoolType, RouterPreference, TokenInRoute } from './types'
import { computeRoutes } from './utils'
const USDC = new Token(1, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 6, 'USDC')
const DAI = new Token(1, '0x6B175474E89094C44Da98b954EedeAC495271d0F', 6, 'DAI')
const MKR = new Token(1, '0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2', 6, 'MKR')
const USDC = new Token(1, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 6, 'USDC', undefined, false)
const USDC_IN_ROUTE = toTokenInRoute(USDC)
const DAI = new Token(1, '0x6B175474E89094C44Da98b954EedeAC495271d0F', 6, 'DAI', undefined, false)
const DAI_IN_ROUTE = toTokenInRoute(DAI)
const MKR = new Token(1, '0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2', 6, 'MKR', undefined, false)
const MKR_IN_ROUTE = toTokenInRoute(MKR)
const ETH = nativeOnChain(ChainId.MAINNET)
const WETH_IN_ROUTE = toTokenInRoute(ETH.wrapped)
// helper function to make amounts more readable
const amount = (raw: TemplateStringsArray) => (parseInt(raw[0]) * 1e6).toString()
const BASE_ARGS = {
amount: '100',
routerPreference: RouterPreference.API,
tradeType: TradeType.EXACT_INPUT,
needsWrapIfUniswapX: false,
uniswapXForceSyntheticQuotes: false,
uniswapXEthOutputEnabled: true,
uniswapXExactOutputEnabled: true,
userDisabledUniswapX: false,
userOptedOutOfUniswapX: false,
isUniswapXDefaultEnabled: false,
sendPortionEnabled: true,
}
function constructArgs(currencyIn: Currency, currencyOut: Currency): GetQuoteArgs {
return {
...BASE_ARGS,
tokenInAddress: currencyIn.isNative ? 'ETH' : currencyIn.address,
tokenInChainId: currencyIn.chainId,
tokenInDecimals: currencyIn.decimals,
tokenInSymbol: currencyIn.symbol,
tokenOutAddress: currencyOut.isNative ? 'ETH' : currencyOut.address,
tokenOutChainId: currencyOut.chainId,
tokenOutDecimals: currencyOut.decimals,
tokenOutSymbol: currencyOut.symbol,
}
}
function toTokenInRoute(token: Token): TokenInRoute {
return {
address: token.address,
chainId: token.chainId,
symbol: token.symbol,
decimals: token.decimals,
buyFeeBps: token.buyFeeBps?.toString(),
sellFeeBps: token.sellFeeBps?.toString(),
}
}
describe('#useRoute', () => {
it('handles empty edges and nodes', () => {
const result = computeRoutes(USDC, DAI, [])
const result = computeRoutes(constructArgs(USDC, DAI), [])
expect(result).toEqual([])
})
it('handles a single route trade from DAI to USDC from v3', () => {
const result = computeRoutes(DAI, USDC, [
const result = computeRoutes(constructArgs(DAI, USDC), [
[
{
type: 'v3-pool',
@ -31,8 +74,8 @@ describe('#useRoute', () => {
sqrtRatioX96: '2437312313659959819381354528',
liquidity: '10272714736694327408',
tickCurrent: '-69633',
tokenIn: DAI,
tokenOut: USDC,
tokenIn: toTokenInRoute(DAI),
tokenOut: toTokenInRoute(USDC),
},
],
])
@ -50,21 +93,21 @@ describe('#useRoute', () => {
})
it('handles a single route trade from DAI to USDC from v2', () => {
const result = computeRoutes(DAI, USDC, [
const result = computeRoutes(constructArgs(DAI, USDC), [
[
{
type: 'v2-pool',
address: '0x1f8F72aA9304c8B593d555F12eF6589cC3A579A2',
amountIn: amount`1`,
amountOut: amount`5`,
tokenIn: DAI,
tokenOut: USDC,
tokenIn: DAI_IN_ROUTE,
tokenOut: USDC_IN_ROUTE,
reserve0: {
token: DAI,
token: DAI_IN_ROUTE,
quotient: amount`100`,
},
reserve1: {
token: USDC,
token: USDC_IN_ROUTE,
quotient: amount`200`,
},
},
@ -84,21 +127,21 @@ describe('#useRoute', () => {
})
it('handles a multi-route trade from DAI to USDC', () => {
const result = computeRoutes(DAI, USDC, [
const result = computeRoutes(constructArgs(DAI, USDC), [
[
{
type: 'v2-pool',
address: '0x1f8F72aA9304c8B593d555F12eF6589cC3A579A2',
amountIn: amount`5`,
amountOut: amount`6`,
tokenIn: DAI,
tokenOut: USDC,
tokenIn: DAI_IN_ROUTE,
tokenOut: USDC_IN_ROUTE,
reserve0: {
token: DAI,
token: DAI_IN_ROUTE,
quotient: amount`1000`,
},
reserve1: {
token: USDC,
token: USDC_IN_ROUTE,
quotient: amount`500`,
},
},
@ -110,8 +153,8 @@ describe('#useRoute', () => {
amountIn: amount`10`,
amountOut: amount`1`,
fee: '3000',
tokenIn: DAI,
tokenOut: MKR,
tokenIn: DAI_IN_ROUTE,
tokenOut: MKR_IN_ROUTE,
sqrtRatioX96: '2437312313659959819381354528',
liquidity: '10272714736694327408',
tickCurrent: '-69633',
@ -122,8 +165,8 @@ describe('#useRoute', () => {
amountIn: amount`1`,
amountOut: amount`200`,
fee: '10000',
tokenIn: MKR,
tokenOut: USDC,
tokenIn: MKR_IN_ROUTE,
tokenOut: USDC_IN_ROUTE,
sqrtRatioX96: '2437312313659959819381354528',
liquidity: '10272714736694327408',
tickCurrent: '-69633',
@ -151,7 +194,7 @@ describe('#useRoute', () => {
})
it('handles a single route trade with same token pair, different fee tiers', () => {
const result = computeRoutes(DAI, USDC, [
const result = computeRoutes(constructArgs(DAI, USDC), [
[
{
type: 'v3-pool',
@ -159,8 +202,8 @@ describe('#useRoute', () => {
amountIn: amount`1`,
amountOut: amount`5`,
fee: '500',
tokenIn: DAI,
tokenOut: USDC,
tokenIn: DAI_IN_ROUTE,
tokenOut: USDC_IN_ROUTE,
sqrtRatioX96: '2437312313659959819381354528',
liquidity: '10272714736694327408',
tickCurrent: '-69633',
@ -173,8 +216,8 @@ describe('#useRoute', () => {
amountIn: amount`10`,
amountOut: amount`50`,
fee: '3000',
tokenIn: DAI,
tokenOut: USDC,
tokenIn: DAI_IN_ROUTE,
tokenOut: USDC_IN_ROUTE,
sqrtRatioX96: '2437312313659959819381354528',
liquidity: '10272714736694327408',
tickCurrent: '-69633',
@ -191,7 +234,7 @@ describe('#useRoute', () => {
})
it('computes mixed routes correctly', () => {
const result = computeRoutes(DAI, MKR, [
const result = computeRoutes(constructArgs(DAI, MKR), [
[
{
type: PoolType.V3Pool,
@ -199,8 +242,8 @@ describe('#useRoute', () => {
amountIn: amount`1`,
amountOut: amount`5`,
fee: '500',
tokenIn: DAI,
tokenOut: USDC,
tokenIn: DAI_IN_ROUTE,
tokenOut: USDC_IN_ROUTE,
sqrtRatioX96: '2437312313659959819381354528',
liquidity: '10272714736694327408',
tickCurrent: '-69633',
@ -210,14 +253,14 @@ describe('#useRoute', () => {
address: 'x2f8F72aA9304c8B593d555F12eF6589cC3A579A2',
amountIn: amount`10`,
amountOut: amount`50`,
tokenIn: USDC,
tokenOut: MKR,
tokenIn: USDC_IN_ROUTE,
tokenOut: MKR_IN_ROUTE,
reserve0: {
token: USDC,
token: USDC_IN_ROUTE,
quotient: amount`100`,
},
reserve1: {
token: MKR,
token: MKR_IN_ROUTE,
quotient: amount`200`,
},
},
@ -236,7 +279,7 @@ describe('#useRoute', () => {
it('outputs native ETH as input currency', () => {
const WETH = ETH.wrapped
const result = computeRoutes(ETH, USDC, [
const result = computeRoutes(constructArgs(ETH, USDC), [
[
{
type: 'v3-pool',
@ -247,8 +290,8 @@ describe('#useRoute', () => {
sqrtRatioX96: '2437312313659959819381354528',
liquidity: '10272714736694327408',
tickCurrent: '-69633',
tokenIn: WETH,
tokenOut: USDC,
tokenIn: WETH_IN_ROUTE,
tokenOut: USDC_IN_ROUTE,
},
],
])
@ -263,7 +306,7 @@ describe('#useRoute', () => {
it('outputs native ETH as output currency', () => {
const WETH = new Token(1, ETH.wrapped.address, 18, 'WETH')
const result = computeRoutes(USDC, ETH, [
const result = computeRoutes(constructArgs(USDC, ETH), [
[
{
type: 'v3-pool',
@ -274,8 +317,8 @@ describe('#useRoute', () => {
sqrtRatioX96: '2437312313659959819381354528',
liquidity: '10272714736694327408',
tickCurrent: '-69633',
tokenIn: USDC,
tokenOut: WETH,
tokenIn: USDC_IN_ROUTE,
tokenOut: WETH_IN_ROUTE,
},
],
])
@ -290,21 +333,21 @@ describe('#useRoute', () => {
it('outputs native ETH as input currency for v2 routes', () => {
const WETH = ETH.wrapped
const result = computeRoutes(ETH, USDC, [
const result = computeRoutes(constructArgs(ETH, USDC), [
[
{
type: 'v2-pool',
address: '0x1f8F72aA9304c8B593d555F12eF6589cC3A579A2',
amountIn: (1e18).toString(),
amountOut: amount`5`,
tokenIn: WETH,
tokenOut: USDC,
tokenIn: WETH_IN_ROUTE,
tokenOut: USDC_IN_ROUTE,
reserve0: {
token: WETH,
token: WETH_IN_ROUTE,
quotient: amount`100`,
},
reserve1: {
token: USDC,
token: USDC_IN_ROUTE,
quotient: amount`200`,
},
},
@ -321,21 +364,21 @@ describe('#useRoute', () => {
it('outputs native ETH as output currency for v2 routes', () => {
const WETH = new Token(1, ETH.wrapped.address, 18, 'WETH')
const result = computeRoutes(USDC, ETH, [
const result = computeRoutes(constructArgs(USDC, ETH), [
[
{
type: 'v2-pool',
address: '0x1f8F72aA9304c8B593d555F12eF6589cC3A579A2',
amountIn: amount`5`,
amountOut: (1e18).toString(),
tokenIn: USDC,
tokenOut: WETH,
tokenIn: USDC_IN_ROUTE,
tokenOut: WETH_IN_ROUTE,
reserve0: {
token: WETH,
token: WETH_IN_ROUTE,
quotient: amount`100`,
},
reserve1: {
token: USDC,
token: USDC_IN_ROUTE,
quotient: amount`200`,
},
},

@ -26,6 +26,7 @@ import {
SubmittableTrade,
SwapFeeInfo,
SwapRouterNativeAssets,
TokenInRoute,
TradeFillType,
TradeResult,
URADutchOrderQuoteData,
@ -47,16 +48,9 @@ interface RouteResult {
* Transforms a Routing API quote into an array of routes that can be used to
* create a `Trade`.
*/
export function computeRoutes(
currencyIn: Currency,
currencyOut: Currency,
routes: ClassicQuoteData['route']
): RouteResult[] | undefined {
export function computeRoutes(args: GetQuoteArgs, routes: ClassicQuoteData['route']): RouteResult[] | undefined {
if (routes.length === 0) return []
const tokenIn = routes[0]?.[0]?.tokenIn
const tokenOut = routes[0]?.[routes[0]?.length - 1]?.tokenOut
if (!tokenIn || !tokenOut) throw new Error('Expected both tokenIn and tokenOut to be present')
const [currencyIn, currencyOut] = getTradeCurrencies(args, false, routes)
try {
return routes.map((route) => {
@ -121,7 +115,11 @@ function toDutchOrderInfo(orderInfoJSON: DutchOrderInfoJSON): DutchOrderInfo {
// Prepares the currencies used for the actual Swap (either UniswapX or Universal Router)
// May not match `currencyIn` that the user selected because for ETH inputs in UniswapX, the actual
// swap will use WETH.
function getTradeCurrencies(args: GetQuoteArgs | GetQuickQuoteArgs, isUniswapXTrade: boolean): [Currency, Currency] {
function getTradeCurrencies(
args: GetQuoteArgs | GetQuickQuoteArgs,
isUniswapXTrade: boolean,
routes?: ClassicQuoteData['route']
): [Currency, Currency] {
const {
tokenInAddress,
tokenInChainId,
@ -136,9 +134,19 @@ function getTradeCurrencies(args: GetQuoteArgs | GetQuickQuoteArgs, isUniswapXTr
const tokenInIsNative = Object.values(SwapRouterNativeAssets).includes(tokenInAddress as SwapRouterNativeAssets)
const tokenOutIsNative = Object.values(SwapRouterNativeAssets).includes(tokenOutAddress as SwapRouterNativeAssets)
const serializedTokenIn = routes?.[0]?.[0]?.tokenIn
const serializedTokenOut = routes?.[0]?.[routes[0]?.length - 1]?.tokenOut
const currencyIn = tokenInIsNative
? nativeOnChain(tokenInChainId)
: parseToken({ address: tokenInAddress, chainId: tokenInChainId, decimals: tokenInDecimals, symbol: tokenInSymbol })
: parseToken({
address: tokenInAddress,
chainId: tokenInChainId,
decimals: tokenInDecimals,
symbol: tokenInSymbol,
buyFeeBps: serializedTokenIn?.buyFeeBps,
sellFeeBps: serializedTokenIn?.sellFeeBps,
})
const currencyOut = tokenOutIsNative
? nativeOnChain(tokenOutChainId)
: parseToken({
@ -146,6 +154,8 @@ function getTradeCurrencies(args: GetQuoteArgs | GetQuickQuoteArgs, isUniswapXTr
chainId: tokenOutChainId,
decimals: tokenOutDecimals,
symbol: tokenOutSymbol,
buyFeeBps: serializedTokenOut?.buyFeeBps,
sellFeeBps: serializedTokenOut?.sellFeeBps,
})
if (!isUniswapXTrade) {
@ -168,8 +178,7 @@ function getSwapFee(data: ClassicQuoteData | URADutchOrderQuoteData): SwapFeeInf
}
function getClassicTradeDetails(
currencyIn: Currency,
currencyOut: Currency,
args: GetQuoteArgs,
data: URAQuoteResponse
): {
gasUseEstimate?: number
@ -181,54 +190,43 @@ function getClassicTradeDetails(
const classicQuote =
data.routing === URAQuoteType.CLASSIC ? data.quote : data.allQuotes.find(isClassicQuoteResponse)?.quote
if (!classicQuote) return {}
if (!classicQuote) {
return {}
}
return {
gasUseEstimate: classicQuote.gasUseEstimate ? parseFloat(classicQuote.gasUseEstimate) : undefined,
gasUseEstimateUSD: classicQuote.gasUseEstimateUSD ? parseFloat(classicQuote.gasUseEstimateUSD) : undefined,
blockNumber: classicQuote.blockNumber,
routes: computeRoutes(currencyIn, currencyOut, classicQuote.route),
routes: computeRoutes(args, classicQuote.route),
swapFee: getSwapFee(classicQuote),
}
}
export function transformQuickRouteToTrade(args: GetQuickQuoteArgs, data: QuickRouteResponse): PreviewTrade {
const { amount, tradeType, inputTax, outputTax } = args
const { amount, tradeType } = args
const [currencyIn, currencyOut] = getTradeCurrencies(args, false)
const [rawAmountIn, rawAmountOut] =
data.tradeType === 'EXACT_IN' ? [amount, data.quote.amount] : [data.quote.amount, amount]
const inputAmount = CurrencyAmount.fromRawAmount(currencyIn, rawAmountIn)
const outputAmount = CurrencyAmount.fromRawAmount(currencyOut, rawAmountOut)
return new PreviewTrade({ inputAmount, outputAmount, tradeType, inputTax, outputTax })
return new PreviewTrade({ inputAmount, outputAmount, tradeType })
}
export async function transformRoutesToTrade(
export async function transformQuoteToTrade(
args: GetQuoteArgs,
data: URAQuoteResponse,
quoteMethod: QuoteMethod
): Promise<TradeResult> {
const {
tradeType,
needsWrapIfUniswapX,
routerPreference,
account,
amount,
isUniswapXDefaultEnabled,
inputTax,
outputTax,
} = args
const { tradeType, needsWrapIfUniswapX, routerPreference, account, amount, isUniswapXDefaultEnabled } = args
const showUniswapXTrade =
data.routing === URAQuoteType.DUTCH_LIMIT &&
(routerPreference === RouterPreference.X || (isUniswapXDefaultEnabled && routerPreference === RouterPreference.API))
const [currencyIn, currencyOut] = getTradeCurrencies(args, showUniswapXTrade)
const { gasUseEstimateUSD, blockNumber, routes, gasUseEstimate, swapFee } = getClassicTradeDetails(
currencyIn,
currencyOut,
data
)
const { gasUseEstimateUSD, blockNumber, routes, gasUseEstimate, swapFee } = getClassicTradeDetails(args, data)
// If the top-level URA quote type is DUTCH_LIMIT, then UniswapX is better for the user
const isUniswapXBetter = data.routing === URAQuoteType.DUTCH_LIMIT
@ -272,8 +270,6 @@ export async function transformRoutesToTrade(
isUniswapXBetter,
requestId: data.quote.requestId,
quoteMethod,
inputTax,
outputTax,
swapFee,
})
@ -310,8 +306,10 @@ export async function transformRoutesToTrade(
return { state: QuoteState.SUCCESS, trade: classicTrade }
}
function parseToken({ address, chainId, decimals, symbol }: ClassicQuoteData['route'][0][0]['tokenIn']): Token {
return new Token(chainId, address, parseInt(decimals.toString()), symbol)
function parseToken({ address, chainId, decimals, symbol, buyFeeBps, sellFeeBps }: TokenInRoute): Token {
const buyFeeBpsBN = buyFeeBps ? BigNumber.from(buyFeeBps) : undefined
const sellFeeBpsBN = sellFeeBps ? BigNumber.from(sellFeeBps) : undefined
return new Token(chainId, address, parseInt(decimals.toString()), symbol, undefined, false, buyFeeBpsBN, sellFeeBpsBN)
}
function parsePool({ fee, sqrtRatioX96, liquidity, tickCurrent, tokenIn, tokenOut }: V3PoolInRoute): Pool {

@ -2,7 +2,6 @@ import { Trans } from '@lingui/macro'
import { ChainId, Currency, CurrencyAmount, Percent, TradeType } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { useConnectionReady } from 'connection/eagerlyConnect'
import { useFotAdjustmentsEnabled } from 'featureFlags/flags/fotAdjustments'
import useAutoSlippageTolerance from 'hooks/useAutoSlippageTolerance'
import { useDebouncedTrade } from 'hooks/useDebouncedTrade'
import { useSwapTaxes } from 'hooks/useSwapTaxes'
@ -112,15 +111,14 @@ export function useDerivedSwapInfo(state: SwapState, chainId: ChainId | undefine
const inputCurrency = useCurrency(inputCurrencyId, chainId)
const outputCurrency = useCurrency(outputCurrencyId, chainId)
const fotAdjustmentsEnabled = useFotAdjustmentsEnabled()
const { inputTax, outputTax } = useSwapTaxes(
inputCurrency?.isToken && fotAdjustmentsEnabled ? inputCurrency.address : undefined,
outputCurrency?.isToken && fotAdjustmentsEnabled ? outputCurrency.address : undefined
)
const recipientLookup = useENS(recipient ?? undefined)
const to: string | null = (recipient === null ? account : recipientLookup.address) ?? null
const { inputTax, outputTax } = useSwapTaxes(
inputCurrency?.isToken ? inputCurrency.address : undefined,
outputCurrency?.isToken ? outputCurrency.address : undefined
)
const relevantTokenBalances = useCurrencyBalances(
account ?? undefined,
useMemo(() => [inputCurrency ?? undefined, outputCurrency ?? undefined], [inputCurrency, outputCurrency])
@ -137,9 +135,7 @@ export function useDerivedSwapInfo(state: SwapState, chainId: ChainId | undefine
parsedAmount,
(isExactIn ? outputCurrency : inputCurrency) ?? undefined,
undefined,
account,
inputTax,
outputTax
account
)
const { data: outputFeeFiatValue } = useUSDPrice(
@ -222,9 +218,9 @@ export function useDerivedSwapInfo(state: SwapState, chainId: ChainId | undefine
trade,
autoSlippage,
allowedSlippage,
outputFeeFiatValue,
inputTax,
outputTax,
outputFeeFiatValue,
}),
[
allowedSlippage,
@ -232,11 +228,11 @@ export function useDerivedSwapInfo(state: SwapState, chainId: ChainId | undefine
currencies,
currencyBalances,
inputError,
inputTax,
outputFeeFiatValue,
outputTax,
parsedAmount,
trade,
inputTax,
outputTax,
]
)
}

@ -3,7 +3,6 @@ import { ChainId, CurrencyAmount, Percent, Token, TradeType } from '@uniswap/sdk
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
import { V3Route } from '@uniswap/smart-order-router'
import { FeeAmount, Pool } from '@uniswap/v3-sdk'
import { ZERO_PERCENT } from 'constants/misc'
import { nativeOnChain } from 'constants/tokens'
import { BigNumber } from 'ethers/lib/ethers'
import JSBI from 'jsbi'
@ -49,8 +48,6 @@ export const TEST_TRADE_EXACT_INPUT = new ClassicTrade({
gasUseEstimateUSD: 1.0,
approveInfo: { needsApprove: false },
quoteMethod: QuoteMethod.CLIENT_SIDE_FALLBACK,
inputTax: ZERO_PERCENT,
outputTax: ZERO_PERCENT,
})
export const TEST_TRADE_EXACT_INPUT_API = new ClassicTrade({
@ -66,8 +63,6 @@ export const TEST_TRADE_EXACT_INPUT_API = new ClassicTrade({
gasUseEstimateUSD: 1.0,
approveInfo: { needsApprove: false },
quoteMethod: QuoteMethod.ROUTING_API,
inputTax: ZERO_PERCENT,
outputTax: ZERO_PERCENT,
})
export const TEST_TRADE_EXACT_OUTPUT = new ClassicTrade({
@ -82,8 +77,6 @@ export const TEST_TRADE_EXACT_OUTPUT = new ClassicTrade({
tradeType: TradeType.EXACT_OUTPUT,
quoteMethod: QuoteMethod.CLIENT_SIDE_FALLBACK,
approveInfo: { needsApprove: false },
inputTax: ZERO_PERCENT,
outputTax: ZERO_PERCENT,
})
export const TEST_ALLOWED_SLIPPAGE = new Percent(2, 100)
@ -127,11 +120,29 @@ export const TEST_DUTCH_TRADE_ETH_INPUT = new DutchOrderTrade({
slippageTolerance: new Percent(5, 100),
})
const SELL_FEE_TOKEN = new Token(
1,
'0x0000000000000000000000000000000000000001',
18,
'ABC',
'Abc',
false,
undefined,
BigNumber.from(300)
)
const TEST_POOL_FOT_1 = new Pool(
SELL_FEE_TOKEN,
TEST_TOKEN_2,
FeeAmount.HIGH,
'2437312313659959819381354528',
'10272714736694327408',
-69633
)
export const TEST_TRADE_FEE_ON_SELL = new ClassicTrade({
v3Routes: [
{
routev3: new V3Route([TEST_POOL_12], TEST_TOKEN_1, TEST_TOKEN_2),
inputAmount: toCurrencyAmount(TEST_TOKEN_1, 1000),
routev3: new V3Route([TEST_POOL_FOT_1], SELL_FEE_TOKEN, TEST_TOKEN_2),
inputAmount: toCurrencyAmount(SELL_FEE_TOKEN, 1000),
outputAmount: toCurrencyAmount(TEST_TOKEN_2, 1000),
},
],
@ -140,16 +151,32 @@ export const TEST_TRADE_FEE_ON_SELL = new ClassicTrade({
gasUseEstimateUSD: 1.0,
approveInfo: { needsApprove: false },
quoteMethod: QuoteMethod.ROUTING_API,
inputTax: new Percent(3, 100),
outputTax: ZERO_PERCENT,
})
const BUY_FEE_TOKEN = new Token(
1,
'0x0000000000000000000000000000000000000002',
18,
'DEF',
'Def',
false,
BigNumber.from(300),
undefined
)
const TEST_POOL_FOT_2 = new Pool(
TEST_TOKEN_1,
BUY_FEE_TOKEN,
FeeAmount.HIGH,
'2437312313659959819381354528',
'10272714736694327408',
-69633
)
export const TEST_TRADE_FEE_ON_BUY = new ClassicTrade({
v3Routes: [
{
routev3: new V3Route([TEST_POOL_12], TEST_TOKEN_1, TEST_TOKEN_2),
routev3: new V3Route([TEST_POOL_FOT_2], TEST_TOKEN_1, BUY_FEE_TOKEN),
inputAmount: toCurrencyAmount(TEST_TOKEN_1, 1000),
outputAmount: toCurrencyAmount(TEST_TOKEN_2, 1000),
outputAmount: toCurrencyAmount(BUY_FEE_TOKEN, 1000),
},
],
v2Routes: [],
@ -157,14 +184,10 @@ export const TEST_TRADE_FEE_ON_BUY = new ClassicTrade({
gasUseEstimateUSD: 1.0,
approveInfo: { needsApprove: false },
quoteMethod: QuoteMethod.ROUTING_API,
inputTax: ZERO_PERCENT,
outputTax: new Percent(3, 100),
})
export const PREVIEW_EXACT_IN_TRADE = new PreviewTrade({
inputAmount: toCurrencyAmount(TEST_TOKEN_1, 1000),
outputAmount: toCurrencyAmount(TEST_TOKEN_2, 1000),
tradeType: TradeType.EXACT_INPUT,
inputTax: new Percent(0, 100),
outputTax: new Percent(0, 100),
})

@ -6112,18 +6112,18 @@
resolved "https://registry.yarnpkg.com/@uniswap/redux-multicall/-/redux-multicall-1.1.8.tgz#9cc5090305b10df68fb6162eb1ba7c2c762f5e7f"
integrity sha512-LttOBVJuoRNC6N4MHsb5dF2GszLsj1ddPKKccEw1XOX17bGrFdm2A6GwKgES+v+Hj3lluDbQL6atcQtymP21iw==
"@uniswap/router-sdk@^1.6.0":
version "1.6.0"
resolved "https://registry.yarnpkg.com/@uniswap/router-sdk/-/router-sdk-1.6.0.tgz#2f51dbba1b01467244b59500ed0da8aa84323f8c"
integrity sha512-onpAzcvEnrsm8tUtu49IrR9EP3n9j0IDpGc0Ee3FDDkVgXrp9cIrAADC+yb56vgLtJFnshbhyIdjXLMIzWe0Gw==
"@uniswap/router-sdk@^1.6.0", "@uniswap/router-sdk@^1.7.1":
version "1.7.1"
resolved "https://registry.yarnpkg.com/@uniswap/router-sdk/-/router-sdk-1.7.1.tgz#642d5804299cd50b1a3ba2fa0a87963320fb7f93"
integrity sha512-uBN9QX3t5lPLkxlkPoQPZpd0eN+GA0Ab9nq1pcPk/XDFuRnRxxVF629Ecz2SfTVm0gooOPO3aU3ETgyB3vuhYA==
dependencies:
"@ethersproject/abi" "^5.5.0"
"@uniswap/sdk-core" "^4"
"@uniswap/swap-router-contracts" "1.1.0"
"@uniswap/sdk-core" "^4.0.7"
"@uniswap/swap-router-contracts" "^1.1.0"
"@uniswap/v2-sdk" "^3.2.0"
"@uniswap/v3-sdk" "^3.10.0"
"@uniswap/sdk-core@4.0.7", "@uniswap/sdk-core@>= 3", "@uniswap/sdk-core@^4", "@uniswap/sdk-core@^4.0.0", "@uniswap/sdk-core@^4.0.2", "@uniswap/sdk-core@^4.0.3", "@uniswap/sdk-core@^4.0.6":
"@uniswap/sdk-core@4.0.7", "@uniswap/sdk-core@>= 3", "@uniswap/sdk-core@^4", "@uniswap/sdk-core@^4.0.0", "@uniswap/sdk-core@^4.0.2", "@uniswap/sdk-core@^4.0.3", "@uniswap/sdk-core@^4.0.6", "@uniswap/sdk-core@^4.0.7":
version "4.0.7"
resolved "https://registry.npmjs.org/@uniswap/sdk-core/-/sdk-core-4.0.7.tgz#90dfd070d7e44494234618af398da158363ae827"
integrity sha512-jscx7KUIWzQatcL5PHY6xy0gEL9IGQcL5h/obxzX9foP2KoNk9cq66Ia8I2Kvpa7zBcPOeW1hU0hJNBq6CzcIQ==
@ -6163,26 +6163,15 @@
node-cache "^5.1.2"
stats-lite "^2.2.0"
"@uniswap/swap-router-contracts@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@uniswap/swap-router-contracts/-/swap-router-contracts-1.1.0.tgz#e027b14d4c172f231c53c48e1fd708a78d7d94d8"
integrity sha512-GPmpx1lvjXWloB95+YUabr3UHJYr3scnSS8EzaNXnNrIz9nYZ+XQcMaJxOKe85Yi7IfcUQpj0HzD2TW99dtolA==
dependencies:
"@openzeppelin/contracts" "3.4.1-solc-0.7-2"
"@uniswap/v2-core" "1.0.1"
"@uniswap/v3-core" "1.0.0"
"@uniswap/v3-periphery" "1.3.0"
hardhat-watcher "^2.1.1"
"@uniswap/swap-router-contracts@^1.2.1", "@uniswap/swap-router-contracts@^1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@uniswap/swap-router-contracts/-/swap-router-contracts-1.3.0.tgz#8d555ca6d74b888d6e02a26ebb806ce315605f1f"
integrity sha512-iKvCuRkHXEe0EMjOf8HFUISTIhlxI57kKFllf3C3PUIE0HmwxrayyoflwAz5u/TRsFGYqJ9IjX2UgzLCsrNa5A==
"@uniswap/swap-router-contracts@^1.1.0", "@uniswap/swap-router-contracts@^1.2.1", "@uniswap/swap-router-contracts@^1.3.0":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@uniswap/swap-router-contracts/-/swap-router-contracts-1.3.1.tgz#0ebbb93eb578625618ed9489872de381f9c66fb4"
integrity sha512-mh/YNbwKb7Mut96VuEtL+Z5bRe0xVIbjjiryn+iMMrK2sFKhR4duk/86mEz0UO5gSx4pQIw9G5276P5heY/7Rg==
dependencies:
"@openzeppelin/contracts" "3.4.2-solc-0.7"
"@uniswap/v2-core" "1.0.1"
"@uniswap/v3-core" "1.0.0"
"@uniswap/v3-periphery" "1.4.1"
"@uniswap/v2-core" "^1.0.1"
"@uniswap/v3-core" "^1.0.0"
"@uniswap/v3-periphery" "^1.4.4"
dotenv "^14.2.0"
hardhat-watcher "^2.1.1"
@ -6259,34 +6248,21 @@
resolved "https://registry.npmjs.org/@uniswap/v3-core/-/v3-core-1.0.0.tgz"
integrity sha512-kSC4djMGKMHj7sLMYVnn61k9nu+lHjMIxgg9CDQT+s2QYLoA56GbSK9Oxr+qJXzzygbkrmuY6cwgP6cW2JXPFA==
"@uniswap/v3-core@^1.0.1":
"@uniswap/v3-core@^1.0.0", "@uniswap/v3-core@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@uniswap/v3-core/-/v3-core-1.0.1.tgz#b6d2bdc6ba3c3fbd610bdc502395d86cd35264a0"
integrity sha512-7pVk4hEm00j9tc71Y9+ssYpO6ytkeI0y7WE9P6UcmNzhxPePwyAxImuhVsTqWK9YFvzgtvzJHi64pBl4jUzKMQ==
"@uniswap/v3-periphery@1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@uniswap/v3-periphery/-/v3-periphery-1.3.0.tgz#37f0a1ef6025221722e50e9f3f2009c2d5d6e4ec"
integrity sha512-HjHdI5RkjBl8zz3bqHShrbULFoZSrjbbrRHoO2vbzn+WRzTa6xY4PWphZv2Tlcb38YEKfKHp6NPl5hVedac8uw==
dependencies:
"@openzeppelin/contracts" "3.4.1-solc-0.7-2"
"@uniswap/lib" "^4.0.1-alpha"
"@uniswap/v2-core" "1.0.1"
"@uniswap/v3-core" "1.0.0"
base64-sol "1.0.1"
hardhat-watcher "^2.1.1"
"@uniswap/v3-periphery@1.4.1", "@uniswap/v3-periphery@^1.0.1", "@uniswap/v3-periphery@^1.1.1":
version "1.4.1"
resolved "https://registry.yarnpkg.com/@uniswap/v3-periphery/-/v3-periphery-1.4.1.tgz#b90f08b7386163c0abfd7258831caef6339c7862"
integrity sha512-Ab0ZCKOQrQMKIcpBTezTsEhWfQjItd0TtkCG8mPhoQu+wC67nPaf4hYUhM6wGHeFUmDiYY5MpEQuokB0ENvoTg==
"@uniswap/v3-periphery@^1.0.1", "@uniswap/v3-periphery@^1.1.1", "@uniswap/v3-periphery@^1.4.4":
version "1.4.4"
resolved "https://registry.yarnpkg.com/@uniswap/v3-periphery/-/v3-periphery-1.4.4.tgz#d2756c23b69718173c5874f37fd4ad57d2f021b7"
integrity sha512-S4+m+wh8HbWSO3DKk4LwUCPZJTpCugIsHrWR86m/OrUyvSqGDTXKFfc2sMuGXCZrD1ZqO3rhQsKgdWg3Hbb2Kw==
dependencies:
"@openzeppelin/contracts" "3.4.2-solc-0.7"
"@uniswap/lib" "^4.0.1-alpha"
"@uniswap/v2-core" "1.0.1"
"@uniswap/v3-core" "1.0.0"
"@uniswap/v2-core" "^1.0.1"
"@uniswap/v3-core" "^1.0.0"
base64-sol "1.0.1"
hardhat-watcher "^2.1.1"
"@uniswap/v3-sdk@^3.10.0":
version "3.10.0"