diff --git a/package.json b/package.json index 7e938ec263..70d538c1d6 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "@uniswap/v2-sdk": "^3.0.0-alpha.0", "@uniswap/v3-core": "1.0.0", "@uniswap/v3-periphery": "1.0.0", - "@uniswap/v3-sdk": "^3.0.0-alpha.2", + "@uniswap/v3-sdk": "^3.0.0-alpha.4", "@web3-react/core": "^6.0.9", "@web3-react/fortmatic-connector": "^6.0.9", "@web3-react/injected-connector": "^6.0.7", diff --git a/src/components/swap/AdvancedSwapDetails.tsx b/src/components/swap/AdvancedSwapDetails.tsx index d53e323862..aad583c4b2 100644 --- a/src/components/swap/AdvancedSwapDetails.tsx +++ b/src/components/swap/AdvancedSwapDetails.tsx @@ -1,11 +1,10 @@ import { Percent, Currency, TradeType } from '@uniswap/sdk-core' import { Trade as V2Trade } from '@uniswap/v2-sdk' import { Trade as V3Trade } from '@uniswap/v3-sdk' -import React, { useContext } from 'react' +import React, { useContext, useMemo } from 'react' import { ThemeContext } from 'styled-components' import { TYPE } from '../../theme' -import { computePriceImpactWithMaximumSlippage } from '../../utils/computePriceImpactWithMaximumSlippage' -import { computeRealizedLPFeeAmount } from '../../utils/prices' +import { computeRealizedLPFeePercent } from '../../utils/prices' import { AutoColumn } from '../Column' import { RowBetween, RowFixed } from '../Row' import FormattedPriceImpact from './FormattedPriceImpact' @@ -19,7 +18,14 @@ export interface AdvancedSwapDetailsProps { export function AdvancedSwapDetails({ trade, allowedSlippage }: AdvancedSwapDetailsProps) { const theme = useContext(ThemeContext) - const realizedLPFee = computeRealizedLPFeeAmount(trade) + const { realizedLPFee, priceImpact } = useMemo(() => { + if (!trade) return { realizedLPFee: undefined, priceImpact: undefined } + + const realizedLpFeePercent = computeRealizedLPFeePercent(trade) + const realizedLPFee = trade.inputAmount.multiply(realizedLpFeePercent) + const priceImpact = trade.priceImpact.subtract(realizedLpFeePercent) + return { priceImpact, realizedLPFee } + }, [trade]) return !trade ? null : ( @@ -30,7 +36,7 @@ export function AdvancedSwapDetails({ trade, allowedSlippage }: AdvancedSwapDeta - {realizedLPFee ? `${realizedLPFee.toSignificant(4)} ${trade.inputAmount.currency.symbol}` : '-'} + {realizedLPFee ? `${realizedLPFee.toSignificant(4)} ${realizedLPFee.currency.symbol}` : '-'} @@ -48,11 +54,24 @@ export function AdvancedSwapDetails({ trade, allowedSlippage }: AdvancedSwapDeta - Execution price vs. spot price + Price Impact - + + + + + + + + {trade.tradeType === TradeType.EXACT_INPUT ? 'Minimum Amount Out' : 'Maximum Amount In'} + + + + {trade.tradeType === TradeType.EXACT_INPUT + ? `${trade.minimumAmountOut(allowedSlippage).toSignificant(6)} ${trade.outputAmount.currency.symbol}` + : `${trade.maximumAmountIn(allowedSlippage).toSignificant(6)} ${trade.inputAmount.currency.symbol}`} diff --git a/src/components/swap/ConfirmSwapModal.tsx b/src/components/swap/ConfirmSwapModal.tsx index 056c058a4b..97161a6a6a 100644 --- a/src/components/swap/ConfirmSwapModal.tsx +++ b/src/components/swap/ConfirmSwapModal.tsx @@ -90,9 +90,9 @@ export default function ConfirmSwapModal({ }, [onConfirm, showAcceptChanges, swapErrorMessage, trade]) // text to show while loading - const pendingText = `Swapping ${trade?.maximumAmountIn(allowedSlippage)?.toSignificant(6)} ${ + const pendingText = `Swapping ${trade?.inputAmount?.toSignificant(6)} ${ trade?.inputAmount?.currency?.symbol - } for ${trade?.minimumAmountOut(allowedSlippage)?.toSignificant(6)} ${trade?.outputAmount?.currency?.symbol}` + } for ${trade?.outputAmount?.toSignificant(6)} ${trade?.outputAmount?.currency?.symbol}` const confirmationContent = useCallback( () => diff --git a/src/components/swap/SwapModalHeader.tsx b/src/components/swap/SwapModalHeader.tsx index aa54bc2184..5a8eabcb54 100644 --- a/src/components/swap/SwapModalHeader.tsx +++ b/src/components/swap/SwapModalHeader.tsx @@ -31,12 +31,10 @@ export const ArrowWrapper = styled.div` margin-top: -18px; margin-bottom: -18px; left: calc(50% - 16px); - /* transform: rotate(90deg); */ display: flex; justify-content: center; align-items: center; background-color: ${({ theme }) => theme.bg1}; - /* border: 4px solid ${({ theme }) => theme.bg0}; */ z-index: 2; ` @@ -53,15 +51,12 @@ export default function SwapModalHeader({ showAcceptChanges: boolean onAcceptChanges: () => void }) { - const maximumAmountIn = trade.maximumAmountIn(allowedSlippage) - const minimumAmountOut = trade.minimumAmountOut(allowedSlippage) - const theme = useContext(ThemeContext) const [showInverted, setShowInverted] = useState(false) - const fiatValueInput = useUSDCValue(maximumAmountIn) - const fiatValueOutput = useUSDCValue(minimumAmountOut) + const fiatValueInput = useUSDCValue(trade.inputAmount) + const fiatValueOutput = useUSDCValue(trade.outputAmount) return ( @@ -86,7 +81,7 @@ export default function SwapModalHeader({ fontWeight={500} color={showAcceptChanges && trade.tradeType === TradeType.EXACT_OUTPUT ? theme.primary1 : ''} > - {maximumAmountIn.toSignificant(6)} + {trade.inputAmount.toSignificant(6)} @@ -117,7 +112,7 @@ export default function SwapModalHeader({ - {minimumAmountOut.toSignificant(6)} + {trade.outputAmount.toSignificant(6)} @@ -127,11 +122,7 @@ export default function SwapModalHeader({ {'Price:'} - + @@ -155,12 +146,12 @@ export default function SwapModalHeader({ ) : null} - {/* + {trade.tradeType === TradeType.EXACT_INPUT ? ( {`Output is estimated. You will receive at least `} - {minimumAmountOut.toSignificant(6)} {trade.outputAmount.currency.symbol} + {trade.minimumAmountOut(allowedSlippage).toSignificant(6)} {trade.outputAmount.currency.symbol} {' or the transaction will revert.'} @@ -168,12 +159,12 @@ export default function SwapModalHeader({ {`Input is estimated. You will sell at most `} - {maximumAmountIn.toSignificant(6)} {trade.inputAmount.currency.symbol} + {trade.maximumAmountIn(allowedSlippage).toSignificant(6)} {trade.inputAmount.currency.symbol} {' or the transaction will revert.'} )} - */} + {recipient !== null ? ( diff --git a/src/hooks/useSwapCallback.ts b/src/hooks/useSwapCallback.ts index 751690acbd..08b89f5273 100644 --- a/src/hooks/useSwapCallback.ts +++ b/src/hooks/useSwapCallback.ts @@ -275,8 +275,8 @@ export function useSwapCallback( .then((response) => { const inputSymbol = trade.inputAmount.currency.symbol const outputSymbol = trade.outputAmount.currency.symbol - const inputAmount = trade.maximumAmountIn(allowedSlippage).toSignificant(4) - const outputAmount = trade.minimumAmountOut(allowedSlippage).toSignificant(4) + const inputAmount = trade.inputAmount.toSignificant(4) + const outputAmount = trade.outputAmount.toSignificant(4) const base = `Swap ${inputAmount} ${inputSymbol} for ${outputAmount} ${outputSymbol}` const withRecipient = @@ -312,5 +312,5 @@ export function useSwapCallback( }, error: null, } - }, [trade, library, account, chainId, recipient, recipientAddressOrName, swapCalls, allowedSlippage, addTransaction]) + }, [trade, library, account, chainId, recipient, recipientAddressOrName, swapCalls, addTransaction]) } diff --git a/src/pages/Swap/index.tsx b/src/pages/Swap/index.tsx index 6290c72a51..193f52cf6f 100644 --- a/src/pages/Swap/index.tsx +++ b/src/pages/Swap/index.tsx @@ -49,7 +49,6 @@ import { import { useExpertModeManager, useUserSingleHopOnly } from '../../state/user/hooks' import { HideSmall, LinkStyledButton, TYPE } from '../../theme' import { computeFiatValuePriceImpact } from '../../utils/computeFiatValuePriceImpact' -import { computePriceImpactWithMaximumSlippage } from '../../utils/computePriceImpactWithMaximumSlippage' import { getTradeVersion } from '../../utils/getTradeVersion' import { isTradeBetter } from '../../utils/isTradeBetter' import { maxAmountSpend } from '../../utils/maxAmountSpend' @@ -132,10 +131,10 @@ export default function Swap({ history }: RouteComponentProps) { [Field.OUTPUT]: parsedAmount, } : { - [Field.INPUT]: independentField === Field.INPUT ? parsedAmount : trade?.maximumAmountIn(allowedSlippage), - [Field.OUTPUT]: independentField === Field.OUTPUT ? parsedAmount : trade?.minimumAmountOut(allowedSlippage), + [Field.INPUT]: independentField === Field.INPUT ? parsedAmount : trade?.inputAmount, + [Field.OUTPUT]: independentField === Field.OUTPUT ? parsedAmount : trade?.outputAmount, }, - [allowedSlippage, independentField, parsedAmount, showWrap, trade] + [independentField, parsedAmount, showWrap, trade] ) const fiatValueInput = useUSDCValue(parsedAmounts[Field.INPUT]) @@ -292,7 +291,7 @@ export default function Swap({ history }: RouteComponentProps) { // warnings on the greater of fiat value price impact and execution price impact const priceImpactSeverity = useMemo(() => { - const executionPriceImpact = trade ? computePriceImpactWithMaximumSlippage(trade, allowedSlippage) : undefined + const executionPriceImpact = trade?.priceImpact return warningSeverity( executionPriceImpact && priceImpact ? executionPriceImpact.greaterThan(priceImpact) @@ -300,7 +299,7 @@ export default function Swap({ history }: RouteComponentProps) { : priceImpact : executionPriceImpact ?? priceImpact ) - }, [allowedSlippage, priceImpact, trade]) + }, [priceImpact, trade]) // show approve flow when: no error on inputs, not approved or pending, or approved in current session // never show if price impact is above threshold in non expert mode @@ -475,7 +474,7 @@ export default function Swap({ history }: RouteComponentProps) { {trade ? ( diff --git a/src/utils/computePriceImpactWithMaximumSlippage.tsx b/src/utils/computePriceImpactWithMaximumSlippage.tsx deleted file mode 100644 index 33a04770a3..0000000000 --- a/src/utils/computePriceImpactWithMaximumSlippage.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { computePriceImpact, Currency, Percent, TradeType } from '@uniswap/sdk-core' -import { Trade as V2Trade } from '@uniswap/v2-sdk' -import { Trade as V3Trade } from '@uniswap/v3-sdk' - -export function computePriceImpactWithMaximumSlippage( - trade: V2Trade | V3Trade, - allowedSlippage: Percent -): Percent { - return computePriceImpact( - trade.route.midPrice, - trade.maximumAmountIn(allowedSlippage), - trade.minimumAmountOut(allowedSlippage) - ) -} diff --git a/src/utils/prices.ts b/src/utils/prices.ts index 67f8995917..51f82668bc 100644 --- a/src/utils/prices.ts +++ b/src/utils/prices.ts @@ -22,15 +22,15 @@ export function computeRealizedLPFeePercent( // for each hop in our trade, take away the x*y=k price impact from 0.3% fees // e.g. for 3 tokens/2 hops: 1 - ((1 - .03) * (1-.03)) percent = ONE_HUNDRED_PERCENT.subtract( - trade.route.pairs.reduce( - (currentFee: Fraction): Fraction => currentFee.multiply(INPUT_FRACTION_AFTER_FEE), + trade.route.pairs.reduce( + (currentFee: Percent): Percent => currentFee.multiply(INPUT_FRACTION_AFTER_FEE), ONE_HUNDRED_PERCENT ) ) } else { percent = ONE_HUNDRED_PERCENT.subtract( - trade.route.pools.reduce( - (currentFee: Fraction, pool): Fraction => + trade.route.pools.reduce( + (currentFee: Percent, pool): Percent => currentFee.multiply(ONE_HUNDRED_PERCENT.subtract(new Fraction(pool.fee, 1_000_000))), ONE_HUNDRED_PERCENT ) @@ -44,14 +44,11 @@ export function computeRealizedLPFeePercent( export function computeRealizedLPFeeAmount( trade?: V2Trade | V3Trade | null ): CurrencyAmount | undefined { - if (trade instanceof V2Trade || trade instanceof V3Trade) { + if (trade) { const realizedLPFee = computeRealizedLPFeePercent(trade) // the amount of the input that accrues to LPs - return CurrencyAmount.fromRawAmount( - trade.inputAmount.currency, - trade.inputAmount.asFraction.multiply(realizedLPFee).quotient - ) + return CurrencyAmount.fromRawAmount(trade.inputAmount.currency, trade.inputAmount.multiply(realizedLPFee).quotient) } return undefined diff --git a/yarn.lock b/yarn.lock index 285e964bb2..cba8406a72 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4478,10 +4478,10 @@ "@uniswap/v3-core" "1.0.0" base64-sol "1.0.1" -"@uniswap/v3-sdk@^3.0.0-alpha.2": - version "3.0.0-alpha.2" - resolved "https://registry.yarnpkg.com/@uniswap/v3-sdk/-/v3-sdk-3.0.0-alpha.2.tgz#c72c2a81da515839f48e8aba6dff2a7163c94da1" - integrity sha512-L5coA6F2/Xq25wLjEddXzj3uXCV0v5TOm7Fsw+Z8PubWmi2sXaJFqUfsoOXSfICD5NjJUb3u3bpe4+ZHRaUrnw== +"@uniswap/v3-sdk@^3.0.0-alpha.4": + version "3.0.0-alpha.4" + resolved "https://registry.yarnpkg.com/@uniswap/v3-sdk/-/v3-sdk-3.0.0-alpha.4.tgz#e8bf26291fd74e36a5a3d9b88f1809a7aceb7d3a" + integrity sha512-BcEH8eHt+b6eaaiLDlzbFox2NquP1H7KgrgmNjAlU/et+vC4azdfNN6SsRlTFzhioPOwHlAKAAZJLq+yzboDOQ== dependencies: "@ethersproject/abi" "^5.0.12" "@ethersproject/solidity" "^5.0.9"