Commit eaf8d5a3 authored by Ian Lapham's avatar Ian Lapham Committed by GitHub

Add routes through ETH (#665)

* add fix for ETH balance fetching

* add tokens to other testnets

* update with Exchange -> Pair

* routes throuh ETH

* fix logs

* fix conflict
parent 02dedcbc
......@@ -152,7 +152,6 @@ export default function CurrencyInputPanel({
value,
field,
onUserInput,
title,
onMax,
atMax,
error,
......@@ -164,7 +163,7 @@ export default function CurrencyInputPanel({
disableTokenSelect = false,
hideBalance = false,
isExchange = false,
exchange = null, // used for double token logo
pair = null, // used for double token logo
customBalance = null, // used for LP balances instead of token balance
hideInput = false,
showSendWithSwap = false
......@@ -251,13 +250,13 @@ export default function CurrencyInputPanel({
>
<Aligner>
{isExchange ? (
<DoubleLogo a0={exchange?.token0.address} a1={exchange?.token1.address} size={24} margin={true} />
<DoubleLogo a0={pair?.token0.address} a1={pair?.token1.address} size={24} margin={true} />
) : token?.address ? (
<TokenLogo address={token?.address} size={'24px'} />
) : null}
{isExchange ? (
<StyledTokenName>
{exchange?.token0.symbol}:{exchange?.token1.symbol}
{pair?.token0.symbol}:{pair?.token1.symbol}
</StyledTokenName>
) : (
<StyledTokenName>{(token && token.symbol) || t('selectToken')}</StyledTokenName>
......
......@@ -3,7 +3,7 @@ import styled from 'styled-components'
import { ethers } from 'ethers'
import { withRouter } from 'react-router-dom'
import { parseUnits, parseEther } from '@ethersproject/units'
import { WETH, TradeType, Route, Exchange, Trade, TokenAmount, JSBI, Percent } from '@uniswap/sdk'
import { WETH, TradeType, Pair, Trade, TokenAmount, JSBI, Percent } from '@uniswap/sdk'
import TokenLogo from '../TokenLogo'
import QuestionHelper from '../Question'
......@@ -21,9 +21,10 @@ import { AutoColumn, ColumnCenter } from '../../components/Column'
import { ButtonPrimary, ButtonError } from '../Button'
import { RowBetween, RowFixed, AutoRow } from '../../components/Row'
import { usePair } from '../../contexts/Pairs'
import { useToken } from '../../contexts/Tokens'
import { usePopups } from '../../contexts/Application'
import { useExchange } from '../../contexts/Exchanges'
import { useRoute } from '../../contexts/Routes'
import { useTransactionAdder } from '../../contexts/Transactions'
import { useAddressAllowance } from '../../contexts/Allowances'
import { useWeb3React, useTokenContract } from '../../hooks'
......@@ -244,9 +245,10 @@ function ExchangePage({ sendingInput = false, history }) {
[Field.OUTPUT]: useToken(fieldData[Field.OUTPUT].address)
}
const exchange: Exchange = useExchange(tokens[Field.INPUT], tokens[Field.OUTPUT])
const route: Route = !!exchange ? new Route([exchange], tokens[Field.INPUT]) : undefined
const emptyReserves: boolean = exchange && JSBI.equal(JSBI.BigInt(0), exchange.reserve0.raw)
const pair: Pair = usePair(tokens[Field.INPUT], tokens[Field.OUTPUT])
const route = useRoute(tokens[Field.INPUT], tokens[Field.OUTPUT])
const noRoute: boolean = !route && !!tokens[Field.INPUT] && !!tokens[Field.OUTPUT]
const emptyReserves = pair && JSBI.equal(JSBI.BigInt(0), pair.reserve0.raw)
// modal and loading
const [showConfirm, setShowConfirm] = useState<boolean>(false)
......@@ -272,6 +274,8 @@ function ExchangePage({ sendingInput = false, history }) {
[Field.OUTPUT]: useAddressBalance(account, tokens[Field.OUTPUT])
}
// console.log(userBalances[Field.OUTPUT]?.raw.toString())
const parsedAmounts: { [field: number]: TokenAmount } = {}
if (typedValue !== '' && typedValue !== '.' && tokens[independentField]) {
try {
......@@ -621,8 +625,9 @@ function ExchangePage({ sendingInput = false, history }) {
if (
parsedAmounts[Field.INPUT] &&
exchange &&
JSBI.greaterThan(parsedAmounts[Field.INPUT].raw, exchange.reserveOf(tokens[Field.INPUT]).raw)
pair &&
route &&
JSBI.greaterThan(parsedAmounts[Field.INPUT].raw, route.pairs[0].reserveOf(tokens[Field.INPUT]).raw)
) {
setTradeError('Insufficient Liquidity')
setIsValid(false)
......@@ -631,8 +636,12 @@ function ExchangePage({ sendingInput = false, history }) {
if (
!ignoreOutput &&
parsedAmounts[Field.OUTPUT] &&
exchange &&
JSBI.greaterThan(parsedAmounts[Field.OUTPUT].raw, exchange.reserveOf(tokens[Field.OUTPUT]).raw)
pair &&
route &&
JSBI.greaterThan(
parsedAmounts[Field.OUTPUT].raw,
route.pairs[route.pairs.length - 1].reserveOf(tokens[Field.OUTPUT]).raw
)
) {
setTradeError('Insufficient Liquidity')
setIsValid(false)
......@@ -657,7 +666,7 @@ function ExchangePage({ sendingInput = false, history }) {
setIsValid(false)
}
}, [
exchange,
pair,
ignoreOutput,
parsedAmounts,
recipient,
......@@ -667,7 +676,8 @@ function ExchangePage({ sendingInput = false, history }) {
showInputUnlock,
showOutputUnlock,
tokens,
userBalances
userBalances,
route
])
// warnings on slippage
......@@ -896,9 +906,8 @@ function ExchangePage({ sendingInput = false, history }) {
atMax={atMaxAmountInput}
token={tokens[Field.INPUT]}
onTokenSelection={address => _onTokenSelect(address)}
title={'Input'}
error={inputError}
exchange={exchange}
pair={pair}
showUnlock={showInputUnlock}
hideBalance={true}
hideInput={true}
......@@ -916,9 +925,8 @@ function ExchangePage({ sendingInput = false, history }) {
value={formattedAmounts[Field.INPUT]}
atMax={atMaxAmountInput}
token={tokens[Field.INPUT]}
title={'Input'}
error={inputError}
exchange={exchange}
pair={pair}
showUnlock={showInputUnlock}
onUserInput={onUserInput}
onMax={() => {
......@@ -942,18 +950,17 @@ function ExchangePage({ sendingInput = false, history }) {
atMax={atMaxAmountOutput}
token={tokens[Field.OUTPUT]}
onTokenSelection={address => onTokenSelection(Field.OUTPUT, address)}
title={'Output'}
error={outputError}
exchange={exchange}
pair={pair}
showUnlock={showOutputUnlock}
/>
{!emptyReserves && ( // hide price if new exchange
{!noRoute && ( // hide price if new exchange
<RowBetween>
<Text fontWeight={500} color="#565A69">
Price
</Text>
<Text fontWeight={500} color="#565A69">
{exchange
{pair
? `1 ${tokens[Field.INPUT].symbol} = ${route?.midPrice.toSignificant(6)} ${
tokens[Field.OUTPUT].symbol
}`
......@@ -989,7 +996,7 @@ function ExchangePage({ sendingInput = false, history }) {
</AutoColumn>
)}
{emptyReserves ? (
{noRoute ? (
<RowBetween style={{ margin: '10px 0' }}>
<TYPE.main>No exchange for this pair.</TYPE.main>
<Link
......
import React, { useState } from 'react'
import { withRouter } from 'react-router-dom'
import { TokenAmount, JSBI, Token, Exchange } from '@uniswap/sdk'
import { TokenAmount, JSBI, Token, Pair } from '@uniswap/sdk'
import Row from '../Row'
import TokenLogo from '../TokenLogo'
......@@ -14,9 +14,9 @@ import { LightCard } from '../Card'
import { AutoColumn, ColumnCenter } from '../Column'
import { ButtonPrimary, ButtonDropwdown, ButtonDropwdownLight } from '../Button'
import { usePair } from '../../contexts/Pairs'
import { useToken } from '../../contexts/Tokens'
import { usePopups } from '../../contexts/Application'
import { useExchange } from '../../contexts/Exchanges'
import { useWeb3React } from '@web3-react/core'
import { useAddressBalance } from '../../contexts/Balances'
......@@ -38,10 +38,10 @@ function PoolFinder({ history }) {
const token0: Token = useToken(token0Address)
const token1: Token = useToken(token1Address)
const exchange: Exchange = useExchange(token0, token1)
const position: TokenAmount = useAddressBalance(account, exchange?.liquidityToken)
const pair: Pair = usePair(token0, token1)
const position: TokenAmount = useAddressBalance(account, pair?.liquidityToken)
const newExchange: boolean = exchange && JSBI.equal(exchange.reserve0.raw, JSBI.BigInt(0))
const newPair: boolean = pair && JSBI.equal(pair.reserve0.raw, JSBI.BigInt(0))
const allowImport: boolean = position && JSBI.greaterThan(position.raw, JSBI.BigInt(0))
function endSearch() {
......@@ -120,7 +120,7 @@ function PoolFinder({ history }) {
{position ? (
!JSBI.equal(position.raw, JSBI.BigInt(0)) ? (
<PositionCard
exchangeAddress={exchange?.liquidityToken.address}
pairAddress={pair?.liquidityToken.address}
token0={token0}
token1={token1}
minimal={true}
......@@ -140,7 +140,7 @@ function PoolFinder({ history }) {
</AutoColumn>
</LightCard>
)
) : newExchange ? (
) : newPair ? (
<LightCard padding="45px">
<AutoColumn gap="8px" justify="center">
<Text color="">No exchange found.</Text>
......
import React from 'react'
import styled from 'styled-components'
import { withRouter } from 'react-router-dom'
import { Percent, Exchange } from '@uniswap/sdk'
import { Percent, Pair } from '@uniswap/sdk'
import { useWeb3React } from '@web3-react/core'
import { useAllBalances } from '../../contexts/Balances'
import { useTotalSupply } from '../../contexts/Exchanges'
import { useTotalSupply } from '../../contexts/Pairs'
import Card from '../Card'
import TokenLogo from '../TokenLogo'
......@@ -20,17 +20,17 @@ const FixedHeightRow = styled(RowBetween)`
height: 24px;
`
function PositionCard({ exchangeAddress, token0, token1, history, minimal = false, ...rest }) {
function PositionCard({ pairAddress, token0, token1, history, minimal = false, ...rest }) {
const { account } = useWeb3React()
const allBalances = useAllBalances()
const tokenAmount0 = allBalances?.[exchangeAddress]?.[token0.address]
const tokenAmount1 = allBalances?.[exchangeAddress]?.[token1.address]
const tokenAmount0 = allBalances?.[pairAddress]?.[token0.address]
const tokenAmount1 = allBalances?.[pairAddress]?.[token1.address]
const exchange = tokenAmount0 && tokenAmount1 && new Exchange(tokenAmount0, tokenAmount1)
const pair = tokenAmount0 && tokenAmount1 && new Pair(tokenAmount0, tokenAmount1)
const userPoolBalance = allBalances?.[account]?.[exchangeAddress]
const totalPoolTokens = useTotalSupply(exchange)
const userPoolBalance = allBalances?.[account]?.[pairAddress]
const totalPoolTokens = useTotalSupply(pair)
const poolTokenPercentage =
!!userPoolBalance && !!totalPoolTokens ? new Percent(userPoolBalance.raw, totalPoolTokens.raw) : undefined
......@@ -39,12 +39,12 @@ function PositionCard({ exchangeAddress, token0, token1, history, minimal = fals
token0 &&
totalPoolTokens &&
userPoolBalance &&
exchange.getLiquidityValue(token0, totalPoolTokens, userPoolBalance, false)
pair.getLiquidityValue(token0, totalPoolTokens, userPoolBalance, false)
const token1Deposited =
token1 &&
totalPoolTokens &&
userPoolBalance &&
exchange.getLiquidityValue(token1, totalPoolTokens, userPoolBalance, false)
pair.getLiquidityValue(token1, totalPoolTokens, userPoolBalance, false)
function DynamicCard({ children, ...rest }) {
if (!minimal) {
......
......@@ -21,10 +21,10 @@ import { ColumnCenter } from '../../components/Column'
import { RowBetween, RowFixed } from '../Row'
import { isAddress } from '../../utils'
import { useAllPairs } from '../../contexts/Pairs'
import { useWeb3React } from '../../hooks'
import { useAllBalances } from '../../contexts/Balances'
import { useTranslation } from 'react-i18next'
import { useAllExchanges } from '../../contexts/Exchanges'
import { useToken, useAllTokens, INITIAL_TOKENS_CONTEXT } from '../../contexts/Tokens'
const TokenModalInfo = styled.div`
......@@ -131,7 +131,7 @@ function SearchModal({
const { account, chainId } = useWeb3React()
const allTokens = useAllTokens()
const allExchanges = useAllExchanges()
const allPairs = useAllPairs()
const allBalances = useAllBalances()
const [searchQuery, setSearchQuery] = useState('')
......@@ -230,7 +230,7 @@ function SearchModal({
const escapeStringRegexp = string => string
const sortedPairList = useMemo(() => {
return Object.keys(allExchanges).sort((a, b) => {
return Object.keys(allPairs).sort((a, b) => {
// sort by balance
const balanceA = allBalances?.[account]?.[a]
const balanceB = allBalances?.[account]?.[b]
......@@ -248,17 +248,17 @@ function SearchModal({
return 0
}
})
}, [account, allBalances, allExchanges, sortDirection])
}, [account, allBalances, allPairs, sortDirection])
const filteredPairList = useMemo(() => {
const isAddress = searchQuery.slice(0, 2) === '0x'
return sortedPairList.filter(exchangeAddress => {
const exchange = allExchanges[exchangeAddress]
return sortedPairList.filter(pairAddress => {
const pair = allPairs[pairAddress]
if (searchQuery === '') {
return true
}
const token0 = allTokens[exchange.token0]
const token1 = allTokens[exchange.token1]
const token0 = allTokens[pair.token0]
const token1 = allTokens[pair.token1]
const regexMatches = Object.keys(token0).map(field => {
if (
(field === 'address' && isAddress) ||
......@@ -275,7 +275,7 @@ function SearchModal({
return regexMatches.some(m => m)
})
}, [allExchanges, allTokens, searchQuery, sortedPairList])
}, [allPairs, allTokens, searchQuery, sortedPairList])
// update the amount shown as filtered list changes
useEffect(() => {
......@@ -296,10 +296,10 @@ function SearchModal({
return (
filteredPairList &&
filteredPairList.map((exchangeAddress, i) => {
const token0 = allTokens[allExchanges[exchangeAddress].token0]
const token1 = allTokens[allExchanges[exchangeAddress].token1]
const balance = allBalances?.[account]?.[exchangeAddress]?.toSignificant(6)
filteredPairList.map((pairAddress, i) => {
const token0 = allTokens[allPairs[pairAddress].token0]
const token1 = allTokens[allPairs[pairAddress].token1]
const balance = allBalances?.[account]?.[pairAddress]?.toSignificant(6)
return (
<MenuItem
key={i}
......
import React, { createContext, useContext, useReducer, useRef, useMemo, useCallback, useEffect, ReactNode } from 'react'
import { TokenAmount, Token, JSBI, WETH } from '@uniswap/sdk'
import { useAllPairs } from './Pairs'
import { useAllTokens } from './Tokens'
import { useBlockNumber } from './Application'
import { useAllExchanges } from './Exchanges'
import { useWeb3React, useDebounce } from '../hooks'
import { getEtherBalance, getTokenBalance, isAddress } from '../utils'
......@@ -120,20 +120,20 @@ function reducer(state: BalancesState, { type, payload }: { type: Action; payloa
}
}
case Action.BATCH_UPDATE_EXCHANGES: {
const { chainId, exchangeAddresses, tokenAddresses, values, blockNumber } = payload
const { chainId, pairAddresses, tokenAddresses, values, blockNumber } = payload
return {
...state,
[chainId]: {
...state?.[chainId],
...exchangeAddresses.reduce((accumulator: any, exchangeAddress: string, i: number) => {
...pairAddresses.reduce((accumulator: any, pairAddress: string, i: number) => {
const tokenAddress = tokenAddresses[i]
const value = values[i]
accumulator[exchangeAddress] = {
...state?.[chainId]?.[exchangeAddress],
...accumulator?.[exchangeAddress],
accumulator[pairAddress] = {
...state?.[chainId]?.[pairAddress],
...accumulator?.[pairAddress],
[tokenAddress]: {
...state?.[chainId]?.[exchangeAddress]?.[tokenAddress],
...state?.[chainId]?.[pairAddress]?.[tokenAddress],
value,
blockNumber
}
......@@ -174,10 +174,10 @@ export default function Provider({ children }: { children: ReactNode }) {
dispatch({ type: Action.BATCH_UPDATE_ACCOUNT, payload: { chainId, address, tokenAddresses, values, blockNumber } })
}, [])
const batchUpdateExchanges = useCallback((chainId, exchangeAddresses, tokenAddresses, values, blockNumber) => {
const batchUpdateExchanges = useCallback((chainId, pairAddresses, tokenAddresses, values, blockNumber) => {
dispatch({
type: Action.BATCH_UPDATE_EXCHANGES,
payload: { chainId, exchangeAddresses, tokenAddresses, values, blockNumber }
payload: { chainId, pairAddresses, tokenAddresses, values, blockNumber }
})
}, [])
......@@ -325,26 +325,25 @@ export function Updater() {
}, [chainId, account, blockNumber, allTokens, fetchBalance, batchUpdateAccount])
// ensure token balances for all exchanges
const allExchanges = useAllExchanges()
const allPairs = useAllPairs()
useEffect(() => {
if (typeof chainId === 'number' && typeof blockNumber === 'number') {
Promise.all(
Object.keys(allExchanges)
.filter(exchangeAddress => {
const token0 = allExchanges[exchangeAddress].token0
const token1 = allExchanges[exchangeAddress].token1
Object.keys(allPairs)
.filter(pairAddress => {
const token0 = allPairs[pairAddress].token0
const token1 = allPairs[pairAddress].token1
const hasValueToken0 = !!stateRef.current?.[chainId]?.[exchangeAddress]?.[token0]?.value
const hasValueToken1 = !!stateRef.current?.[chainId]?.[exchangeAddress]?.[token1]?.value
const hasValueToken0 = !!stateRef.current?.[chainId]?.[pairAddress]?.[token0]?.value
const hasValueToken1 = !!stateRef.current?.[chainId]?.[pairAddress]?.[token1]?.value
const cachedFetchedAsOfToken0 = fetchedAsOfCache.current?.[chainId]?.[exchangeAddress]?.token0
const cachedFetchedAsOfToken1 = fetchedAsOfCache.current?.[chainId]?.[exchangeAddress]?.token1
const cachedFetchedAsOfToken0 = fetchedAsOfCache.current?.[chainId]?.[pairAddress]?.token0
const cachedFetchedAsOfToken1 = fetchedAsOfCache.current?.[chainId]?.[pairAddress]?.token1
const fetchedAsOfToken0 =
stateRef.current?.[chainId]?.[exchangeAddress]?.[token0]?.blockNumber ?? cachedFetchedAsOfToken0
stateRef.current?.[chainId]?.[pairAddress]?.[token0]?.blockNumber ?? cachedFetchedAsOfToken0
const fetchedAsOfToken1 =
stateRef.current?.[chainId]?.[exchangeAddress]?.[token1]?.blockNumber ?? cachedFetchedAsOfToken1
stateRef.current?.[chainId]?.[pairAddress]?.[token1]?.blockNumber ?? cachedFetchedAsOfToken1
// if there's no values, and they're not being fetched, we need to fetch!
if (
......@@ -367,37 +366,37 @@ export function Updater() {
return false
}
})
.map(async exchangeAddress => {
const token0 = allExchanges[exchangeAddress].token0
const token1 = allExchanges[exchangeAddress].token1
.map(async pairAddress => {
const token0 = allPairs[pairAddress].token0
const token1 = allPairs[pairAddress].token1
fetchedAsOfCache.current = {
...fetchedAsOfCache.current,
[chainId]: {
...fetchedAsOfCache.current?.[chainId],
[exchangeAddress]: {
...fetchedAsOfCache.current?.[chainId]?.[exchangeAddress],
[pairAddress]: {
...fetchedAsOfCache.current?.[chainId]?.[pairAddress],
[token0]: blockNumber,
[token1]: blockNumber
}
}
}
return Promise.all([
fetchBalance(exchangeAddress, token0),
fetchBalance(exchangeAddress, token1)
]).then(([valueToken0, valueToken1]) => ({ exchangeAddress, token0, token1, valueToken0, valueToken1 }))
fetchBalance(pairAddress, token0),
fetchBalance(pairAddress, token1)
]).then(([valueToken0, valueToken1]) => ({ pairAddress, token0, token1, valueToken0, valueToken1 }))
})
).then(results => {
batchUpdateExchanges(
chainId,
results.flatMap(result => [result.exchangeAddress, result.exchangeAddress]),
results.flatMap(result => [result.pairAddress, result.pairAddress]),
results.flatMap(result => [result.token0, result.token1]),
results.flatMap(result => [result.valueToken0, result.valueToken1]),
blockNumber
)
})
}
}, [chainId, account, blockNumber, allExchanges, fetchBalance, batchUpdateExchanges])
}, [chainId, account, blockNumber, allPairs, fetchBalance, batchUpdateExchanges])
return null
}
......@@ -472,17 +471,17 @@ export function useAddressBalance(address: string, token: Token): TokenAmount |
export function useAccountLPBalances(account: string) {
const { chainId } = useWeb3React()
const [, { startListening, stopListening }] = useBalancesContext()
const allExchanges = useAllExchanges()
const allPairs = useAllPairs()
useEffect(() => {
Object.keys(allExchanges).map(exchangeAddress => {
Object.keys(allPairs).map(pairAddress => {
if (typeof chainId === 'number' && isAddress(account)) {
startListening(chainId, account, exchangeAddress)
startListening(chainId, account, pairAddress)
return () => {
stopListening(chainId, account, exchangeAddress)
stopListening(chainId, account, pairAddress)
}
}
return true
})
}, [account, allExchanges, chainId, startListening, stopListening])
}, [account, allPairs, chainId, startListening, stopListening])
}
import React, { createContext, useContext, useReducer, useMemo, useCallback, useEffect, useState } from 'react'
import { useAddressBalance } from './Balances'
import { useWeb3React, useExchangeContract } from '../hooks'
import { useWeb3React, usePairContract } from '../hooks'
import { INITIAL_TOKENS_CONTEXT } from './Tokens'
import { ChainId, WETH, Token, TokenAmount, Exchange, JSBI } from '@uniswap/sdk'
import { ChainId, WETH, Token, TokenAmount, Pair, JSBI } from '@uniswap/sdk'
const UPDATE = 'UPDATE'
const ALL_EXCHANGES: [Token, Token][] = [
const ALL_PAIRS: [Token, Token][] = [
[
INITIAL_TOKENS_CONTEXT[ChainId.RINKEBY][WETH[ChainId.RINKEBY].address],
INITIAL_TOKENS_CONTEXT[ChainId.RINKEBY]['0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735'] //dai
......@@ -17,30 +17,29 @@ const ALL_EXCHANGES: [Token, Token][] = [
]
]
const EXCHANGE_MAP: {
const PAIR_MAP: {
[chainId: number]: { [token0Address: string]: { [token1Address: string]: string } }
} = ALL_EXCHANGES.reduce((exchangeMap, [tokenA, tokenB]) => {
} = ALL_PAIRS.reduce((pairMap, [tokenA, tokenB]) => {
const tokens: [Token, Token] = tokenA?.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA]
// ensure exchanges are unique
if (exchangeMap?.[tokens[0].chainId]?.[tokens[0].address]?.[tokens[1].address] !== undefined)
if (pairMap?.[tokens[0].chainId]?.[tokens[0].address]?.[tokens[1].address] !== undefined)
throw Error(`Duplicate exchange: ${tokenA} ${tokenB}`)
return {
...exchangeMap,
...pairMap,
[tokens[0].chainId]: {
...exchangeMap?.[tokens[0].chainId],
...pairMap?.[tokens[0].chainId],
[tokens[0].address]: {
...exchangeMap?.[tokens[0].chainId]?.[tokens[0].address],
[tokens[1].address]: Exchange.getAddress(...tokens)
...pairMap?.[tokens[0].chainId]?.[tokens[0].address],
[tokens[1].address]: Pair.getAddress(...tokens)
}
}
}
}, {})
const ExchangeContext = createContext([])
const PairContext = createContext([])
function useExchangesContext() {
return useContext(ExchangeContext)
function usePairContext() {
return useContext(PairContext)
}
function reducer(state, { type, payload }) {
......@@ -56,7 +55,7 @@ function reducer(state, { type, payload }) {
...state?.[tokensSorted[0].chainId],
[tokensSorted[0].address]: {
...state?.[tokensSorted[0].chainId]?.[tokensSorted[0].address],
[tokensSorted[1].address]: Exchange.getAddress(tokensSorted[0], tokensSorted[1])
[tokensSorted[1].address]: Pair.getAddress(tokensSorted[0], tokensSorted[1])
}
}
}
......@@ -68,22 +67,20 @@ function reducer(state, { type, payload }) {
}
export default function Provider({ children }) {
const [state, dispatch] = useReducer(reducer, EXCHANGE_MAP)
const [state, dispatch] = useReducer(reducer, PAIR_MAP)
const update = useCallback((chainId, tokens) => {
dispatch({ type: UPDATE, payload: { chainId, tokens } })
}, [])
return (
<ExchangeContext.Provider value={useMemo(() => [state, { update }], [state, update])}>
{children}
</ExchangeContext.Provider>
<PairContext.Provider value={useMemo(() => [state, { update }], [state, update])}>{children}</PairContext.Provider>
)
}
export function useExchangeAddress(tokenA?: Token, tokenB?: Token): string | undefined {
export function usePairAddress(tokenA?: Token, tokenB?: Token): string | undefined {
const { chainId } = useWeb3React()
const [state, { update }] = useExchangesContext()
const [state, { update }] = usePairContext()
const tokens: [Token, Token] = tokenA && tokenB && tokenA.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA]
......@@ -91,79 +88,81 @@ export function useExchangeAddress(tokenA?: Token, tokenB?: Token): string | und
useEffect(() => {
if (address === undefined && tokenA && tokenB) {
const exchangeAddress = Exchange.getAddress(...tokens)
exchangeAddress && update(chainId, tokens)
const pairAddress = Pair.getAddress(...tokens)
pairAddress && update(chainId, tokens)
}
}, [chainId, address, tokenA, tokenB, tokens, update])
return address
}
export function useExchange(tokenA?: Token, tokenB?: Token): Exchange | undefined {
const address = useExchangeAddress(tokenA, tokenB)
export function usePair(tokenA?: Token, tokenB?: Token): Pair | undefined {
const address = usePairAddress(tokenA, tokenB)
const tokenAmountA = useAddressBalance(address, tokenA)
const tokenAmountB = useAddressBalance(address, tokenB)
const pair = tokenAmountA && tokenAmountB && new Pair(tokenAmountA, tokenAmountB)
const exchange = tokenAmountA && tokenAmountB && new Exchange(tokenAmountA, tokenAmountB)
// return pair
return exchange
return useMemo(() => {
return pair
}, [pair])
}
export function useAllExchangesRaw() {
export function useAllPairsRaw() {
const { chainId } = useWeb3React()
const [state] = useExchangesContext()
const [state] = usePairContext()
const allExchangeDetails = state?.[chainId]
return allExchangeDetails
}
export function useAllExchanges() {
export function useAllPairs() {
const { chainId } = useWeb3React()
const [state] = useExchangesContext()
const [state] = usePairContext()
const allExchangeDetails = state?.[chainId]
const allPairDetails = state?.[chainId]
const allExchanges = useMemo(() => {
if (!allExchangeDetails) {
const allPairs = useMemo(() => {
if (!allPairDetails) {
return {}
}
const formattedExchanges = {}
Object.keys(allExchangeDetails).map(token0Address => {
return Object.keys(allExchangeDetails[token0Address]).map(token1Address => {
const exchangeAddress = allExchangeDetails[token0Address][token1Address]
return (formattedExchanges[exchangeAddress] = {
Object.keys(allPairDetails).map(token0Address => {
return Object.keys(allPairDetails[token0Address]).map(token1Address => {
const pairAddress = allPairDetails[token0Address][token1Address]
return (formattedExchanges[pairAddress] = {
token0: token0Address,
token1: token1Address
})
})
})
return formattedExchanges
}, [allExchangeDetails])
}, [allPairDetails])
return useMemo(() => {
return allExchanges || {}
}, [allExchanges])
return allPairs || {}
}, [allPairs])
}
export function useTotalSupply(exchange: Exchange) {
export function useTotalSupply(pair: Pair) {
const { library } = useWeb3React()
const [totalPoolTokens, setTotalPoolTokens] = useState<TokenAmount>()
const exchangeContract = useExchangeContract(exchange?.liquidityToken.address)
const pairContract = usePairContract(pair?.liquidityToken.address)
const fetchPoolTokens = useCallback(async () => {
!!exchangeContract &&
exchangeContract
!!pairContract &&
pairContract
.deployed()
.then(() => {
if (exchangeContract) {
exchangeContract.totalSupply().then(totalSupply => {
if (totalSupply !== undefined && exchange?.liquidityToken?.decimals) {
if (pairContract) {
pairContract.totalSupply().then(totalSupply => {
if (totalSupply !== undefined && pair?.liquidityToken?.decimals) {
const supplyFormatted = JSBI.BigInt(totalSupply)
const tokenSupplyFormatted = new TokenAmount(exchange?.liquidityToken, supplyFormatted)
const tokenSupplyFormatted = new TokenAmount(pair?.liquidityToken, supplyFormatted)
setTotalPoolTokens(tokenSupplyFormatted)
}
})
......@@ -175,7 +174,7 @@ export function useTotalSupply(exchange: Exchange) {
* fix this
*/
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [exchangeContract])
}, [pairContract])
// on the block make sure we're updated
useEffect(() => {
......
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'
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[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 && !tokenA.equals(WETH[chainId]) ? tokenA : null, WETH[chainId])
const bToETH = usePair(tokenB && !tokenB.equals(WETH[chainId]) ? 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 pairs, possibly to reference empty pair
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)
}
}
/**
* @todo
* same infinite render bug here when including
* any token or pair instance as dependency (bug also in exchanegs and balances)
*/
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [route, requiresHop, update, chainId])
return useMemo(() => route, [route])
}
......@@ -10,6 +10,7 @@ export const ALL_TOKENS = [
WETH[ChainId.RINKEBY],
new Token(ChainId.RINKEBY, '0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735', 18, 'DAI', 'Dai Stablecoin'),
new Token(ChainId.RINKEBY, '0x8ab15C890E5C03B5F240f2D146e3DF54bEf3Df44', 18, 'IANV2', 'IAn V2 /Coin'),
new Token(ChainId.RINKEBY, '0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85', 18, 'MKR', 'Maker'),
//Kovan Tokens
WETH[ChainId.KOVAN],
......
......@@ -210,16 +210,16 @@ export function useFactoryContract(withSignerIfPossible = true) {
}, [chainId, library, withSignerIfPossible, account])
}
export function useExchangeContract(exchangeAddress, withSignerIfPossible = true) {
export function usePairContract(pairAddress, withSignerIfPossible = true) {
const { library, account } = useWeb3React()
return useMemo(() => {
try {
return getExchangeContract(exchangeAddress, library, withSignerIfPossible ? account : undefined)
return getExchangeContract(pairAddress, library, withSignerIfPossible ? account : undefined)
} catch {
return null
}
}, [exchangeAddress, library, withSignerIfPossible, account])
}, [pairAddress, library, withSignerIfPossible, account])
}
export function useCopyClipboard(timeout = 500) {
......
......@@ -11,8 +11,9 @@ import ApplicationContextProvider, { Updater as ApplicationContextUpdater } from
import TransactionContextProvider, { Updater as TransactionContextUpdater } from './contexts/Transactions'
import BalancesContextProvider, { Updater as BalancesContextUpdater } from './contexts/Balances'
import TokensContextProvider from './contexts/Tokens'
import ExchangesContextProvider from './contexts/Exchanges'
import ExchangesContextProvider from './contexts/Pairs'
import AllowancesContextProvider from './contexts/Allowances'
import RoutesContextProvider from './contexts/Routes'
import App from './pages/App'
import ThemeProvider, { GlobalStyle } from './theme'
import './i18n'
......@@ -42,11 +43,13 @@ function ContextProviders({ children }) {
<ApplicationContextProvider>
<TransactionContextProvider>
<ExchangesContextProvider>
<TokensContextProvider>
<BalancesContextProvider>
<AllowancesContextProvider>{children}</AllowancesContextProvider>
</BalancesContextProvider>
</TokensContextProvider>
<RoutesContextProvider>
<TokensContextProvider>
<BalancesContextProvider>
<AllowancesContextProvider>{children}</AllowancesContextProvider>
</BalancesContextProvider>
</TokensContextProvider>
</RoutesContextProvider>
</ExchangesContextProvider>
</TransactionContextProvider>
</ApplicationContextProvider>
......
......@@ -2,7 +2,7 @@ import React, { useReducer, useState, useCallback, useEffect } from 'react'
import styled from 'styled-components'
import { ethers } from 'ethers'
import { parseUnits, parseEther } from '@ethersproject/units'
import { WETH, TokenAmount, JSBI, Percent, Route, Token, Exchange } from '@uniswap/sdk'
import { WETH, TokenAmount, JSBI, Percent, Route, Token, Pair } from '@uniswap/sdk'
import TokenLogo from '../../components/TokenLogo'
import DoubleLogo from '../../components/DoubleLogo'
......@@ -22,7 +22,7 @@ import { useWeb3React } from '../../hooks'
import { useAddressBalance } from '../../contexts/Balances'
import { useAddressAllowance } from '../../contexts/Allowances'
import { useTransactionAdder } from '../../contexts/Transactions'
import { useExchange, useTotalSupply } from '../../contexts/Exchanges'
import { usePair, useTotalSupply } from '../../contexts/Pairs'
import { BigNumber } from 'ethers/utils'
import { ROUTER_ADDRESSES } from '../../constants'
......@@ -159,9 +159,9 @@ export default function AddLiquidity({ token0, token1 }) {
}
// exhchange data
const exchange: Exchange = useExchange(tokens[Field.INPUT], tokens[Field.OUTPUT])
const route: Route = exchange ? new Route([exchange], tokens[independentField]) : undefined
const totalSupply: TokenAmount = useTotalSupply(exchange)
const pair: Pair = usePair(tokens[Field.INPUT], tokens[Field.OUTPUT])
const route: Route = pair ? new Route([pair], tokens[independentField]) : undefined
const totalSupply: TokenAmount = useTotalSupply(pair)
const [noLiquidity, setNoLiquidity] = useState<boolean>(false) // used to detect new exchange
// state for amount approvals
......@@ -178,14 +178,10 @@ export default function AddLiquidity({ token0, token1 }) {
// check if no exchange or no liquidity
useEffect(() => {
if (
exchange &&
JSBI.equal(exchange.reserve0.raw, JSBI.BigInt(0)) &&
JSBI.equal(exchange.reserve1.raw, JSBI.BigInt(0))
) {
if (pair && JSBI.equal(pair.reserve0.raw, JSBI.BigInt(0)) && JSBI.equal(pair.reserve1.raw, JSBI.BigInt(0))) {
setNoLiquidity(true)
}
}, [exchange])
}, [pair])
// track non relational amounts if first person to add liquidity
const [nonrelationalAmounts, setNonrelationalAmounts] = useState({
......@@ -238,13 +234,13 @@ export default function AddLiquidity({ token0, token1 }) {
// check for estimated liquidity minted
const liquidityMinted: TokenAmount =
!!exchange &&
!!pair &&
!!parsedAmounts[Field.INPUT] &&
!!parsedAmounts[Field.OUTPUT] &&
!JSBI.equal(parsedAmounts[Field.INPUT].raw, JSBI.BigInt(0)) &&
!JSBI.equal(parsedAmounts[Field.OUTPUT].raw, JSBI.BigInt(0))
? exchange.getLiquidityMinted(
totalSupply ? totalSupply : new TokenAmount(exchange?.liquidityToken, JSBI.BigInt(0)),
? pair.getLiquidityMinted(
totalSupply ? totalSupply : new TokenAmount(pair?.liquidityToken, JSBI.BigInt(0)),
parsedAmounts[Field.INPUT],
parsedAmounts[Field.OUTPUT]
)
......@@ -571,9 +567,8 @@ export default function AddLiquidity({ token0, token1 }) {
atMax={atMaxAmountInput}
token={tokens[Field.INPUT]}
onTokenSelection={onTokenSelection}
title={'Deposit'}
error={inputError}
exchange={exchange}
pair={pair}
showUnlock={showInputUnlock}
disableTokenSelect
/>
......@@ -590,9 +585,8 @@ export default function AddLiquidity({ token0, token1 }) {
atMax={atMaxAmountOutput}
token={tokens[Field.OUTPUT]}
onTokenSelection={onTokenSelection}
title={'Deposit'}
error={outputError}
exchange={exchange}
pair={pair}
showUnlock={showOutputUnlock}
disableTokenSelect
/>
......@@ -618,7 +612,7 @@ export default function AddLiquidity({ token0, token1 }) {
{!noLiquidity && (
<FixedBottom>
<PositionCard
exchangeAddress={exchange?.liquidityToken?.address}
pairAddress={pair?.liquidityToken?.address}
token0={tokens[Field.INPUT]}
token1={tokens[Field.OUTPUT]}
minimal={true}
......
......@@ -2,7 +2,7 @@ import React, { useReducer, useState, useCallback, useEffect } from 'react'
import styled from 'styled-components'
import { ethers } from 'ethers'
import { parseUnits } from '@ethersproject/units'
import { TokenAmount, JSBI, Route, WETH, Percent, Token, Exchange } from '@uniswap/sdk'
import { TokenAmount, JSBI, Route, WETH, Percent, Token, Pair } from '@uniswap/sdk'
import Slider from '../../components/Slider'
import TokenLogo from '../../components/TokenLogo'
......@@ -21,9 +21,9 @@ import Row, { RowBetween, RowFixed } from '../../components/Row'
import { useToken } from '../../contexts/Tokens'
import { useWeb3React } from '../../hooks'
import { useAllBalances } from '../../contexts/Balances'
import { useExchangeContract } from '../../hooks'
import { usePairContract } from '../../hooks'
import { useTransactionAdder } from '../../contexts/Transactions'
import { useExchange, useTotalSupply } from '../../contexts/Exchanges'
import { usePair, useTotalSupply } from '../../contexts/Pairs'
import { BigNumber } from 'ethers/utils'
import { splitSignature } from '@ethersproject/bytes'
......@@ -160,14 +160,14 @@ export default function RemoveLiquidity({ token0, token1 }) {
[Field.TOKEN1]: outputToken
}
const exchange: Exchange = useExchange(inputToken, outputToken)
const exchangeContract: ethers.Contract = useExchangeContract(exchange?.liquidityToken.address)
const pair: Pair = usePair(inputToken, outputToken)
const pairContract: ethers.Contract = usePairContract(pair?.liquidityToken.address)
// pool token data
const totalPoolTokens: TokenAmount = useTotalSupply(exchange)
const totalPoolTokens: TokenAmount = useTotalSupply(pair)
const allBalances: TokenAmount[] = useAllBalances()
const userLiquidity: TokenAmount = allBalances?.[account]?.[exchange?.liquidityToken?.address]
const userLiquidity: TokenAmount = allBalances?.[account]?.[pair?.liquidityToken?.address]
// input state
const [state, dispatch] = useReducer(reducer, initializeRemoveState(userLiquidity?.toExact(), token0, token1))
......@@ -175,19 +175,19 @@ export default function RemoveLiquidity({ token0, token1 }) {
const TokensDeposited: { [field: number]: TokenAmount } = {
[Field.TOKEN0]:
exchange &&
pair &&
totalPoolTokens &&
userLiquidity &&
exchange.getLiquidityValue(tokens[Field.TOKEN0], totalPoolTokens, userLiquidity, false),
pair.getLiquidityValue(tokens[Field.TOKEN0], totalPoolTokens, userLiquidity, false),
[Field.TOKEN1]:
exchange &&
pair &&
totalPoolTokens &&
userLiquidity &&
exchange.getLiquidityValue(tokens[Field.TOKEN1], totalPoolTokens, userLiquidity, false)
pair.getLiquidityValue(tokens[Field.TOKEN1], totalPoolTokens, userLiquidity, false)
}
const route: Route = exchange
? new Route([exchange], independentField !== Field.LIQUIDITY ? tokens[independentField] : tokens[Field.TOKEN1])
const route: Route = pair
? new Route([pair], independentField !== Field.LIQUIDITY ? tokens[independentField] : tokens[Field.TOKEN1])
: undefined
// update input value when user types
......@@ -199,7 +199,7 @@ export default function RemoveLiquidity({ token0, token1 }) {
onUserInput(
Field.LIQUIDITY,
new TokenAmount(
exchange?.liquidityToken,
pair?.liquidityToken,
JSBI.divide(JSBI.multiply(userLiquidity.raw, JSBI.BigInt(newPercent)), JSBI.BigInt(100))
).toExact()
)
......@@ -240,8 +240,8 @@ export default function RemoveLiquidity({ token0, token1 }) {
}
}
if (independentField === Field.LIQUIDITY) {
const typedValueParsed = parseUnits(typedValue, exchange?.liquidityToken.decimals).toString()
const formattedAmount = new TokenAmount(exchange?.liquidityToken, typedValueParsed)
const typedValueParsed = parseUnits(typedValue, pair?.liquidityToken.decimals).toString()
const formattedAmount = new TokenAmount(pair?.liquidityToken, typedValueParsed)
if (typedValueParsed !== '0') {
if (JSBI.lessThanOrEqual(formattedAmount.raw, userLiquidity?.raw)) {
poolTokenAmount = typedValueParsed
......@@ -256,19 +256,19 @@ export default function RemoveLiquidity({ token0, token1 }) {
// set parsed amounts based on live amount of liquidity
parsedAmounts[Field.LIQUIDITY] =
exchange && poolTokenAmount && userLiquidity && new TokenAmount(exchange.liquidityToken, poolTokenAmount)
pair && poolTokenAmount && userLiquidity && new TokenAmount(pair.liquidityToken, poolTokenAmount)
parsedAmounts[Field.TOKEN0] =
totalPoolTokens &&
exchange &&
pair &&
parsedAmounts[Field.LIQUIDITY] &&
exchange.getLiquidityValue(tokens[Field.TOKEN0], totalPoolTokens, parsedAmounts[Field.LIQUIDITY], false)
pair.getLiquidityValue(tokens[Field.TOKEN0], totalPoolTokens, parsedAmounts[Field.LIQUIDITY], false)
parsedAmounts[Field.TOKEN1] =
totalPoolTokens &&
exchange &&
pair &&
parsedAmounts[Field.LIQUIDITY] &&
exchange.getLiquidityValue(tokens[Field.TOKEN1], totalPoolTokens, parsedAmounts[Field.LIQUIDITY], false)
pair.getLiquidityValue(tokens[Field.TOKEN1], totalPoolTokens, parsedAmounts[Field.LIQUIDITY], false)
// derived percent for advanced mode
const derivedPerecent =
......@@ -358,7 +358,7 @@ export default function RemoveLiquidity({ token0, token1 }) {
const [pendingConfirmation, setPendingConfirmation] = useState(true) // waiting for
async function onSign() {
const nonce = await exchangeContract.nonces(account)
const nonce = await pairContract.nonces(account)
const newDeadline: number = Math.ceil(Date.now() / 1000) + DEADLINE_FROM_NOW
setDeadline(newDeadline)
......@@ -374,7 +374,7 @@ export default function RemoveLiquidity({ token0, token1 }) {
name: 'Uniswap V2',
version: '1',
chainId: chainId,
verifyingContract: exchange.liquidityToken.address
verifyingContract: pair.liquidityToken.address
}
const Permit = [
......@@ -646,12 +646,11 @@ export default function RemoveLiquidity({ token0, token1 }) {
onUserInput={onUserInput}
onMax={onMax}
atMax={atMaxAmount}
title={'Burn'}
error={poolTokenError}
disableTokenSelect
token={exchange?.liquidityToken}
token={pair?.liquidityToken}
isExchange={true}
exchange={exchange}
pair={pair}
/>
<ColumnCenter>
<ArrowDown size="16" color="#888D9B" />
......@@ -663,7 +662,6 @@ export default function RemoveLiquidity({ token0, token1 }) {
onMax={onMax}
atMax={atMaxAmount}
token={tokens[Field.TOKEN0]}
title={'Withdraw'}
error={inputError}
disableTokenSelect
customBalance={TokensDeposited[Field.TOKEN0]}
......@@ -678,7 +676,6 @@ export default function RemoveLiquidity({ token0, token1 }) {
onMax={onMax}
atMax={atMaxAmount}
token={tokens[Field.TOKEN1]}
title={'Withdraw'}
error={outputError}
disableTokenSelect
customBalance={TokensDeposited[Field.TOKEN1]}
......@@ -689,11 +686,11 @@ export default function RemoveLiquidity({ token0, token1 }) {
<RowBetween>
Price:
<div>
1 {exchange?.token0.symbol} ={' '}
1 {pair?.token0.symbol} ={' '}
{independentField === Field.TOKEN0 || independentField === Field.LIQUIDITY
? route?.midPrice.toSignificant(6)
: route?.midPrice.invert().toSignificant(6)}{' '}
{exchange?.token1.symbol}
{pair?.token1.symbol}
</div>
</RowBetween>
</div>
......@@ -717,9 +714,9 @@ export default function RemoveLiquidity({ token0, token1 }) {
</ButtonPrimary>
<FixedBottom>
<PositionCard
exchangeAddress={exchange?.liquidityToken.address}
token0={exchange?.token0}
token1={exchange?.token1}
pairAddress={pair?.liquidityToken.address}
token0={pair?.token0}
token1={pair?.token1}
minimal={true}
/>
</FixedBottom>
......
......@@ -14,9 +14,9 @@ import { AutoColumn } from '../../components/Column'
import { ArrowRight } from 'react-feather'
import { ButtonPrimary } from '../../components/Button'
import { useAllPairs } from '../../contexts/Pairs'
import { useWeb3React } from '@web3-react/core'
import { useAllTokens } from '../../contexts/Tokens'
import { useAllExchanges } from '../../contexts/Exchanges'
import { useAllBalances, useAccountLPBalances } from '../../contexts/Balances'
const Positions = styled.div`
......@@ -35,27 +35,27 @@ function Supply({ history }) {
const allTokens = useAllTokens()
const allBalances = useAllBalances()
const allExchanges = useAllExchanges()
const allPairs = useAllPairs()
// initiate listener for LP balances
useAccountLPBalances(account)
const filteredExchangeList = Object.keys(allExchanges)
.filter((exchangeAddress, i) => {
const filteredExchangeList = Object.keys(allPairs)
.filter((pairAddress, i) => {
return (
allBalances &&
allBalances[account] &&
allBalances[account][exchangeAddress] &&
JSBI.greaterThan(allBalances[account][exchangeAddress].raw, JSBI.BigInt(0))
allBalances[account][pairAddress] &&
JSBI.greaterThan(allBalances[account][pairAddress].raw, JSBI.BigInt(0))
)
})
.map((exchangeAddress, i) => {
.map((pairAddress, i) => {
return (
<PositionCard
key={i}
exchangeAddress={exchangeAddress}
token0={allTokens[allExchanges[exchangeAddress].token0]}
token1={allTokens[allExchanges[exchangeAddress].token1]}
pairAddress={pairAddress}
token0={allTokens[allPairs[pairAddress].token0]}
token1={allTokens[allPairs[pairAddress].token1]}
/>
)
})
......
......@@ -142,8 +142,8 @@ export function getFactoryContract(networkId, library, account) {
}
// account is optional
export function getExchangeContract(exchangeAddress, library, account) {
return getContract(exchangeAddress, EXCHANGE_ABI, library, account)
export function getExchangeContract(pairAddress, library, account) {
return getContract(pairAddress, EXCHANGE_ABI, library, account)
}
// get token name
......@@ -198,7 +198,7 @@ export async function getTokenDecimals(tokenAddress, library) {
}
// get the exchange address for a token from the factory
export async function getTokenExchangeAddressFromFactory(tokenAddress, networkId, library) {
export async function getTokenpairAddressFromFactory(tokenAddress, networkId, library) {
return getFactoryContract(networkId, library).getExchange(tokenAddress)
}
......
......@@ -2385,10 +2385,10 @@
semver "^6.3.0"
tsutils "^3.17.1"
"@uniswap/sdk@@uniswap/sdk@2.0.0-beta.19":
version "2.0.0-beta.19"
resolved "https://registry.yarnpkg.com/@uniswap/sdk/-/sdk-2.0.0-beta.19.tgz#1f0228a1d5451d62f209e09c48cd1d6bea5ffe01"
integrity sha512-mqDZkeX2TU7e3yOOKHSeUryv94//mJ6dsU6dCv6FExrfOY9yi6+O5ZWpe43rVi0XFVdQGRIRhJapdWKWaGsung==
"@uniswap/sdk@@uniswap/sdk@2.0.0-beta.20":
version "2.0.0-beta.20"
resolved "https://registry.yarnpkg.com/@uniswap/sdk/-/sdk-2.0.0-beta.20.tgz#f541909158d053d8bf9ae8af62b2b4f83cc7068c"
integrity sha512-PuXlwGKrEd3L+eIs4oQZQ3IFnVZe/JN9U2jyV6DPjO/dmBL8mzCaqMAiAmQSEAIrBSHFTpxYwklltbY/bU7+Dg==
dependencies:
"@ethersproject/address" "^5.0.0-beta.134"
"@ethersproject/contracts" "^5.0.0-beta.143"
......
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