Token check (#610)
* update market rate calculation and input parsing for 0 decimal tokens * remove style bump and revert tokens * add custom warning for pasted tokens * update centering * upload dark theme * update copy and loading state * copy edits * update color * multiple cards
This commit is contained in:
parent
8290cf565f
commit
e05be71ea5
@ -18,7 +18,7 @@ import Modal from '../Modal'
|
|||||||
import TokenLogo from '../TokenLogo'
|
import TokenLogo from '../TokenLogo'
|
||||||
import SearchIcon from '../../assets/images/magnifying-glass.svg'
|
import SearchIcon from '../../assets/images/magnifying-glass.svg'
|
||||||
import { useTransactionAdder, usePendingApproval } from '../../contexts/Transactions'
|
import { useTransactionAdder, usePendingApproval } from '../../contexts/Transactions'
|
||||||
import { useTokenDetails, useAllTokenDetails } from '../../contexts/Tokens'
|
import { useTokenDetails, useAllTokenDetails, INITIAL_TOKENS_CONTEXT } from '../../contexts/Tokens'
|
||||||
import { useAddressBalance } from '../../contexts/Balances'
|
import { useAddressBalance } from '../../contexts/Balances'
|
||||||
import { ReactComponent as Close } from '../../assets/images/x.svg'
|
import { ReactComponent as Close } from '../../assets/images/x.svg'
|
||||||
import { transparentize } from 'polished'
|
import { transparentize } from 'polished'
|
||||||
@ -244,6 +244,10 @@ const TokenFullName = styled.div`
|
|||||||
color: ${({ theme }) => theme.chaliceGray};
|
color: ${({ theme }) => theme.chaliceGray};
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const FadedSpan = styled.span`
|
||||||
|
color: ${({ theme }) => theme.royalBlue};
|
||||||
|
`
|
||||||
|
|
||||||
const TokenRowBalance = styled.div`
|
const TokenRowBalance = styled.div`
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
@ -284,7 +288,8 @@ export default function CurrencyInputPanel({
|
|||||||
disableTokenSelect,
|
disableTokenSelect,
|
||||||
selectedTokenAddress = '',
|
selectedTokenAddress = '',
|
||||||
showUnlock,
|
showUnlock,
|
||||||
value
|
value,
|
||||||
|
urlAddedTokens
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
@ -431,6 +436,7 @@ export default function CurrencyInputPanel({
|
|||||||
onDismiss={() => {
|
onDismiss={() => {
|
||||||
setModalIsOpen(false)
|
setModalIsOpen(false)
|
||||||
}}
|
}}
|
||||||
|
urlAddedTokens={urlAddedTokens}
|
||||||
onTokenSelect={onCurrencySelected}
|
onTokenSelect={onCurrencySelected}
|
||||||
allBalances={allBalances}
|
allBalances={allBalances}
|
||||||
/>
|
/>
|
||||||
@ -439,7 +445,7 @@ export default function CurrencyInputPanel({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function CurrencySelectModal({ isOpen, onDismiss, onTokenSelect }) {
|
function CurrencySelectModal({ isOpen, onDismiss, onTokenSelect, urlAddedTokens }) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const [searchQuery, setSearchQuery] = useState('')
|
const [searchQuery, setSearchQuery] = useState('')
|
||||||
@ -447,7 +453,7 @@ function CurrencySelectModal({ isOpen, onDismiss, onTokenSelect }) {
|
|||||||
|
|
||||||
const allTokens = useAllTokenDetails()
|
const allTokens = useAllTokenDetails()
|
||||||
|
|
||||||
const { account } = useWeb3React()
|
const { account, chainId } = useWeb3React()
|
||||||
|
|
||||||
// BigNumber.js instance
|
// BigNumber.js instance
|
||||||
const ethPrice = useETHPriceInUSD()
|
const ethPrice = useETHPriceInUSD()
|
||||||
@ -589,13 +595,25 @@ function CurrencySelectModal({ isOpen, onDismiss, onTokenSelect }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return filteredTokenList.map(({ address, symbol, name, balance, usdBalance }) => {
|
return filteredTokenList.map(({ address, symbol, name, balance, usdBalance }) => {
|
||||||
|
const urlAdded = urlAddedTokens && urlAddedTokens.hasOwnProperty(address)
|
||||||
|
const customAdded =
|
||||||
|
address !== 'ETH' &&
|
||||||
|
INITIAL_TOKENS_CONTEXT[chainId] &&
|
||||||
|
!INITIAL_TOKENS_CONTEXT[chainId].hasOwnProperty(address) &&
|
||||||
|
!urlAdded
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TokenModalRow key={address} onClick={() => _onTokenSelect(address)}>
|
<TokenModalRow key={address} onClick={() => _onTokenSelect(address)}>
|
||||||
<TokenRowLeft>
|
<TokenRowLeft>
|
||||||
<TokenLogo address={address} size={'2rem'} />
|
<TokenLogo address={address} size={'2rem'} />
|
||||||
<TokenSymbolGroup>
|
<TokenSymbolGroup>
|
||||||
<span id="symbol">{symbol}</span>
|
<div>
|
||||||
<TokenFullName>{name}</TokenFullName>
|
<span id="symbol">{symbol}</span>
|
||||||
|
<FadedSpan>
|
||||||
|
{urlAdded && '(Added by URL)'} {customAdded && '(Added by user)'}
|
||||||
|
</FadedSpan>
|
||||||
|
</div>
|
||||||
|
<TokenFullName> {name}</TokenFullName>
|
||||||
</TokenSymbolGroup>
|
</TokenSymbolGroup>
|
||||||
</TokenRowLeft>
|
</TokenRowLeft>
|
||||||
<TokenRowRight>
|
<TokenRowRight>
|
||||||
|
@ -10,7 +10,7 @@ import { brokenTokens } from '../../constants'
|
|||||||
import { amountFormatter, calculateGasMargin } from '../../utils'
|
import { amountFormatter, calculateGasMargin } from '../../utils'
|
||||||
|
|
||||||
import { useExchangeContract } from '../../hooks'
|
import { useExchangeContract } from '../../hooks'
|
||||||
import { useTokenDetails } from '../../contexts/Tokens'
|
import { useTokenDetails, INITIAL_TOKENS_CONTEXT } from '../../contexts/Tokens'
|
||||||
import { useTransactionAdder } from '../../contexts/Transactions'
|
import { useTransactionAdder } from '../../contexts/Transactions'
|
||||||
import { useAddressBalance, useExchangeReserves } from '../../contexts/Balances'
|
import { useAddressBalance, useExchangeReserves } from '../../contexts/Balances'
|
||||||
import { useAddressAllowance } from '../../contexts/Allowances'
|
import { useAddressAllowance } from '../../contexts/Allowances'
|
||||||
@ -23,6 +23,7 @@ import AddressInputPanel from '../AddressInputPanel'
|
|||||||
import OversizedPanel from '../OversizedPanel'
|
import OversizedPanel from '../OversizedPanel'
|
||||||
import TransactionDetails from '../TransactionDetails'
|
import TransactionDetails from '../TransactionDetails'
|
||||||
import ArrowDown from '../../assets/svg/SVGArrowDown'
|
import ArrowDown from '../../assets/svg/SVGArrowDown'
|
||||||
|
import WarningCard from '../WarningCard'
|
||||||
|
|
||||||
const INPUT = 0
|
const INPUT = 0
|
||||||
const OUTPUT = 1
|
const OUTPUT = 1
|
||||||
@ -248,7 +249,15 @@ function getMarketRate(
|
|||||||
|
|
||||||
export default function ExchangePage({ initialCurrency, sending = false, params }) {
|
export default function ExchangePage({ initialCurrency, sending = false, params }) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { account, error } = useWeb3React()
|
const { account, chainId, error } = useWeb3React()
|
||||||
|
|
||||||
|
const urlAddedTokens = {}
|
||||||
|
if (params.inputCurrency) {
|
||||||
|
urlAddedTokens[params.inputCurrency] = true
|
||||||
|
}
|
||||||
|
if (params.outputCurrency) {
|
||||||
|
urlAddedTokens[params.outputCurrency] = true
|
||||||
|
}
|
||||||
|
|
||||||
// BigNumber.js instance
|
// BigNumber.js instance
|
||||||
const ethPrice = useETHPriceInUSD()
|
const ethPrice = useETHPriceInUSD()
|
||||||
@ -710,10 +719,54 @@ export default function ExchangePage({ initialCurrency, sending = false, params
|
|||||||
|
|
||||||
const toggleWalletModal = useWalletModalToggle()
|
const toggleWalletModal = useWalletModalToggle()
|
||||||
|
|
||||||
|
const newInputDetected =
|
||||||
|
inputCurrency !== 'ETH' && inputCurrency && !INITIAL_TOKENS_CONTEXT[chainId].hasOwnProperty(inputCurrency)
|
||||||
|
|
||||||
|
const newOutputDetected =
|
||||||
|
outputCurrency !== 'ETH' && outputCurrency && !INITIAL_TOKENS_CONTEXT[chainId].hasOwnProperty(outputCurrency)
|
||||||
|
|
||||||
|
const [showInputWarning, setShowInputWarning] = useState(false)
|
||||||
|
const [showOutputWarning, setShowOutputWarning] = useState(false)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (newInputDetected) {
|
||||||
|
setShowInputWarning(true)
|
||||||
|
} else {
|
||||||
|
setShowInputWarning(false)
|
||||||
|
}
|
||||||
|
}, [newInputDetected, setShowInputWarning])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (newOutputDetected) {
|
||||||
|
setShowOutputWarning(true)
|
||||||
|
} else {
|
||||||
|
setShowOutputWarning(false)
|
||||||
|
}
|
||||||
|
}, [newOutputDetected, setShowOutputWarning])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{showInputWarning && (
|
||||||
|
<WarningCard
|
||||||
|
onDismiss={() => {
|
||||||
|
setShowInputWarning(false)
|
||||||
|
}}
|
||||||
|
urlAddedTokens={urlAddedTokens}
|
||||||
|
currency={inputCurrency}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{showOutputWarning && (
|
||||||
|
<WarningCard
|
||||||
|
onDismiss={() => {
|
||||||
|
setShowOutputWarning(false)
|
||||||
|
}}
|
||||||
|
urlAddedTokens={urlAddedTokens}
|
||||||
|
currency={outputCurrency}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<CurrencyInputPanel
|
<CurrencyInputPanel
|
||||||
title={t('input')}
|
title={t('input')}
|
||||||
|
urlAddedTokens={urlAddedTokens}
|
||||||
description={inputValueFormatted && independentField === OUTPUT ? estimatedText : ''}
|
description={inputValueFormatted && independentField === OUTPUT ? estimatedText : ''}
|
||||||
extraText={inputBalanceFormatted && formatBalance(inputBalanceFormatted)}
|
extraText={inputBalanceFormatted && formatBalance(inputBalanceFormatted)}
|
||||||
extraTextClickHander={() => {
|
extraTextClickHander={() => {
|
||||||
@ -764,6 +817,7 @@ export default function ExchangePage({ initialCurrency, sending = false, params
|
|||||||
title={t('output')}
|
title={t('output')}
|
||||||
description={outputValueFormatted && independentField === INPUT ? estimatedText : ''}
|
description={outputValueFormatted && independentField === INPUT ? estimatedText : ''}
|
||||||
extraText={outputBalanceFormatted && formatBalance(outputBalanceFormatted)}
|
extraText={outputBalanceFormatted && formatBalance(outputBalanceFormatted)}
|
||||||
|
urlAddedTokens={urlAddedTokens}
|
||||||
onCurrencySelected={outputCurrency => {
|
onCurrencySelected={outputCurrency => {
|
||||||
dispatchSwapState({
|
dispatchSwapState({
|
||||||
type: 'SELECT_CURRENCY',
|
type: 'SELECT_CURRENCY',
|
||||||
|
180
src/components/WarningCard/index.js
Normal file
180
src/components/WarningCard/index.js
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
import React, { useState } from 'react'
|
||||||
|
import styled, { keyframes } from 'styled-components'
|
||||||
|
|
||||||
|
import { useWeb3React } from '../../hooks'
|
||||||
|
import { useTokenDetails } from '../../contexts/Tokens'
|
||||||
|
import { getEtherscanLink } from '../../utils'
|
||||||
|
|
||||||
|
import { Link } from '../../theme'
|
||||||
|
import TokenLogo from '../TokenLogo'
|
||||||
|
import { ReactComponent as Close } from '../../assets/images/x.svg'
|
||||||
|
import question from '../../assets/images/question.svg'
|
||||||
|
|
||||||
|
const Flex = styled.div`
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 2rem;
|
||||||
|
|
||||||
|
button {
|
||||||
|
max-width: 20rem;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const Wrapper = styled.div`
|
||||||
|
background: rgba(243, 190, 30, 0.1);
|
||||||
|
position: relative;
|
||||||
|
padding: 1rem;
|
||||||
|
border: 0.5px solid #f3be1e;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: 1fr 1fr 1fr;
|
||||||
|
grid-row-gap: 10px;
|
||||||
|
`
|
||||||
|
|
||||||
|
const Row = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-items: flex-start;
|
||||||
|
& > * {
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const CloseColor = styled(Close)`
|
||||||
|
color: #aeaeae;
|
||||||
|
`
|
||||||
|
|
||||||
|
const CloseIcon = styled.div`
|
||||||
|
position: absolute;
|
||||||
|
right: 1rem;
|
||||||
|
top: 14px;
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
height: 14px;
|
||||||
|
width: 14px;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const QuestionWrapper = styled.button`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
margin-left: 0.4rem;
|
||||||
|
padding: 0.2rem;
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
outline: none;
|
||||||
|
cursor: default;
|
||||||
|
border-radius: 36px;
|
||||||
|
|
||||||
|
:hover,
|
||||||
|
:focus {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const HelpCircleStyled = styled.img`
|
||||||
|
height: 18px;
|
||||||
|
width: 18px;
|
||||||
|
`
|
||||||
|
|
||||||
|
const fadeIn = keyframes`
|
||||||
|
from {
|
||||||
|
opacity : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity : 1;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const Popup = styled(Flex)`
|
||||||
|
position: absolute;
|
||||||
|
width: 228px;
|
||||||
|
right: 110px;
|
||||||
|
top: 4px;
|
||||||
|
z-index: 10;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.6rem 1rem;
|
||||||
|
line-height: 150%;
|
||||||
|
background: ${({ theme }) => theme.backgroundColor};
|
||||||
|
border: 1px solid ${({ theme }) => theme.mercuryGray};
|
||||||
|
border-radius: 8px;
|
||||||
|
animation: ${fadeIn} 0.15s linear;
|
||||||
|
color: ${({ theme }) => theme.textColor};
|
||||||
|
font-style: italic;
|
||||||
|
|
||||||
|
box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.04), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04),
|
||||||
|
0px 24px 32px rgba(0, 0, 0, 0.04);
|
||||||
|
|
||||||
|
${({ theme }) => theme.mediaWidth.upToSmall`
|
||||||
|
left: 2px;
|
||||||
|
top: 50px;
|
||||||
|
`}
|
||||||
|
`
|
||||||
|
|
||||||
|
const Text = styled.div`
|
||||||
|
color: ${({ theme }) => theme.textColor};
|
||||||
|
`
|
||||||
|
|
||||||
|
function WarningCard({ onDismiss, urlAddedTokens, currency }) {
|
||||||
|
const [showPopup, setPopup] = useState()
|
||||||
|
const { chainId } = useWeb3React()
|
||||||
|
const { symbol: inputSymbol, name: inputName } = useTokenDetails(currency)
|
||||||
|
const fromURL = urlAddedTokens.hasOwnProperty(currency)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Wrapper>
|
||||||
|
<CloseIcon onClick={() => onDismiss()}>
|
||||||
|
<CloseColor alt={'close icon'} />
|
||||||
|
</CloseIcon>
|
||||||
|
<Row style={{ fontSize: '12px' }}>
|
||||||
|
<Text>{fromURL ? 'Token imported by URL ' : 'Token imported by user'}</Text>
|
||||||
|
<QuestionWrapper
|
||||||
|
onClick={() => {
|
||||||
|
setPopup(!showPopup)
|
||||||
|
}}
|
||||||
|
onMouseEnter={() => {
|
||||||
|
setPopup(true)
|
||||||
|
}}
|
||||||
|
onMouseLeave={() => {
|
||||||
|
setPopup(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<HelpCircleStyled src={question} alt="popup" />
|
||||||
|
</QuestionWrapper>
|
||||||
|
{showPopup ? (
|
||||||
|
<Popup>
|
||||||
|
<Text>
|
||||||
|
The Uniswap smart contracts are designed to support any ERC20 token on Ethereum. Any token can be loaded
|
||||||
|
into the interface by entering its Ethereum address into the search field or passing it as a URL
|
||||||
|
parameter. Be careful when interacting with imported tokens as they have not been verified.
|
||||||
|
</Text>
|
||||||
|
</Popup>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
)}
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<TokenLogo address={currency} />
|
||||||
|
<div style={{ fontWeight: 500 }}>{inputName && inputSymbol ? inputName + ' (' + inputSymbol + ')' : ''}</div>
|
||||||
|
<Link style={{ fontWeight: 400 }} href={getEtherscanLink(chainId, currency, 'address')}>
|
||||||
|
(View on Etherscan)
|
||||||
|
</Link>
|
||||||
|
</Row>
|
||||||
|
<Row style={{ fontSize: '12px', fontStyle: 'italic' }}>
|
||||||
|
<Text>Please verify the legitimacy of this token before making any transactions.</Text>
|
||||||
|
</Row>
|
||||||
|
</Wrapper>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default WarningCard
|
@ -26,7 +26,7 @@ const ETH = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const INITIAL_TOKENS_CONTEXT = {
|
export const INITIAL_TOKENS_CONTEXT = {
|
||||||
1: {
|
1: {
|
||||||
'0xB6eD7644C69416d67B522e20bC294A9a9B405B31': {
|
'0xB6eD7644C69416d67B522e20bC294A9a9B405B31': {
|
||||||
[NAME]: '0xBitcoin Token',
|
[NAME]: '0xBitcoin Token',
|
||||||
@ -662,7 +662,6 @@ export function useTokenDetails(tokenAddress) {
|
|||||||
library
|
library
|
||||||
) {
|
) {
|
||||||
let stale = false
|
let stale = false
|
||||||
|
|
||||||
const namePromise = getTokenName(tokenAddress, library).catch(() => null)
|
const namePromise = getTokenName(tokenAddress, library).catch(() => null)
|
||||||
const symbolPromise = getTokenSymbol(tokenAddress, library).catch(() => null)
|
const symbolPromise = getTokenSymbol(tokenAddress, library).catch(() => null)
|
||||||
const decimalsPromise = getTokenDecimals(tokenAddress, library).catch(() => null)
|
const decimalsPromise = getTokenDecimals(tokenAddress, library).catch(() => null)
|
||||||
|
@ -10,11 +10,13 @@ import CurrencyInputPanel from '../../components/CurrencyInputPanel'
|
|||||||
import OversizedPanel from '../../components/OversizedPanel'
|
import OversizedPanel from '../../components/OversizedPanel'
|
||||||
import ContextualInfo from '../../components/ContextualInfo'
|
import ContextualInfo from '../../components/ContextualInfo'
|
||||||
import { ReactComponent as Plus } from '../../assets/images/plus-blue.svg'
|
import { ReactComponent as Plus } from '../../assets/images/plus-blue.svg'
|
||||||
|
import WarningCard from '../../components/WarningCard'
|
||||||
|
|
||||||
import { useWeb3React, useExchangeContract } from '../../hooks'
|
import { useWeb3React, useExchangeContract } from '../../hooks'
|
||||||
import { brokenTokens } from '../../constants'
|
import { brokenTokens } from '../../constants'
|
||||||
import { amountFormatter, calculateGasMargin } from '../../utils'
|
import { amountFormatter, calculateGasMargin } from '../../utils'
|
||||||
import { useTransactionAdder } from '../../contexts/Transactions'
|
import { useTransactionAdder } from '../../contexts/Transactions'
|
||||||
import { useTokenDetails } from '../../contexts/Tokens'
|
import { useTokenDetails, INITIAL_TOKENS_CONTEXT } from '../../contexts/Tokens'
|
||||||
import { useAddressBalance, useExchangeReserves, useETHPriceInUSD } from '../../contexts/Balances'
|
import { useAddressBalance, useExchangeReserves, useETHPriceInUSD } from '../../contexts/Balances'
|
||||||
import { useAddressAllowance } from '../../contexts/Allowances'
|
import { useAddressAllowance } from '../../contexts/Allowances'
|
||||||
|
|
||||||
@ -198,11 +200,16 @@ function getMarketRate(reserveETH, reserveToken, decimals, invert = false) {
|
|||||||
|
|
||||||
export default function AddLiquidity({ params }) {
|
export default function AddLiquidity({ params }) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { library, account, active } = useWeb3React()
|
const { library, account, active, chainId } = useWeb3React()
|
||||||
|
|
||||||
// BigNumber.js instance
|
// BigNumber.js instance
|
||||||
const ethPrice = useETHPriceInUSD()
|
const ethPrice = useETHPriceInUSD()
|
||||||
|
|
||||||
|
const urlAddedTokens = {}
|
||||||
|
if (params.token) {
|
||||||
|
urlAddedTokens[params.token] = true
|
||||||
|
}
|
||||||
|
|
||||||
// clear url of query
|
// clear url of query
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const history = createBrowserHistory()
|
const history = createBrowserHistory()
|
||||||
@ -578,6 +585,18 @@ export default function AddLiquidity({ params }) {
|
|||||||
const isValid =
|
const isValid =
|
||||||
(inputError === null || outputError === null) && !zeroDecimalError && !showUnlock && !brokenTokenWarning
|
(inputError === null || outputError === null) && !zeroDecimalError && !showUnlock && !brokenTokenWarning
|
||||||
|
|
||||||
|
const newOutputDetected =
|
||||||
|
outputCurrency !== 'ETH' && outputCurrency && !INITIAL_TOKENS_CONTEXT[chainId].hasOwnProperty(outputCurrency)
|
||||||
|
|
||||||
|
const [showOutputWarning, setShowOutputWarning] = useState(false)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (newOutputDetected) {
|
||||||
|
setShowOutputWarning(true)
|
||||||
|
} else {
|
||||||
|
setShowOutputWarning(false)
|
||||||
|
}
|
||||||
|
}, [newOutputDetected, setShowOutputWarning])
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isNewExchange ? (
|
{isNewExchange ? (
|
||||||
@ -591,7 +610,15 @@ export default function AddLiquidity({ params }) {
|
|||||||
<NewExchangeWarningText>{t('initialExchangeRate', { symbol })}</NewExchangeWarningText>
|
<NewExchangeWarningText>{t('initialExchangeRate', { symbol })}</NewExchangeWarningText>
|
||||||
</NewExchangeWarning>
|
</NewExchangeWarning>
|
||||||
) : null}
|
) : null}
|
||||||
|
{showOutputWarning && (
|
||||||
|
<WarningCard
|
||||||
|
onDismiss={() => {
|
||||||
|
setShowOutputWarning(false)
|
||||||
|
}}
|
||||||
|
urlAddedTokens={urlAddedTokens}
|
||||||
|
currency={outputCurrency}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<CurrencyInputPanel
|
<CurrencyInputPanel
|
||||||
title={t('deposit')}
|
title={t('deposit')}
|
||||||
extraText={inputBalance && formatBalance(amountFormatter(inputBalance, 18, 4))}
|
extraText={inputBalance && formatBalance(amountFormatter(inputBalance, 18, 4))}
|
||||||
@ -625,6 +652,7 @@ export default function AddLiquidity({ params }) {
|
|||||||
extraText={
|
extraText={
|
||||||
outputBalance && decimals && formatBalance(amountFormatter(outputBalance, decimals, Math.min(decimals, 4)))
|
outputBalance && decimals && formatBalance(amountFormatter(outputBalance, decimals, Math.min(decimals, 4)))
|
||||||
}
|
}
|
||||||
|
urlAddedTokens={urlAddedTokens}
|
||||||
selectedTokenAddress={outputCurrency}
|
selectedTokenAddress={outputCurrency}
|
||||||
onCurrencySelected={outputCurrency => {
|
onCurrencySelected={outputCurrency => {
|
||||||
dispatchAddLiquidityState({ type: 'SELECT_CURRENCY', payload: outputCurrency })
|
dispatchAddLiquidityState({ type: 'SELECT_CURRENCY', payload: outputCurrency })
|
||||||
|
@ -7,7 +7,7 @@ import styled from 'styled-components'
|
|||||||
|
|
||||||
import { useWeb3React, useExchangeContract } from '../../hooks'
|
import { useWeb3React, useExchangeContract } from '../../hooks'
|
||||||
import { useTransactionAdder } from '../../contexts/Transactions'
|
import { useTransactionAdder } from '../../contexts/Transactions'
|
||||||
import { useTokenDetails } from '../../contexts/Tokens'
|
import { useTokenDetails, INITIAL_TOKENS_CONTEXT } from '../../contexts/Tokens'
|
||||||
import { useAddressBalance, useETHPriceInUSD } from '../../contexts/Balances'
|
import { useAddressBalance, useETHPriceInUSD } from '../../contexts/Balances'
|
||||||
|
|
||||||
import { calculateGasMargin, amountFormatter } from '../../utils'
|
import { calculateGasMargin, amountFormatter } from '../../utils'
|
||||||
@ -18,6 +18,7 @@ import CurrencyInputPanel from '../../components/CurrencyInputPanel'
|
|||||||
import ContextualInfo from '../../components/ContextualInfo'
|
import ContextualInfo from '../../components/ContextualInfo'
|
||||||
import OversizedPanel from '../../components/OversizedPanel'
|
import OversizedPanel from '../../components/OversizedPanel'
|
||||||
import ArrowDown from '../../assets/svg/SVGArrowDown'
|
import ArrowDown from '../../assets/svg/SVGArrowDown'
|
||||||
|
import WarningCard from '../../components/WarningCard'
|
||||||
|
|
||||||
// denominated in bips
|
// denominated in bips
|
||||||
const ALLOWED_SLIPPAGE = ethers.utils.bigNumberify(200)
|
const ALLOWED_SLIPPAGE = ethers.utils.bigNumberify(200)
|
||||||
@ -144,7 +145,7 @@ function calculateSlippageBounds(value) {
|
|||||||
|
|
||||||
export default function RemoveLiquidity({ params }) {
|
export default function RemoveLiquidity({ params }) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { library, account, active } = useWeb3React()
|
const { library, account, active, chainId } = useWeb3React()
|
||||||
|
|
||||||
const addTransaction = useTransactionAdder()
|
const addTransaction = useTransactionAdder()
|
||||||
|
|
||||||
@ -194,6 +195,11 @@ export default function RemoveLiquidity({ params }) {
|
|||||||
const exchangeETHBalance = useAddressBalance(exchangeAddress, 'ETH')
|
const exchangeETHBalance = useAddressBalance(exchangeAddress, 'ETH')
|
||||||
const exchangeTokenBalance = useAddressBalance(exchangeAddress, outputCurrency)
|
const exchangeTokenBalance = useAddressBalance(exchangeAddress, outputCurrency)
|
||||||
|
|
||||||
|
const urlAddedTokens = {}
|
||||||
|
if (params.poolTokenAddress) {
|
||||||
|
urlAddedTokens[params.poolTokenAddress] = true
|
||||||
|
}
|
||||||
|
|
||||||
// input validation
|
// input validation
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (valueParsed && poolTokenBalance) {
|
if (valueParsed && poolTokenBalance) {
|
||||||
@ -355,8 +361,30 @@ export default function RemoveLiquidity({ params }) {
|
|||||||
|
|
||||||
const marketRate = getMarketRate(exchangeETHBalance, exchangeTokenBalance, decimals)
|
const marketRate = getMarketRate(exchangeETHBalance, exchangeTokenBalance, decimals)
|
||||||
|
|
||||||
|
const newOutputDetected =
|
||||||
|
outputCurrency !== 'ETH' && outputCurrency && !INITIAL_TOKENS_CONTEXT[chainId].hasOwnProperty(outputCurrency)
|
||||||
|
|
||||||
|
const [showCustomTokenWarning, setShowCustomTokenWarning] = useState(false)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (newOutputDetected) {
|
||||||
|
setShowCustomTokenWarning(true)
|
||||||
|
} else {
|
||||||
|
setShowCustomTokenWarning(false)
|
||||||
|
}
|
||||||
|
}, [newOutputDetected])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{showCustomTokenWarning && (
|
||||||
|
<WarningCard
|
||||||
|
onDismiss={() => {
|
||||||
|
setShowCustomTokenWarning(false)
|
||||||
|
}}
|
||||||
|
urlAddedTokens={urlAddedTokens}
|
||||||
|
currency={outputCurrency}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<CurrencyInputPanel
|
<CurrencyInputPanel
|
||||||
title={t('poolTokens')}
|
title={t('poolTokens')}
|
||||||
extraText={poolTokenBalance && formatBalance(amountFormatter(poolTokenBalance, 18, 4))}
|
extraText={poolTokenBalance && formatBalance(amountFormatter(poolTokenBalance, 18, 4))}
|
||||||
@ -368,6 +396,7 @@ export default function RemoveLiquidity({ params }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
urlAddedTokens={urlAddedTokens}
|
||||||
onCurrencySelected={setOutputCurrency}
|
onCurrencySelected={setOutputCurrency}
|
||||||
onValueChange={setValue}
|
onValueChange={setValue}
|
||||||
value={value}
|
value={value}
|
||||||
|
Loading…
Reference in New Issue
Block a user