Commit 9b2fe0bd authored by Moody Salem's avatar Moody Salem Committed by GitHub

Use best trade to get the best route (#731)

parent cb00e0ba
import React, { useState, useReducer, useCallback, useEffect } from 'react' import React, { useState, useCallback, useEffect } from 'react'
import { parseEther, parseUnits } from '@ethersproject/units'
import { Fraction, JSBI, Percent, TokenAmount, TradeType, WETH } from '@uniswap/sdk'
import { ArrowDown, ChevronDown, ChevronUp, Repeat } from 'react-feather'
import { withRouter } from 'react-router-dom' import { withRouter } from 'react-router-dom'
import { parseUnits, parseEther } from '@ethersproject/units'
import { BigNumber } from '@ethersproject/bignumber' import { BigNumber } from '@ethersproject/bignumber'
import { Zero, MaxUint256 } from '@ethersproject/constants' import { Zero, MaxUint256 } from '@ethersproject/constants'
import { Contract } from '@ethersproject/contracts' import { Contract } from '@ethersproject/contracts'
import { WETH, TradeType, Pair, Trade, TokenAmount, JSBI, Percent, Fraction } from '@uniswap/sdk' import { Field, SwapAction, useSwapStateReducer } from './swap-store'
import { Text } from 'rebass'
import { Field, initializeSwapState, reducer, SwapAction } from './swap-store' import Card, { BlueCard, GreyCard, YellowCard } from '../../components/Card'
import { AutoColumn, ColumnCenter } from '../../components/Column'
import { AutoRow, RowBetween, RowFixed } from '../../components/Row'
import { ROUTER_ADDRESS } from '../../constants'
import { useAddressAllowance } from '../../contexts/Allowances'
import { useUserAdvanced } from '../../contexts/Application'
import { useAddressBalance, useAllBalances } from '../../contexts/Balances'
import { useDarkModeManager, useLocalStorageTokens } from '../../contexts/LocalStorage'
import { usePair } from '../../contexts/Pairs'
import { useAllTokens, useToken } from '../../contexts/Tokens'
import { usePendingApproval, useTransactionAdder } from '../../contexts/Transactions'
import { useTokenContract, useWeb3React } from '../../hooks'
import { useTradeExactIn, useTradeExactOut } from '../../hooks/Trades'
import { Hover, theme, TYPE } from '../../theme'
import { Link } from '../../theme/components'
import { calculateGasMargin, getEtherscanLink, getProviderOrSigner, getRouterContract, isWETH } from '../../utils'
import Copy from '../AccountDetails/Copy'
import AddressInputPanel from '../AddressInputPanel'
import { ButtonError, ButtonLight, ButtonPrimary } from '../Button'
import ConfirmationModal from '../ConfirmationModal'
import CurrencyInputPanel from '../CurrencyInputPanel'
import QuestionHelper from '../Question'
import SlippageTabs from '../SlippageTabs'
import TokenLogo from '../TokenLogo'
import { import {
AdvancedDropwdown, AdvancedDropwdown,
ArrowWrapper, ArrowWrapper,
...@@ -22,36 +47,8 @@ import { ...@@ -22,36 +47,8 @@ import {
TruncatedText, TruncatedText,
Wrapper Wrapper
} from './styleds' } from './styleds'
import Copy from '../AccountDetails/Copy'
import TokenLogo from '../TokenLogo'
import SlippageTabs from '../SlippageTabs'
import QuestionHelper from '../Question'
import AddressInputPanel from '../AddressInputPanel'
import ConfirmationModal from '../ConfirmationModal'
import CurrencyInputPanel from '../CurrencyInputPanel'
// import BalanceCard from '../BalanceCard'
import { Link } from '../../theme/components'
import { Text } from 'rebass'
import { theme, TYPE, Hover } from '../../theme'
import { AutoColumn, ColumnCenter } from '../../components/Column'
import { RowBetween, RowFixed, AutoRow } from '../../components/Row'
import { ArrowDown, ChevronDown, ChevronUp, Repeat } from 'react-feather'
import { ButtonPrimary, ButtonError, ButtonLight } from '../Button'
import Card, { GreyCard, BlueCard, YellowCard } from '../../components/Card'
import { usePair } from '../../contexts/Pairs' // import BalanceCard from '../BalanceCard'
import { useRoute } from '../../contexts/Routes'
import { useAddressAllowance } from '../../contexts/Allowances'
import { useToken, useAllTokens } from '../../contexts/Tokens'
import { useWeb3React, useTokenContract } from '../../hooks'
import { useAddressBalance, useAllBalances } from '../../contexts/Balances'
import { useTransactionAdder, usePendingApproval } from '../../contexts/Transactions'
import { useUserAdvanced } from '../../contexts/Application'
import { ROUTER_ADDRESS } from '../../constants'
import { getRouterContract, calculateGasMargin, getProviderOrSigner, getEtherscanLink, isWETH } from '../../utils'
import { useLocalStorageTokens } from '../../contexts/LocalStorage'
import { useDarkModeManager } from '../../contexts/LocalStorage'
function hex(value: JSBI) { function hex(value: JSBI) {
return BigNumber.from(value.toString()) return BigNumber.from(value.toString())
...@@ -79,7 +76,6 @@ const ALLOWED_SLIPPAGE_HIGH = 500 ...@@ -79,7 +76,6 @@ const ALLOWED_SLIPPAGE_HIGH = 500
function ExchangePage({ sendingInput = false, history, params }) { function ExchangePage({ sendingInput = false, history, params }) {
// text translation // text translation
// const { t } = useTranslation() // const { t } = useTranslation()
const { chainId, account, library } = useWeb3React() const { chainId, account, library } = useWeb3React()
// adding notifications on txns // adding notifications on txns
...@@ -92,33 +88,7 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -92,33 +88,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
const [ENS, setENS] = useState<string>('') const [ENS, setENS] = useState<string>('')
// trade details, check query params for initial state // trade details, check query params for initial state
const [state, dispatch] = useReducer( const [state, dispatch] = useSwapStateReducer(params)
reducer,
{
independentField: params.outputTokenAddress && !params.inputTokenAddress ? Field.OUTPUT : Field.INPUT,
inputTokenAddress: params.inputTokenAddress ? params.inputTokenAddress : WETH[chainId].address,
outputTokenAddress: params.outputTokenAddress ? params.outputTokenAddress : '',
typedValue:
params.inputTokenAddress && !params.outputTokenAddress
? params.inputTokenAmount
? params.inputTokenAmount
: ''
: !params.inputTokenAddress && params.outputTokenAddress
? params.outputTokenAmount
? params.outputTokenAmount
: ''
: params.inputTokenAddress && params.outputTokenAddress
? params.inputTokenAmount
? params.inputTokenAmount
: ''
: ''
? ''
: ''
? ''
: ''
},
initializeSwapState
)
const { independentField, typedValue, ...fieldData } = state const { independentField, typedValue, ...fieldData } = state
const dependentField: Field = independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT const dependentField: Field = independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT
...@@ -161,13 +131,6 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -161,13 +131,6 @@ function ExchangePage({ sendingInput = false, history, params }) {
// check on pending approvals for token amounts // check on pending approvals for token amounts
const pendingApprovalInput = usePendingApproval(tokens[Field.INPUT]?.address) const pendingApprovalInput = usePendingApproval(tokens[Field.INPUT]?.address)
// entities for swap
const pair: Pair = usePair(tokens[Field.INPUT], tokens[Field.OUTPUT])
const route = useRoute(tokens[Field.INPUT], tokens[Field.OUTPUT])
// check for invalid selection
const noRoute: boolean = !route && !!tokens[Field.INPUT] && !!tokens[Field.OUTPUT]
// modal and loading // modal and loading
const [showConfirm, setShowConfirm] = useState<boolean>(false) const [showConfirm, setShowConfirm] = useState<boolean>(false)
const [showAdvanced, setShowAdvanced] = useState<boolean>(false) const [showAdvanced, setShowAdvanced] = useState<boolean>(false)
...@@ -202,14 +165,16 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -202,14 +165,16 @@ function ExchangePage({ sendingInput = false, history, params }) {
} }
} }
// get trade const pair = usePair(tokens[Field.INPUT], tokens[Field.OUTPUT])
let trade: Trade let bestTradeExactIn = useTradeExactIn(tradeType === TradeType.EXACT_INPUT ? parsedAmounts[independentField] : null, tokens[Field.OUTPUT])
try { let bestTradeExactOut = useTradeExactOut(tokens[Field.INPUT], tradeType === TradeType.EXACT_OUTPUT ? parsedAmounts[independentField] : null)
trade =
!!route && !!parsedAmounts[independentField] const trade = tradeType === TradeType.EXACT_INPUT ? bestTradeExactIn : bestTradeExactOut
? new Trade(route, parsedAmounts[independentField], tradeType) const route = trade?.route
: undefined const userHasSpecifiedInputOutput = !!parsedAmounts[independentField] &&
} catch (error) {} parsedAmounts[independentField].greaterThan(JSBI.BigInt(0)) &&
!!tokens[Field.INPUT] && !!tokens[Field.OUTPUT]
const noRoute = !route
const slippageFromTrade: Percent = trade && trade.slippage const slippageFromTrade: Percent = trade && trade.slippage
...@@ -241,18 +206,18 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -241,18 +206,18 @@ function ExchangePage({ sendingInput = false, history, params }) {
type: SwapAction.SELECT_TOKEN, type: SwapAction.SELECT_TOKEN,
payload: { field, address } payload: { field, address }
}) })
}, []) }, [dispatch])
const onSwapTokens = useCallback(() => { const onSwapTokens = useCallback(() => {
dispatch({ dispatch({
type: SwapAction.SWITCH_TOKENS, type: SwapAction.SWITCH_TOKENS,
payload: undefined payload: undefined
}) })
}, []) }, [dispatch])
const onUserInput = useCallback((field: Field, typedValue: string) => { const onUserInput = useCallback((field: Field, typedValue: string) => {
dispatch({ type: SwapAction.TYPE, payload: { field, typedValue } }) dispatch({ type: SwapAction.TYPE, payload: { field, typedValue } })
}, []) }, [dispatch])
const onMaxInput = useCallback((typedValue: string) => { const onMaxInput = useCallback((typedValue: string) => {
dispatch({ dispatch({
...@@ -262,7 +227,7 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -262,7 +227,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
typedValue typedValue
} }
}) })
}, []) }, [dispatch])
const onMaxOutput = useCallback((typedValue: string) => { const onMaxOutput = useCallback((typedValue: string) => {
dispatch({ dispatch({
...@@ -272,7 +237,7 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -272,7 +237,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
typedValue typedValue
} }
}) })
}, []) }, [dispatch])
// reset field if sending with with swap is cancled // reset field if sending with with swap is cancled
useEffect(() => { useEffect(() => {
...@@ -295,7 +260,8 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -295,7 +260,8 @@ function ExchangePage({ sendingInput = false, history, params }) {
? userBalances[Field.INPUT].subtract(MIN_ETHER) ? userBalances[Field.INPUT].subtract(MIN_ETHER)
: userBalances[Field.INPUT] : userBalances[Field.INPUT]
: undefined : undefined
} catch {} } catch {
}
const atMaxAmountInput: boolean = const atMaxAmountInput: boolean =
!!maxAmountInput && !!parsedAmounts[Field.INPUT] !!maxAmountInput && !!parsedAmounts[Field.INPUT]
...@@ -340,7 +306,7 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -340,7 +306,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
return null return null
} }
const slippageAdjustedAmounts: { [field: number]: TokenAmount } = { const slippageAdjustedAmounts: { [field in Field]: TokenAmount } = {
[Field.INPUT]: [Field.INPUT]:
Field.INPUT === independentField Field.INPUT === independentField
? parsedAmounts[Field.INPUT] ? parsedAmounts[Field.INPUT]
...@@ -582,7 +548,6 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -582,7 +548,6 @@ function ExchangePage({ sendingInput = false, history, params }) {
if ( if (
parsedAmounts[Field.INPUT] && parsedAmounts[Field.INPUT] &&
pair &&
route && route &&
JSBI.greaterThan(parsedAmounts[Field.INPUT].raw, route.pairs[0].reserveOf(tokens[Field.INPUT]).raw) JSBI.greaterThan(parsedAmounts[Field.INPUT].raw, route.pairs[0].reserveOf(tokens[Field.INPUT]).raw)
) { ) {
...@@ -593,7 +558,6 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -593,7 +558,6 @@ function ExchangePage({ sendingInput = false, history, params }) {
if ( if (
!ignoreOutput && !ignoreOutput &&
parsedAmounts[Field.OUTPUT] && parsedAmounts[Field.OUTPUT] &&
pair &&
route && route &&
JSBI.greaterThan( JSBI.greaterThan(
parsedAmounts[Field.OUTPUT].raw, parsedAmounts[Field.OUTPUT].raw,
...@@ -631,11 +595,10 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -631,11 +595,10 @@ function ExchangePage({ sendingInput = false, history, params }) {
dependentField, dependentField,
ignoreOutput, ignoreOutput,
independentField, independentField,
pair,
parsedAmounts, parsedAmounts,
recipientError, recipientError,
route,
tokens, tokens,
route,
trade, trade,
userBalances userBalances
]) ])
...@@ -669,7 +632,7 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -669,7 +632,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
<Text fontSize={36} fontWeight={500}> <Text fontSize={36} fontWeight={500}>
{parsedAmounts[Field.INPUT]?.toSignificant(6)} {tokens[Field.INPUT]?.symbol} {parsedAmounts[Field.INPUT]?.toSignificant(6)} {tokens[Field.INPUT]?.symbol}
</Text> </Text>
<TokenLogo address={tokens[Field.INPUT]?.address} size={'30px'} /> <TokenLogo address={tokens[Field.INPUT]?.address} size={'30px'}/>
</RowBetween> </RowBetween>
<TYPE.darkGray fontSize={20}>To</TYPE.darkGray> <TYPE.darkGray fontSize={20}>To</TYPE.darkGray>
{ENS ? ( {ENS ? (
...@@ -681,7 +644,7 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -681,7 +644,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
{recipient?.slice(0, 8)}...{recipient?.slice(34, 42)} {recipient?.slice(0, 8)}...{recipient?.slice(34, 42)}
</TYPE.blue> </TYPE.blue>
</Link> </Link>
<Copy toCopy={recipient} /> <Copy toCopy={recipient}/>
</AutoRow> </AutoRow>
</AutoColumn> </AutoColumn>
) : ( ) : (
...@@ -691,7 +654,7 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -691,7 +654,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
{recipient?.slice(0, 6)}...{recipient?.slice(36, 42)} {recipient?.slice(0, 6)}...{recipient?.slice(36, 42)}
</TYPE.blue> </TYPE.blue>
</Link> </Link>
<Copy toCopy={recipient} /> <Copy toCopy={recipient}/>
</AutoRow> </AutoRow>
)} )}
</AutoColumn> </AutoColumn>
...@@ -703,7 +666,7 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -703,7 +666,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
<AutoColumn gap="lg" style={{ marginTop: '40px' }}> <AutoColumn gap="lg" style={{ marginTop: '40px' }}>
<AutoColumn gap="sm"> <AutoColumn gap="sm">
<AutoRow gap="10px"> <AutoRow gap="10px">
<TokenLogo address={tokens[Field.OUTPUT]?.address} size={'30px'} /> <TokenLogo address={tokens[Field.OUTPUT]?.address} size={'30px'}/>
<Text fontSize={36} fontWeight={500}> <Text fontSize={36} fontWeight={500}>
{slippageAdjustedAmounts[Field.OUTPUT]?.toSignificant(4)} {tokens[Field.OUTPUT]?.symbol} {slippageAdjustedAmounts[Field.OUTPUT]?.toSignificant(4)} {tokens[Field.OUTPUT]?.symbol}
</Text> </Text>
...@@ -731,14 +694,14 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -731,14 +694,14 @@ function ExchangePage({ sendingInput = false, history, params }) {
{/* {!!slippageAdjustedAmounts[Field.INPUT] && slippageAdjustedAmounts[Field.INPUT].toSignificant(6)} */} {/* {!!slippageAdjustedAmounts[Field.INPUT] && slippageAdjustedAmounts[Field.INPUT].toSignificant(6)} */}
</TruncatedText> </TruncatedText>
<RowFixed gap="4px"> <RowFixed gap="4px">
<TokenLogo address={tokens[Field.INPUT]?.address} size={'24px'} /> <TokenLogo address={tokens[Field.INPUT]?.address} size={'24px'}/>
<Text fontSize={24} fontWeight={500} style={{ marginLeft: '10px' }}> <Text fontSize={24} fontWeight={500} style={{ marginLeft: '10px' }}>
{tokens[Field.INPUT]?.symbol || ''} {tokens[Field.INPUT]?.symbol || ''}
</Text> </Text>
</RowFixed> </RowFixed>
</RowBetween> </RowBetween>
<RowFixed> <RowFixed>
<ArrowDown size="16" color={theme(isDark).text2} /> <ArrowDown size="16" color={theme(isDark).text2}/>
</RowFixed> </RowFixed>
<RowBetween align="flex-end"> <RowBetween align="flex-end">
<TruncatedText fontSize={24} fontWeight={500} color={warningHigh ? theme(isDark).red1 : ''}> <TruncatedText fontSize={24} fontWeight={500} color={warningHigh ? theme(isDark).red1 : ''}>
...@@ -747,7 +710,7 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -747,7 +710,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
{/* {!!slippageAdjustedAmounts[Field.OUTPUT] && slippageAdjustedAmounts[Field.OUTPUT].toSignificant(6)} */} {/* {!!slippageAdjustedAmounts[Field.OUTPUT] && slippageAdjustedAmounts[Field.OUTPUT].toSignificant(6)} */}
</TruncatedText> </TruncatedText>
<RowFixed gap="4px"> <RowFixed gap="4px">
<TokenLogo address={tokens[Field.OUTPUT]?.address} size={'24px'} /> <TokenLogo address={tokens[Field.OUTPUT]?.address} size={'24px'}/>
<Text fontSize={24} fontWeight={500} style={{ marginLeft: '10px' }}> <Text fontSize={24} fontWeight={500} style={{ marginLeft: '10px' }}>
{tokens[Field.OUTPUT]?.symbol || ''} {tokens[Field.OUTPUT]?.symbol || ''}
</Text> </Text>
...@@ -805,19 +768,19 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -805,19 +768,19 @@ function ExchangePage({ sendingInput = false, history, params }) {
color={theme(isDark).text2} color={theme(isDark).text2}
style={{ justifyContent: 'center', alignItems: 'center', display: 'flex' }} style={{ justifyContent: 'center', alignItems: 'center', display: 'flex' }}
> >
{pair && showInverted {trade && showInverted
? route.midPrice.invert().toSignificant(6) + ? (trade?.executionPrice?.invert()?.toSignificant(6) ?? '') +
' ' + ' ' +
tokens[Field.INPUT]?.symbol + tokens[Field.INPUT]?.symbol +
' / ' + ' / ' +
tokens[Field.OUTPUT]?.symbol tokens[Field.OUTPUT]?.symbol
: route.midPrice.toSignificant(6) + : (trade?.executionPrice?.toSignificant(6) ?? '') +
' ' + ' ' +
tokens[Field.OUTPUT]?.symbol + tokens[Field.OUTPUT]?.symbol +
' / ' + ' / ' +
tokens[Field.INPUT]?.symbol} tokens[Field.INPUT]?.symbol}
<StyledBalanceMaxMini onClick={() => setShowInverted(!showInverted)}> <StyledBalanceMaxMini onClick={() => setShowInverted(!showInverted)}>
<Repeat size={14} /> <Repeat size={14}/>
</StyledBalanceMaxMini> </StyledBalanceMaxMini>
</Text> </Text>
</RowBetween> </RowBetween>
...@@ -827,7 +790,8 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -827,7 +790,8 @@ function ExchangePage({ sendingInput = false, history, params }) {
<TYPE.black fontSize={14} fontWeight={400}> <TYPE.black fontSize={14} fontWeight={400}>
{independentField === Field.INPUT ? (sending ? 'Min sent' : 'Minimum received') : 'Maximum sold'} {independentField === Field.INPUT ? (sending ? 'Min sent' : 'Minimum received') : 'Maximum sold'}
</TYPE.black> </TYPE.black>
<QuestionHelper text="A boundary is set so you are protected from large price movements after you submit your trade." /> <QuestionHelper
text="A boundary is set so you are protected from large price movements after you submit your trade."/>
</RowFixed> </RowFixed>
<RowFixed> <RowFixed>
<TYPE.black fontSize={14}> <TYPE.black fontSize={14}>
...@@ -857,7 +821,7 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -857,7 +821,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
<TYPE.black color={theme(isDark).text1} fontSize={14} fontWeight={400}> <TYPE.black color={theme(isDark).text1} fontSize={14} fontWeight={400}>
Price impact Price impact
</TYPE.black> </TYPE.black>
<QuestionHelper text="The difference between the market price and your price due to trade size." /> <QuestionHelper text="The difference between the market price and your price due to trade size."/>
</RowFixed> </RowFixed>
<ErrorText <ErrorText
fontWeight={500} fontWeight={500}
...@@ -878,7 +842,8 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -878,7 +842,8 @@ function ExchangePage({ sendingInput = false, history, params }) {
<TYPE.black fontSize={14} fontWeight={400}> <TYPE.black fontSize={14} fontWeight={400}>
Liquidity Provider Fee Liquidity Provider Fee
</TYPE.black> </TYPE.black>
<QuestionHelper text="A portion of each trade (0.3%) goes to liquidity providers to incentivize liquidity on the protocol." /> <QuestionHelper
text="A portion of each trade (0.3%) goes to liquidity providers to incentivize liquidity on the protocol."/>
</RowFixed> </RowFixed>
<TYPE.black fontSize={14}> <TYPE.black fontSize={14}>
{feeTimesInputFormatted {feeTimesInputFormatted
...@@ -900,12 +865,12 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -900,12 +865,12 @@ function ExchangePage({ sendingInput = false, history, params }) {
} }
} }
const PriceBar = function() { const PriceBar = function () {
return ( return (
<AutoRow justify="space-between"> <AutoRow justify="space-between">
<AutoColumn justify="center"> <AutoColumn justify="center">
<Text fontWeight={500} fontSize={16} color={theme(isDark).text2}> <Text fontWeight={500} fontSize={16} color={theme(isDark).text2}>
{pair ? `${route.midPrice.toSignificant(6)} ` : '-'} {trade ? `${trade.executionPrice.toSignificant(6)} ` : '-'}
</Text> </Text>
<Text fontWeight={500} fontSize={16} color={theme(isDark).text3} pt={1}> <Text fontWeight={500} fontSize={16} color={theme(isDark).text3} pt={1}>
{tokens[Field.OUTPUT]?.symbol} / {tokens[Field.INPUT]?.symbol} {tokens[Field.OUTPUT]?.symbol} / {tokens[Field.INPUT]?.symbol}
...@@ -913,7 +878,7 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -913,7 +878,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
</AutoColumn> </AutoColumn>
<AutoColumn justify="center"> <AutoColumn justify="center">
<Text fontWeight={500} fontSize={16} color={theme(isDark).text2}> <Text fontWeight={500} fontSize={16} color={theme(isDark).text2}>
{pair ? `${route.midPrice.invert().toSignificant(6)} ` : '-'} {trade ? `${trade.executionPrice.invert().toSignificant(6)} ` : '-'}
</Text> </Text>
<Text fontWeight={500} fontSize={16} color={theme(isDark).text3} pt={1}> <Text fontWeight={500} fontSize={16} color={theme(isDark).text3} pt={1}>
{tokens[Field.INPUT]?.symbol} / {tokens[Field.OUTPUT]?.symbol} {tokens[Field.INPUT]?.symbol} / {tokens[Field.OUTPUT]?.symbol}
...@@ -1002,7 +967,7 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -1002,7 +967,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
Max Max
</MaxButton> </MaxButton>
)} )}
<StyledNumerical value={formattedAmounts[Field.INPUT]} onUserInput={val => onUserInput(Field.INPUT, val)} /> <StyledNumerical value={formattedAmounts[Field.INPUT]} onUserInput={val => onUserInput(Field.INPUT, val)}/>
<CurrencyInputPanel <CurrencyInputPanel
field={Field.INPUT} field={Field.INPUT}
value={formattedAmounts[Field.INPUT]} value={formattedAmounts[Field.INPUT]}
...@@ -1048,7 +1013,7 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -1048,7 +1013,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
<ColumnCenter> <ColumnCenter>
<RowBetween padding="0 12px"> <RowBetween padding="0 12px">
<ArrowWrapper onClick={onSwapTokens}> <ArrowWrapper onClick={onSwapTokens}>
<ArrowDown size="16" color={theme(isDark).text2} onClick={onSwapTokens} /> <ArrowDown size="16" color={theme(isDark).text2} onClick={onSwapTokens}/>
</ArrowWrapper> </ArrowWrapper>
<StyledBalanceMaxMini onClick={() => setSendingWithSwap(false)} style={{ marginRight: '0px' }}> <StyledBalanceMaxMini onClick={() => setSendingWithSwap(false)} style={{ marginRight: '0px' }}>
<TYPE.blue>Remove Swap</TYPE.blue> <TYPE.blue>Remove Swap</TYPE.blue>
...@@ -1086,7 +1051,7 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -1086,7 +1051,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
/> />
{sendingWithSwap && ( {sendingWithSwap && (
<RowBetween padding="0 12px"> <RowBetween padding="0 12px">
<ArrowDown size="16" /> <ArrowDown size="16"/>
</RowBetween> </RowBetween>
)} )}
</> </>
...@@ -1118,7 +1083,7 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -1118,7 +1083,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
{!noRoute && tokens[Field.OUTPUT] && tokens[Field.INPUT] && ( {!noRoute && tokens[Field.OUTPUT] && tokens[Field.INPUT] && (
<Card padding={advanced ? '.25rem 1.25rem 0 .75rem' : '.25rem .7rem .25rem 1.25rem'} borderRadius={'20px'}> <Card padding={advanced ? '.25rem 1.25rem 0 .75rem' : '.25rem .7rem .25rem 1.25rem'} borderRadius={'20px'}>
{advanced ? ( {advanced ? (
<PriceBar /> <PriceBar/>
) : ( ) : (
<AutoColumn gap="4px"> <AutoColumn gap="4px">
{' '} {' '}
...@@ -1132,23 +1097,23 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -1132,23 +1097,23 @@ function ExchangePage({ sendingInput = false, history, params }) {
color={theme(isDark).text2} color={theme(isDark).text2}
style={{ justifyContent: 'center', alignItems: 'center', display: 'flex' }} style={{ justifyContent: 'center', alignItems: 'center', display: 'flex' }}
> >
{pair && showInverted {trade && showInverted
? route.midPrice.invert().toSignificant(6) + ? (trade?.executionPrice?.invert()?.toSignificant(6) ?? '') +
' ' + ' ' +
tokens[Field.INPUT]?.symbol + tokens[Field.INPUT]?.symbol +
' per ' + ' per ' +
tokens[Field.OUTPUT]?.symbol tokens[Field.OUTPUT]?.symbol
: route.midPrice.toSignificant(6) + : (trade?.executionPrice?.toSignificant(6) ?? '') +
' ' + ' ' +
tokens[Field.OUTPUT]?.symbol + tokens[Field.OUTPUT]?.symbol +
' per ' + ' per ' +
tokens[Field.INPUT]?.symbol} tokens[Field.INPUT]?.symbol}
<StyledBalanceMaxMini onClick={() => setShowInverted(!showInverted)}> <StyledBalanceMaxMini onClick={() => setShowInverted(!showInverted)}>
<Repeat size={14} /> <Repeat size={14}/>
</StyledBalanceMaxMini> </StyledBalanceMaxMini>
</Text> </Text>
</RowBetween> </RowBetween>
{pair && (warningHigh || warningMedium) && ( {trade && (warningHigh || warningMedium) && (
<RowBetween> <RowBetween>
<TYPE.main <TYPE.main
style={{ justifyContent: 'center', alignItems: 'center', display: 'flex' }} style={{ justifyContent: 'center', alignItems: 'center', display: 'flex' }}
...@@ -1164,7 +1129,8 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -1164,7 +1129,8 @@ function ExchangePage({ sendingInput = false, history, params }) {
: priceSlippage.toFixed(4) + '%' : priceSlippage.toFixed(4) + '%'
: '-'}{' '} : '-'}{' '}
</ErrorText> </ErrorText>
<QuestionHelper text="The difference between the market price and your quoted price due to trade size." /> <QuestionHelper
text="The difference between the market price and your quoted price due to trade size."/>
</RowFixed> </RowFixed>
</RowBetween> </RowBetween>
)} )}
...@@ -1174,7 +1140,7 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -1174,7 +1140,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
)} )}
</AutoColumn> </AutoColumn>
<BottomGrouping> <BottomGrouping>
{noRoute ? ( {noRoute && userHasSpecifiedInputOutput ? (
<GreyCard style={{ textAlign: 'center' }}> <GreyCard style={{ textAlign: 'center' }}>
<TYPE.main>No path found.</TYPE.main> <TYPE.main>No path found.</TYPE.main>
...@@ -1240,7 +1206,7 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -1240,7 +1206,7 @@ function ExchangePage({ sendingInput = false, history, params }) {
<Text fontSize={16} fontWeight={500} style={{ userSelect: 'none' }}> <Text fontSize={16} fontWeight={500} style={{ userSelect: 'none' }}>
Show Advanced Show Advanced
</Text> </Text>
<ChevronDown color={theme(isDark).text2} /> <ChevronDown color={theme(isDark).text2}/>
</RowBetween> </RowBetween>
</Hover> </Hover>
)} )}
...@@ -1251,10 +1217,10 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -1251,10 +1217,10 @@ function ExchangePage({ sendingInput = false, history, params }) {
<Text fontSize={16} color={theme(isDark).text2} fontWeight={500} style={{ userSelect: 'none' }}> <Text fontSize={16} color={theme(isDark).text2} fontWeight={500} style={{ userSelect: 'none' }}>
Hide Advanced Hide Advanced
</Text> </Text>
<ChevronUp color={theme(isDark).text2} /> <ChevronUp color={theme(isDark).text2}/>
</RowBetween> </RowBetween>
</Hover> </Hover>
<SectionBreak /> <SectionBreak/>
<AutoColumn style={{ padding: '0 20px' }}> <AutoColumn style={{ padding: '0 20px' }}>
<RowBetween> <RowBetween>
<RowFixed> <RowFixed>
...@@ -1307,7 +1273,8 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -1307,7 +1273,8 @@ function ExchangePage({ sendingInput = false, history, params }) {
<TYPE.black fontSize={14} fontWeight={400} color={theme(isDark).text1}> <TYPE.black fontSize={14} fontWeight={400} color={theme(isDark).text1}>
Price Impact Price Impact
</TYPE.black> </TYPE.black>
<QuestionHelper text="The difference between the market price and your quoted price due to trade size." /> <QuestionHelper
text="The difference between the market price and your quoted price due to trade size."/>
</RowFixed> </RowFixed>
<ErrorText <ErrorText
fontWeight={500} fontWeight={500}
...@@ -1328,7 +1295,8 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -1328,7 +1295,8 @@ function ExchangePage({ sendingInput = false, history, params }) {
<TYPE.black fontSize={14} fontWeight={400} color={theme(isDark).text1}> <TYPE.black fontSize={14} fontWeight={400} color={theme(isDark).text1}>
Liquidity Provider Fee Liquidity Provider Fee
</TYPE.black> </TYPE.black>
<QuestionHelper text="A portion of each trade (0.03%) goes to liquidity providers to incentivize liquidity on the protocol." /> <QuestionHelper
text="A portion of each trade (0.03%) goes to liquidity providers to incentivize liquidity on the protocol."/>
</RowFixed> </RowFixed>
<TYPE.black fontSize={14} color={theme(isDark).text1}> <TYPE.black fontSize={14} color={theme(isDark).text1}>
{feeTimesInputFormatted {feeTimesInputFormatted
...@@ -1337,12 +1305,13 @@ function ExchangePage({ sendingInput = false, history, params }) { ...@@ -1337,12 +1305,13 @@ function ExchangePage({ sendingInput = false, history, params }) {
</TYPE.black> </TYPE.black>
</RowBetween> </RowBetween>
</AutoColumn> </AutoColumn>
<SectionBreak /> <SectionBreak/>
<RowFixed padding={'0 20px'}> <RowFixed padding={'0 20px'}>
<TYPE.black fontWeight={400} fontSize={14} color={theme(isDark).text1}> <TYPE.black fontWeight={400} fontSize={14} color={theme(isDark).text1}>
Set front running resistance Set front running resistance
</TYPE.black> </TYPE.black>
<QuestionHelper text="Your transaction will revert if the price changes more than this amount after you submit your trade." /> <QuestionHelper
text="Your transaction will revert if the price changes more than this amount after you submit your trade."/>
</RowFixed> </RowFixed>
<SlippageTabs <SlippageTabs
rawSlippage={allowedSlippage} rawSlippage={allowedSlippage}
......
import { WETH } from '@uniswap/sdk'
import { useReducer } from 'react'
import { useWeb3React } from '../../hooks'
import { QueryParams } from '../../utils'
export enum Field { export enum Field {
INPUT, INPUT,
OUTPUT OUTPUT
...@@ -93,3 +98,34 @@ export function reducer( ...@@ -93,3 +98,34 @@ export function reducer(
} }
} }
} }
export function useSwapStateReducer(params: QueryParams) {
const { chainId } = useWeb3React()
return useReducer(
reducer,
{
independentField: params.outputTokenAddress && !params.inputTokenAddress ? Field.OUTPUT : Field.INPUT,
inputTokenAddress: params.inputTokenAddress ? params.inputTokenAddress : WETH[chainId].address,
outputTokenAddress: params.outputTokenAddress ? params.outputTokenAddress : '',
typedValue:
params.inputTokenAddress && !params.outputTokenAddress
? params.inputTokenAmount
? params.inputTokenAmount
: ''
: !params.inputTokenAddress && params.outputTokenAddress
? params.outputTokenAmount
? params.outputTokenAmount
: ''
: params.inputTokenAddress && params.outputTokenAddress
? params.inputTokenAmount
? params.inputTokenAmount
: ''
: ''
? ''
: ''
? ''
: ''
},
initializeSwapState
)
}
...@@ -16,13 +16,29 @@ const ADD_POPUP = 'ADD_POPUP' ...@@ -16,13 +16,29 @@ const ADD_POPUP = 'ADD_POPUP'
const USER_ADVANCED = 'USER_ADVANCED' const USER_ADVANCED = 'USER_ADVANCED'
const TOGGLE_USER_ADVANCED = 'TOGGLE_USER_ADVANCED' const TOGGLE_USER_ADVANCED = 'TOGGLE_USER_ADVANCED'
const ApplicationContext = createContext() interface ApplicationState {
BLOCK_NUMBER: {},
USD_PRICE: {},
POPUP_LIST: Array<{ key: number; show: boolean; content: React.ReactElement }>,
POPUP_KEY: number,
WALLET_MODAL_OPEN: boolean,
USER_ADVANCED: boolean
}
const ApplicationContext = createContext<[ApplicationState, { [updater: string]: (...args: any[]) => void }]>([{
[BLOCK_NUMBER]: {},
[USD_PRICE]: {},
[POPUP_LIST]: [],
[POPUP_KEY]: 0,
[WALLET_MODAL_OPEN]: false,
[USER_ADVANCED]: false
}, {}])
function useApplicationContext() { function useApplicationContext() {
return useContext(ApplicationContext) return useContext(ApplicationContext)
} }
function reducer(state, { type, payload }) { function reducer(state: ApplicationState, { type, payload }): ApplicationState {
switch (type) { switch (type) {
case UPDATE_BLOCK_NUMBER: { case UPDATE_BLOCK_NUMBER: {
const { networkId, blockNumber } = payload const { networkId, blockNumber } = payload
...@@ -66,19 +82,19 @@ export default function Provider({ children }) { ...@@ -66,19 +82,19 @@ export default function Provider({ children }) {
const updateBlockNumber = useCallback((networkId, blockNumber) => { const updateBlockNumber = useCallback((networkId, blockNumber) => {
dispatch({ type: UPDATE_BLOCK_NUMBER, payload: { networkId, blockNumber } }) dispatch({ type: UPDATE_BLOCK_NUMBER, payload: { networkId, blockNumber } })
}, []) }, [dispatch])
const toggleWalletModal = useCallback(() => { const toggleWalletModal = useCallback(() => {
dispatch({ type: TOGGLE_WALLET_MODAL }) dispatch({ type: TOGGLE_WALLET_MODAL, payload: null })
}, []) }, [dispatch])
const toggleUserAdvanced = useCallback(() => { const toggleUserAdvanced = useCallback(() => {
dispatch({ type: TOGGLE_USER_ADVANCED }) dispatch({ type: TOGGLE_USER_ADVANCED, payload: null })
}, []) }, [dispatch])
const setPopups = useCallback(newList => { const setPopups = useCallback(newList => {
dispatch({ type: ADD_POPUP, payload: { newList } }) dispatch({ type: ADD_POPUP, payload: { newList } })
}, []) }, [dispatch])
return ( return (
<ApplicationContext.Provider <ApplicationContext.Provider
...@@ -105,7 +121,7 @@ export function Updater() { ...@@ -105,7 +121,7 @@ export function Updater() {
if (library) { if (library) {
let stale = false let stale = false
function update() { const update = () => {
library library
.getBlockNumber() .getBlockNumber()
.then(blockNumber => { .then(blockNumber => {
...@@ -164,13 +180,13 @@ export function useToggleUserAdvanced() { ...@@ -164,13 +180,13 @@ export function useToggleUserAdvanced() {
return toggleUserAdvanced return toggleUserAdvanced
} }
export function usePopups() { export function usePopups(): [ApplicationState['POPUP_LIST'], (content: React.ReactElement) => void, (key: number) => void] {
const [state, { setPopups }] = useApplicationContext() const [state, { setPopups }] = useApplicationContext()
const index = state[POPUP_KEY] const index = state[POPUP_KEY]
const currentPopups = state[POPUP_LIST] const currentPopups = state[POPUP_LIST]
function addPopup(content) { function addPopup(content: React.ReactElement): void {
const newItem = { const newItem = {
show: true, show: true,
key: index, key: index,
...@@ -180,7 +196,7 @@ export function usePopups() { ...@@ -180,7 +196,7 @@ export function usePopups() {
setPopups(currentPopups) setPopups(currentPopups)
} }
function removePopup(key) { function removePopup(key: number): void {
currentPopups.map(item => { currentPopups.map(item => {
if (key === item.key) { if (key === item.key) {
item.show = false item.show = false
......
import React, { createContext, useContext, useReducer, useMemo, useCallback, useEffect } from 'react'
import { WETH, Token, Route, JSBI } from '@uniswap/sdk'
import { useWeb3React } from '../hooks'
import { usePair } from '../contexts/Pairs'
import { isWETH } from '../utils'
const UPDATE = 'UPDATE'
interface RouteState {
[chainId: number]: {
[tokenAddress: string]: {
[tokenAddress: string]: {
route: Route
}
}
}
}
const RouteContext = createContext<[RouteState, { [k: string]: (...args: any) => void }]>([{}, {}])
function useRouteContext() {
return useContext(RouteContext)
}
function reducer(state: RouteState, { type, payload }) {
switch (type) {
case UPDATE: {
const { tokens, route, chainId } = payload
return {
...state,
[chainId]: {
...state[chainId],
[tokens[0]]: {
...state[chainId]?.[tokens[0]],
[tokens[1]]: {
route
}
}
}
}
}
default: {
throw Error(`Unexpected action type in ExchangesContext reducer: '${type}'.`)
}
}
}
export default function Provider({ children }) {
const [state, dispatch] = useReducer(reducer, {})
const update = useCallback((tokens, route, chainId) => {
dispatch({ type: UPDATE, payload: { tokens, route, chainId } })
}, [])
return (
<RouteContext.Provider value={useMemo(() => [state, { update }], [state, update])}>
{children}
</RouteContext.Provider>
)
}
/**
* @param tokenA input to token to be sold
* @param tokenB output token to be bought
*
* This hook finds either a direct pair between tokenA and tokenB or,
* a one-hop route that goes through token<->WETH pairs
*
* if neither exists returns null
*/
export function useRoute(tokenA: Token, tokenB: Token) {
const [state, { update }] = useRouteContext()
const { chainId } = useWeb3React()
let route: Route = state?.[chainId]?.[tokenA?.address]?.[tokenB?.address]?.route
// check for direct pair between tokens
const defaultPair = usePair(tokenA, tokenB)
// get token<->WETH pairs
const aToETH = usePair(tokenA && !isWETH(tokenA) ? tokenA : null, WETH[chainId])
const bToETH = usePair(tokenB && !isWETH(tokenB) ? tokenB : null, WETH[chainId])
// needs to route through WETH
const requiresHop =
defaultPair &&
JSBI.equal(defaultPair?.reserve0?.raw, JSBI.BigInt(0)) &&
JSBI.equal(defaultPair?.reserve1?.raw, JSBI.BigInt(0))
useEffect(() => {
if (!route && tokenA && tokenB) {
if (!requiresHop && defaultPair) {
update([tokenA.address, tokenB.address], new Route([defaultPair], tokenA), chainId)
}
if (
requiresHop &&
aToETH &&
bToETH &&
// check there is liquidity in both token<->ETH pairs
JSBI.notEqual(JSBI.BigInt(0), aToETH.reserve0.raw) &&
JSBI.notEqual(JSBI.BigInt(0), bToETH.reserve0.raw)
) {
const routeThroughETH = new Route([aToETH, bToETH], tokenA)
update([tokenA.address, tokenB.address], routeThroughETH, chainId)
}
}
}, [route, requiresHop, update, chainId, tokenA, tokenB, defaultPair, aToETH, bToETH])
return useMemo(() => route, [route])
}
...@@ -16,7 +16,11 @@ const ADD = 'ADD' ...@@ -16,7 +16,11 @@ const ADD = 'ADD'
const CHECK = 'CHECK' const CHECK = 'CHECK'
const FINALIZE = 'FINALIZE' const FINALIZE = 'FINALIZE'
const TransactionsContext = createContext() interface TransactionState {
}
const TransactionsContext = createContext<[TransactionState, { [updater: string]: (...args: any[]) => void }]>([{}, {}])
export function useTransactionsContext() { export function useTransactionsContext() {
return useContext(TransactionsContext) return useContext(TransactionsContext)
...@@ -134,10 +138,12 @@ export function Updater() { ...@@ -134,10 +138,12 @@ export function Updater() {
finalize(chainId, hash, receipt) finalize(chainId, hash, receipt)
// add success or failure popup // add success or failure popup
if (receipt.status === 1) { if (receipt.status === 1) {
addPopup(<TxnPopup hash={hash} success={true} summary={allTransactions[hash]?.response?.summary} />) addPopup(<TxnPopup popKey={1} hash={hash} success={true}
summary={allTransactions[hash]?.response?.summary}/>)
} else { } else {
addPopup( addPopup(
<TxnPopup hash={hash} success={false} summary={allTransactions[hash]?.response?.summary} /> <TxnPopup popKey={2} hash={hash} success={false}
summary={allTransactions[hash]?.response?.summary}/>
) )
} }
} }
......
import { useMemo } from 'react'
import { WETH, Token, TokenAmount, Trade } from '@uniswap/sdk'
import { useWeb3React } from './index'
import { usePair } from '../contexts/Pairs'
import { isWETH } from '../utils'
/**
* Returns the best trade for the exact amount of tokens in to the given token out
*/
export function useTradeExactIn(amountIn?: TokenAmount, tokenOut?: Token): Trade | null {
const { chainId } = useWeb3React()
// check for direct pair between tokens
const pairBetween = usePair(amountIn?.token, tokenOut)
// get token<->WETH pairs
const aToETH = usePair(amountIn && !isWETH(amountIn.token) ? amountIn.token : null, WETH[chainId])
const bToETH = usePair(tokenOut && !isWETH(tokenOut) ? tokenOut : null, WETH[chainId])
return useMemo(() => {
const allPairs = [pairBetween, aToETH, bToETH].filter(p => !!p)
if (amountIn && allPairs.length > 0 && tokenOut) {
return Trade.bestTradeExactIn(allPairs, amountIn, tokenOut)[0] ?? null
}
return null
}, [aToETH, bToETH, pairBetween, amountIn, tokenOut])
}
/**
* Returns the best trade for the token in to the exact amount of token out
*/
export function useTradeExactOut(tokenIn?: Token, amountOut?: TokenAmount): Trade | null {
const { chainId } = useWeb3React()
// check for direct pair between tokens
const pairBetween = usePair(amountOut?.token, tokenIn)
// get token<->WETH pairs
const aToETH = usePair(amountOut && !isWETH(amountOut.token) ? amountOut.token : null, WETH[chainId])
const bToETH = usePair(tokenIn && !isWETH(tokenIn) ? tokenIn : null, WETH[chainId])
return useMemo(() => {
const allPairs = [pairBetween, aToETH, bToETH].filter(p => !!p)
if (amountOut && allPairs.length > 0 && tokenIn) {
return Trade.bestTradeExactOut(allPairs, tokenIn, amountOut)[0] ?? null
}
return null
}, [pairBetween, aToETH, bToETH, amountOut, tokenIn])
}
...@@ -12,7 +12,6 @@ import TransactionContextProvider, { Updater as TransactionContextUpdater } from ...@@ -12,7 +12,6 @@ import TransactionContextProvider, { Updater as TransactionContextUpdater } from
import BalancesContextProvider, { Updater as BalancesContextUpdater } from './contexts/Balances' import BalancesContextProvider, { Updater as BalancesContextUpdater } from './contexts/Balances'
import ExchangesContextProvider from './contexts/Pairs' import ExchangesContextProvider from './contexts/Pairs'
import AllowancesContextProvider from './contexts/Allowances' import AllowancesContextProvider from './contexts/Allowances'
import RoutesContextProvider from './contexts/Routes'
import App from './pages/App' import App from './pages/App'
import ThemeProvider, { GlobalStyle } from './theme' import ThemeProvider, { GlobalStyle } from './theme'
import './i18n' import './i18n'
...@@ -42,11 +41,9 @@ function ContextProviders({ children }) { ...@@ -42,11 +41,9 @@ function ContextProviders({ children }) {
<ApplicationContextProvider> <ApplicationContextProvider>
<TransactionContextProvider> <TransactionContextProvider>
<ExchangesContextProvider> <ExchangesContextProvider>
<RoutesContextProvider>
<BalancesContextProvider> <BalancesContextProvider>
<AllowancesContextProvider>{children}</AllowancesContextProvider> <AllowancesContextProvider>{children}</AllowancesContextProvider>
</BalancesContextProvider> </BalancesContextProvider>
</RoutesContextProvider>
</ExchangesContextProvider> </ExchangesContextProvider>
</TransactionContextProvider> </TransactionContextProvider>
</ApplicationContextProvider> </ApplicationContextProvider>
......
...@@ -69,7 +69,7 @@ function parseUrlTokenAmount(paramName: string): string { ...@@ -69,7 +69,7 @@ function parseUrlTokenAmount(paramName: string): string {
return value return value
} }
interface QueryParams { export interface QueryParams {
readonly inputTokenAddress: string readonly inputTokenAddress: string
readonly outputTokenAddress: string readonly outputTokenAddress: string
readonly inputTokenAmount: string readonly inputTokenAmount: string
......
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