Commit e311e2fc authored by Noah Zinsmeister's avatar Noah Zinsmeister Committed by GitHub

mainnet (#782)

* mainnet config

* fix token + pair sorting

* standardize wrapped useWeb3React imports

* add final return to pair sorting

* add connecting pairs

* break tokens out into separate files

revert isAddress change

* filter out duplicate pairs

* remove add liquidity prompts

* link to v1 trades that are invalid on v2

* forward v2 subdomain to apex

* update blog link

* get rid of smart quotes

* link to uniswap info in position card

* improve pair sorting/searching

break out token identification

fix crash on early pool position clicks

change pair token separator from : to /
parent 9c4f63f4
...@@ -7,6 +7,12 @@ ...@@ -7,6 +7,12 @@
conditions = {Country=["BY","CU","IR","IQ","CI","LR","KP","SD","SY","ZW"]} conditions = {Country=["BY","CU","IR","IQ","CI","LR","KP","SD","SY","ZW"]}
headers = {Link="<https://uniswap.exchange>"} headers = {Link="<https://uniswap.exchange>"}
# forward v2 subdomain to apex
[[redirects]]
from = "https://v2.uniswap.exchange/*"
to = "https://uniswap.exchange/:splat"
status = 301
# support SPA setup # support SPA setup
[[redirects]] [[redirects]]
from = "/*" from = "/*"
......
...@@ -158,15 +158,15 @@ export default function Header() { ...@@ -158,15 +158,15 @@ export default function Header() {
return ( return (
<HeaderFrame> <HeaderFrame>
<MigrateBanner> <MigrateBanner>
{/* <b>Uniswap V2 is live.&nbsp;</b> Move your liquidity now using the&nbsp; */} Uniswap V2 is live! Read the&nbsp;
<b>Testnet only.</b>&nbsp;Uniswap V2 has not been launched and is coming soon.&nbsp;Read the&nbsp; <Link href="https://uniswap.org/blog/launch-uniswap-v2/">
{/* <Link href="https://migrate.uniswap.exchange/">
<b>migration helper</b>
</Link>
&nbsp;or read the&nbsp; */}
<Link href="https://uniswap.org/blog/uniswap-v2/">
<b>blog post ↗</b> <b>blog post ↗</b>
</Link> </Link>
&nbsp;or&nbsp;
<Link href="https://migrate.uniswap.exchange/">
<b>migrate your liquidity ↗</b>
</Link>
.
</MigrateBanner> </MigrateBanner>
<RowBetween padding="1rem"> <RowBetween padding="1rem">
<HeaderElement> <HeaderElement>
......
...@@ -15,7 +15,7 @@ import { AutoColumn, ColumnCenter } from '../Column' ...@@ -15,7 +15,7 @@ import { AutoColumn, ColumnCenter } from '../Column'
import { ButtonPrimary, ButtonDropwdown, ButtonDropwdownLight } from '../Button' import { ButtonPrimary, ButtonDropwdown, ButtonDropwdownLight } from '../Button'
import { useToken } from '../../hooks/Tokens' import { useToken } from '../../hooks/Tokens'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '../../hooks'
import { usePairAdder } from '../../state/user/hooks' import { usePairAdder } from '../../state/user/hooks'
import { usePair } from '../../data/Reserves' import { usePair } from '../../data/Reserves'
......
...@@ -4,7 +4,7 @@ import { darken } from 'polished' ...@@ -4,7 +4,7 @@ import { darken } from 'polished'
import { RouteComponentProps, withRouter } from 'react-router-dom' import { RouteComponentProps, withRouter } from 'react-router-dom'
import { Percent, Pair, JSBI } from '@uniswap/sdk' import { Percent, Pair, JSBI } from '@uniswap/sdk'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '../../hooks'
import { useTotalSupply } from '../../data/TotalSupply' import { useTotalSupply } from '../../data/TotalSupply'
import { useTokenBalance } from '../../state/wallet/hooks' import { useTokenBalance } from '../../state/wallet/hooks'
...@@ -80,7 +80,7 @@ function PositionCard({ pair, history, border, minimal = false }: PositionCardPr ...@@ -80,7 +80,7 @@ function PositionCard({ pair, history, border, minimal = false }: PositionCardPr
<RowFixed> <RowFixed>
<DoubleLogo a0={token0?.address || ''} a1={token1?.address || ''} margin={true} size={20} /> <DoubleLogo a0={token0?.address || ''} a1={token1?.address || ''} margin={true} size={20} />
<Text fontWeight={500} fontSize={20}> <Text fontWeight={500} fontSize={20}>
{token0?.symbol}:{token1?.symbol} {token0?.symbol}/{token1?.symbol}
</Text> </Text>
</RowFixed> </RowFixed>
<RowFixed> <RowFixed>
...@@ -134,7 +134,7 @@ function PositionCard({ pair, history, border, minimal = false }: PositionCardPr ...@@ -134,7 +134,7 @@ function PositionCard({ pair, history, border, minimal = false }: PositionCardPr
<RowFixed> <RowFixed>
<DoubleLogo a0={token0?.address || ''} a1={token1?.address || ''} margin={true} size={20} /> <DoubleLogo a0={token0?.address || ''} a1={token1?.address || ''} margin={true} size={20} />
<Text fontWeight={500} fontSize={20}> <Text fontWeight={500} fontSize={20}>
{token0?.symbol}:{token1?.symbol} {token0?.symbol}/{token1?.symbol}
</Text> </Text>
</RowFixed> </RowFixed>
<RowFixed> <RowFixed>
...@@ -204,7 +204,7 @@ function PositionCard({ pair, history, border, minimal = false }: PositionCardPr ...@@ -204,7 +204,7 @@ function PositionCard({ pair, history, border, minimal = false }: PositionCardPr
)} )}
<AutoRow justify="center" marginTop={'10px'}> <AutoRow justify="center" marginTop={'10px'}>
<Link>View pool information ↗</Link> <Link href={`https://uniswap.info/pair/${pair?.liquidityToken.address}`}>View pool information ↗</Link>
</AutoRow> </AutoRow>
<RowBetween marginTop="10px"> <RowBetween marginTop="10px">
<ButtonSecondary <ButtonSecondary
......
This diff is collapsed.
...@@ -2,7 +2,8 @@ import React, { useState, useEffect } from 'react' ...@@ -2,7 +2,8 @@ import React, { useState, useEffect } from 'react'
import ReactGA from 'react-ga' import ReactGA from 'react-ga'
import styled from 'styled-components' import styled from 'styled-components'
import { isMobile } from 'react-device-detect' import { isMobile } from 'react-device-detect'
import { useWeb3React, UnsupportedChainIdError } from '@web3-react/core' import { UnsupportedChainIdError } from '@web3-react/core'
import { useWeb3React } from '../../hooks'
import { URI_AVAILABLE } from '@web3-react/walletconnect-connector' import { URI_AVAILABLE } from '@web3-react/walletconnect-connector'
import { useWalletModalOpen, useWalletModalToggle } from '../../state/application/hooks' import { useWalletModalOpen, useWalletModalToggle } from '../../state/application/hooks'
......
import { Trade } from '@uniswap/sdk'
import React, { useContext } from 'react' import React, { useContext } from 'react'
import { Text } from 'rebass' import { Text } from 'rebass'
import { ThemeContext } from 'styled-components' import { ThemeContext } from 'styled-components'
import { V1_TRADE_LINK_THRESHOLD } from '../../constants'
import { useV1TradeLinkIfBetter } from '../../data/V1'
import { Link } from '../../theme' import { Link } from '../../theme'
import { YellowCard } from '../Card' import { YellowCard } from '../Card'
import { AutoColumn } from '../Column' import { AutoColumn } from '../Column'
export default function V1TradeLink({ bestV2Trade }: { bestV2Trade?: Trade }) { export default function V1TradeLink({ v1TradeLinkIfBetter }: { v1TradeLinkIfBetter: string }) {
const v1TradeLinkIfBetter = useV1TradeLinkIfBetter(bestV2Trade, V1_TRADE_LINK_THRESHOLD)
const theme = useContext(ThemeContext) const theme = useContext(ThemeContext)
return v1TradeLinkIfBetter ? ( return v1TradeLinkIfBetter ? (
<YellowCard style={{ marginTop: '12px', padding: '8px 4px' }}> <YellowCard style={{ marginTop: '12px', padding: '8px 4px' }}>
......
...@@ -15,7 +15,7 @@ export const network = new NetworkConnector({ ...@@ -15,7 +15,7 @@ export const network = new NetworkConnector({
}) })
export const injected = new InjectedConnector({ export const injected = new InjectedConnector({
supportedChainIds: [3, 4, 5, 42] supportedChainIds: [1, 3, 4, 5, 42]
}) })
// mainnet only // mainnet only
......
import { Token, ChainId } from '@uniswap/sdk'
export default [
new Token(ChainId.KOVAN, '0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa', 18, 'DAI', 'Dai Stablecoin'),
new Token(ChainId.KOVAN, '0xAaF64BFCC32d0F15873a02163e7E500671a4ffcD', 18, 'MKR', 'Maker')
]
This diff is collapsed.
import { Token, ChainId } from '@uniswap/sdk'
export default [
new Token(ChainId.RINKEBY, '0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735', 18, 'DAI', 'Dai Stablecoin'),
new Token(ChainId.RINKEBY, '0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85', 18, 'MKR', 'Maker')
]
import { Token, ChainId } from '@uniswap/sdk'
export default [new Token(ChainId.ROPSTEN, '0xaD6D458402F60fD3Bd25163575031ACDce07538D', 18, 'DAI', 'Dai Stablecoin')]
import { Contract } from '@ethersproject/contracts' import { Contract } from '@ethersproject/contracts'
import { Token, TokenAmount, Pair, Trade, ChainId, WETH, Route, TradeType, Percent } from '@uniswap/sdk' import { Token, TokenAmount, Pair, Trade, ChainId, WETH, Route, TradeType, Percent } from '@uniswap/sdk'
import useSWR from 'swr' import useSWR from 'swr'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '../hooks'
import IUniswapV1Factory from '../constants/abis/v1_factory.json' import IUniswapV1Factory from '../constants/abis/v1_factory.json'
import { V1_FACTORY_ADDRESS } from '../constants' import { V1_FACTORY_ADDRESS } from '../constants'
...@@ -41,49 +41,63 @@ function useMockV1Pair(token?: Token) { ...@@ -41,49 +41,63 @@ function useMockV1Pair(token?: Token) {
: undefined : undefined
} }
export function useV1TradeLinkIfBetter(trade: Trade, minimumDelta: Percent = new Percent('0')): string { export function useV1TradeLinkIfBetter(
const inputPair = useMockV1Pair(trade?.route?.input) isExactIn: boolean,
const outputPair = useMockV1Pair(trade?.route?.output) inputToken: Token,
outputToken: Token,
exactAmount: TokenAmount,
v2Trade: Trade,
minimumDelta: Percent = new Percent('0')
): string {
const { chainId } = useWeb3React()
const input = inputToken
const output = outputToken
const mainnet = chainId === ChainId.MAINNET
const mainnet = trade?.route?.input?.chainId === ChainId.MAINNET // get the mock v1 pairs
const inputIsWETH = mainnet && trade?.route?.input?.equals(WETH[ChainId.MAINNET]) const inputPair = useMockV1Pair(input)
const outputIsWETH = mainnet && trade?.route?.output?.equals(WETH[ChainId.MAINNET]) const outputPair = useMockV1Pair(output)
const neitherWETH = mainnet && !!trade && !inputIsWETH && !outputIsWETH
const inputIsWETH = mainnet && input?.equals(WETH[ChainId.MAINNET])
const outputIsWETH = mainnet && output?.equals(WETH[ChainId.MAINNET])
// construct a direct or through ETH v1 route
let pairs: Pair[] let pairs: Pair[]
if (inputIsWETH && outputPair) { if (inputIsWETH && outputPair) {
pairs = [outputPair] pairs = [outputPair]
} else if (outputIsWETH && inputPair) { } else if (outputIsWETH && inputPair) {
pairs = [inputPair] pairs = [inputPair]
} else if (neitherWETH && inputPair && outputPair) { }
// if neither are WETH, it's token-to-token (if they both exist)
else if (inputPair && outputPair) {
pairs = [inputPair, outputPair] pairs = [inputPair, outputPair]
} }
const route = pairs && new Route(pairs, trade.route.input) const route = pairs && new Route(pairs, input)
const v1Trade = const v1Trade =
route && route && exactAmount
new Trade( ? new Trade(route, exactAmount, isExactIn ? TradeType.EXACT_INPUT : TradeType.EXACT_OUTPUT)
route, : undefined
trade.tradeType === TradeType.EXACT_INPUT ? trade.inputAmount : trade.outputAmount,
trade.tradeType
)
let v1HasBetterTrade = false let v1HasBetterTrade = false
if (v1Trade) { if (v1Trade) {
if (trade.tradeType === TradeType.EXACT_INPUT) { if (isExactIn) {
// check if the output amount on v1, discounted by minimumDelta, is greater than on v2 // discount the v1 output amount by minimumDelta
const discountedV1Output = v1Trade.outputAmount.multiply(new Percent('1').subtract(minimumDelta)) const discountedV1Output = v1Trade?.outputAmount.multiply(new Percent('1').subtract(minimumDelta))
v1HasBetterTrade = discountedV1Output.greaterThan(trade.outputAmount) // check if the discounted v1 amount is still greater than v2, short-circuiting if no v2 trade exists
v1HasBetterTrade = !!!v2Trade || discountedV1Output.greaterThan(v2Trade.outputAmount)
} else { } else {
// check if the input amount on v1, inflated by minimumDelta, is less than on v2 // inflate the v1 amount by minimumDelta
const inflatedV1Input = v1Trade.inputAmount.multiply(new Percent('1').add(minimumDelta)) const inflatedV1Input = v1Trade?.inputAmount.multiply(new Percent('1').add(minimumDelta))
v1HasBetterTrade = inflatedV1Input.lessThan(trade.inputAmount) // check if the inflated v1 amount is still less than v2, short-circuiting if no v2 trade exists
v1HasBetterTrade = !!!v2Trade || inflatedV1Input.lessThan(v2Trade.inputAmount)
} }
} }
return v1HasBetterTrade return v1HasBetterTrade
? `https://v1.uniswap.exchange/swap?inputCurrency=${ ? `https://v1.uniswap.exchange/swap?inputCurrency=${inputIsWETH ? 'ETH' : input.address}&outputCurrency=${
inputIsWETH ? 'ETH' : trade.route.input.address outputIsWETH ? 'ETH' : output.address
}&outputCurrency=${outputIsWETH ? 'ETH' : trade.route.output.address}` }`
: undefined : undefined
} }
import { ChainId, Token, WETH } from '@uniswap/sdk' import { Token, WETH } from '@uniswap/sdk'
import { useEffect, useMemo } from 'react' import { useEffect, useMemo } from 'react'
import { useAddUserToken, useFetchTokenByAddress, useUserAddedTokens } from '../state/user/hooks' import { useAddUserToken, useFetchTokenByAddress, useUserAddedTokens } from '../state/user/hooks'
import { useWeb3React } from './index' import { useWeb3React } from './index'
import MAINNET_TOKENS from '../constants/tokens/mainnet'
import RINKEBY_TOKENS from '../constants/tokens/rinkeby'
import KOVAN_TOKENS from '../constants/tokens/kovan'
import ROPSTEN_TOKENS from '../constants/tokens/ropsten'
export const ALL_TOKENS = [ export const ALL_TOKENS = [
// WETH on all chains // WETH on all chains
...Object.values(WETH), ...Object.values(WETH),
// chain-specific tokens
// Mainnet Tokens ...MAINNET_TOKENS,
new Token(ChainId.MAINNET, '0x6B175474E89094C44Da98b954EedeAC495271d0F', 18, 'DAI', 'Dai Stablecoin'), ...RINKEBY_TOKENS,
new Token(ChainId.MAINNET, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 6, 'USDC', 'USD//C'), ...KOVAN_TOKENS,
new Token(ChainId.MAINNET, '0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2', 18, 'MKR', 'Maker'), ...ROPSTEN_TOKENS
// Rinkeby Tokens
new Token(ChainId.RINKEBY, '0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735', 18, 'DAI', 'Dai Stablecoin'),
new Token(ChainId.RINKEBY, '0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85', 18, 'MKR', 'Maker'),
// Kovan Tokens
new Token(ChainId.KOVAN, '0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa', 18, 'DAI', 'Dai Stablecoin'),
new Token(ChainId.KOVAN, '0xAaF64BFCC32d0F15873a02163e7E500671a4ffcD', 18, 'MKR', 'Maker'),
// Ropsten Tokens
new Token(ChainId.ROPSTEN, '0xaD6D458402F60fD3Bd25163575031ACDce07538D', 18, 'DAI', 'Dai Stablecoin')
// Goerli Tokens
] ]
// remap WETH to ETH // remap WETH to ETH
.map(token => { .map(token => {
......
...@@ -23,15 +23,23 @@ function useAllCommonPairs(tokenA?: Token, tokenB?: Token): Pair[] { ...@@ -23,15 +23,23 @@ function useAllCommonPairs(tokenA?: Token, tokenB?: Token): Pair[] {
const aToUSDC = usePair(tokenA, chainId === ChainId.MAINNET ? USDC : null) const aToUSDC = usePair(tokenA, chainId === ChainId.MAINNET ? USDC : null)
const bToUSDC = usePair(tokenB, chainId === ChainId.MAINNET ? USDC : null) const bToUSDC = usePair(tokenB, chainId === ChainId.MAINNET ? USDC : null)
return useMemo(() => [pairBetween, aToETH, bToETH, aToDAI, bToDAI, aToUSDC, bToUSDC].filter(p => !!p), [ // get connecting pairs
pairBetween, const DAIToETH = usePair(chainId === ChainId.MAINNET ? DAI : null, WETH[chainId])
aToETH, const USDCToETH = usePair(chainId === ChainId.MAINNET ? USDC : null, WETH[chainId])
bToETH, const DAIToUSDC = usePair(chainId === ChainId.MAINNET ? DAI : null, chainId === ChainId.MAINNET ? USDC : null)
aToDAI,
bToDAI, // only pass along valid pairs, non-duplicated pairs
aToUSDC, return useMemo(
bToUSDC () =>
]) [pairBetween, aToETH, bToETH, aToDAI, bToDAI, aToUSDC, bToUSDC, DAIToETH, USDCToETH, DAIToUSDC]
// filter out invalid pairs
.filter(p => !!p)
// filter out duplicated pairs
.filter(
(p, i, pairs) => i === pairs.findIndex(pair => pair?.liquidityToken.address === p.liquidityToken.address)
),
[pairBetween, aToETH, bToETH, aToDAI, bToDAI, aToUSDC, bToUSDC, DAIToETH, USDCToETH, DAIToUSDC]
)
} }
/** /**
......
...@@ -14,7 +14,7 @@ import { RowBetween } from '../../components/Row' ...@@ -14,7 +14,7 @@ import { RowBetween } from '../../components/Row'
import { ButtonPrimary, ButtonSecondary } from '../../components/Button' import { ButtonPrimary, ButtonSecondary } from '../../components/Button'
import { AutoColumn, ColumnCenter } from '../../components/Column' import { AutoColumn, ColumnCenter } from '../../components/Column'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '../../hooks'
import { usePair } from '../../data/Reserves' import { usePair } from '../../data/Reserves'
import { useAllDummyPairs } from '../../state/user/hooks' import { useAllDummyPairs } from '../../state/user/hooks'
......
...@@ -39,10 +39,9 @@ import { useDefaultsFromURL, useDerivedSwapInfo, useSwapActionHandlers, useSwapS ...@@ -39,10 +39,9 @@ import { useDefaultsFromURL, useDerivedSwapInfo, useSwapActionHandlers, useSwapS
import { useHasPendingApproval } from '../../state/transactions/hooks' import { useHasPendingApproval } from '../../state/transactions/hooks'
import { useAllTokenBalancesTreatingWETHasETH } from '../../state/wallet/hooks' import { useAllTokenBalancesTreatingWETHasETH } from '../../state/wallet/hooks'
import { CursorPointer, TYPE } from '../../theme' import { CursorPointer, TYPE } from '../../theme'
import { Link } from '../../theme/components'
import { computeSlippageAdjustedAmounts, computeTradePriceBreakdown, warningServerity } from '../../utils/prices' import { computeSlippageAdjustedAmounts, computeTradePriceBreakdown, warningServerity } from '../../utils/prices'
export default function Send({ history, location: { search } }: RouteComponentProps) { export default function Send({ location: { search } }: RouteComponentProps) {
useDefaultsFromURL(search) useDefaultsFromURL(search)
// text translation // text translation
...@@ -61,7 +60,14 @@ export default function Send({ history, location: { search } }: RouteComponentPr ...@@ -61,7 +60,14 @@ export default function Send({ history, location: { search } }: RouteComponentPr
// trade details, check query params for initial state // trade details, check query params for initial state
const { independentField, typedValue } = useSwapState() const { independentField, typedValue } = useSwapState()
const { parsedAmounts, bestTrade, tokenBalances, tokens, error: swapError } = useDerivedSwapInfo() const {
parsedAmounts,
bestTrade,
tokenBalances,
tokens,
error: swapError,
v1TradeLinkIfBetter
} = useDerivedSwapInfo()
const isSwapValid = !swapError && !recipientError && bestTrade const isSwapValid = !swapError && !recipientError && bestTrade
const dependentField: Field = independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT const dependentField: Field = independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT
...@@ -474,13 +480,6 @@ export default function Send({ history, location: { search } }: RouteComponentPr ...@@ -474,13 +480,6 @@ export default function Send({ history, location: { search } }: RouteComponentPr
) : noRoute && userHasSpecifiedInputOutput ? ( ) : noRoute && userHasSpecifiedInputOutput ? (
<GreyCard style={{ textAlign: 'center' }}> <GreyCard style={{ textAlign: 'center' }}>
<TYPE.main mb="4px">Insufficient liquidity for this trade.</TYPE.main> <TYPE.main mb="4px">Insufficient liquidity for this trade.</TYPE.main>
<Link
onClick={() => {
history.push('/add/' + tokens[Field.INPUT]?.address + '-' + tokens[Field.OUTPUT]?.address)
}}
>
Add liquidity now.
</Link>
</GreyCard> </GreyCard>
) : mustApprove === true ? ( ) : mustApprove === true ? (
<ButtonLight onClick={approveCallback} disabled={pendingApprovalInput}> <ButtonLight onClick={approveCallback} disabled={pendingApprovalInput}>
...@@ -507,7 +506,7 @@ export default function Send({ history, location: { search } }: RouteComponentPr ...@@ -507,7 +506,7 @@ export default function Send({ history, location: { search } }: RouteComponentPr
</Text> </Text>
</ButtonError> </ButtonError>
)} )}
<V1TradeLink bestV2Trade={bestTrade} /> <V1TradeLink v1TradeLinkIfBetter={v1TradeLinkIfBetter} />
</BottomGrouping> </BottomGrouping>
{bestTrade && ( {bestTrade && (
<AdvancedSwapDetailsDropdown <AdvancedSwapDetailsDropdown
......
...@@ -25,11 +25,11 @@ import { useWalletModalToggle } from '../../state/application/hooks' ...@@ -25,11 +25,11 @@ import { useWalletModalToggle } from '../../state/application/hooks'
import { Field } from '../../state/swap/actions' import { Field } from '../../state/swap/actions'
import { useDefaultsFromURL, useDerivedSwapInfo, useSwapActionHandlers, useSwapState } from '../../state/swap/hooks' import { useDefaultsFromURL, useDerivedSwapInfo, useSwapActionHandlers, useSwapState } from '../../state/swap/hooks'
import { useHasPendingApproval } from '../../state/transactions/hooks' import { useHasPendingApproval } from '../../state/transactions/hooks'
import { CursorPointer, Link, TYPE } from '../../theme' import { CursorPointer, TYPE } from '../../theme'
import { computeSlippageAdjustedAmounts, computeTradePriceBreakdown, warningServerity } from '../../utils/prices' import { computeSlippageAdjustedAmounts, computeTradePriceBreakdown, warningServerity } from '../../utils/prices'
import SwapModalHeader from '../../components/swap/SwapModalHeader' import SwapModalHeader from '../../components/swap/SwapModalHeader'
export default function Swap({ history, location: { search } }: RouteComponentProps) { export default function Swap({ location: { search } }: RouteComponentProps) {
useDefaultsFromURL(search) useDefaultsFromURL(search)
// text translation // text translation
// const { t } = useTranslation() // const { t } = useTranslation()
...@@ -40,7 +40,7 @@ export default function Swap({ history, location: { search } }: RouteComponentPr ...@@ -40,7 +40,7 @@ export default function Swap({ history, location: { search } }: RouteComponentPr
const toggleWalletModal = useWalletModalToggle() const toggleWalletModal = useWalletModalToggle()
const { independentField, typedValue } = useSwapState() const { independentField, typedValue } = useSwapState()
const { bestTrade, tokenBalances, parsedAmounts, tokens, error } = useDerivedSwapInfo() const { bestTrade, tokenBalances, parsedAmounts, tokens, error, v1TradeLinkIfBetter } = useDerivedSwapInfo()
const isValid = !error const isValid = !error
const dependentField: Field = independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT const dependentField: Field = independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT
...@@ -277,14 +277,6 @@ export default function Swap({ history, location: { search } }: RouteComponentPr ...@@ -277,14 +277,6 @@ export default function Swap({ history, location: { search } }: RouteComponentPr
) : noRoute && userHasSpecifiedInputOutput ? ( ) : noRoute && userHasSpecifiedInputOutput ? (
<GreyCard style={{ textAlign: 'center' }}> <GreyCard style={{ textAlign: 'center' }}>
<TYPE.main mb="4px">Insufficient liquidity for this trade.</TYPE.main> <TYPE.main mb="4px">Insufficient liquidity for this trade.</TYPE.main>
<Link
onClick={() => {
history.push('/add/' + tokens[Field.INPUT]?.address + '-' + tokens[Field.OUTPUT]?.address)
}}
>
{' '}
Add liquidity now.
</Link>
</GreyCard> </GreyCard>
) : mustApprove === true ? ( ) : mustApprove === true ? (
<ButtonLight onClick={approveCallback} disabled={pendingApprovalInput}> <ButtonLight onClick={approveCallback} disabled={pendingApprovalInput}>
...@@ -308,7 +300,7 @@ export default function Swap({ history, location: { search } }: RouteComponentPr ...@@ -308,7 +300,7 @@ export default function Swap({ history, location: { search } }: RouteComponentPr
</Text> </Text>
</ButtonError> </ButtonError>
)} )}
<V1TradeLink bestV2Trade={bestTrade} /> <V1TradeLink v1TradeLinkIfBetter={v1TradeLinkIfBetter} />
</BottomGrouping> </BottomGrouping>
{bestTrade && ( {bestTrade && (
<AdvancedSwapDetailsDropdown <AdvancedSwapDetailsDropdown
......
...@@ -8,6 +8,8 @@ import { useTradeExactIn, useTradeExactOut } from '../../hooks/Trades' ...@@ -8,6 +8,8 @@ import { useTradeExactIn, useTradeExactOut } from '../../hooks/Trades'
import { AppDispatch, AppState } from '../index' import { AppDispatch, AppState } from '../index'
import { useTokenBalancesTreatWETHAsETH } from '../wallet/hooks' import { useTokenBalancesTreatWETHAsETH } from '../wallet/hooks'
import { Field, selectToken, setDefaultsFromURL, switchTokens, typeInput } from './actions' import { Field, selectToken, setDefaultsFromURL, switchTokens, typeInput } from './actions'
import { useV1TradeLinkIfBetter } from '../../data/V1'
import { V1_TRADE_LINK_THRESHOLD } from '../../constants'
export function useSwapState(): AppState['swap'] { export function useSwapState(): AppState['swap'] {
return useSelector<AppState, AppState['swap']>(state => state.swap) return useSelector<AppState, AppState['swap']>(state => state.swap)
...@@ -68,6 +70,7 @@ export function useDerivedSwapInfo(): { ...@@ -68,6 +70,7 @@ export function useDerivedSwapInfo(): {
parsedAmounts: { [field in Field]?: TokenAmount } parsedAmounts: { [field in Field]?: TokenAmount }
bestTrade?: Trade bestTrade?: Trade
error?: string error?: string
v1TradeLinkIfBetter?: string
} { } {
const { account } = useWeb3React() const { account } = useWeb3React()
...@@ -106,6 +109,16 @@ export function useDerivedSwapInfo(): { ...@@ -106,6 +109,16 @@ export function useDerivedSwapInfo(): {
[Field.OUTPUT]: tokenOut [Field.OUTPUT]: tokenOut
} }
// get link to trade on v1, if a better rate exists
const v1TradeLinkIfBetter = useV1TradeLinkIfBetter(
isExactIn,
tokens[Field.INPUT],
tokens[Field.OUTPUT],
isExactIn ? parsedAmounts[Field.INPUT] : parsedAmounts[Field.OUTPUT],
bestTrade,
V1_TRADE_LINK_THRESHOLD
)
let error: string | undefined let error: string | undefined
if (!account) { if (!account) {
error = 'Connect Wallet' error = 'Connect Wallet'
...@@ -132,7 +145,8 @@ export function useDerivedSwapInfo(): { ...@@ -132,7 +145,8 @@ export function useDerivedSwapInfo(): {
tokenBalances, tokenBalances,
parsedAmounts, parsedAmounts,
bestTrade, bestTrade,
error error,
v1TradeLinkIfBetter
} }
} }
......
import { ChainId, JSBI, Pair, Token, TokenAmount, WETH } from '@uniswap/sdk' import { ChainId, JSBI, Pair, Token, TokenAmount, WETH } from '@uniswap/sdk'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '../../hooks'
import { useCallback, useMemo } from 'react' import { useCallback, useMemo } from 'react'
import { shallowEqual, useDispatch, useSelector } from 'react-redux' import { shallowEqual, useDispatch, useSelector } from 'react-redux'
import { useAllTokens } from '../../hooks/Tokens' import { useAllTokens } from '../../hooks/Tokens'
......
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