show currency values and price impact in the confirmation modal (fixes https://github.com/Uniswap/v3-interface/issues/92)
This commit is contained in:
parent
f4e994867e
commit
300dd70804
32
src/components/CurrencyInputPanel/FiatValue.tsx
Normal file
32
src/components/CurrencyInputPanel/FiatValue.tsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { CurrencyAmount, Percent } from '@uniswap/sdk-core'
|
||||||
|
import React, { useMemo } from 'react'
|
||||||
|
import useTheme from '../../hooks/useTheme'
|
||||||
|
import { TYPE } from '../../theme'
|
||||||
|
import { warningSeverity } from '../../utils/prices'
|
||||||
|
|
||||||
|
export function FiatValue({
|
||||||
|
fiatValue,
|
||||||
|
priceImpact,
|
||||||
|
}: {
|
||||||
|
fiatValue: CurrencyAmount | null | undefined
|
||||||
|
priceImpact?: Percent
|
||||||
|
}) {
|
||||||
|
const theme = useTheme()
|
||||||
|
const priceImpactColor = useMemo(() => {
|
||||||
|
if (!priceImpact) return undefined
|
||||||
|
if (priceImpact.lessThan('0')) return theme.green1
|
||||||
|
const severity = warningSeverity(priceImpact)
|
||||||
|
if (severity < 1) return theme.text4
|
||||||
|
if (severity < 3) return theme.yellow1
|
||||||
|
return theme.red1
|
||||||
|
}, [priceImpact, theme.green1, theme.red1, theme.text4, theme.yellow1])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TYPE.body fontSize={14} color={fiatValue ? theme.text2 : theme.text4}>
|
||||||
|
{fiatValue ? '~' : ''}${fiatValue ? Number(fiatValue?.toSignificant(6)).toLocaleString('en') : '-'}
|
||||||
|
{priceImpact ? (
|
||||||
|
<span style={{ color: priceImpactColor }}> ({priceImpact.multiply(-100).toSignificant(3)}%)</span>
|
||||||
|
) : null}
|
||||||
|
</TYPE.body>
|
||||||
|
)
|
||||||
|
}
|
@ -1,10 +1,9 @@
|
|||||||
import { Pair } from '@uniswap/v2-sdk'
|
import { Pair } from '@uniswap/v2-sdk'
|
||||||
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
|
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
|
||||||
import React, { useState, useCallback, useMemo } from 'react'
|
import React, { useState, useCallback } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { darken } from 'polished'
|
import { darken } from 'polished'
|
||||||
import { useCurrencyBalance } from '../../state/wallet/hooks'
|
import { useCurrencyBalance } from '../../state/wallet/hooks'
|
||||||
import { warningSeverity } from '../../utils/prices'
|
|
||||||
import CurrencySearchModal from '../SearchModal/CurrencySearchModal'
|
import CurrencySearchModal from '../SearchModal/CurrencySearchModal'
|
||||||
import CurrencyLogo from '../CurrencyLogo'
|
import CurrencyLogo from '../CurrencyLogo'
|
||||||
import DoubleCurrencyLogo from '../DoubleLogo'
|
import DoubleCurrencyLogo from '../DoubleLogo'
|
||||||
@ -18,6 +17,7 @@ import { useTranslation } from 'react-i18next'
|
|||||||
import useTheme from '../../hooks/useTheme'
|
import useTheme from '../../hooks/useTheme'
|
||||||
import { Lock } from 'react-feather'
|
import { Lock } from 'react-feather'
|
||||||
import { AutoColumn } from 'components/Column'
|
import { AutoColumn } from 'components/Column'
|
||||||
|
import { FiatValue } from './FiatValue'
|
||||||
|
|
||||||
const InputPanel = styled.div<{ hideInput?: boolean }>`
|
const InputPanel = styled.div<{ hideInput?: boolean }>`
|
||||||
${({ theme }) => theme.flexColumnNoWrap}
|
${({ theme }) => theme.flexColumnNoWrap}
|
||||||
@ -196,15 +196,6 @@ export default function CurrencyInputPanel({
|
|||||||
setModalOpen(false)
|
setModalOpen(false)
|
||||||
}, [setModalOpen])
|
}, [setModalOpen])
|
||||||
|
|
||||||
const priceImpactColor = useMemo(() => {
|
|
||||||
if (!priceImpact) return undefined
|
|
||||||
if (priceImpact.lessThan('0')) return theme.green1
|
|
||||||
const severity = warningSeverity(priceImpact)
|
|
||||||
if (severity < 1) return theme.text4
|
|
||||||
if (severity < 3) return theme.yellow1
|
|
||||||
return theme.red1
|
|
||||||
}, [priceImpact, theme.green1, theme.red1, theme.text4, theme.yellow1])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InputPanel id={id} hideInput={hideInput} {...rest}>
|
<InputPanel id={id} hideInput={hideInput} {...rest}>
|
||||||
{locked && (
|
{locked && (
|
||||||
@ -291,12 +282,7 @@ export default function CurrencyInputPanel({
|
|||||||
</RowFixed>
|
</RowFixed>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<TYPE.body fontSize={14} color={fiatValue ? theme.text2 : theme.text4}>
|
<FiatValue fiatValue={fiatValue} priceImpact={priceImpact} />
|
||||||
{fiatValue ? '~' : ''}${fiatValue ? Number(fiatValue?.toSignificant(6)).toLocaleString('en') : '-'}
|
|
||||||
{priceImpact ? (
|
|
||||||
<span style={{ color: priceImpactColor }}> ({priceImpact.multiply(-100).toSignificant(3)}%)</span>
|
|
||||||
) : null}
|
|
||||||
</TYPE.body>
|
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
</FiatRow>
|
</FiatRow>
|
||||||
)}
|
)}
|
||||||
|
@ -5,10 +5,12 @@ import React, { useContext, useState } from 'react'
|
|||||||
import { ArrowDown, AlertTriangle } from 'react-feather'
|
import { ArrowDown, AlertTriangle } from 'react-feather'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import styled, { ThemeContext } from 'styled-components'
|
import styled, { ThemeContext } from 'styled-components'
|
||||||
|
import { useUSDCValue } from '../../hooks/useUSDCPrice'
|
||||||
import { TYPE } from '../../theme'
|
import { TYPE } from '../../theme'
|
||||||
import { ButtonPrimary } from '../Button'
|
import { ButtonPrimary } from '../Button'
|
||||||
import { isAddress, shortenAddress } from '../../utils'
|
import { computeFiatValuePriceImpact, isAddress, shortenAddress } from '../../utils'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
|
import { FiatValue } from '../CurrencyInputPanel/FiatValue'
|
||||||
import CurrencyLogo from '../CurrencyLogo'
|
import CurrencyLogo from '../CurrencyLogo'
|
||||||
import { RowBetween, RowFixed } from '../Row'
|
import { RowBetween, RowFixed } from '../Row'
|
||||||
import { TruncatedText, SwapShowAcceptChanges } from './styleds'
|
import { TruncatedText, SwapShowAcceptChanges } from './styleds'
|
||||||
@ -57,17 +59,18 @@ export default function SwapModalHeader({
|
|||||||
|
|
||||||
const [showInverted, setShowInverted] = useState<boolean>(false)
|
const [showInverted, setShowInverted] = useState<boolean>(false)
|
||||||
|
|
||||||
|
const fiatValueInput = useUSDCValue(maximumAmountIn)
|
||||||
|
const fiatValueOutput = useUSDCValue(minimumAmountOut)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AutoColumn gap={'4px'} style={{ marginTop: '1rem' }}>
|
<AutoColumn gap={'4px'} style={{ marginTop: '1rem' }}>
|
||||||
<DarkGreyCard padding="0.75rem 1rem">
|
<DarkGreyCard padding="0.75rem 1rem">
|
||||||
<AutoColumn gap={'8px'}>
|
<AutoColumn gap={'8px'}>
|
||||||
<RowBetween>
|
<RowBetween>
|
||||||
<TYPE.body color={theme.text3} fontWeight={500} fontSize={14}>
|
<TYPE.body color={theme.text3} fontWeight={500} fontSize={14}>
|
||||||
{'From'}
|
From
|
||||||
</TYPE.body>
|
|
||||||
<TYPE.body fontSize={14} color={theme.text3}>
|
|
||||||
{'$-'}
|
|
||||||
</TYPE.body>
|
</TYPE.body>
|
||||||
|
<FiatValue fiatValue={fiatValueInput} />
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
<RowBetween align="center">
|
<RowBetween align="center">
|
||||||
<RowFixed gap={'0px'}>
|
<RowFixed gap={'0px'}>
|
||||||
@ -95,10 +98,13 @@ export default function SwapModalHeader({
|
|||||||
<AutoColumn gap={'8px'}>
|
<AutoColumn gap={'8px'}>
|
||||||
<RowBetween>
|
<RowBetween>
|
||||||
<TYPE.body color={theme.text3} fontWeight={500} fontSize={14}>
|
<TYPE.body color={theme.text3} fontWeight={500} fontSize={14}>
|
||||||
{'To'}
|
To
|
||||||
</TYPE.body>
|
</TYPE.body>
|
||||||
<TYPE.body fontSize={14} color={theme.text3}>
|
<TYPE.body fontSize={14} color={theme.text3}>
|
||||||
{'$-'}
|
<FiatValue
|
||||||
|
fiatValue={fiatValueOutput}
|
||||||
|
priceImpact={computeFiatValuePriceImpact(fiatValueInput, fiatValueOutput)}
|
||||||
|
/>
|
||||||
</TYPE.body>
|
</TYPE.body>
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
<RowBetween align="flex-end">
|
<RowBetween align="flex-end">
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { CurrencyAmount, currencyEquals, 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 { AdvancedSwapDetails } from 'components/swap/AdvancedSwapDetails'
|
import { AdvancedSwapDetails } from 'components/swap/AdvancedSwapDetails'
|
||||||
@ -6,26 +6,27 @@ import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter
|
|||||||
import { MouseoverTooltip, MouseoverTooltipContent } from 'components/Tooltip'
|
import { MouseoverTooltip, MouseoverTooltipContent } from 'components/Tooltip'
|
||||||
import JSBI from 'jsbi'
|
import JSBI from 'jsbi'
|
||||||
import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react'
|
import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react'
|
||||||
import { ArrowDown, HelpCircle, CheckCircle, Info, X } from 'react-feather'
|
import { ArrowDown, CheckCircle, HelpCircle, Info, X } from 'react-feather'
|
||||||
import ReactGA from 'react-ga'
|
import ReactGA from 'react-ga'
|
||||||
import { RouteComponentProps } from 'react-router-dom'
|
import { Link, RouteComponentProps } from 'react-router-dom'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import { ThemeContext } from 'styled-components'
|
import { ThemeContext } from 'styled-components'
|
||||||
import AddressInputPanel from '../../components/AddressInputPanel'
|
import AddressInputPanel from '../../components/AddressInputPanel'
|
||||||
import { ButtonConfirmed, ButtonError, ButtonLight, ButtonPrimary, ButtonGray } from '../../components/Button'
|
import { ButtonConfirmed, ButtonError, ButtonGray, ButtonLight, ButtonPrimary } from '../../components/Button'
|
||||||
import { GreyCard } from '../../components/Card'
|
import { GreyCard } from '../../components/Card'
|
||||||
import { AutoColumn } from '../../components/Column'
|
import { AutoColumn } from '../../components/Column'
|
||||||
import CurrencyInputPanel from '../../components/CurrencyInputPanel'
|
import CurrencyInputPanel from '../../components/CurrencyInputPanel'
|
||||||
import CurrencyLogo from '../../components/CurrencyLogo'
|
import CurrencyLogo from '../../components/CurrencyLogo'
|
||||||
import Loader from '../../components/Loader'
|
import Loader from '../../components/Loader'
|
||||||
import { AutoRow, RowBetween, RowFixed } from '../../components/Row'
|
import { AutoRow, RowBetween, RowFixed } from '../../components/Row'
|
||||||
|
import BetterTradeLink from '../../components/swap/BetterTradeLink'
|
||||||
import confirmPriceImpactWithoutFee from '../../components/swap/confirmPriceImpactWithoutFee'
|
import confirmPriceImpactWithoutFee from '../../components/swap/confirmPriceImpactWithoutFee'
|
||||||
import ConfirmSwapModal from '../../components/swap/ConfirmSwapModal'
|
import ConfirmSwapModal from '../../components/swap/ConfirmSwapModal'
|
||||||
|
|
||||||
import { ArrowWrapper, BottomGrouping, Dots, SwapCallbackError, Wrapper } from '../../components/swap/styleds'
|
import { ArrowWrapper, BottomGrouping, Dots, SwapCallbackError, Wrapper } from '../../components/swap/styleds'
|
||||||
|
import SwapHeader from '../../components/swap/SwapHeader'
|
||||||
import TradePrice from '../../components/swap/TradePrice'
|
import TradePrice from '../../components/swap/TradePrice'
|
||||||
import TokenWarningModal from '../../components/TokenWarningModal'
|
import TokenWarningModal from '../../components/TokenWarningModal'
|
||||||
import { ONE_HUNDRED_PERCENT } from '../../constants'
|
|
||||||
import { useActiveWeb3React } from '../../hooks'
|
import { useActiveWeb3React } from '../../hooks'
|
||||||
import { useAllTokens, useCurrency } from '../../hooks/Tokens'
|
import { useAllTokens, useCurrency } from '../../hooks/Tokens'
|
||||||
import { ApprovalState, useApproveCallbackFromTrade } from '../../hooks/useApproveCallback'
|
import { ApprovalState, useApproveCallbackFromTrade } from '../../hooks/useApproveCallback'
|
||||||
@ -47,27 +48,13 @@ import {
|
|||||||
} from '../../state/swap/hooks'
|
} from '../../state/swap/hooks'
|
||||||
import { useExpertModeManager, useUserSingleHopOnly, useUserSlippageTolerance } from '../../state/user/hooks'
|
import { useExpertModeManager, useUserSingleHopOnly, useUserSlippageTolerance } from '../../state/user/hooks'
|
||||||
import { LinkStyledButton, TYPE } from '../../theme'
|
import { LinkStyledButton, TYPE } from '../../theme'
|
||||||
|
import { computeFiatValuePriceImpact } from '../../utils'
|
||||||
import { getTradeVersion } from '../../utils/getTradeVersion'
|
import { getTradeVersion } from '../../utils/getTradeVersion'
|
||||||
|
import { isTradeBetter } from '../../utils/isTradeBetter'
|
||||||
import { maxAmountSpend } from '../../utils/maxAmountSpend'
|
import { maxAmountSpend } from '../../utils/maxAmountSpend'
|
||||||
import { warningSeverity } from '../../utils/prices'
|
import { warningSeverity } from '../../utils/prices'
|
||||||
import AppBody from '../AppBody'
|
import AppBody from '../AppBody'
|
||||||
|
|
||||||
import { Link } from 'react-router-dom'
|
|
||||||
import { isTradeBetter } from '../../utils/isTradeBetter'
|
|
||||||
import BetterTradeLink from '../../components/swap/BetterTradeLink'
|
|
||||||
import SwapHeader from '../../components/swap/SwapHeader'
|
|
||||||
|
|
||||||
function computeFiatValuePriceImpact(
|
|
||||||
fiatValueInput: CurrencyAmount | undefined | null,
|
|
||||||
fiatValueOutput: CurrencyAmount | undefined | null
|
|
||||||
): Percent | undefined {
|
|
||||||
if (!fiatValueOutput || !fiatValueInput) return undefined
|
|
||||||
if (!currencyEquals(fiatValueInput.currency, fiatValueOutput.currency)) return undefined
|
|
||||||
if (JSBI.equal(fiatValueInput.raw, JSBI.BigInt(0))) return undefined
|
|
||||||
const pct = ONE_HUNDRED_PERCENT.subtract(fiatValueOutput.divide(fiatValueInput))
|
|
||||||
return new Percent(pct.numerator, pct.denominator)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Swap({ history }: RouteComponentProps) {
|
export default function Swap({ history }: RouteComponentProps) {
|
||||||
const loadedUrlParams = useDefaultsFromURLSearch()
|
const loadedUrlParams = useDefaultsFromURLSearch()
|
||||||
|
|
||||||
|
14
src/utils/computeFiatValuePriceImpact.tsx
Normal file
14
src/utils/computeFiatValuePriceImpact.tsx
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { CurrencyAmount, currencyEquals, Percent } from '@uniswap/sdk-core'
|
||||||
|
import JSBI from 'jsbi'
|
||||||
|
import { ONE_HUNDRED_PERCENT } from '../constants'
|
||||||
|
|
||||||
|
export function computeFiatValuePriceImpact(
|
||||||
|
fiatValueInput: CurrencyAmount | undefined | null,
|
||||||
|
fiatValueOutput: CurrencyAmount | undefined | null
|
||||||
|
): Percent | undefined {
|
||||||
|
if (!fiatValueOutput || !fiatValueInput) return undefined
|
||||||
|
if (!currencyEquals(fiatValueInput.currency, fiatValueOutput.currency)) return undefined
|
||||||
|
if (JSBI.equal(fiatValueInput.raw, JSBI.BigInt(0))) return undefined
|
||||||
|
const pct = ONE_HUNDRED_PERCENT.subtract(fiatValueOutput.divide(fiatValueInput))
|
||||||
|
return new Percent(pct.numerator, pct.denominator)
|
||||||
|
}
|
@ -119,3 +119,4 @@ export function supportedChainId(chainId: number): ChainId | undefined {
|
|||||||
export function formattedFeeAmount(feeAmount: FeeAmount): number {
|
export function formattedFeeAmount(feeAmount: FeeAmount): number {
|
||||||
return feeAmount / 10000
|
return feeAmount / 10000
|
||||||
}
|
}
|
||||||
|
export { computeFiatValuePriceImpact } from './computeFiatValuePriceImpact'
|
||||||
|
Loading…
Reference in New Issue
Block a user