Commit 1f41587b authored by Moody Salem's avatar Moody Salem

fix the swap notification

parent 9b639bee
...@@ -10,8 +10,7 @@ import { Link } from 'react-router-dom' ...@@ -10,8 +10,7 @@ import { Link } from 'react-router-dom'
import styled from 'styled-components' import styled from 'styled-components'
import { MEDIA_WIDTHS } from 'theme' import { MEDIA_WIDTHS } from 'theme'
import { PositionDetails } from 'types/position' import { PositionDetails } from 'types/position'
import { basisPointsToPercent } from 'utils' import { TokenAmount, WETH9, Price, Token, Percent } from '@uniswap/sdk-core'
import { TokenAmount, WETH9, Price, Token } from '@uniswap/sdk-core'
import { formatPrice, formatTokenAmount } from 'utils/formatTokenAmount' import { formatPrice, formatTokenAmount } from 'utils/formatTokenAmount'
import Loader from 'components/Loader' import Loader from 'components/Loader'
import { unwrappedToken } from 'utils/wrappedCurrency' import { unwrappedToken } from 'utils/wrappedCurrency'
...@@ -238,7 +237,7 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr ...@@ -238,7 +237,7 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr
</DataText> </DataText>
&nbsp; &nbsp;
<Badge> <Badge>
<BadgeText>{basisPointsToPercent(feeAmount / 100).toSignificant()}%</BadgeText> <BadgeText>{new Percent(feeAmount, 1_000_000).toSignificant()}%</BadgeText>
</Badge> </Badge>
</PrimaryPositionIdData> </PrimaryPositionIdData>
<BadgeWrapper> <BadgeWrapper>
......
import JSBI from 'jsbi'
import React, { useContext, useRef, useState } from 'react' import React, { useContext, useRef, useState } from 'react'
import { Settings, X } from 'react-feather' import { Settings, X } from 'react-feather'
import ReactGA from 'react-ga' import ReactGA from 'react-ga'
...@@ -194,7 +195,7 @@ export default function SettingsTab() { ...@@ -194,7 +195,7 @@ export default function SettingsTab() {
Transaction Settings Transaction Settings
</Text> </Text>
<TransactionSettings <TransactionSettings
rawSlippage={userSlippageTolerance} rawSlippage={JSBI.toNumber(userSlippageTolerance.numerator)}
setRawSlippage={setUserslippageTolerance} setRawSlippage={setUserslippageTolerance}
deadline={ttl} deadline={ttl}
setDeadline={setTtl} setDeadline={setTtl}
......
...@@ -43,7 +43,7 @@ export default function ConfirmSwapModal({ ...@@ -43,7 +43,7 @@ export default function ConfirmSwapModal({
attemptingTxn: boolean attemptingTxn: boolean
txHash: string | undefined txHash: string | undefined
recipient: string | null recipient: string | null
allowedSlippage: number allowedSlippage: Percent
onAcceptChanges: () => void onAcceptChanges: () => void
onConfirm: () => void onConfirm: () => void
swapErrorMessage: string | undefined swapErrorMessage: string | undefined
...@@ -86,12 +86,10 @@ export default function ConfirmSwapModal({ ...@@ -86,12 +86,10 @@ export default function ConfirmSwapModal({
) : null ) : null
}, [allowedSlippage, onConfirm, showAcceptChanges, swapErrorMessage, trade]) }, [allowedSlippage, onConfirm, showAcceptChanges, swapErrorMessage, trade])
const slippageTolerancePercent = new Percent(allowedSlippage, 10_000)
// text to show while loading // text to show while loading
const pendingText = `Swapping ${trade?.maximumAmountIn(slippageTolerancePercent)?.toSignificant(6)} ${ const pendingText = `Swapping ${trade?.maximumAmountIn(allowedSlippage)?.toSignificant(6)} ${
trade?.inputAmount?.currency?.symbol trade?.inputAmount?.currency?.symbol
} for ${trade?.minimumAmountOut(slippageTolerancePercent)?.toSignificant(6)} ${trade?.outputAmount?.currency?.symbol}` } for ${trade?.minimumAmountOut(allowedSlippage)?.toSignificant(6)} ${trade?.outputAmount?.currency?.symbol}`
const confirmationContent = useCallback( const confirmationContent = useCallback(
() => () =>
......
...@@ -19,14 +19,13 @@ export default function SwapModalFooter({ ...@@ -19,14 +19,13 @@ export default function SwapModalFooter({
disabledConfirm, disabledConfirm,
}: { }: {
trade: V2Trade | V3Trade trade: V2Trade | V3Trade
allowedSlippage: number allowedSlippage: Percent
onConfirm: () => void onConfirm: () => void
swapErrorMessage: string | undefined swapErrorMessage: string | undefined
disabledConfirm: boolean disabledConfirm: boolean
}) { }) {
const [showInverted, setShowInverted] = useState<boolean>(false) const [showInverted, setShowInverted] = useState<boolean>(false)
const theme = useContext(ThemeContext) const theme = useContext(ThemeContext)
const slippageTolerancePercent = new Percent(allowedSlippage, 10_000)
const { priceImpactWithoutFee } = useMemo(() => computeTradePriceBreakdown(trade), [trade]) const { priceImpactWithoutFee } = useMemo(() => computeTradePriceBreakdown(trade), [trade])
const severity = warningSeverity(priceImpactWithoutFee) const severity = warningSeverity(priceImpactWithoutFee)
...@@ -49,7 +48,7 @@ export default function SwapModalFooter({ ...@@ -49,7 +48,7 @@ export default function SwapModalFooter({
paddingLeft: '10px', paddingLeft: '10px',
}} }}
> >
{formatExecutionPrice(trade, showInverted, slippageTolerancePercent)} {formatExecutionPrice(trade, showInverted, allowedSlippage)}
<StyledBalanceMaxMini onClick={() => setShowInverted(!showInverted)}> <StyledBalanceMaxMini onClick={() => setShowInverted(!showInverted)}>
<Repeat size={14} /> <Repeat size={14} />
</StyledBalanceMaxMini> </StyledBalanceMaxMini>
......
...@@ -21,14 +21,13 @@ export default function SwapModalHeader({ ...@@ -21,14 +21,13 @@ export default function SwapModalHeader({
onAcceptChanges, onAcceptChanges,
}: { }: {
trade: V2Trade | V3Trade trade: V2Trade | V3Trade
allowedSlippage: number allowedSlippage: Percent
recipient: string | null recipient: string | null
showAcceptChanges: boolean showAcceptChanges: boolean
onAcceptChanges: () => void onAcceptChanges: () => void
}) { }) {
const slippageTolerancePercent = new Percent(allowedSlippage, 10_000) const maximumAmountIn = trade.maximumAmountIn(allowedSlippage)
const maximumAmountIn = trade.maximumAmountIn(slippageTolerancePercent) const minimumAmountOut = trade.minimumAmountOut(allowedSlippage)
const minimumAmountOut = trade.minimumAmountOut(slippageTolerancePercent)
const theme = useContext(ThemeContext) const theme = useContext(ThemeContext)
......
...@@ -207,7 +207,7 @@ export const SUPPORTED_WALLETS: { [key: string]: WalletInfo } = { ...@@ -207,7 +207,7 @@ export const SUPPORTED_WALLETS: { [key: string]: WalletInfo } = {
export const NetworkContextName = 'NETWORK' export const NetworkContextName = 'NETWORK'
// default allowed slippage, in bips // default allowed slippage, in bips
export const INITIAL_ALLOWED_SLIPPAGE = 50 export const INITIAL_ALLOWED_SLIPPAGE = new Percent(50, 10_000)
// 20 minutes, denominated in seconds // 20 minutes, denominated in seconds
export const DEFAULT_DEADLINE_FROM_NOW = 60 * 20 export const DEFAULT_DEADLINE_FROM_NOW = 60 * 20
......
...@@ -99,13 +99,13 @@ export function useApproveCallback( ...@@ -99,13 +99,13 @@ export function useApproveCallback(
} }
// wraps useApproveCallback in the context of a swap // wraps useApproveCallback in the context of a swap
export function useApproveCallbackFromTrade(trade: V2Trade | V3Trade | undefined, allowedSlippage: number) { export function useApproveCallbackFromTrade(trade: V2Trade | V3Trade | undefined, allowedSlippage: Percent) {
const { chainId } = useActiveWeb3React() const { chainId } = useActiveWeb3React()
const swapRouterAddress = SWAP_ROUTER_ADDRESSES[chainId as ChainId] const swapRouterAddress = SWAP_ROUTER_ADDRESSES[chainId as ChainId]
const amountToApprove = useMemo( const amountToApprove = useMemo(() => (trade ? trade.maximumAmountIn(allowedSlippage) : undefined), [
() => (trade ? trade.maximumAmountIn(new Percent(allowedSlippage, 10_000)) : undefined), trade,
[trade, allowedSlippage] allowedSlippage,
) ])
return useApproveCallback( return useApproveCallback(
amountToApprove, amountToApprove,
trade instanceof V2Trade ? V2_ROUTER_ADDRESS : trade instanceof V3Trade ? swapRouterAddress : undefined trade instanceof V2Trade ? V2_ROUTER_ADDRESS : trade instanceof V3Trade ? swapRouterAddress : undefined
......
...@@ -269,13 +269,13 @@ export function useV2LiquidityTokenPermit( ...@@ -269,13 +269,13 @@ export function useV2LiquidityTokenPermit(
return useERC20Permit(liquidityAmount, spender, REMOVE_V2_LIQUIDITY_PERMIT_INFO) return useERC20Permit(liquidityAmount, spender, REMOVE_V2_LIQUIDITY_PERMIT_INFO)
} }
export function useERC20PermitFromTrade(trade: V2Trade | V3Trade | undefined, allowedSlippage: number) { export function useERC20PermitFromTrade(trade: V2Trade | V3Trade | undefined, allowedSlippage: Percent) {
const { chainId } = useActiveWeb3React() const { chainId } = useActiveWeb3React()
const swapRouterAddress = SWAP_ROUTER_ADDRESSES[chainId as ChainId] const swapRouterAddress = SWAP_ROUTER_ADDRESSES[chainId as ChainId]
const amountToApprove = useMemo( const amountToApprove = useMemo(() => (trade ? trade.maximumAmountIn(allowedSlippage) : undefined), [
() => (trade ? trade.maximumAmountIn(new Percent(allowedSlippage, 10_000)) : undefined), trade,
[trade, allowedSlippage] allowedSlippage,
) ])
return useERC20Permit( return useERC20Permit(
amountToApprove, amountToApprove,
......
import JSBI from 'jsbi'
import { BigNumber } from '@ethersproject/bignumber' import { BigNumber } from '@ethersproject/bignumber'
import { Router, Trade as V2Trade } from '@uniswap/v2-sdk' import { Router, Trade as V2Trade } from '@uniswap/v2-sdk'
import { SwapRouter, Trade as V3Trade } from '@uniswap/v3-sdk' import { SwapRouter, Trade as V3Trade } from '@uniswap/v3-sdk'
import { ChainId, Percent, TradeType } from '@uniswap/sdk-core' import { ChainId, Percent, TradeType } from '@uniswap/sdk-core'
import { useMemo } from 'react' import { useMemo } from 'react'
import { BIPS_BASE, INITIAL_ALLOWED_SLIPPAGE } from '../constants' import { INITIAL_ALLOWED_SLIPPAGE } from '../constants'
import { SWAP_ROUTER_ADDRESSES } from '../constants/v3' import { SWAP_ROUTER_ADDRESSES } from '../constants/v3'
import { getTradeVersion } from '../utils/getTradeVersion' import { getTradeVersion } from '../utils/getTradeVersion'
import { useTransactionAdder } from '../state/transactions/hooks' import { useTransactionAdder } from '../state/transactions/hooks'
...@@ -52,7 +51,7 @@ interface FailedCall extends SwapCallEstimate { ...@@ -52,7 +51,7 @@ interface FailedCall extends SwapCallEstimate {
*/ */
function useSwapCallArguments( function useSwapCallArguments(
trade: V2Trade | V3Trade | undefined, // trade to execute, required trade: V2Trade | V3Trade | undefined, // trade to execute, required
allowedSlippage: number = INITIAL_ALLOWED_SLIPPAGE, // in bips allowedSlippage: Percent = INITIAL_ALLOWED_SLIPPAGE, // in bips
recipientAddressOrName: string | null, // the ENS name or address of the recipient of the trade, or null if swap should be returned to sender recipientAddressOrName: string | null, // the ENS name or address of the recipient of the trade, or null if swap should be returned to sender
signatureData: SignatureData | null | undefined signatureData: SignatureData | null | undefined
): SwapCall[] { ): SwapCall[] {
...@@ -72,7 +71,7 @@ function useSwapCallArguments( ...@@ -72,7 +71,7 @@ function useSwapCallArguments(
swapMethods.push( swapMethods.push(
Router.swapCallParameters(trade, { Router.swapCallParameters(trade, {
feeOnTransfer: false, feeOnTransfer: false,
allowedSlippage: new Percent(JSBI.BigInt(allowedSlippage), BIPS_BASE), allowedSlippage,
recipient, recipient,
deadline: deadline.toNumber(), deadline: deadline.toNumber(),
}) })
...@@ -82,7 +81,7 @@ function useSwapCallArguments( ...@@ -82,7 +81,7 @@ function useSwapCallArguments(
swapMethods.push( swapMethods.push(
Router.swapCallParameters(trade, { Router.swapCallParameters(trade, {
feeOnTransfer: true, feeOnTransfer: true,
allowedSlippage: new Percent(JSBI.BigInt(allowedSlippage), BIPS_BASE), allowedSlippage,
recipient, recipient,
deadline: deadline.toNumber(), deadline: deadline.toNumber(),
}) })
...@@ -100,7 +99,7 @@ function useSwapCallArguments( ...@@ -100,7 +99,7 @@ function useSwapCallArguments(
const { value, calldata } = SwapRouter.swapCallParameters(trade, { const { value, calldata } = SwapRouter.swapCallParameters(trade, {
recipient, recipient,
slippageTolerance: new Percent(JSBI.BigInt(allowedSlippage), BIPS_BASE), slippageTolerance: allowedSlippage,
deadline: deadline.toString(), deadline: deadline.toString(),
...(signatureData ...(signatureData
? { ? {
...@@ -139,7 +138,7 @@ function useSwapCallArguments( ...@@ -139,7 +138,7 @@ function useSwapCallArguments(
// and the user has approved the slippage adjusted input amount for the trade // and the user has approved the slippage adjusted input amount for the trade
export function useSwapCallback( export function useSwapCallback(
trade: V2Trade | V3Trade | undefined, // trade to execute, required trade: V2Trade | V3Trade | undefined, // trade to execute, required
allowedSlippage: number = INITIAL_ALLOWED_SLIPPAGE, // in bips allowedSlippage: Percent = INITIAL_ALLOWED_SLIPPAGE, // in bips
recipientAddressOrName: string | null, // the ENS name or address of the recipient of the trade, or null if swap should be returned to sender recipientAddressOrName: string | null, // the ENS name or address of the recipient of the trade, or null if swap should be returned to sender
signatureData: SignatureData | undefined | null signatureData: SignatureData | undefined | null
): { state: SwapCallbackState; callback: null | (() => Promise<string>); error: string | null } { ): { state: SwapCallbackState; callback: null | (() => Promise<string>); error: string | null } {
...@@ -261,9 +260,8 @@ export function useSwapCallback( ...@@ -261,9 +260,8 @@ export function useSwapCallback(
.then((response) => { .then((response) => {
const inputSymbol = trade.inputAmount.currency.symbol const inputSymbol = trade.inputAmount.currency.symbol
const outputSymbol = trade.outputAmount.currency.symbol const outputSymbol = trade.outputAmount.currency.symbol
const slippageTolerancePercent = new Percent(allowedSlippage) const inputAmount = trade.maximumAmountIn(allowedSlippage).toSignificant(4)
const inputAmount = trade.maximumAmountIn(slippageTolerancePercent).toSignificant(3) const outputAmount = trade.minimumAmountOut(allowedSlippage).toSignificant(4)
const outputAmount = trade.minimumAmountOut(slippageTolerancePercent).toSignificant(3)
const base = `Swap ${inputAmount} ${inputSymbol} for ${outputAmount} ${outputSymbol}` const base = `Swap ${inputAmount} ${inputSymbol} for ${outputAmount} ${outputSymbol}`
const withRecipient = const withRecipient =
......
import { TransactionResponse } from '@ethersproject/providers' import { TransactionResponse } from '@ethersproject/providers'
import { Currency, TokenAmount, Percent, ETHER } from '@uniswap/sdk-core' import { Currency, TokenAmount, ETHER } from '@uniswap/sdk-core'
import React, { useCallback, useContext, useMemo, useState } from 'react' import React, { useCallback, useContext, useMemo, useState } from 'react'
import { WETH9 } from '@uniswap/sdk-core' import { WETH9 } from '@uniswap/sdk-core'
import { Link2, AlertTriangle, ChevronRight } from 'react-feather' import { Link2, AlertTriangle, ChevronRight } from 'react-feather'
...@@ -45,7 +45,6 @@ import { useTranslation } from 'react-i18next' ...@@ -45,7 +45,6 @@ import { useTranslation } from 'react-i18next'
import { useMintState, useMintActionHandlers, useDerivedMintInfo, useRangeHopCallbacks } from 'state/mint/hooks' import { useMintState, useMintActionHandlers, useDerivedMintInfo, useRangeHopCallbacks } from 'state/mint/hooks'
import { FeeAmount, NonfungiblePositionManager } from '@uniswap/v3-sdk' import { FeeAmount, NonfungiblePositionManager } from '@uniswap/v3-sdk'
import { NONFUNGIBLE_POSITION_MANAGER_ADDRESSES } from 'constants/v3' import { NONFUNGIBLE_POSITION_MANAGER_ADDRESSES } from 'constants/v3'
import JSBI from 'jsbi'
import { useV3PositionFromTokenId } from 'hooks/useV3Positions' import { useV3PositionFromTokenId } from 'hooks/useV3Positions'
import { useDerivedPositionInfo } from 'hooks/useDerivedPositionInfo' import { useDerivedPositionInfo } from 'hooks/useDerivedPositionInfo'
import { PositionPreview } from 'components/PositionPreview' import { PositionPreview } from 'components/PositionPreview'
...@@ -140,7 +139,6 @@ export default function AddLiquidity({ ...@@ -140,7 +139,6 @@ export default function AddLiquidity({
// txn values // txn values
const deadline = useTransactionDeadline() // custom from users settings const deadline = useTransactionDeadline() // custom from users settings
const [allowedSlippage] = useUserSlippageTolerance() // custom from users const [allowedSlippage] = useUserSlippageTolerance() // custom from users
const fractionalizedTolerance = new Percent(JSBI.BigInt(allowedSlippage), JSBI.BigInt(10000))
const [txHash, setTxHash] = useState<string>('') const [txHash, setTxHash] = useState<string>('')
// get formatted amounts // get formatted amounts
...@@ -187,17 +185,17 @@ export default function AddLiquidity({ ...@@ -187,17 +185,17 @@ export default function AddLiquidity({
return return
} }
if (position && account && deadline && fractionalizedTolerance) { if (position && account && deadline) {
const { calldata, value } = const { calldata, value } =
hasExistingPosition && tokenId hasExistingPosition && tokenId
? NonfungiblePositionManager.addCallParameters(position, { ? NonfungiblePositionManager.addCallParameters(position, {
tokenId, tokenId,
slippageTolerance: fractionalizedTolerance, slippageTolerance: allowedSlippage,
deadline: deadline.toString(), deadline: deadline.toString(),
useEther: currencyA === ETHER || currencyB === ETHER, useEther: currencyA === ETHER || currencyB === ETHER,
}) })
: NonfungiblePositionManager.addCallParameters(position, { : NonfungiblePositionManager.addCallParameters(position, {
slippageTolerance: fractionalizedTolerance, slippageTolerance: allowedSlippage,
recipient: account, recipient: account,
deadline: deadline.toString(), deadline: deadline.toString(),
useEther: currencyA === ETHER || currencyB === ETHER, useEther: currencyA === ETHER || currencyB === ETHER,
......
...@@ -17,7 +17,7 @@ import { AddRemoveTabs } from '../../components/NavigationTabs' ...@@ -17,7 +17,7 @@ import { AddRemoveTabs } from '../../components/NavigationTabs'
import { MinimalPositionCard } from '../../components/PositionCard' import { MinimalPositionCard } from '../../components/PositionCard'
import Row, { RowBetween, RowFlat } from '../../components/Row' import Row, { RowBetween, RowFlat } from '../../components/Row'
import { V2_ROUTER_ADDRESS } from '../../constants' import { V2_ROUTER_ADDRESS, ZERO_PERCENT } from '../../constants'
import { useV2RouterContract } from '../../hooks/useContract' import { useV2RouterContract } from '../../hooks/useContract'
import { PairState } from '../../hooks/useV2Pairs' import { PairState } from '../../hooks/useV2Pairs'
import { useActiveWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
...@@ -138,8 +138,8 @@ export default function AddLiquidity({ ...@@ -138,8 +138,8 @@ export default function AddLiquidity({
} }
const amountsMin = { const amountsMin = {
[Field.CURRENCY_A]: calculateSlippageAmount(parsedAmountA, noLiquidity ? 0 : allowedSlippage)[0], [Field.CURRENCY_A]: calculateSlippageAmount(parsedAmountA, noLiquidity ? ZERO_PERCENT : allowedSlippage)[0],
[Field.CURRENCY_B]: calculateSlippageAmount(parsedAmountB, noLiquidity ? 0 : allowedSlippage)[0], [Field.CURRENCY_B]: calculateSlippageAmount(parsedAmountB, noLiquidity ? ZERO_PERCENT : allowedSlippage)[0],
} }
let estimate, let estimate,
...@@ -248,9 +248,9 @@ export default function AddLiquidity({ ...@@ -248,9 +248,9 @@ export default function AddLiquidity({
</Text> </Text>
</Row> </Row>
<TYPE.italic fontSize={12} textAlign="left" padding={'8px 0 0 0 '}> <TYPE.italic fontSize={12} textAlign="left" padding={'8px 0 0 0 '}>
{`Output is estimated. If the price changes by more than ${ {`Output is estimated. If the price changes by more than ${allowedSlippage.toSignificant(
allowedSlippage / 100 4
}% your transaction will revert.`} )}% your transaction will revert.`}
</TYPE.italic> </TYPE.italic>
</AutoColumn> </AutoColumn>
) )
......
...@@ -191,7 +191,10 @@ function V2PairMigration({ ...@@ -191,7 +191,10 @@ function V2PairMigration({
position && position &&
new TokenAmount( new TokenAmount(
token0, token0,
JSBI.divide(JSBI.multiply(position.amount0.raw, JSBI.BigInt(10000 - allowedSlippage)), JSBI.BigInt(10000)) JSBI.divide(
JSBI.multiply(position.amount0.raw, JSBI.BigInt(10000 - JSBI.toNumber(allowedSlippage.numerator))),
JSBI.BigInt(10000)
)
), ),
[token0, position, allowedSlippage] [token0, position, allowedSlippage]
) )
...@@ -200,7 +203,10 @@ function V2PairMigration({ ...@@ -200,7 +203,10 @@ function V2PairMigration({
position && position &&
new TokenAmount( new TokenAmount(
token1, token1,
JSBI.divide(JSBI.multiply(position.amount1.raw, JSBI.BigInt(10000 - allowedSlippage)), JSBI.BigInt(10000)) JSBI.divide(
JSBI.multiply(position.amount1.raw, JSBI.BigInt(10000 - JSBI.toNumber(allowedSlippage.numerator))),
JSBI.BigInt(10000)
)
), ),
[token1, position, allowedSlippage] [token1, position, allowedSlippage]
) )
......
...@@ -13,7 +13,7 @@ import Row, { RowBetween, RowFixed } from 'components/Row' ...@@ -13,7 +13,7 @@ import Row, { RowBetween, RowFixed } from 'components/Row'
import DoubleCurrencyLogo from 'components/DoubleLogo' import DoubleCurrencyLogo from 'components/DoubleLogo'
import { ButtonText, TYPE } from 'theme' import { ButtonText, TYPE } from 'theme'
import Badge, { BadgeVariant } from 'components/Badge' import Badge, { BadgeVariant } from 'components/Badge'
import { basisPointsToPercent, calculateGasMargin } from 'utils' import { calculateGasMargin } from 'utils'
import { ButtonConfirmed, ButtonPrimary } from 'components/Button' import { ButtonConfirmed, ButtonPrimary } from 'components/Button'
import { DarkCard, DarkGreyCard } from 'components/Card' import { DarkCard, DarkGreyCard } from 'components/Card'
import CurrencyLogo from 'components/CurrencyLogo' import CurrencyLogo from 'components/CurrencyLogo'
...@@ -23,7 +23,7 @@ import { currencyId } from 'utils/currencyId' ...@@ -23,7 +23,7 @@ import { currencyId } from 'utils/currencyId'
import { formatTokenAmount } from 'utils/formatTokenAmount' import { formatTokenAmount } from 'utils/formatTokenAmount'
import { useV3PositionFees } from 'hooks/useV3PositionFees' import { useV3PositionFees } from 'hooks/useV3PositionFees'
import { BigNumber } from '@ethersproject/bignumber' import { BigNumber } from '@ethersproject/bignumber'
import { WETH9, Currency, CurrencyAmount } from '@uniswap/sdk-core' import { WETH9, Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import { useActiveWeb3React } from 'hooks' import { useActiveWeb3React } from 'hooks'
import { useV3NFTPositionManagerContract } from 'hooks/useContract' import { useV3NFTPositionManagerContract } from 'hooks/useContract'
import { useIsTransactionPending, useTransactionAdder } from 'state/transactions/hooks' import { useIsTransactionPending, useTransactionAdder } from 'state/transactions/hooks'
...@@ -263,7 +263,7 @@ export function PositionPage({ ...@@ -263,7 +263,7 @@ export function PositionPage({
&nbsp;{currencyQuote?.symbol}&nbsp;/&nbsp;{currencyBase?.symbol} &nbsp;{currencyQuote?.symbol}&nbsp;/&nbsp;{currencyBase?.symbol}
</TYPE.label> </TYPE.label>
<Badge> <Badge>
<BadgeText>{basisPointsToPercent(feeAmount / 100).toSignificant()}%</BadgeText> <BadgeText>{new Percent(feeAmount, 1_000_000).toSignificant()}%</BadgeText>
</Badge> </Badge>
</RowFixed> </RowFixed>
......
...@@ -310,9 +310,9 @@ export default function RemoveLiquidity({ ...@@ -310,9 +310,9 @@ export default function RemoveLiquidity({
</RowBetween> </RowBetween>
<TYPE.italic fontSize={12} color={theme.text2} textAlign="left" padding={'12px 0 0 0'}> <TYPE.italic fontSize={12} color={theme.text2} textAlign="left" padding={'12px 0 0 0'}>
{`Output is estimated. If the price changes by more than ${ {`Output is estimated. If the price changes by more than ${allowedSlippage.toSignificant(
allowedSlippage / 100 4
}% your transaction will revert.`} )}% your transaction will revert.`}
</TYPE.italic> </TYPE.italic>
</AutoColumn> </AutoColumn>
) )
......
import { CurrencyAmount, Percent, Token } from '@uniswap/sdk-core' import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk' import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk' import { Trade as V3Trade } from '@uniswap/v3-sdk'
import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter' import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter'
...@@ -122,14 +122,8 @@ export default function Swap({ history }: RouteComponentProps) { ...@@ -122,14 +122,8 @@ export default function Swap({ history }: RouteComponentProps) {
[Field.OUTPUT]: parsedAmount, [Field.OUTPUT]: parsedAmount,
} }
: { : {
[Field.INPUT]: [Field.INPUT]: independentField === Field.INPUT ? parsedAmount : trade?.maximumAmountIn(allowedSlippage),
independentField === Field.INPUT [Field.OUTPUT]: independentField === Field.OUTPUT ? parsedAmount : trade?.minimumAmountOut(allowedSlippage),
? parsedAmount
: trade?.maximumAmountIn(new Percent(allowedSlippage, 10_000)),
[Field.OUTPUT]:
independentField === Field.OUTPUT
? parsedAmount
: trade?.minimumAmountOut(new Percent(allowedSlippage, 10_000)),
}, },
[allowedSlippage, independentField, parsedAmount, showWrap, trade] [allowedSlippage, independentField, parsedAmount, showWrap, trade]
) )
...@@ -246,13 +240,9 @@ export default function Swap({ history }: RouteComponentProps) { ...@@ -246,13 +240,9 @@ export default function Swap({ history }: RouteComponentProps) {
trade?.inputAmount?.currency?.symbol, trade?.inputAmount?.currency?.symbol,
trade?.outputAmount?.currency?.symbol, trade?.outputAmount?.currency?.symbol,
getTradeVersion(trade), getTradeVersion(trade),
singleHopOnly ? 'SH' : 'MH',
].join('/'), ].join('/'),
}) })
ReactGA.event({
category: 'Routing',
action: singleHopOnly ? 'Swap with multihop disabled' : 'Swap with multihop enabled',
})
}) })
.catch((error) => { .catch((error) => {
setSwapState({ setSwapState({
...@@ -403,7 +393,7 @@ export default function Swap({ history }: RouteComponentProps) { ...@@ -403,7 +393,7 @@ export default function Swap({ history }: RouteComponentProps) {
) : null} ) : null}
{trade ? ( {trade ? (
<TradePrice <TradePrice
price={trade.worstExecutionPrice(new Percent(allowedSlippage, 10_000))} price={trade.worstExecutionPrice(allowedSlippage)}
showInverted={showInverted} showInverted={showInverted}
setShowInverted={setShowInverted} setShowInverted={setShowInverted}
/> />
......
import { ChainId, Token } from '@uniswap/sdk-core' import { ChainId, Percent, Token } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk' import { Pair } from '@uniswap/v2-sdk'
import flatMap from 'lodash.flatmap' import flatMap from 'lodash.flatmap'
import { useCallback, useMemo } from 'react' import { useCallback, useMemo } from 'react'
...@@ -100,12 +100,14 @@ export function useUserSingleHopOnly(): [boolean, (newSingleHopOnly: boolean) => ...@@ -100,12 +100,14 @@ export function useUserSingleHopOnly(): [boolean, (newSingleHopOnly: boolean) =>
return [singleHopOnly, setSingleHopOnly] return [singleHopOnly, setSingleHopOnly]
} }
export function useUserSlippageTolerance(): [number, (slippage: number) => void] { export function useUserSlippageTolerance(): [Percent, (slippageBips: number) => void] {
const dispatch = useDispatch<AppDispatch>() const dispatch = useDispatch<AppDispatch>()
const userSlippageTolerance = useSelector<AppState, AppState['user']['userSlippageTolerance']>((state) => { const userSlippageTolerance = useSelector<AppState, AppState['user']['userSlippageTolerance']>((state) => {
return state.user.userSlippageTolerance return state.user.userSlippageTolerance
}) })
const percentage = useMemo(() => new Percent(userSlippageTolerance, 10_000), [userSlippageTolerance])
const setUserSlippageTolerance = useCallback( const setUserSlippageTolerance = useCallback(
(userSlippageTolerance: number) => { (userSlippageTolerance: number) => {
dispatch(updateUserSlippageTolerance({ userSlippageTolerance })) dispatch(updateUserSlippageTolerance({ userSlippageTolerance }))
...@@ -113,7 +115,7 @@ export function useUserSlippageTolerance(): [number, (slippage: number) => void] ...@@ -113,7 +115,7 @@ export function useUserSlippageTolerance(): [number, (slippage: number) => void]
[dispatch] [dispatch]
) )
return [userSlippageTolerance, setUserSlippageTolerance] return [percentage, setUserSlippageTolerance]
} }
export function useUserTransactionTTL(): [number, (slippage: number) => void] { export function useUserTransactionTTL(): [number, (slippage: number) => void] {
......
...@@ -27,7 +27,7 @@ describe('swap reducer', () => { ...@@ -27,7 +27,7 @@ describe('swap reducer', () => {
} as any) } as any)
store.dispatch(updateVersion()) store.dispatch(updateVersion())
expect(store.getState().userDeadline).toEqual(DEFAULT_DEADLINE_FROM_NOW) expect(store.getState().userDeadline).toEqual(DEFAULT_DEADLINE_FROM_NOW)
expect(store.getState().userSlippageTolerance).toEqual(INITIAL_ALLOWED_SLIPPAGE) expect(store.getState().userSlippageTolerance).toEqual(50)
}) })
}) })
}) })
import { INITIAL_ALLOWED_SLIPPAGE, DEFAULT_DEADLINE_FROM_NOW } from '../../constants' import { DEFAULT_DEADLINE_FROM_NOW } from '../../constants'
import { createReducer } from '@reduxjs/toolkit' import { createReducer } from '@reduxjs/toolkit'
import { updateVersion } from '../global/actions' import { updateVersion } from '../global/actions'
import { import {
...@@ -62,7 +62,7 @@ export const initialState: UserState = { ...@@ -62,7 +62,7 @@ export const initialState: UserState = {
matchesDarkMode: false, matchesDarkMode: false,
userExpertMode: false, userExpertMode: false,
userSingleHopOnly: false, userSingleHopOnly: false,
userSlippageTolerance: INITIAL_ALLOWED_SLIPPAGE, userSlippageTolerance: 50,
userDeadline: DEFAULT_DEADLINE_FROM_NOW, userDeadline: DEFAULT_DEADLINE_FROM_NOW,
tokens: {}, tokens: {},
pairs: {}, pairs: {},
...@@ -76,7 +76,7 @@ export default createReducer(initialState, (builder) => ...@@ -76,7 +76,7 @@ export default createReducer(initialState, (builder) =>
// slippage isnt being tracked in local storage, reset to default // slippage isnt being tracked in local storage, reset to default
// noinspection SuspiciousTypeOfGuard // noinspection SuspiciousTypeOfGuard
if (typeof state.userSlippageTolerance !== 'number') { if (typeof state.userSlippageTolerance !== 'number') {
state.userSlippageTolerance = INITIAL_ALLOWED_SLIPPAGE state.userSlippageTolerance = 50
} }
// deadline isnt being tracked in local storage, reset to default // deadline isnt being tracked in local storage, reset to default
......
import { BigNumber } from '@ethersproject/bignumber' import { BigNumber } from '@ethersproject/bignumber'
import { AddressZero } from '@ethersproject/constants' import { AddressZero } from '@ethersproject/constants'
import { TokenAmount, Token, ChainId, Percent } from '@uniswap/sdk-core' import { TokenAmount, Token, ChainId, Percent } from '@uniswap/sdk-core'
import { JSBI } from '@uniswap/v2-sdk' import { getEtherscanLink, calculateSlippageAmount, isAddress, shortenAddress, calculateGasMargin } from '.'
import {
getEtherscanLink,
calculateSlippageAmount,
isAddress,
shortenAddress,
calculateGasMargin,
basisPointsToPercent,
} from '.'
describe('utils', () => { describe('utils', () => {
describe('#getEtherscanLink', () => { describe('#getEtherscanLink', () => {
...@@ -37,12 +28,23 @@ describe('utils', () => { ...@@ -37,12 +28,23 @@ describe('utils', () => {
describe('#calculateSlippageAmount', () => { describe('#calculateSlippageAmount', () => {
it('bounds are correct', () => { it('bounds are correct', () => {
const tokenAmount = new TokenAmount(new Token(ChainId.MAINNET, AddressZero, 0), '100') const tokenAmount = new TokenAmount(new Token(ChainId.MAINNET, AddressZero, 0), '100')
expect(() => calculateSlippageAmount(tokenAmount, -1)).toThrow() expect(() => calculateSlippageAmount(tokenAmount, new Percent(-1, 10_000))).toThrow()
expect(calculateSlippageAmount(tokenAmount, 0).map((bound) => bound.toString())).toEqual(['100', '100']) expect(calculateSlippageAmount(tokenAmount, new Percent(0, 10_000)).map((bound) => bound.toString())).toEqual([
expect(calculateSlippageAmount(tokenAmount, 100).map((bound) => bound.toString())).toEqual(['99', '101']) '100',
expect(calculateSlippageAmount(tokenAmount, 200).map((bound) => bound.toString())).toEqual(['98', '102']) '100',
expect(calculateSlippageAmount(tokenAmount, 10000).map((bound) => bound.toString())).toEqual(['0', '200']) ])
expect(() => calculateSlippageAmount(tokenAmount, 10001)).toThrow() expect(calculateSlippageAmount(tokenAmount, new Percent(100, 10_000)).map((bound) => bound.toString())).toEqual([
'99',
'101',
])
expect(calculateSlippageAmount(tokenAmount, new Percent(200, 10_000)).map((bound) => bound.toString())).toEqual([
'98',
'102',
])
expect(
calculateSlippageAmount(tokenAmount, new Percent(10000, 10_000)).map((bound) => bound.toString())
).toEqual(['0', '200'])
expect(() => calculateSlippageAmount(tokenAmount, new Percent(10001, 10_000))).toThrow()
}) })
}) })
...@@ -92,12 +94,4 @@ describe('utils', () => { ...@@ -92,12 +94,4 @@ describe('utils', () => {
expect(calculateGasMargin(BigNumber.from(50)).toString()).toEqual('55') expect(calculateGasMargin(BigNumber.from(50)).toString()).toEqual('55')
}) })
}) })
describe('#basisPointsToPercent', () => {
it('converts basis points numbers to percents', () => {
expect(basisPointsToPercent(100).equalTo(new Percent(JSBI.BigInt(1), JSBI.BigInt(100)))).toBeTruthy()
expect(basisPointsToPercent(500).equalTo(new Percent(JSBI.BigInt(5), JSBI.BigInt(100)))).toBeTruthy()
expect(basisPointsToPercent(50).equalTo(new Percent(JSBI.BigInt(5), JSBI.BigInt(1000)))).toBeTruthy()
})
})
}) })
...@@ -63,18 +63,16 @@ export function calculateGasMargin(value: BigNumber): BigNumber { ...@@ -63,18 +63,16 @@ export function calculateGasMargin(value: BigNumber): BigNumber {
return value.mul(BigNumber.from(10000).add(BigNumber.from(1000))).div(BigNumber.from(10000)) return value.mul(BigNumber.from(10000).add(BigNumber.from(1000))).div(BigNumber.from(10000))
} }
// converts a basis points value to a sdk percent export function calculateSlippageAmount(value: CurrencyAmount, slippage: Percent): [JSBI, JSBI] {
export function basisPointsToPercent(num: number): Percent { if (
return new Percent(JSBI.BigInt(num), JSBI.BigInt(10000)) JSBI.lessThan(slippage.numerator, JSBI.BigInt(0)) ||
} JSBI.greaterThan(slippage.numerator, JSBI.BigInt(10_000)) ||
!JSBI.equal(slippage.denominator, JSBI.BigInt(10_000))
export function calculateSlippageAmount(value: CurrencyAmount, slippage: number): [JSBI, JSBI] { )
if (slippage < 0 || slippage > 10000) { throw new Error('Unexpected slippage')
throw Error(`Unexpected slippage value: ${slippage}`)
}
return [ return [
JSBI.divide(JSBI.multiply(value.raw, JSBI.BigInt(10000 - slippage)), JSBI.BigInt(10000)), JSBI.divide(JSBI.multiply(value.raw, JSBI.subtract(JSBI.BigInt(10000), slippage.numerator)), JSBI.BigInt(10000)),
JSBI.divide(JSBI.multiply(value.raw, JSBI.BigInt(10000 + slippage)), JSBI.BigInt(10000)), JSBI.divide(JSBI.multiply(value.raw, JSBI.add(JSBI.BigInt(10000), slippage.numerator)), JSBI.BigInt(10000)),
] ]
} }
......
...@@ -6,7 +6,6 @@ import { Trade as V3Trade } from '@uniswap/v3-sdk' ...@@ -6,7 +6,6 @@ import { Trade as V3Trade } from '@uniswap/v3-sdk'
import { ALLOWED_PRICE_IMPACT_HIGH, ALLOWED_PRICE_IMPACT_LOW, ALLOWED_PRICE_IMPACT_MEDIUM } from '../constants' import { ALLOWED_PRICE_IMPACT_HIGH, ALLOWED_PRICE_IMPACT_LOW, ALLOWED_PRICE_IMPACT_MEDIUM } from '../constants'
import { Field } from '../state/swap/actions' import { Field } from '../state/swap/actions'
import { basisPointsToPercent } from './index'
const THIRTY_BIPS_FEE = new Percent(JSBI.BigInt(30), JSBI.BigInt(10000)) const THIRTY_BIPS_FEE = new Percent(JSBI.BigInt(30), JSBI.BigInt(10000))
const ONE_HUNDRED_PERCENT = new Percent(JSBI.BigInt(10000), JSBI.BigInt(10000)) const ONE_HUNDRED_PERCENT = new Percent(JSBI.BigInt(10000), JSBI.BigInt(10000))
...@@ -78,12 +77,11 @@ export function computeTradePriceBreakdown( ...@@ -78,12 +77,11 @@ export function computeTradePriceBreakdown(
// computes the minimum amount out and maximum amount in for a trade given a user specified allowed slippage in bips // computes the minimum amount out and maximum amount in for a trade given a user specified allowed slippage in bips
export function computeSlippageAdjustedAmounts( export function computeSlippageAdjustedAmounts(
trade: V2Trade | V3Trade | undefined, trade: V2Trade | V3Trade | undefined,
allowedSlippage: number allowedSlippage: Percent
): { [field in Field]?: CurrencyAmount } { ): { [field in Field]?: CurrencyAmount } {
const pct = basisPointsToPercent(allowedSlippage)
return { return {
[Field.INPUT]: trade?.maximumAmountIn(pct), [Field.INPUT]: trade?.maximumAmountIn(allowedSlippage),
[Field.OUTPUT]: trade?.minimumAmountOut(pct), [Field.OUTPUT]: trade?.minimumAmountOut(allowedSlippage),
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment