diff --git a/src/components/Settings/index.tsx b/src/components/Settings/index.tsx
index b438d6a450..dc6ccc6431 100644
--- a/src/components/Settings/index.tsx
+++ b/src/components/Settings/index.tsx
@@ -246,7 +246,7 @@ export default function SettingsTab() {
{/* WIP */}
toggleDarkMode()}>
- {darkMode ? : }
+ {darkMode ? : }
diff --git a/src/components/swap/BetterTradeLink.tsx b/src/components/swap/BetterTradeLink.tsx
index c0840085be..06265f94e3 100644
--- a/src/components/swap/BetterTradeLink.tsx
+++ b/src/components/swap/BetterTradeLink.tsx
@@ -14,7 +14,7 @@ function VersionLinkContainer({ children }: { children: React.ReactNode }) {
const theme = useContext(ThemeContext)
return (
-
+
{children}
diff --git a/src/components/swap/ConfirmSwapModal.tsx b/src/components/swap/ConfirmSwapModal.tsx
index 93e55b81a0..2c0cc3f1c6 100644
--- a/src/components/swap/ConfirmSwapModal.tsx
+++ b/src/components/swap/ConfirmSwapModal.tsx
@@ -1,4 +1,4 @@
-import { currencyEquals } from '@uniswap/sdk-core'
+import { currencyEquals, Percent } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import React, { useCallback, useMemo } from 'react'
@@ -86,10 +86,12 @@ export default function ConfirmSwapModal({
) : null
}, [allowedSlippage, onConfirm, showAcceptChanges, swapErrorMessage, trade])
+ const slippageTolerancePercent = new Percent(allowedSlippage, 10_000)
+
// text to show while loading
- const pendingText = `Swapping ${trade?.inputAmount?.toSignificant(6)} ${
+ const pendingText = `Swapping ${trade?.maximumAmountIn(slippageTolerancePercent)?.toSignificant(6)} ${
trade?.inputAmount?.currency?.symbol
- } for ${trade?.outputAmount?.toSignificant(6)} ${trade?.outputAmount?.currency?.symbol}`
+ } for ${trade?.minimumAmountOut(slippageTolerancePercent)?.toSignificant(6)} ${trade?.outputAmount?.currency?.symbol}`
const confirmationContent = useCallback(
() =>
diff --git a/src/components/swap/SwapModalFooter.tsx b/src/components/swap/SwapModalFooter.tsx
index 774b09b9a1..3732d3a726 100644
--- a/src/components/swap/SwapModalFooter.tsx
+++ b/src/components/swap/SwapModalFooter.tsx
@@ -1,23 +1,14 @@
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
-import { TradeType } from '@uniswap/sdk-core'
+import { Percent } from '@uniswap/sdk-core'
import React, { useContext, useMemo, useState } from 'react'
import { Repeat } from 'react-feather'
import { Text } from 'rebass'
import { ThemeContext } from 'styled-components'
-import { Field } from '../../state/swap/actions'
-import { TYPE } from '../../theme'
-import {
- computeSlippageAdjustedAmounts,
- computeTradePriceBreakdown,
- formatExecutionPrice,
- warningSeverity,
-} from '../../utils/prices'
+import { computeTradePriceBreakdown, formatExecutionPrice, warningSeverity } from '../../utils/prices'
import { ButtonError } from '../Button'
import { AutoColumn } from '../Column'
-import QuestionHelper from '../QuestionHelper'
-import { AutoRow, RowBetween, RowFixed } from '../Row'
-import FormattedPriceImpact from './FormattedPriceImpact'
+import { AutoRow, RowBetween } from '../Row'
import { StyledBalanceMaxMini, SwapCallbackError } from './styleds'
export default function SwapModalFooter({
@@ -35,11 +26,8 @@ export default function SwapModalFooter({
}) {
const [showInverted, setShowInverted] = useState(false)
const theme = useContext(ThemeContext)
- const slippageAdjustedAmounts = useMemo(() => computeSlippageAdjustedAmounts(trade, allowedSlippage), [
- allowedSlippage,
- trade,
- ])
- const { priceImpactWithoutFee, realizedLPFee } = useMemo(() => computeTradePriceBreakdown(trade), [trade])
+ const slippageTolerancePercent = new Percent(allowedSlippage, 10_000)
+ const { priceImpactWithoutFee } = useMemo(() => computeTradePriceBreakdown(trade), [trade])
const severity = warningSeverity(priceImpactWithoutFee)
return (
@@ -61,53 +49,12 @@ export default function SwapModalFooter({
paddingLeft: '10px',
}}
>
- {formatExecutionPrice(trade, showInverted)}
+ {formatExecutionPrice(trade, showInverted, slippageTolerancePercent)}
setShowInverted(!showInverted)}>
-
-
-
-
- {trade.tradeType === TradeType.EXACT_INPUT ? 'Minimum received' : 'Maximum sold'}
-
-
-
-
-
- {trade.tradeType === TradeType.EXACT_INPUT
- ? slippageAdjustedAmounts[Field.OUTPUT]?.toSignificant(4) ?? '-'
- : slippageAdjustedAmounts[Field.INPUT]?.toSignificant(4) ?? '-'}
-
-
- {trade.tradeType === TradeType.EXACT_INPUT
- ? trade.outputAmount.currency.symbol
- : trade.inputAmount.currency.symbol}
-
-
-
-
-
-
- Price Impact
-
-
-
-
-
-
-
-
- Liquidity Provider Fee
-
-
-
-
- {realizedLPFee ? realizedLPFee?.toSignificant(6) + ' ' + trade.inputAmount.currency.symbol : '-'}
-
-
diff --git a/src/components/swap/SwapModalHeader.tsx b/src/components/swap/SwapModalHeader.tsx
index 6f9c2c11bc..616d641648 100644
--- a/src/components/swap/SwapModalHeader.tsx
+++ b/src/components/swap/SwapModalHeader.tsx
@@ -1,15 +1,13 @@
-import { TradeType } from '@uniswap/sdk-core'
+import { Percent, TradeType } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
-import React, { useContext, useMemo } from 'react'
+import React, { useContext } from 'react'
import { ArrowDown, AlertTriangle } from 'react-feather'
import { Text } from 'rebass'
import { ThemeContext } from 'styled-components'
-import { Field } from '../../state/swap/actions'
import { TYPE } from '../../theme'
import { ButtonPrimary } from '../Button'
import { isAddress, shortenAddress } from '../../utils'
-import { computeSlippageAdjustedAmounts, computeTradePriceBreakdown, warningSeverity } from '../../utils/prices'
import { AutoColumn } from '../Column'
import CurrencyLogo from '../CurrencyLogo'
import { RowBetween, RowFixed } from '../Row'
@@ -28,12 +26,9 @@ export default function SwapModalHeader({
showAcceptChanges: boolean
onAcceptChanges: () => void
}) {
- const slippageAdjustedAmounts = useMemo(() => computeSlippageAdjustedAmounts(trade, allowedSlippage), [
- trade,
- allowedSlippage,
- ])
- const { priceImpactWithoutFee } = useMemo(() => computeTradePriceBreakdown(trade), [trade])
- const priceImpactSeverity = warningSeverity(priceImpactWithoutFee)
+ const slippageTolerancePercent = new Percent(allowedSlippage, 10_000)
+ const maximumAmountIn = trade.maximumAmountIn(slippageTolerancePercent)
+ const minimumAmountOut = trade.minimumAmountOut(slippageTolerancePercent)
const theme = useContext(ThemeContext)
@@ -47,7 +42,7 @@ export default function SwapModalHeader({
fontWeight={500}
color={showAcceptChanges && trade.tradeType === TradeType.EXACT_OUTPUT ? theme.primary1 : ''}
>
- {trade.inputAmount.toSignificant(6)}
+ {maximumAmountIn.toSignificant(6)}
@@ -62,18 +57,8 @@ export default function SwapModalHeader({
- 2
- ? theme.red1
- : showAcceptChanges && trade.tradeType === TradeType.EXACT_INPUT
- ? theme.primary1
- : ''
- }
- >
- {trade.outputAmount.toSignificant(6)}
+
+ {minimumAmountOut.toSignificant(6)}
@@ -103,7 +88,7 @@ export default function SwapModalHeader({
{`Output is estimated. You will receive at least `}
- {slippageAdjustedAmounts[Field.OUTPUT]?.toSignificant(6)} {trade.outputAmount.currency.symbol}
+ {minimumAmountOut.toSignificant(6)} {trade.outputAmount.currency.symbol}
{' or the transaction will revert.'}
@@ -111,7 +96,7 @@ export default function SwapModalHeader({
{`Input is estimated. You will sell at most `}
- {slippageAdjustedAmounts[Field.INPUT]?.toSignificant(6)} {trade.inputAmount.currency.symbol}
+ {maximumAmountIn.toSignificant(6)} {trade.inputAmount.currency.symbol}
{' or the transaction will revert.'}
diff --git a/src/components/swap/TradePrice.tsx b/src/components/swap/TradePrice.tsx
index c2f275cf39..77016112b1 100644
--- a/src/components/swap/TradePrice.tsx
+++ b/src/components/swap/TradePrice.tsx
@@ -8,7 +8,7 @@ import { StyledBalanceMaxMini } from './styleds'
import Switch from '../../assets/svg/switch.svg'
interface TradePriceProps {
- price?: Price
+ price: Price
showInverted: boolean
setShowInverted: (showInverted: boolean) => void
}
@@ -23,10 +23,10 @@ const StyledPriceContainer = styled.div`
export default function TradePrice({ price, showInverted, setShowInverted }: TradePriceProps) {
const theme = useContext(ThemeContext)
- const formattedPrice = showInverted ? price?.toSignificant(6) : price?.invert()?.toSignificant(6)
+ const formattedPrice = showInverted ? price.toSignificant(6) : price.invert()?.toSignificant(6)
- const label = showInverted ? `${price?.quoteCurrency?.symbol}` : `${price?.baseCurrency?.symbol} `
- const labelInverted = showInverted ? `${price?.baseCurrency?.symbol} ` : `${price?.quoteCurrency?.symbol}`
+ const label = showInverted ? `${price.quoteCurrency?.symbol}` : `${price.baseCurrency?.symbol} `
+ const labelInverted = showInverted ? `${price.baseCurrency?.symbol} ` : `${price.quoteCurrency?.symbol}`
const flipPrice = useCallback(() => setShowInverted(!showInverted), [setShowInverted, showInverted])
return (
diff --git a/src/hooks/useSwapCallback.ts b/src/hooks/useSwapCallback.ts
index b0cad08e1d..e1f14534bf 100644
--- a/src/hooks/useSwapCallback.ts
+++ b/src/hooks/useSwapCallback.ts
@@ -233,8 +233,7 @@ export function useSwapCallback(
: recipientAddressOrName
}`
- const withVersion =
- tradeVersion === Version.v2 ? withRecipient : `${withRecipient} on ${(tradeVersion as any).toUpperCase()}`
+ const withVersion = tradeVersion === Version.v3 ? withRecipient : `${withRecipient} on ${tradeVersion}`
addTransaction(response, {
summary: withVersion,
diff --git a/src/pages/Swap/index.tsx b/src/pages/Swap/index.tsx
index da9e2e8c94..501baf6dc3 100644
--- a/src/pages/Swap/index.tsx
+++ b/src/pages/Swap/index.tsx
@@ -1,36 +1,38 @@
-import JSBI from 'jsbi'
import { CurrencyAmount, Percent, Token } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
+import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter'
+import JSBI from 'jsbi'
import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react'
import { ArrowDown, Repeat, Unlock } from 'react-feather'
import ReactGA from 'react-ga'
+import { RouteComponentProps } from 'react-router-dom'
import { Text } from 'rebass'
import { ThemeContext } from 'styled-components'
import AddressInputPanel from '../../components/AddressInputPanel'
-import { ButtonError, ButtonLight, ButtonPrimary, ButtonConfirmed } from '../../components/Button'
+import { ButtonConfirmed, ButtonError, ButtonLight, ButtonPrimary } from '../../components/Button'
import { GreyCard } from '../../components/Card'
import { AutoColumn } from '../../components/Column'
-import BetterTradeLink from '../../components/swap/BetterTradeLink'
-import ConfirmSwapModal from '../../components/swap/ConfirmSwapModal'
import CurrencyInputPanel from '../../components/CurrencyInputPanel'
+import CurrencyLogo from '../../components/CurrencyLogo'
+import Loader from '../../components/Loader'
+import ProgressSteps from '../../components/ProgressSteps'
import { AutoRow } from '../../components/Row'
+import BetterTradeLink from '../../components/swap/BetterTradeLink'
import confirmPriceImpactWithoutFee from '../../components/swap/confirmPriceImpactWithoutFee'
+import ConfirmSwapModal from '../../components/swap/ConfirmSwapModal'
import { ArrowWrapper, BottomGrouping, SwapCallbackError, Wrapper } from '../../components/swap/styleds'
+import SwapHeader from '../../components/swap/SwapHeader'
import TradePrice from '../../components/swap/TradePrice'
import TokenWarningModal from '../../components/TokenWarningModal'
-import ProgressSteps from '../../components/ProgressSteps'
-import SwapHeader from '../../components/swap/SwapHeader'
-import CurrencyLogo from '../../components/CurrencyLogo'
-import { V3TradeState } from '../../hooks/useBestV3Trade'
-import useToggledVersion, { Version } from '../../hooks/useToggledVersion'
-import { getTradeVersion } from '../../utils/getTradeVersion'
import { useActiveWeb3React } from '../../hooks'
-import { useCurrency, useAllTokens } from '../../hooks/Tokens'
+import { useAllTokens, useCurrency } from '../../hooks/Tokens'
import { ApprovalState, useApproveCallbackFromTrade } from '../../hooks/useApproveCallback'
+import { V3TradeState } from '../../hooks/useBestV3Trade'
import useENSAddress from '../../hooks/useENSAddress'
import { useIsSwapUnsupported } from '../../hooks/useIsSwapUnsupported'
import { useSwapCallback } from '../../hooks/useSwapCallback'
+import useToggledVersion, { Version } from '../../hooks/useToggledVersion'
import useWrapCallback, { WrapType } from '../../hooks/useWrapCallback'
import { useWalletModalToggle } from '../../state/application/hooks'
import { Field } from '../../state/swap/actions'
@@ -40,15 +42,13 @@ import {
useSwapActionHandlers,
useSwapState,
} from '../../state/swap/hooks'
-import { useExpertModeManager, useUserSlippageTolerance, useUserSingleHopOnly } from '../../state/user/hooks'
+import { useExpertModeManager, useUserSingleHopOnly, useUserSlippageTolerance } from '../../state/user/hooks'
import { LinkStyledButton, TYPE } from '../../theme'
+import { getTradeVersion } from '../../utils/getTradeVersion'
import { isTradeBetter } from '../../utils/isTradeBetter'
import { maxAmountSpend } from '../../utils/maxAmountSpend'
import { computeTradePriceBreakdown, warningSeverity } from '../../utils/prices'
import AppBody from '../AppBody'
-import Loader from '../../components/Loader'
-import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter'
-import { RouteComponentProps } from 'react-router-dom'
export default function Swap({ history }: RouteComponentProps) {
const loadedUrlParams = useDefaultsFromURLSearch()
@@ -391,11 +391,10 @@ export default function Swap({ history }: RouteComponentProps) {
setShowInverted={setShowInverted}
/>
) : null}
- {toggledVersion === Version.v3 && v3TradeState === V3TradeState.VALID && isTradeBetter(v3Trade, v2Trade) ? (
+ {![V3TradeState.VALID, V3TradeState.SYNCING].includes(v3TradeState) ? null : toggledVersion ===
+ Version.v3 && isTradeBetter(v3Trade, v2Trade) ? (
- ) : toggledVersion === Version.v2 &&
- v3TradeState === V3TradeState.VALID &&
- isTradeBetter(v2Trade, v3Trade) ? (
+ ) : toggledVersion === Version.v2 && isTradeBetter(v2Trade, v3Trade) ? (
) : null}
diff --git a/src/utils/isTradeBetter.ts b/src/utils/isTradeBetter.ts
index 7622f39184..2c4a9197a7 100644
--- a/src/utils/isTradeBetter.ts
+++ b/src/utils/isTradeBetter.ts
@@ -18,6 +18,7 @@ export function isTradeBetter(
!currencyEquals(tradeA.inputAmount.currency, tradeB.inputAmount.currency) ||
!currencyEquals(tradeB.outputAmount.currency, tradeB.outputAmount.currency)
) {
+ console.error('Comparing incomparable trades', tradeA, tradeB)
return false
}
diff --git a/src/utils/prices.ts b/src/utils/prices.ts
index ab0631956e..49884cc298 100644
--- a/src/utils/prices.ts
+++ b/src/utils/prices.ts
@@ -1,5 +1,5 @@
import JSBI from 'jsbi'
-import { BLOCKED_PRICE_IMPACT_NON_EXPERT } from '../constants'
+import { BLOCKED_PRICE_IMPACT_NON_EXPERT, ZERO_PERCENT } from '../constants'
import { CurrencyAmount, Fraction, Percent, TokenAmount } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
@@ -104,15 +104,19 @@ export function warningSeverity(priceImpact: Percent | undefined): 0 | 1 | 2 | 3
return 0
}
-export function formatExecutionPrice(trade: V2Trade | V3Trade | undefined, inverted: boolean | undefined): string {
+export function formatExecutionPrice(
+ trade: V2Trade | V3Trade | undefined,
+ inverted: boolean | undefined,
+ slippageTolerance: Percent = ZERO_PERCENT
+): string {
if (!trade) {
return ''
}
return inverted
- ? `${trade.executionPrice.invert().toSignificant(6)} ${trade.inputAmount.currency.symbol} / ${
- trade.outputAmount.currency.symbol
- }`
- : `${trade.executionPrice.toSignificant(6)} ${trade.outputAmount.currency.symbol} / ${
+ ? `${trade.worstExecutionPrice(slippageTolerance).invert().toSignificant(6)} ${
+ trade.inputAmount.currency.symbol
+ } / ${trade.outputAmount.currency.symbol}`
+ : `${trade.worstExecutionPrice(slippageTolerance).toSignificant(6)} ${trade.outputAmount.currency.symbol} / ${
trade.inputAmount.currency.symbol
}`
}