Commit 2ca3bf8d authored by ianlapham's avatar ianlapham

add slider to remove

parent 236c3030
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
"private": true, "private": true,
"dependencies": { "dependencies": {
"@ethersproject/units": "^5.0.0-beta.132", "@ethersproject/units": "^5.0.0-beta.132",
"@material-ui/core": "^4.9.5",
"@reach/dialog": "^0.2.8", "@reach/dialog": "^0.2.8",
"@reach/tooltip": "^0.2.0", "@reach/tooltip": "^0.2.0",
"@types/jest": "^25.1.3", "@types/jest": "^25.1.3",
......
import React from 'react' import React from 'react'
import { Button as RebassButton } from 'rebass/styled-components' import { Button as RebassButton } from 'rebass/styled-components'
import styled from 'styled-components' import styled from 'styled-components'
import { darken } from 'polished' import { darken, lighten } from 'polished'
import { RowBetween } from '../Row' import { RowBetween } from '../Row'
import { ChevronDown } from 'react-feather' import { ChevronDown } from 'react-feather'
...@@ -87,6 +87,24 @@ export const ButtonEmpty = styled(Base)` ...@@ -87,6 +87,24 @@ export const ButtonEmpty = styled(Base)`
} }
` `
const ButtonConfirmedStyle = styled(Base)`
background-color: ${({ theme }) => lighten(0.5, theme.connectedGreen)};
border: 1px solid ${({ theme }) => theme.connectedGreen};
&:disabled {
opacity: 50%;
cursor: auto;
}
`
export function ButtonConfirmed({ children, confirmed, ...rest }) {
if (confirmed) {
return <ButtonConfirmedStyle {...rest}>{children}</ButtonConfirmedStyle>
} else {
return <ButtonPrimary {...rest}>{children}</ButtonPrimary>
}
}
export function ButtonDropwdown({ disabled, children, ...rest }) { export function ButtonDropwdown({ disabled, children, ...rest }) {
return ( return (
<ButtonPrimary {...rest}> <ButtonPrimary {...rest}>
......
...@@ -8,9 +8,12 @@ const Card = styled(Box)` ...@@ -8,9 +8,12 @@ const Card = styled(Box)`
padding: ${({ padding }) => padding}; padding: ${({ padding }) => padding};
border: ${({ border }) => border}; border: ${({ border }) => border};
` `
export default Card export default Card
export const LightCard = styled(Card)` export const LightCard = styled(Card)`
border: 1px solid ${({ theme }) => theme.outlineGrey}; border: 1px solid ${({ theme }) => theme.outlineGrey};
` `
export const GreyCard = styled(Card)`
background-color: rgba(255, 255, 255, 0.6);
`
import React, { useState } from 'react' import React from 'react'
import styled from 'styled-components' import styled from 'styled-components'
import { ButtonPrimary } from '../Button' import { ButtonPrimary } from '../Button'
...@@ -6,6 +6,7 @@ import { AutoColumn, ColumnCenter } from '../Column' ...@@ -6,6 +6,7 @@ import { AutoColumn, ColumnCenter } from '../Column'
import Row, { RowBetween, RowFlat, RowFixed } from '../Row' import Row, { RowBetween, RowFlat, RowFixed } from '../Row'
import { ArrowDown } from 'react-feather' import { ArrowDown } from 'react-feather'
import { ButtonConfirmed } from '../Button'
import { Text } from 'rebass' import { Text } from 'rebass'
import { LightCard } from '../Card' import { LightCard } from '../Card'
import Modal from '../Modal' import Modal from '../Modal'
...@@ -35,6 +36,10 @@ const ConfirmedIcon = styled(ColumnCenter)` ...@@ -35,6 +36,10 @@ const ConfirmedIcon = styled(ColumnCenter)`
padding: 60px 0; padding: 60px 0;
` `
const ConfirmedText = styled(Text)`
color: ${({ theme, confirmed }) => (confirmed ? theme.connectedGreen : theme.white)};
`
export default function ConfirmationModal({ export default function ConfirmationModal({
isOpen, isOpen,
onDismiss, onDismiss,
...@@ -46,23 +51,23 @@ export default function ConfirmationModal({ ...@@ -46,23 +51,23 @@ export default function ConfirmationModal({
transactionType, transactionType,
pendingConfirmation, pendingConfirmation,
hash, hash,
contractCall signed = false,
contractCall,
attemptedRemoval = false,
extraCall = undefined
}) { }) {
const { address: address0, symbol: symbol0 } = amount0?.token || {} const { address: address0, symbol: symbol0 } = amount0?.token || {}
const { address: address1, symbol: symbol1 } = amount1?.token || {} const { address: address1, symbol: symbol1 } = amount1?.token || {}
const { chainId } = useWeb3React() const { chainId } = useWeb3React()
const [confirmed, setConfirmed] = useState(false)
function WrappedOnDismissed() { function WrappedOnDismissed() {
onDismiss() onDismiss()
setConfirmed(false)
} }
return ( return (
<Modal isOpen={isOpen} onDismiss={onDismiss}> <Modal isOpen={isOpen} onDismiss={WrappedOnDismissed}>
{!confirmed ? ( {!attemptedRemoval ? (
<Wrapper> <Wrapper>
<Section gap="40px"> <Section gap="40px">
<RowBetween> <RowBetween>
...@@ -195,22 +200,51 @@ export default function ConfirmationModal({ ...@@ -195,22 +200,51 @@ export default function ConfirmationModal({
</Text> </Text>
</RowBetween> </RowBetween>
)} )}
<ButtonPrimary {transactionType === TRANSACTION_TYPE.REMOVE ? (
style={{ margin: '20px 0' }} <RowBetween gap="20px">
onClick={() => { <ButtonConfirmed
setConfirmed(true) style={{ margin: '20px 0' }}
contractCall() width="48%"
}} onClick={() => {
> extraCall()
<Text fontWeight={500} fontSize={20}> }}
Confirm{' '} confirmed={signed}
{transactionType === TRANSACTION_TYPE.ADD disabled={signed}
? 'Supply' >
: transactionType === TRANSACTION_TYPE.REMOVE <ConfirmedText fontWeight={500} fontSize={20} confirmed={signed}>
? 'Remove' {signed ? 'Signed' : 'Sign'}
: 'Swap'} </ConfirmedText>
</Text> </ButtonConfirmed>
</ButtonPrimary> <ButtonPrimary
width="48%"
disabled={!signed}
style={{ margin: '20px 0' }}
onClick={() => {
contractCall()
}}
>
<Text fontWeight={500} fontSize={20}>
Confirm Remove
</Text>
</ButtonPrimary>
</RowBetween>
) : (
<ButtonPrimary
style={{ margin: '20px 0' }}
onClick={() => {
contractCall()
}}
>
<Text fontWeight={500} fontSize={20}>
Confirm{' '}
{transactionType === TRANSACTION_TYPE.ADD
? 'Supply'
: transactionType === TRANSACTION_TYPE.REMOVE
? 'Remove'
: 'Swap'}
</Text>
</ButtonPrimary>
)}
{transactionType === TRANSACTION_TYPE.ADD && ( {transactionType === TRANSACTION_TYPE.ADD && (
<Text fontSize={12} color="#565A69" textAlign="center"> <Text fontSize={12} color="#565A69" textAlign="center">
{`Output is estimated. You will receive at least ${liquidityAmount?.toFixed( {`Output is estimated. You will receive at least ${liquidityAmount?.toFixed(
......
...@@ -245,7 +245,7 @@ export default function CurrencyInputPanel({ ...@@ -245,7 +245,7 @@ export default function CurrencyInputPanel({
<ErrorSpan data-tip={'Enter max'} error={!!error} onClick={() => {}}></ErrorSpan> <ErrorSpan data-tip={'Enter max'} error={!!error} onClick={() => {}}></ErrorSpan>
<ClickableText onClick={onMax}> <ClickableText onClick={onMax}>
<Text> <Text>
Balance: {customBalance ? customBalance.toSignificant(4) : userTokenBalance?.toSignificant(4)} Balance: {customBalance ? customBalance?.toSignificant(4) : userTokenBalance?.toSignificant(4)}
</Text> </Text>
</ClickableText> </ClickableText>
</RowBetween> </RowBetween>
...@@ -273,7 +273,7 @@ export default function CurrencyInputPanel({ ...@@ -273,7 +273,7 @@ export default function CurrencyInputPanel({
> >
<Aligner> <Aligner>
{isExchange ? ( {isExchange ? (
<DoubleLogo a0={exchange?.token0.address} a1={exchange?.token1.address} margin={true} /> <DoubleLogo a0={exchange?.token0.address} a1={exchange?.token1.address} size={24} margin={true} />
) : token?.address ? ( ) : token?.address ? (
<TokenLogo address={token?.address} size={'24px'} /> <TokenLogo address={token?.address} size={'24px'} />
) : null} ) : null}
......
...@@ -7,7 +7,7 @@ export default function DoubleTokenLogo({ a0, a1, size = 16, margin = false }) { ...@@ -7,7 +7,7 @@ export default function DoubleTokenLogo({ a0, a1, size = 16, margin = false }) {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
margin-right: ${({ sizeraw, margin }) => margin && (sizeraw / 2 + 10).toString() + 'px'}; margin-right: ${({ sizeraw, margin }) => margin && (sizeraw / 3 + 8).toString() + 'px'};
` `
const HigherLogo = styled(TokenLogo)` const HigherLogo = styled(TokenLogo)`
......
import React, { useState, useReducer, useCallback, useEffect } from 'react' import React, { useState, useReducer, useCallback, useEffect } from 'react'
import { ethers } from 'ethers'
import styled from 'styled-components' import styled from 'styled-components'
import { ethers } from 'ethers'
import { parseUnits, parseEther } from '@ethersproject/units' import { parseUnits, parseEther } from '@ethersproject/units'
import { WETH, TradeType, Route, Trade, TokenAmount, JSBI } from '@uniswap/sdk' import { WETH, TradeType, Route, Trade, TokenAmount, JSBI } from '@uniswap/sdk'
import { useWeb3React } from '../../hooks'
import { useToken } from '../../contexts/Tokens' import { useToken } from '../../contexts/Tokens'
import { useExchange } from '../../contexts/Exchanges' import { useExchange } from '../../contexts/Exchanges'
import { useTransactionAdder } from '../../contexts/Transactions' import { useWeb3React } from '../../hooks'
import { useAddressBalance } from '../../contexts/Balances' import { useAddressBalance } from '../../contexts/Balances'
import { useTransactionAdder } from '../../contexts/Transactions'
import { useAddressAllowance } from '../../contexts/Allowances' import { useAddressAllowance } from '../../contexts/Allowances'
import ConfirmationModal from '../ConfirmationModal'
import CurrencyInputPanel from '../CurrencyInputPanel'
import { Text } from 'rebass' import { Text } from 'rebass'
import { ButtonPrimary } from '../Button'
import { AutoColumn, ColumnCenter } from '../../components/Column'
import { RowBetween } from '../../components/Row' import { RowBetween } from '../../components/Row'
import { ButtonPrimary } from '../Button'
import { ArrowDown, ArrowUp } from 'react-feather' import { ArrowDown, ArrowUp } from 'react-feather'
import CurrencyInputPanel from '../CurrencyInputPanel' import { AutoColumn, ColumnCenter } from '../../components/Column'
import ConfirmationModal from '../ConfirmationModal'
import { TRANSACTION_TYPE, ROUTER_ADDRESSES } from '../../constants'
import { getRouterContract, calculateGasMargin } from '../../utils' import { getRouterContract, calculateGasMargin } from '../../utils'
import { TRANSACTION_TYPE } from '../../constants'
const ArrowWrapper = styled.div` const ArrowWrapper = styled.div`
padding: 4px; padding: 4px;
...@@ -138,6 +138,7 @@ function reducer( ...@@ -138,6 +138,7 @@ function reducer(
export default function ExchangePage() { export default function ExchangePage() {
const { chainId, account, library } = useWeb3React() const { chainId, account, library } = useWeb3React()
const routerAddress = ROUTER_ADDRESSES[chainId]
const [state, dispatch] = useReducer(reducer, WETH[chainId].address, initializeSwapState) const [state, dispatch] = useReducer(reducer, WETH[chainId].address, initializeSwapState)
const { independentField, typedValue, ...fieldData } = state const { independentField, typedValue, ...fieldData } = state
...@@ -326,8 +327,6 @@ export default function ExchangePage() { ...@@ -326,8 +327,6 @@ export default function ExchangePage() {
: calculateSlippageAmount(parsedAmounts[Field.OUTPUT])?.[0] : calculateSlippageAmount(parsedAmounts[Field.OUTPUT])?.[0]
} }
const routerAddress = '0xd9210Ff5A0780E083BB40e30d005d93a2DcFA4EF'
const inputApproval = useAddressAllowance(account, tokens[Field.INPUT], routerAddress) const inputApproval = useAddressAllowance(account, tokens[Field.INPUT], routerAddress)
const outputApproval = useAddressAllowance(account, tokens[Field.OUTPUT], routerAddress) const outputApproval = useAddressAllowance(account, tokens[Field.OUTPUT], routerAddress)
......
import React from 'react'
import styled from 'styled-components'
import { withRouter } from 'react-router-dom'
import { Percent, Exchange } from '@uniswap/sdk'
import { useWeb3React } from '@web3-react/core'
import { useAllBalances } from '../../contexts/Balances'
import { useTotalSupply } from '../../contexts/Exchanges'
import Card from '../Card'
import TokenLogo from '../TokenLogo'
import DoubleLogo from '../DoubleLogo'
import { Text } from 'rebass'
import { GreyCard } from '../../components/Card'
import { AutoColumn } from '../Column'
import { ButtonSecondary } from '../Button'
import { RowBetween, RowFixed } from '../Row'
const FixedHeightRow = styled(RowBetween)`
height: 24px;
`
function PositionCard({ exchangeAddress, 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 exchange = tokenAmount0 && tokenAmount1 && new Exchange(tokenAmount0, tokenAmount1)
const userPoolBalance = allBalances?.[account]?.[exchangeAddress]
const totalPoolTokens = useTotalSupply(exchange)
const poolTokenPercentage =
!!userPoolBalance && !!totalPoolTokens ? new Percent(userPoolBalance.raw, totalPoolTokens.raw) : undefined
const token0Deposited = poolTokenPercentage?.multiply(allBalances[exchangeAddress][token0.address])
const token1Deposited = poolTokenPercentage?.multiply(allBalances[exchangeAddress][token1.address])
function DynamicCard({ children, ...rest }) {
if (!minimal) {
return (
<Card border="1px solid #EDEEF2" {...rest}>
{children}
</Card>
)
} else {
return <GreyCard {...rest}>{children}</GreyCard>
}
}
return (
<DynamicCard {...rest}>
<AutoColumn gap="20px">
<FixedHeightRow>
<Text fontWeight={500} fontSize={16}>
Current Position
</Text>
</FixedHeightRow>
<FixedHeightRow>
<RowFixed>
<DoubleLogo a0={token0?.address || ''} a1={token1?.address || ''} margin={true} size={24} />
<Text fontWeight={500} fontSize={20}>
{token0?.symbol}:{token1?.symbol}
</Text>
</RowFixed>
<Text fontWeight={500} fontSize={20}>
{userPoolBalance ? userPoolBalance.toFixed(6) : '-'}
</Text>
</FixedHeightRow>
<AutoColumn gap="12px">
<FixedHeightRow>
<Text color="#888D9B" fontSize={16} fontWeight={500}>
{token0?.symbol} Deposited:
</Text>
{token0Deposited ? (
<RowFixed>
<TokenLogo address={token0?.address || ''} />
<Text color="#888D9B" fontSize={16} fontWeight={500} marginLeft={'6px'}>
{token0Deposited?.toFixed(8)}
</Text>
</RowFixed>
) : (
'-'
)}
</FixedHeightRow>
<FixedHeightRow>
<Text color="#888D9B" fontSize={16} fontWeight={500}>
{token1?.symbol} Deposited:
</Text>
{token1Deposited ? (
<RowFixed>
<TokenLogo address={token1.address || ''} />
<Text color="#888D9B" fontSize={16} fontWeight={500} marginLeft={'6px'}>
{token1Deposited?.toFixed(8)}
</Text>
</RowFixed>
) : (
'-'
)}
</FixedHeightRow>
{!minimal && (
<FixedHeightRow>
<Text color="#888D9B" fontSize={16} fontWeight={500}>
Your pool share:
</Text>
<Text color="#888D9B" fontSize={16} fontWeight={500}>
{poolTokenPercentage ? poolTokenPercentage.toFixed(2) + '%' : '-'}
</Text>
</FixedHeightRow>
)}
</AutoColumn>
{!minimal && (
<RowBetween>
<ButtonSecondary
width="48%"
onClick={() => {
history.push('/add/' + token0?.address + '-' + token1?.address)
}}
>
Add
</ButtonSecondary>
<ButtonSecondary
width="48%"
onClick={() => {
history.push('/remove/' + token0?.address + '-' + token1?.address)
}}
>
Remove
</ButtonSecondary>
</RowBetween>
)}
</AutoColumn>
</DynamicCard>
)
}
export default withRouter(PositionCard)
...@@ -201,8 +201,8 @@ function SearchModal({ history, isOpen, onDismiss, onTokenSelect, field, urlAdde ...@@ -201,8 +201,8 @@ function SearchModal({ history, isOpen, onDismiss, onTokenSelect, field, urlAdde
} }
// amount of tokens to display at once // amount of tokens to display at once
const [tokensShown, setTokensShown] = useState(0) const [, setTokensShown] = useState(0)
const [pairsShown, setPairsShown] = useState(0) const [, setPairsShown] = useState(0)
// filters on results // filters on results
const FILTERS = { const FILTERS = {
......
import React from 'react'
import Slider from '@material-ui/core/Slider'
import { withStyles } from '@material-ui/core/styles'
const IOSSlider = withStyles({
root: {
width: '95%',
color: '#3880ff',
height: 4,
padding: '15px 0'
},
thumb: {
height: 28,
width: 28,
backgroundColor: '##2172E5',
marginTop: -14,
marginLeft: -14,
'&:focus,&:hover,&$active': {
boxShadow:
'0px 0px 1px rgba(0, 0, 0, 0.04), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04), 0px 24px 32px rgba(0, 0, 0, 0.04)',
// Reset on touch devices, it doesn't add specificity
'@media (hover: none)': {}
}
},
active: {},
track: {
height: 4
},
rail: {
height: 2,
opacity: 0.5,
backgroundColor: '#bfbfbf'
},
mark: {
backgroundColor: '#bfbfbf',
height: 8,
width: 1,
marginTop: -3
},
markActive: {
opacity: 1,
backgroundColor: 'currentColor'
}
})(Slider)
export default function InputSlider({ value, onChange }) {
return <IOSSlider value={typeof value === 'number' ? value : 0} onChange={onChange} aria-labelledby="input-slider" />
}
...@@ -26,8 +26,7 @@ const Emoji = styled.span` ...@@ -26,8 +26,7 @@ const Emoji = styled.span`
font-size: ${({ size }) => size}; font-size: ${({ size }) => size};
width: ${({ size }) => size}; width: ${({ size }) => size};
height: ${({ size }) => size}; height: ${({ size }) => size};
margin-bottom: -2px; margin-bottom: -4px;
margin-right: ${({ sizeraw, margin }) => margin && (sizeraw / 2 + 10).toString() + 'px'};
` `
const StyledEthereumLogo = styled(EthereumLogo)` const StyledEthereumLogo = styled(EthereumLogo)`
...@@ -35,7 +34,7 @@ const StyledEthereumLogo = styled(EthereumLogo)` ...@@ -35,7 +34,7 @@ const StyledEthereumLogo = styled(EthereumLogo)`
height: ${({ size }) => size}; height: ${({ size }) => size};
` `
export default function TokenLogo({ address, size = '1rem', ...rest }) { export default function TokenLogo({ address, size = '24px', ...rest }) {
const [error, setError] = useState(false) const [error, setError] = useState(false)
const { chainId } = useWeb3React() const { chainId } = useWeb3React()
......
import React, { createContext, useContext, useReducer, useRef, useMemo, useCallback, useEffect, ReactNode } from 'react' import React, { createContext, useContext, useReducer, useRef, useMemo, useCallback, useEffect, ReactNode } from 'react'
import { TokenAmount, Token, JSBI, WETH } from '@uniswap/sdk' import { TokenAmount, Token, JSBI, WETH } from '@uniswap/sdk'
import { useWeb3React, useDebounce } from '../hooks'
import { getEtherBalance, getTokenBalance, isAddress } from '../utils'
import { useBlockNumber } from './Application'
import { useAllTokens } from './Tokens' import { useAllTokens } from './Tokens'
import { useBlockNumber } from './Application'
import { useAllExchanges } from './Exchanges' import { useAllExchanges } from './Exchanges'
import { useWeb3React, useDebounce } from '../hooks'
import { getEtherBalance, getTokenBalance, isAddress } from '../utils'
const LOCAL_STORAGE_KEY = 'BALANCES' const LOCAL_STORAGE_KEY = 'BALANCES'
const SHORT_BLOCK_TIMEOUT = (60 * 2) / 15 // in seconds, represented as a block number delta const SHORT_BLOCK_TIMEOUT = (60 * 2) / 15 // in seconds, represented as a block number delta
...@@ -408,30 +409,23 @@ export function useAllBalances(): Array<TokenAmount> { ...@@ -408,30 +409,23 @@ export function useAllBalances(): Array<TokenAmount> {
const allTokens = useAllTokens() const allTokens = useAllTokens()
const formattedBalances = useMemo(() => { const formattedBalances = useMemo(() => {
if (!state?.[chainId]) { if (!state || !state[chainId]) {
return {} return {}
} else { } else {
let newBalances = {} let newBalances = {}
Object.keys(state[chainId]).map(address => { Object.keys(state[chainId]).map(address => {
return Object.keys(state[chainId][address]).map(tokenAddress => { return Object.keys(state[chainId][address]).map(tokenAddress => {
if (state?.[chainId][address][tokenAddress].value) { if (state[chainId][address][tokenAddress].value) {
return (newBalances[chainId] = { newBalances[chainId] = {
...newBalances[chainId], ...newBalances[chainId],
[address]: { [address]: {
...newBalances[chainId]?.[address], ...newBalances[chainId]?.[address],
[tokenAddress]: new TokenAmount( [tokenAddress]: new TokenAmount(
// if token not in token list, must be an exchange - allTokens[tokenAddress] ? allTokens[tokenAddress] : new Token(chainId, tokenAddress, 18),
/**
* @TODO
*
* should we live fetch data here if token not in list
*
*/
allTokens && allTokens[tokenAddress] ? allTokens[tokenAddress] : new Token(chainId, tokenAddress, 18),
JSBI.BigInt(state?.[chainId][address][tokenAddress].value) JSBI.BigInt(state?.[chainId][address][tokenAddress].value)
) )
} }
}) }
} }
}) })
}) })
...@@ -485,7 +479,3 @@ export function useAccountLPBalances(account: string) { ...@@ -485,7 +479,3 @@ export function useAccountLPBalances(account: string) {
}) })
}, [account, allExchanges, chainId, startListening, stopListening]) }, [account, allExchanges, chainId, startListening, stopListening])
} }
export function useExchangeReserves(tokenAddress: string) {
return []
}
import React, { createContext, useContext, useReducer, useMemo, useCallback, useEffect } from 'react' import React, { createContext, useContext, useReducer, useMemo, useCallback, useEffect, useState } from 'react'
import { ChainId, WETH, Token, Exchange } from '@uniswap/sdk'
import { INITIAL_TOKENS_CONTEXT } from './Tokens'
import { useAddressBalance } from './Balances' import { useAddressBalance } from './Balances'
import { useWeb3React, useExchangeContract } from '../hooks'
import { useWeb3React } from '../hooks' import { INITIAL_TOKENS_CONTEXT } from './Tokens'
import { ChainId, WETH, Token, TokenAmount, Exchange, JSBI } from '@uniswap/sdk'
const UPDATE = 'UPDATE' const UPDATE = 'UPDATE'
...@@ -138,3 +139,46 @@ export function useAllExchanges() { ...@@ -138,3 +139,46 @@ export function useAllExchanges() {
return allExchanges || {} return allExchanges || {}
}, [allExchanges]) }, [allExchanges])
} }
export function useTotalSupply(exchange: Exchange) {
const { library } = useWeb3React()
const [totalPoolTokens, setTotalPoolTokens] = useState<TokenAmount>()
const exchangeContract = useExchangeContract(exchange?.liquidityToken.address)
const fetchPoolTokens = useCallback(async () => {
!!exchangeContract &&
exchangeContract
.deployed()
.then(() => {
if (exchangeContract) {
exchangeContract.totalSupply().then(totalSupply => {
if (totalSupply !== undefined && exchange?.liquidityToken?.decimals) {
const supplyFormatted = JSBI.BigInt(totalSupply)
const tokenSupplyFormatted = new TokenAmount(exchange?.liquidityToken, supplyFormatted)
setTotalPoolTokens(tokenSupplyFormatted)
}
})
}
})
.catch(e => {
console.log('error')
})
/**
* @todo
* fix this
*/
}, [exchangeContract])
// on the block make sure we're updated
useEffect(() => {
fetchPoolTokens()
library.on('block', fetchPoolTokens)
return () => {
library.removeListener('block', fetchPoolTokens)
}
}, [fetchPoolTokens, library])
return totalPoolTokens
}
...@@ -108,7 +108,7 @@ export function useToken(tokenAddress: string): Token { ...@@ -108,7 +108,7 @@ export function useToken(tokenAddress: string): Token {
return token return token
} }
export function useAllTokens() { export function useAllTokens(): string[] {
const { chainId } = useWeb3React() const { chainId } = useWeb3React()
const [state] = useTokensContext() const [state] = useTokensContext()
......
...@@ -47,8 +47,8 @@ const Body = styled.div` ...@@ -47,8 +47,8 @@ const Body = styled.div`
max-width: 28rem; max-width: 28rem;
width: 90%; width: 90%;
background: ${({ theme }) => theme.panelBackground}; background: ${({ theme }) => theme.panelBackground};
box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.04), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04), box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04),
0px 24px 32px rgba(0, 0, 0, 0.04); 0px 24px 32px rgba(0, 0, 0, 0.01);
border-radius: 20px; border-radius: 20px;
padding: 2rem 1rem; padding: 2rem 1rem;
` `
......
This diff is collapsed.
This diff is collapsed.
import React, { useEffect, useState, useCallback } from 'react' import React, { useState } from 'react'
import styled from 'styled-components' import styled from 'styled-components'
import { TokenAmount, JSBI, Percent, Token } from '@uniswap/sdk' import { JSBI } from '@uniswap/sdk'
import ReactGA from 'react-ga'
import { withRouter } from 'react-router-dom' import { useWeb3React } from '@web3-react/core'
import { useAllTokens } from '../../contexts/Tokens'
import { useAllExchanges } from '../../contexts/Exchanges'
import { useAllBalances, useAccountLPBalances } from '../../contexts/Balances'
import { Link } from '../../theme'
import { AutoColumn } from '../../components/Column'
import Row, { RowBetween, RowFixed } from '../../components/Row'
import { ButtonDropwdown, ButtonSecondary } from '../../components/Button'
import Card from '../../components/Card' import Card from '../../components/Card'
import { Text } from 'rebass'
import DoubleLogo from '../../components/DoubleLogo'
import SearchModal from '../../components/SearchModal' import SearchModal from '../../components/SearchModal'
import PositionCard from '../../components/PositionCard'
import Row, { RowBetween } from '../../components/Row'
import { Link } from '../../theme'
import { Text } from 'rebass'
import { AutoColumn } from '../../components/Column'
import { ArrowRight } from 'react-feather' import { ArrowRight } from 'react-feather'
import { ButtonDropwdown } from '../../components/Button'
import { useAllExchanges } from '../../contexts/Exchanges'
import { useAllBalances, useAccountLPBalances } from '../../contexts/Balances'
import { useWeb3React } from '@web3-react/core'
import { useAllTokens } from '../../contexts/Tokens'
import { useExchangeContract } from '../../hooks'
import TokenLogo from '../../components/TokenLogo'
const Positions = styled.div` const Positions = styled.div`
position: relative; position: relative;
margin-top: 38px; margin-top: 38px;
` `
const FixedBottom = styled.div` const FixedBottom = styled.div`
position: absolute; position: absolute;
bottom: -240px; bottom: -240px;
width: 100%; width: 100%;
` `
function ExchangeCard({ exchangeAddress, token0, token1, history, allBalances }) { export default function Supply() {
const { account, chainId } = useWeb3React()
const userPoolBalance = allBalances?.[account]?.[exchangeAddress]
const [totalPoolTokens, setTotalPoolTokens] = useState()
// get the total pool token supply
const exchangeContract = useExchangeContract(exchangeAddress)
const fetchPoolTokens = useCallback(() => {
if (exchangeContract) {
exchangeContract.totalSupply().then(totalSupply => {
if (totalSupply !== undefined) {
const supplyFormatted = JSBI.BigInt(totalSupply)
const tokenSupplyFormatted = new TokenAmount(new Token(chainId, exchangeAddress, 18), supplyFormatted)
setTotalPoolTokens(tokenSupplyFormatted)
}
})
}
}, [exchangeContract, chainId, exchangeAddress])
useEffect(() => {
fetchPoolTokens()
}, [fetchPoolTokens])
const poolTokenPercentage =
!!userPoolBalance && !!totalPoolTokens ? new Percent(userPoolBalance.raw, totalPoolTokens.raw) : undefined
const token0Deposited = poolTokenPercentage?.multiply(allBalances[exchangeAddress][token0.address])
const token1Deposited = poolTokenPercentage?.multiply(allBalances[exchangeAddress][token1.address])
return (
<Card border="1px solid #EDEEF2">
<AutoColumn gap="20px">
<RowBetween>
<RowFixed>
<DoubleLogo a0={token0?.address || ''} a1={token1?.address || ''} margin={true} size={24} />
<Text fontWeight={500} fontSize={20}>
{token0?.symbol}:{token1?.symbol}
</Text>
</RowFixed>
<Text fontWeight={500} fontSize={20}>
{userPoolBalance ? userPoolBalance.toFixed(6) : '-'}
</Text>
</RowBetween>
<AutoColumn gap="12px">
<RowBetween>
<Text color="#888D9B" fontSize={16} fontWeight={500}>
{token0?.symbol} Deposited:
</Text>
{token0Deposited ? (
<RowFixed>
<TokenLogo address={token0?.address || ''} />
<Text color="#888D9B" fontSize={16} fontWeight={500}>
{token0Deposited?.toSignificant(6)}
</Text>
</RowFixed>
) : (
'-'
)}
</RowBetween>
<RowBetween>
<Text color="#888D9B" fontSize={16} fontWeight={500}>
{token1?.symbol} Deposited:
</Text>
{token1Deposited ? (
<RowFixed>
<TokenLogo address={token1.address || ''} />
<Text color="#888D9B" fontSize={16} fontWeight={500}>
{token1Deposited?.toSignificant(6)}
</Text>
</RowFixed>
) : (
'-'
)}
</RowBetween>
<RowBetween>
<Text color="#888D9B" fontSize={16} fontWeight={500}>
Your pool share:
</Text>
<Text color="#888D9B" fontSize={16} fontWeight={500}>
{poolTokenPercentage ? poolTokenPercentage.toFixed(2) + '%' : '-'}
</Text>
</RowBetween>
</AutoColumn>
<RowBetween>
<ButtonSecondary
width="48%"
onClick={() => {
history.push('/add/' + token0?.address + '-' + token1?.address)
}}
>
Add
</ButtonSecondary>
<ButtonSecondary
width="48%"
onClick={() => {
history.push('/remove/' + token0?.address + '-' + token1?.address)
}}
>
Remove
</ButtonSecondary>
</RowBetween>
</AutoColumn>
</Card>
)
}
function Supply({ history }) {
useEffect(() => {
ReactGA.pageview(window.location.pathname + window.location.search)
}, [])
const { account } = useWeb3React() const { account } = useWeb3React()
const [showSearch, setShowSearch] = useState(false)
const [showSearch, toggleSearch] = useState(false)
const exchanges = useAllExchanges()
const allTokens = useAllTokens() const allTokens = useAllTokens()
const allBalances = useAllBalances() const allBalances = useAllBalances()
const allExchanges = useAllExchanges()
// initiate listener for LP balances // initiate listener for LP balances
useAccountLPBalances(account) useAccountLPBalances(account)
const filteredPairList = Object.keys(exchanges).map((exchangeAddress, i) => { const filteredExchangeList = Object.keys(allExchanges).map((exchangeAddress, i) => {
const exchange = exchanges[exchangeAddress] const balance = allBalances?.[account]?.[exchangeAddress]
// gate on positive address return (
if (allBalances?.[account]?.[exchangeAddress]) { balance &&
const token0 = allTokens[exchange.token0] JSBI.greaterThan(balance.raw, JSBI.BigInt(0)) && (
const token1 = allTokens[exchange.token1] <PositionCard
return (
<ExchangeCard
history={history}
key={i} key={i}
exchangeAddress={exchangeAddress} exchangeAddress={exchangeAddress}
token0={token0} token0={allTokens[allExchanges[exchangeAddress].token0]}
token1={token1} token1={allTokens[allExchanges[exchangeAddress].token1]}
allBalances={allBalances}
/> />
) )
} else { )
return ''
}
}) })
return ( return (
<> <>
<ButtonDropwdown <ButtonDropwdown
onClick={() => { onClick={() => {
toggleSearch(true) setShowSearch(true)
}} }}
> >
<Text fontSize={20}>Find a pool</Text> <Text fontSize={20}>Find a pool</Text>
...@@ -193,7 +70,7 @@ function Supply({ history }) { ...@@ -193,7 +70,7 @@ function Supply({ history }) {
<Text fontWeight={500}>View on Uniswap.info</Text> <Text fontWeight={500}>View on Uniswap.info</Text>
</Link> </Link>
</RowBetween> </RowBetween>
{filteredPairList} {filteredExchangeList}
</AutoColumn> </AutoColumn>
<FixedBottom> <FixedBottom>
<Card bg="rgba(255, 255, 255, 0.6)" padding={'24px'}> <Card bg="rgba(255, 255, 255, 0.6)" padding={'24px'}>
...@@ -216,11 +93,9 @@ function Supply({ history }) { ...@@ -216,11 +93,9 @@ function Supply({ history }) {
<SearchModal <SearchModal
isOpen={showSearch} isOpen={showSearch}
onDismiss={() => { onDismiss={() => {
toggleSearch(false) setShowSearch(false)
}} }}
/> />
</> </>
) )
} }
export default withRouter(Supply)
...@@ -6,15 +6,7 @@ import ROUTER_ABI from '../constants/abis/router' ...@@ -6,15 +6,7 @@ import ROUTER_ABI from '../constants/abis/router'
import ERC20_ABI from '../constants/abis/erc20' import ERC20_ABI from '../constants/abis/erc20'
import ERC20_BYTES32_ABI from '../constants/abis/erc20_bytes32' import ERC20_BYTES32_ABI from '../constants/abis/erc20_bytes32'
import { FACTORY_ADDRESSES, SUPPORTED_THEMES } from '../constants' import { FACTORY_ADDRESSES, SUPPORTED_THEMES } from '../constants'
import { import { bigNumberify, keccak256, defaultAbiCoder, toUtf8Bytes, solidityPack } from 'ethers/utils'
BigNumber,
bigNumberify,
getAddress,
keccak256,
defaultAbiCoder,
toUtf8Bytes,
solidityPack
} from 'ethers/utils'
import UncheckedJsonRpcSigner from './signer' import UncheckedJsonRpcSigner from './signer'
......
This diff is collapsed.
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