Commit 807860aa authored by Ian Lapham's avatar Ian Lapham Committed by GitHub

refactor review modals (#60)

parent ee0db4f2
...@@ -11,6 +11,8 @@ import Settings from '../Settings' ...@@ -11,6 +11,8 @@ import Settings from '../Settings'
import { useDispatch } from 'react-redux' import { useDispatch } from 'react-redux'
import { AppDispatch } from 'state' import { AppDispatch } from 'state'
import { resetMintState } from 'state/mint/actions' import { resetMintState } from 'state/mint/actions'
import { TYPE } from 'theme'
import useTheme from 'hooks/useTheme'
const Tabs = styled.div` const Tabs = styled.div`
${({ theme }) => theme.flexRowNoWrap} ${({ theme }) => theme.flexRowNoWrap}
...@@ -85,6 +87,8 @@ export function FindPoolTabs({ origin }: { origin: string }) { ...@@ -85,6 +87,8 @@ export function FindPoolTabs({ origin }: { origin: string }) {
} }
export function AddRemoveTabs({ adding, creating }: { adding: boolean; creating: boolean }) { export function AddRemoveTabs({ adding, creating }: { adding: boolean; creating: boolean }) {
const theme = useTheme()
// reset states on back // reset states on back
const dispatch = useDispatch<AppDispatch>() const dispatch = useDispatch<AppDispatch>()
...@@ -97,9 +101,11 @@ export function AddRemoveTabs({ adding, creating }: { adding: boolean; creating: ...@@ -97,9 +101,11 @@ export function AddRemoveTabs({ adding, creating }: { adding: boolean; creating:
adding && dispatch(resetMintState()) adding && dispatch(resetMintState())
}} }}
> >
<StyledArrowLeft /> <StyledArrowLeft stroke={theme.text2} opacity="0.6" />
</HistoryLink> </HistoryLink>
<ActiveText>{creating ? 'Create a pair' : adding ? 'Add Liquidity' : 'Remove Liquidity'}</ActiveText> <TYPE.black fontWeight={500} fontSize={16} style={{ opacity: '0.6' }}>
{creating ? 'Create a pair' : adding ? 'Add Liquidity' : 'Remove Liquidity'}
</TYPE.black>
<Settings /> <Settings />
</RowBetween> </RowBetween>
</Tabs> </Tabs>
......
...@@ -24,7 +24,6 @@ const Section = styled(AutoColumn)<{ inline?: boolean }>` ...@@ -24,7 +24,6 @@ const Section = styled(AutoColumn)<{ inline?: boolean }>`
` `
const BottomSection = styled(Section)` const BottomSection = styled(Section)`
// background-color: ${({ theme }) => theme.bg2};
border-bottom-left-radius: 20px; border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px; border-bottom-right-radius: 20px;
` `
...@@ -157,7 +156,7 @@ export function ConfirmationModalContent({ ...@@ -157,7 +156,7 @@ export function ConfirmationModalContent({
bottomContent?: () => React.ReactNode | undefined bottomContent?: () => React.ReactNode | undefined
}) { }) {
return ( return (
<Wrapper> <Wrapper style={{ padding: 0 }}>
<Section> <Section>
<RowBetween> <RowBetween>
<Text fontWeight={500} fontSize={16}> <Text fontWeight={500} fontSize={16}>
......
import { Currency, CurrencyAmount, Fraction, Percent } from '@uniswap/sdk-core'
import React from 'react'
import { Text } from 'rebass'
import { ButtonPrimary } from '../../components/Button'
import { RowBetween, RowFixed } from '../../components/Row'
import CurrencyLogo from '../../components/CurrencyLogo'
import { Field } from '../../state/mint/actions'
import { TYPE } from '../../theme'
export function ConfirmAddModalBottom({
noLiquidity,
price,
currencies,
parsedAmounts,
poolTokenPercentage,
onAdd,
}: {
noLiquidity?: boolean
price?: Fraction
currencies: { [field in Field]?: Currency }
parsedAmounts: { [field in Field]?: CurrencyAmount }
poolTokenPercentage?: Percent
onAdd: () => void
}) {
return (
<>
<RowBetween>
<TYPE.body>{currencies[Field.CURRENCY_A]?.symbol} Deposited</TYPE.body>
<RowFixed>
<CurrencyLogo currency={currencies[Field.CURRENCY_A]} style={{ marginRight: '8px' }} />
<TYPE.body>{parsedAmounts[Field.CURRENCY_A]?.toSignificant(6)}</TYPE.body>
</RowFixed>
</RowBetween>
<RowBetween>
<TYPE.body>{currencies[Field.CURRENCY_B]?.symbol} Deposited</TYPE.body>
<RowFixed>
<CurrencyLogo currency={currencies[Field.CURRENCY_B]} style={{ marginRight: '8px' }} />
<TYPE.body>{parsedAmounts[Field.CURRENCY_B]?.toSignificant(6)}</TYPE.body>
</RowFixed>
</RowBetween>
<RowBetween>
<TYPE.body>Rates</TYPE.body>
<TYPE.body>
{`1 ${currencies[Field.CURRENCY_A]?.symbol} = ${price?.toSignificant(4)} ${
currencies[Field.CURRENCY_B]?.symbol
}`}
</TYPE.body>
</RowBetween>
<RowBetween style={{ justifyContent: 'flex-end' }}>
<TYPE.body>
{`1 ${currencies[Field.CURRENCY_B]?.symbol} = ${price?.invert().toSignificant(4)} ${
currencies[Field.CURRENCY_A]?.symbol
}`}
</TYPE.body>
</RowBetween>
<RowBetween>
<TYPE.body>Share of Pool:</TYPE.body>
<TYPE.body>{noLiquidity ? '100' : poolTokenPercentage?.toSignificant(4)}%</TYPE.body>
</RowBetween>
<ButtonPrimary style={{ margin: '20px 0 0 0' }} onClick={onAdd}>
<Text fontWeight={500} fontSize={20}>
{noLiquidity ? 'Create Pool & Supply' : 'Confirm Supply'}
</Text>
</ButtonPrimary>
</>
)
}
import React, { useState } from 'react'
import { ButtonPrimary } from '../../components/Button'
import { RowBetween, RowFixed } from '../../components/Row'
import CurrencyLogo from '../../components/CurrencyLogo'
import { Field } from '../../state/mint/actions'
import { TYPE, ExternalLink } from '../../theme'
import { AutoColumn } from 'components/Column'
import { OutlineCard, GreyCard, BlueCard } from 'components/Card'
import styled from 'styled-components'
import { Break } from 'components/earn/styled'
import useTheme from 'hooks/useTheme'
import { AlertOctagon } from 'react-feather'
import { ToggleWrapper, ToggleElement } from 'components/Toggle/MultiToggle'
import { useTranslation } from 'react-i18next'
import { Price, Currency, CurrencyAmount } from '@uniswap/sdk-core'
const Wrapper = styled(AutoColumn)`
padding: 1rem 0;
`
export function ConfirmContent({
currencies,
parsedAmounts,
onAdd,
}: {
noLiquidity?: boolean
price?: Price
currencies: { [field in Field]?: Currency }
parsedAmounts: { [field in Field]?: CurrencyAmount }
onAdd: () => void
}) {
const currencyA: Currency | undefined = currencies[Field.CURRENCY_A]
const currencyB: Currency | undefined = currencies[Field.CURRENCY_B]
const [rateCurrency, setRateCurrency] = useState<Currency | undefined>(currencyA)
const theme = useTheme()
const { t } = useTranslation()
return (
<Wrapper gap="lg">
<OutlineCard>
<AutoColumn gap="md">
<RowBetween>
<RowFixed>
<CurrencyLogo currency={currencyA} />
<TYPE.label ml="8px">{currencyA?.symbol}</TYPE.label>
</RowFixed>
<RowFixed>
<TYPE.label mr="8px">{parsedAmounts[Field.CURRENCY_A]?.toSignificant(6)}</TYPE.label>
<GreyCard padding="4px 8px" width="fit-content" borderRadius="12px">
<TYPE.darkGray>50%</TYPE.darkGray>
</GreyCard>
</RowFixed>
</RowBetween>
<RowBetween>
<RowFixed>
<CurrencyLogo currency={currencyB} />
<TYPE.label ml="8px">{currencyB?.symbol}</TYPE.label>
</RowFixed>
<RowFixed>
<TYPE.label mr="8px">{parsedAmounts[Field.CURRENCY_B]?.toSignificant(6)}</TYPE.label>
<GreyCard padding="4px 8px" borderRadius="12px" width="fit-content">
<TYPE.darkGray>50%</TYPE.darkGray>
</GreyCard>
</RowFixed>
</RowBetween>
<Break />
<RowBetween>
<TYPE.label>{t('feePool')}</TYPE.label>
<TYPE.label>0.6%</TYPE.label>
</RowBetween>
</AutoColumn>
</OutlineCard>
<BlueCard padding="12px">
<RowBetween>
<AlertOctagon stroke={theme.primary1} width={'90px'} />
<TYPE.blue ml="12px" fontSize="14px">
{t('rebalanceMessage')}
</TYPE.blue>
</RowBetween>
</BlueCard>
<OutlineCard padding="16px">
<AutoColumn gap="md">
<RowBetween>
<TYPE.label>Position Limits</TYPE.label>
{currencyA && currencyB && (
<ToggleWrapper width="80px">
<ToggleElement
fontSize="10px"
isActive={rateCurrency === currencyA}
onClick={() => setRateCurrency(currencyA)}
>
{currencyA?.symbol}
</ToggleElement>
<ToggleElement
fontSize="10px"
isActive={rateCurrency === currencyB}
onClick={() => setRateCurrency(currencyB)}
>
{currencyB?.symbol}
</ToggleElement>
</ToggleWrapper>
)}
</RowBetween>
<RowBetween>
<AutoColumn gap="2px">
<TYPE.darkGray>Lower Limit</TYPE.darkGray>
<TYPE.label fontSize="14px">1621.82</TYPE.label>
<GreyCard padding="4px" borderRadius="4px" mt="6px">
<RowFixed>
<CurrencyLogo currency={currencyA} size="12px" />
<TYPE.label fontSize="12px" ml="6px">
100%
</TYPE.label>
<TYPE.label fontSize="12px" ml="6px">
{currencyA?.symbol}
</TYPE.label>
</RowFixed>
</GreyCard>
</AutoColumn>
<AutoColumn gap="2px">
<TYPE.darkGray>Entry Price</TYPE.darkGray>
<TYPE.label fontSize="14px">1621.82</TYPE.label>
<GreyCard padding="4px" borderRadius="4px" mt="6px">
<TYPE.label fontSize="12px" ml="6px">
50%/50%
</TYPE.label>
</GreyCard>
</AutoColumn>
<AutoColumn gap="2px">
<TYPE.darkGray>Upper Limit</TYPE.darkGray>
<TYPE.label fontSize="14px">1621.82</TYPE.label>
<GreyCard padding="4px" borderRadius="4px" mt="6px">
<RowFixed>
<CurrencyLogo currency={currencyB} size="12px" />
<TYPE.label fontSize="12px" ml="6px">
100%
</TYPE.label>
<TYPE.label fontSize="12px" ml="6px">
{currencyB?.symbol}
</TYPE.label>
</RowFixed>
</GreyCard>
</AutoColumn>
</RowBetween>
</AutoColumn>
</OutlineCard>
<TYPE.main>
{t('addEarnHelper')}
<ExternalLink href="">{t('learnMoreAboutFess')}</ExternalLink>
</TYPE.main>
<ButtonPrimary onClick={onAdd} fontSize="20px">
{t('addLiquidity')}
</ButtonPrimary>
</Wrapper>
)
}
export default ConfirmContent
...@@ -12,8 +12,7 @@ import { PositionPreview } from 'components/PositionPreview' ...@@ -12,8 +12,7 @@ import { PositionPreview } from 'components/PositionPreview'
import { RangeBadge } from './styled' import { RangeBadge } from './styled'
const Wrapper = styled.div` const Wrapper = styled.div`
padding: 20px; padding-top: 20px;
min-width: 460px;
` `
export const Badge = styled(Card)<{ inRange?: boolean }>` export const Badge = styled(Card)<{ inRange?: boolean }>`
......
...@@ -2,7 +2,7 @@ import { TransactionResponse } from '@ethersproject/providers' ...@@ -2,7 +2,7 @@ import { TransactionResponse } from '@ethersproject/providers'
import { Currency, TokenAmount, ETHER } from '@uniswap/sdk-core' import { Currency, TokenAmount, ETHER } from '@uniswap/sdk-core'
import React, { useCallback, useContext, useMemo, useState } from 'react' import React, { useCallback, useContext, useMemo, useState } from 'react'
import { WETH9 } from '@uniswap/sdk-core' import { WETH9 } from '@uniswap/sdk-core'
import { Link2, AlertTriangle, ChevronRight } from 'react-feather' import { Link2, AlertTriangle } from 'react-feather'
import ReactGA from 'react-ga' import ReactGA from 'react-ga'
import { useV3NFTPositionManagerContract } from '../../hooks/useContract' import { useV3NFTPositionManagerContract } from '../../hooks/useContract'
import { RouteComponentProps } from 'react-router-dom' import { RouteComponentProps } from 'react-router-dom'
...@@ -11,9 +11,9 @@ import { ThemeContext } from 'styled-components' ...@@ -11,9 +11,9 @@ import { ThemeContext } from 'styled-components'
import { ButtonError, ButtonLight, ButtonPrimary, ButtonText } from '../../components/Button' import { ButtonError, ButtonLight, ButtonPrimary, ButtonText } from '../../components/Button'
import { YellowCard, OutlineCard, BlueCard } from '../../components/Card' import { YellowCard, OutlineCard, BlueCard } from '../../components/Card'
import { AutoColumn, ColumnCenter } from '../../components/Column' import { AutoColumn, ColumnCenter } from '../../components/Column'
import { TransactionSubmittedContent, ConfirmationPendingContent } from '../../components/TransactionConfirmationModal' import TransactionConfirmationModal, { ConfirmationModalContent } from '../../components/TransactionConfirmationModal'
import CurrencyInputPanel from '../../components/CurrencyInputPanel' import CurrencyInputPanel from '../../components/CurrencyInputPanel'
import { AutoRow, RowBetween, RowFixed } from '../../components/Row' import { RowBetween, RowFixed } from '../../components/Row'
import { useIsSwapUnsupported } from '../../hooks/useIsSwapUnsupported' import { useIsSwapUnsupported } from '../../hooks/useIsSwapUnsupported'
import Review from './Review' import Review from './Review'
import { useActiveWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
...@@ -36,7 +36,6 @@ import { ...@@ -36,7 +36,6 @@ import {
CurrencyDropdown, CurrencyDropdown,
ScrollableContent, ScrollableContent,
StyledInput, StyledInput,
FixedPreview,
Wrapper, Wrapper,
RangeBadge, RangeBadge,
ScrollablePage, ScrollablePage,
...@@ -54,6 +53,7 @@ import RangeSelector from 'components/RangeSelector' ...@@ -54,6 +53,7 @@ import RangeSelector from 'components/RangeSelector'
import RateToggle from 'components/RateToggle' import RateToggle from 'components/RateToggle'
import { BigNumber } from '@ethersproject/bignumber' import { BigNumber } from '@ethersproject/bignumber'
import { calculateGasMargin } from 'utils' import { calculateGasMargin } from 'utils'
import { AddRemoveTabs } from 'components/NavigationTabs'
export default function AddLiquidity({ export default function AddLiquidity({
match: { match: {
...@@ -305,8 +305,6 @@ export default function AddLiquidity({ ...@@ -305,8 +305,6 @@ export default function AddLiquidity({
setTxHash('') setTxHash('')
}, [onFieldAInput, txHash]) }, [onFieldAInput, txHash])
// const isCreate = history.location.pathname.includes('/create')
const addIsUnsupported = useIsSwapUnsupported(currencies?.CURRENCY_A, currencies?.CURRENCY_B) const addIsUnsupported = useIsSwapUnsupported(currencies?.CURRENCY_A, currencies?.CURRENCY_B)
const clearAll = useCallback(() => { const clearAll = useCallback(() => {
...@@ -332,137 +330,140 @@ export default function AddLiquidity({ ...@@ -332,137 +330,140 @@ export default function AddLiquidity({
return ( return (
<ScrollablePage> <ScrollablePage>
<ScrollableContent> <ScrollableContent>
<AutoRow gap="2px" marginBottom="20px"> <TransactionConfirmationModal
<ButtonText opacity={'0.4'} onClick={() => history.push('/pool')}> isOpen={showConfirm}
Pool onDismiss={handleDismissConfirmation}
</ButtonText> attemptingTxn={attemptingTxn}
<ChevronRight size={16} opacity={'0.4'} /> hash={txHash}
<ButtonText opacity={showConfirm ? '0.4' : '1'} onClick={() => (showConfirm ? setShowConfirm(false) : null)}> content={() => (
Configure <ConfirmationModalContent
</ButtonText> title={'Add Liquidity'}
<ChevronRight size={16} opacity={'0.4'} /> onDismiss={handleDismissConfirmation}
<ButtonText topContent={() => (
opacity={showConfirm ? '1' : '0.1'} <Review
onClick={() => (!showConfirm ? setShowConfirm(true) : null)} currencies={currencies}
disabled={!isValid} parsedAmounts={parsedAmounts}
> position={position}
Review existingPosition={existingPosition}
</ButtonText> priceLower={priceLower}
</AutoRow> priceUpper={priceUpper}
{showConfirm ? ( outOfRange={outOfRange}
<AppBody> />
<Review )}
currencies={currencies} bottomContent={() => (
parsedAmounts={parsedAmounts} <ButtonPrimary onClick={onAdd}>
position={position} <Text fontWeight={500} fontSize={20}>
existingPosition={existingPosition} Add
priceLower={priceLower} </Text>
priceUpper={priceUpper} </ButtonPrimary>
outOfRange={outOfRange} )}
/> />
</AppBody> )}
) : ( pendingText={pendingText}
<AppBody> />
<Wrapper> <AppBody>
<AutoColumn gap="lg"> <AddRemoveTabs creating={false} adding={true} />
{!hasExistingPosition ? ( <Wrapper>
<> <AutoColumn gap="lg">
<AutoColumn gap="md"> {!hasExistingPosition ? (
<RowBetween paddingBottom="20px"> <>
<TYPE.label>Select a pair</TYPE.label> <AutoColumn gap="md">
<ButtonText onClick={clearAll}> <RowBetween paddingBottom="20px">
<TYPE.blue fontSize="12px">Clear All</TYPE.blue> <TYPE.label>Select a pair</TYPE.label>
</ButtonText> <ButtonText onClick={clearAll}>
</RowBetween> <TYPE.blue fontSize="12px">Clear All</TYPE.blue>
</ButtonText>
<RowBetween> </RowBetween>
<CurrencyDropdown
value={formattedAmounts[Field.CURRENCY_A]} <RowBetween>
onUserInput={onFieldAInput} <CurrencyDropdown
hideInput={true} value={formattedAmounts[Field.CURRENCY_A]}
onMax={() => { onUserInput={onFieldAInput}
onFieldAInput(maxAmounts[Field.CURRENCY_A]?.toExact() ?? '') hideInput={true}
}} onMax={() => {
onCurrencySelect={handleCurrencyASelect} onFieldAInput(maxAmounts[Field.CURRENCY_A]?.toExact() ?? '')
showMaxButton={!atMaxAmounts[Field.CURRENCY_A]} }}
currency={currencies[Field.CURRENCY_A]} onCurrencySelect={handleCurrencyASelect}
id="add-liquidity-input-tokena" showMaxButton={!atMaxAmounts[Field.CURRENCY_A]}
showCommonBases currency={currencies[Field.CURRENCY_A]}
/> id="add-liquidity-input-tokena"
showCommonBases
<CurrencyDropdown
value={formattedAmounts[Field.CURRENCY_B]}
hideInput={true}
onUserInput={onFieldBInput}
onCurrencySelect={handleCurrencyBSelect}
onMax={() => {
onFieldBInput(maxAmounts[Field.CURRENCY_B]?.toExact() ?? '')
}}
showMaxButton={!atMaxAmounts[Field.CURRENCY_B]}
currency={currencies[Field.CURRENCY_B]}
id="add-liquidity-input-tokenb"
showCommonBases
/>
</RowBetween>
</AutoColumn>{' '}
</>
) : (
<RowBetween>
<RowFixed>
<DoubleCurrencyLogo
currency0={baseCurrency ?? undefined}
currency1={quoteCurrency ?? undefined}
size={24}
margin={true}
/> />
<TYPE.label ml="10px" fontSize="24px">
{quoteCurrency?.symbol} / {baseCurrency?.symbol}
</TYPE.label>
</RowFixed>
<RangeBadge inRange={!outOfRange}>{outOfRange ? 'Out of range' : 'In Range'}</RangeBadge>
</RowBetween>
)}
{hasExistingPosition && existingPosition ? ( <CurrencyDropdown
<PositionPreview position={existingPosition} title={'Current Position'} /> value={formattedAmounts[Field.CURRENCY_B]}
) : ( hideInput={true}
<> onUserInput={onFieldBInput}
<FeeSelector onCurrencySelect={handleCurrencyBSelect}
disabled={!currencyB || !currencyA} onMax={() => {
feeAmount={feeAmount} onFieldBInput(maxAmounts[Field.CURRENCY_B]?.toExact() ?? '')
handleFeePoolSelect={handleFeePoolSelect} }}
showMaxButton={!atMaxAmounts[Field.CURRENCY_B]}
currency={currencies[Field.CURRENCY_B]}
id="add-liquidity-input-tokenb"
showCommonBases
/>
</RowBetween>
</AutoColumn>{' '}
</>
) : (
<RowBetween>
<RowFixed>
<DoubleCurrencyLogo
currency0={currencyA ?? undefined}
currency1={currencyB ?? undefined}
size={24}
margin={true}
/> />
<TYPE.label ml="10px" fontSize="24px">
{noLiquidity && ( {currencyA?.symbol} / {currencyB?.symbol}
<DynamicSection disabled={!currencyA || !currencyB}> </TYPE.label>
<AutoColumn gap="md"> </RowFixed>
<BlueCard width="100%" padding="1rem"> <RangeBadge inRange={!outOfRange}>{outOfRange ? 'Out of range' : 'In Range'}</RangeBadge>
You are the first to provide liquidity to this pool. </RowBetween>
</BlueCard> )}
<RowBetween>
<TYPE.label>{t('selectStartingPrice')}</TYPE.label> {hasExistingPosition && existingPosition ? (
{baseCurrency && quoteCurrency ? ( <PositionPreview position={existingPosition} title={'Current Position'} />
<RateToggle ) : (
currencyA={baseCurrency} <>
currencyB={quoteCurrency} <FeeSelector
handleRateToggle={() => { disabled={!currencyB || !currencyA}
onLeftRangeInput('') feeAmount={feeAmount}
onRightRangeInput('') handleFeePoolSelect={handleFeePoolSelect}
setBaseCurrency(quoteCurrency) />
}}
/> {noLiquidity && (
) : null} <DynamicSection disabled={!currencyA || !currencyB}>
</RowBetween> <AutoColumn gap="md">
<BlueCard width="100%" padding="1rem">
<OutlineCard padding="12px"> You are the first to provide liquidity to this pool.
<StyledInput </BlueCard>
className="start-price-input" <RowBetween>
value={startPriceTypedValue} <TYPE.label>{t('selectStartingPrice')}</TYPE.label>
onUserInput={onStartPriceInput} {baseCurrency && quoteCurrency ? (
<RateToggle
currencyA={baseCurrency}
currencyB={quoteCurrency}
handleRateToggle={() => {
onLeftRangeInput('')
onRightRangeInput('')
setBaseCurrency(quoteCurrency)
}}
/> />
</OutlineCard> ) : null}
<RowBetween style={{ backgroundColor: theme.bg6, padding: '12px', borderRadius: '12px' }}> </RowBetween>
<TYPE.main>Starting {baseCurrency?.symbol} Price:</TYPE.main>
<OutlineCard padding="12px">
<StyledInput
className="start-price-input"
value={startPriceTypedValue}
onUserInput={onStartPriceInput}
/>
</OutlineCard>
<RowBetween style={{ backgroundColor: theme.bg6, padding: '12px', borderRadius: '12px' }}>
<TYPE.main>Current {baseCurrency?.symbol} Price:</TYPE.main>
<TYPE.main>
{price ? ( {price ? (
<TYPE.main> <TYPE.main>
{invertPrice ? price?.invert()?.toSignificant(8) : price?.toSignificant(8)}{' '} {invertPrice ? price?.invert()?.toSignificant(8) : price?.toSignificant(8)}{' '}
...@@ -471,151 +472,119 @@ export default function AddLiquidity({ ...@@ -471,151 +472,119 @@ export default function AddLiquidity({
) : ( ) : (
'-' '-'
)} )}
</RowBetween>
</AutoColumn>
</DynamicSection>
)}
<DynamicSection
gap="md"
disabled={!feeAmount || invalidPool || (noLiquidity && !startPriceTypedValue)}
>
<RowBetween>
<TYPE.label>{t('selectLiquidityRange')}</TYPE.label>
{baseCurrency && quoteCurrency ? (
<RateToggle
currencyA={baseCurrency}
currencyB={quoteCurrency}
handleRateToggle={() => {
onLeftRangeInput('')
onRightRangeInput('')
setBaseCurrency(quoteCurrency)
}}
/>
) : null}
</RowBetween>
{price && baseCurrency && quoteCurrency && !noLiquidity && (
<RowBetween style={{ backgroundColor: theme.bg6, padding: '12px', borderRadius: '12px' }}>
<TYPE.main>Current {baseCurrency?.symbol} Price:</TYPE.main>
<TYPE.main>
{invertPrice ? price.invert().toSignificant(3) : price.toSignificant(3)}{' '}
{quoteCurrency?.symbol}
</TYPE.main> </TYPE.main>
</RowBetween> </RowBetween>
)} </AutoColumn>
<RangeSelector
priceLower={priceLower}
priceUpper={priceUpper}
getDecrementLower={getDecrementLower}
getIncrementLower={getIncrementLower}
getDecrementUpper={getDecrementUpper}
getIncrementUpper={getIncrementUpper}
onLeftRangeInput={onLeftRangeInput}
onRightRangeInput={onRightRangeInput}
currencyA={baseCurrency}
currencyB={quoteCurrency}
feeAmount={feeAmount}
/>
{outOfRange ? (
<YellowCard padding="8px 12px" borderRadius="12px">
<RowBetween>
<AlertTriangle stroke={theme.yellow3} size="16px" />
<TYPE.yellow ml="12px" fontSize="12px">
{t('inactiveRangeWarning')}
</TYPE.yellow>
</RowBetween>
</YellowCard>
) : null}
{invalidRange ? (
<YellowCard padding="8px 12px" borderRadius="12px">
<RowBetween>
<AlertTriangle stroke={theme.yellow3} size="16px" />
<TYPE.yellow ml="12px" fontSize="12px">
{t('invalidRangeWarning')}
</TYPE.yellow>
</RowBetween>
</YellowCard>
) : null}
</DynamicSection> </DynamicSection>
</> )}
)}
<DynamicSection
<DynamicSection gap="md"
disabled={tickLower === undefined || tickUpper === undefined || invalidPool || invalidRange} disabled={!feeAmount || invalidPool || (noLiquidity && !startPriceTypedValue)}
> >
<AutoColumn gap="md"> <RowBetween>
<TYPE.label>{hasExistingPosition ? 'Add more liquidity' : t('depositAmounts')}</TYPE.label> <TYPE.label>{t('selectLiquidityRange')}</TYPE.label>
{baseCurrency && quoteCurrency ? (
<RateToggle
currencyA={baseCurrency}
currencyB={quoteCurrency}
handleRateToggle={() => {
onLeftRangeInput('')
onRightRangeInput('')
setBaseCurrency(quoteCurrency)
}}
/>
) : null}
</RowBetween>
{price && baseCurrency && quoteCurrency && !noLiquidity && (
<RowBetween style={{ backgroundColor: theme.bg6, padding: '12px', borderRadius: '12px' }}>
<TYPE.main>Current Price</TYPE.main>
<TYPE.main>
{invertPrice ? price.invert().toSignificant(3) : price.toSignificant(3)}{' '}
{quoteCurrency?.symbol} = 1 {baseCurrency.symbol}
</TYPE.main>
</RowBetween>
)}
<CurrencyInputPanel <RangeSelector
value={formattedAmounts[Field.CURRENCY_A]} priceLower={priceLower}
onUserInput={onFieldAInput} priceUpper={priceUpper}
onMax={() => { getDecrementLower={getDecrementLower}
onFieldAInput(maxAmounts[Field.CURRENCY_A]?.toExact() ?? '') getIncrementLower={getIncrementLower}
}} getDecrementUpper={getDecrementUpper}
onCurrencySelect={handleCurrencyASelect} getIncrementUpper={getIncrementUpper}
showMaxButton={!atMaxAmounts[Field.CURRENCY_A]} onLeftRangeInput={onLeftRangeInput}
currency={currencies[Field.CURRENCY_A]} onRightRangeInput={onRightRangeInput}
id="add-liquidity-input-tokena" currencyA={baseCurrency}
showCommonBases currencyB={quoteCurrency}
locked={depositADisabled} feeAmount={feeAmount}
/> />
<ColumnCenter> {outOfRange ? (
<Link2 stroke={theme.text2} size={'24px'} /> <YellowCard padding="8px 12px" borderRadius="12px">
</ColumnCenter> <RowBetween>
<AlertTriangle stroke={theme.yellow3} size="16px" />
<TYPE.yellow ml="12px" fontSize="12px">
{t('inactiveRangeWarning')}
</TYPE.yellow>
</RowBetween>
</YellowCard>
) : null}
<CurrencyInputPanel {invalidRange ? (
value={formattedAmounts[Field.CURRENCY_B]} <YellowCard padding="8px 12px" borderRadius="12px">
onUserInput={onFieldBInput} <RowBetween>
onCurrencySelect={handleCurrencyBSelect} <AlertTriangle stroke={theme.yellow3} size="16px" />
onMax={() => { <TYPE.yellow ml="12px" fontSize="12px">
onFieldBInput(maxAmounts[Field.CURRENCY_B]?.toExact() ?? '') {t('invalidRangeWarning')}
}} </TYPE.yellow>
showMaxButton={!atMaxAmounts[Field.CURRENCY_B]} </RowBetween>
currency={currencies[Field.CURRENCY_B]} </YellowCard>
id="add-liquidity-input-tokenb" ) : null}
showCommonBases </DynamicSection>
locked={depositBDisabled} </>
/> )}
</AutoColumn>
</DynamicSection> <DynamicSection
</AutoColumn> disabled={tickLower === undefined || tickUpper === undefined || invalidPool || invalidRange}
</Wrapper> >
</AppBody> <AutoColumn gap="md">
)} <TYPE.label>{hasExistingPosition ? 'Add more liquidity' : t('depositAmounts')}</TYPE.label>
</ScrollableContent>
{addIsUnsupported && ( <CurrencyInputPanel
<UnsupportedCurrencyFooter value={formattedAmounts[Field.CURRENCY_A]}
show={addIsUnsupported} onUserInput={onFieldAInput}
currencies={[currencies.CURRENCY_A, currencies.CURRENCY_B]} onMax={() => {
/> onFieldAInput(maxAmounts[Field.CURRENCY_A]?.toExact() ?? '')
)} }}
<FixedPreview> onCurrencySelect={handleCurrencyASelect}
{attemptingTxn ? ( showMaxButton={!atMaxAmounts[Field.CURRENCY_A]}
<ConfirmationPendingContent onDismiss={handleDismissConfirmation} pendingText={pendingText} inline={true} /> currency={currencies[Field.CURRENCY_A]}
) : txHash && chainId ? ( id="add-liquidity-input-tokena"
<TransactionSubmittedContent showCommonBases
chainId={chainId} locked={depositADisabled}
hash={txHash} />
onDismiss={handleDismissConfirmation}
inline={true} <ColumnCenter>
/> <Link2 stroke={theme.text2} size={'24px'} />
) : ( </ColumnCenter>
<AutoColumn gap="md">
<TYPE.label fontSize="16px">{showConfirm ? 'Review and submit' : 'Configure Position'}</TYPE.label> <CurrencyInputPanel
{/* <TYPE.main fontWeight={400} fontSize="14px"> value={formattedAmounts[Field.CURRENCY_B]}
Learn more about Uniswap V3 liquidity pools. onUserInput={onFieldBInput}
</TYPE.main> */} onCurrencySelect={handleCurrencyBSelect}
{noLiquidity && ( onMax={() => {
<BlueCard width="100%" padding="1rem"> onFieldBInput(maxAmounts[Field.CURRENCY_B]?.toExact() ?? '')
You are the first to provide liquidity to this pool. }}
</BlueCard> showMaxButton={!atMaxAmounts[Field.CURRENCY_B]}
)} currency={currencies[Field.CURRENCY_B]}
{showConfirm ? ( id="add-liquidity-input-tokenb"
showCommonBases
locked={depositBDisabled}
/>
</AutoColumn>
</DynamicSection>
<div> <div>
{addIsUnsupported ? ( {addIsUnsupported ? (
<ButtonPrimary disabled={true} borderRadius="12px" padding={'12px'}> <ButtonPrimary disabled={true} borderRadius="12px" padding={'12px'}>
...@@ -667,10 +636,8 @@ export default function AddLiquidity({ ...@@ -667,10 +636,8 @@ export default function AddLiquidity({
)} )}
<ButtonError <ButtonError
onClick={() => { onClick={() => {
onAdd() expertMode ? onAdd() : setShowConfirm(true)
}} }}
style={{ borderRadius: '12px' }}
padding={'12px'}
disabled={ disabled={
!isValid || !isValid ||
(approvalA !== ApprovalState.APPROVED && !depositADisabled) || (approvalA !== ApprovalState.APPROVED && !depositADisabled) ||
...@@ -678,29 +645,22 @@ export default function AddLiquidity({ ...@@ -678,29 +645,22 @@ export default function AddLiquidity({
} }
error={!isValid && !!parsedAmounts[Field.CURRENCY_A] && !!parsedAmounts[Field.CURRENCY_B]} error={!isValid && !!parsedAmounts[Field.CURRENCY_A] && !!parsedAmounts[Field.CURRENCY_B]}
> >
<Text fontWeight={500}> <Text fontWeight={500}>{errorMessage ? errorMessage : 'Add'}</Text>
{errorMessage ? errorMessage : noLiquidity ? 'Create Pool and Add' : 'Add'}
</Text>
</ButtonError> </ButtonError>
</AutoColumn> </AutoColumn>
)} )}
</div> </div>
) : ( </AutoColumn>
<ButtonError </Wrapper>
onClick={() => { </AppBody>
expertMode ? onAdd() : setShowConfirm(true) {/* )} */}
}} </ScrollableContent>
style={{ borderRadius: '12px' }} {addIsUnsupported && (
padding={'12px'} <UnsupportedCurrencyFooter
disabled={!isValid} show={addIsUnsupported}
error={!isValid && !!parsedAmounts[Field.CURRENCY_A] && !!parsedAmounts[Field.CURRENCY_B]} currencies={[currencies.CURRENCY_A, currencies.CURRENCY_B]}
> />
<Text fontWeight={500}>{errorMessage ?? 'Review'}</Text> )}
</ButtonError>
)}
</AutoColumn>
)}
</FixedPreview>
</ScrollablePage> </ScrollablePage>
) )
} }
import React, { useCallback, useMemo, useState } from 'react' import React, { useCallback, useMemo, useState } from 'react'
import { useV3PositionFromTokenId } from 'hooks/useV3Positions' import { useV3PositionFromTokenId } from 'hooks/useV3Positions'
import { Redirect, RouteComponentProps, Link } from 'react-router-dom' import { Redirect, RouteComponentProps } from 'react-router-dom'
import AppBody from '../AppBody' import AppBody from '../AppBody'
import { BigNumber } from '@ethersproject/bignumber' import { BigNumber } from '@ethersproject/bignumber'
import useDebouncedChangeHandler from 'hooks/useDebouncedChangeHandler' import useDebouncedChangeHandler from 'hooks/useDebouncedChangeHandler'
import { useBurnV3ActionHandlers, useBurnV3State, useDerivedV3BurnInfo } from 'state/burn/v3/hooks' import { useBurnV3ActionHandlers, useBurnV3State, useDerivedV3BurnInfo } from 'state/burn/v3/hooks'
import Slider from 'components/Slider' import Slider from 'components/Slider'
import { AutoRow, RowBetween, RowFixed } from 'components/Row' import { AutoRow, RowBetween, RowFixed } from 'components/Row'
import TransactionConfirmationModal from '../../components/TransactionConfirmationModal' import TransactionConfirmationModal, { ConfirmationModalContent } from '../../components/TransactionConfirmationModal'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
import { ButtonConfirmed, ButtonText } from 'components/Button' import { ButtonConfirmed, ButtonPrimary } from 'components/Button'
import { LightCard } from 'components/Card' import { LightCard } from 'components/Card'
import { Text } from 'rebass' import { Text } from 'rebass'
import CurrencyLogo from 'components/CurrencyLogo' import CurrencyLogo from 'components/CurrencyLogo'
...@@ -23,7 +23,6 @@ import { TransactionResponse } from '@ethersproject/providers' ...@@ -23,7 +23,6 @@ import { TransactionResponse } from '@ethersproject/providers'
import { useTransactionAdder } from 'state/transactions/hooks' import { useTransactionAdder } from 'state/transactions/hooks'
import { WETH9, CurrencyAmount } from '@uniswap/sdk-core' import { WETH9, CurrencyAmount } from '@uniswap/sdk-core'
import { TYPE } from 'theme' import { TYPE } from 'theme'
import styled from 'styled-components'
import { Wrapper, SmallMaxButton } from './styled' import { Wrapper, SmallMaxButton } from './styled'
import Loader from 'components/Loader' import Loader from 'components/Loader'
import { useToken } from 'hooks/Tokens' import { useToken } from 'hooks/Tokens'
...@@ -33,13 +32,11 @@ import { RangeBadge } from 'pages/AddLiquidity/styled' ...@@ -33,13 +32,11 @@ import { RangeBadge } from 'pages/AddLiquidity/styled'
import { Break } from 'components/earn/styled' import { Break } from 'components/earn/styled'
import { NonfungiblePositionManager } from '@uniswap/v3-sdk' import { NonfungiblePositionManager } from '@uniswap/v3-sdk'
import { calculateGasMargin } from 'utils' import { calculateGasMargin } from 'utils'
import useTheme from 'hooks/useTheme'
import { AddRemoveTabs } from 'components/NavigationTabs'
export const UINT128MAX = BigNumber.from(2).pow(128).sub(1) export const UINT128MAX = BigNumber.from(2).pow(128).sub(1)
const UnstyledLink = styled(Link)`
text-decoration: none;
`
// redirect invalid tokenIds // redirect invalid tokenIds
export default function RemoveLiquidityV3({ export default function RemoveLiquidityV3({
location, location,
...@@ -63,7 +60,7 @@ export default function RemoveLiquidityV3({ ...@@ -63,7 +60,7 @@ export default function RemoveLiquidityV3({
} }
function Remove({ tokenId }: { tokenId: BigNumber }) { function Remove({ tokenId }: { tokenId: BigNumber }) {
const { position } = useV3PositionFromTokenId(tokenId) const { position } = useV3PositionFromTokenId(tokenId)
const theme = useTheme()
const { account, chainId, library } = useActiveWeb3React() const { account, chainId, library } = useActiveWeb3React()
// currencies from position // currencies from position
...@@ -98,7 +95,6 @@ function Remove({ tokenId }: { tokenId: BigNumber }) { ...@@ -98,7 +95,6 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
const addTransaction = useTransactionAdder() const addTransaction = useTransactionAdder()
const positionManager = useV3NFTPositionManagerContract() const positionManager = useV3NFTPositionManagerContract()
const burn = useCallback(async () => { const burn = useCallback(async () => {
setShowConfirm(true)
setAttemptingTxn(true) setAttemptingTxn(true)
if ( if (
!positionManager || !positionManager ||
...@@ -113,7 +109,6 @@ function Remove({ tokenId }: { tokenId: BigNumber }) { ...@@ -113,7 +109,6 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
!liquidityPercentage || !liquidityPercentage ||
!library !library
) { ) {
setShowConfirm(false)
return return
} }
...@@ -165,7 +160,6 @@ function Remove({ tokenId }: { tokenId: BigNumber }) { ...@@ -165,7 +160,6 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
}) })
}) })
.catch((error) => { .catch((error) => {
setShowConfirm(false)
setAttemptingTxn(false) setAttemptingTxn(false)
console.error(error) console.error(error)
}) })
...@@ -200,6 +194,67 @@ function Remove({ tokenId }: { tokenId: BigNumber }) { ...@@ -200,6 +194,67 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
currency0?.symbol currency0?.symbol
} and ${liquidityValue1?.toSignificant(6)} ${currency1?.symbol}` } and ${liquidityValue1?.toSignificant(6)} ${currency1?.symbol}`
function modalHeader() {
return (
<AutoColumn gap={'sm'} style={{ marginTop: '20px' }}>
<RowBetween align="flex-end">
<Text fontSize={16} fontWeight={500}>
{currency0?.symbol}:
</Text>
<RowFixed>
<Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
{liquidityValue0 && <FormattedCurrencyAmount currencyAmount={liquidityValue0} />}
</Text>
<CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={currency0} />
</RowFixed>
</RowBetween>
<RowBetween align="flex-end">
<Text fontSize={16} fontWeight={500}>
{currency1?.symbol}:
</Text>
<RowFixed>
<Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
{liquidityValue1 && <FormattedCurrencyAmount currencyAmount={liquidityValue1} />}
</Text>
<CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={currency1} />
</RowFixed>
</RowBetween>
{feeValue0?.greaterThan(0) || feeValue1?.greaterThan(0) ? (
<>
<TYPE.italic fontSize={12} color={theme.text2} textAlign="left" padding={'8px 0 0 0'}>
{`You will also collect fees earned from this position.`}
</TYPE.italic>
<RowBetween>
<Text fontSize={16} fontWeight={500}>
{currency0?.symbol} from fees:
</Text>
<RowFixed>
<Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
{feeValue0 && <FormattedCurrencyAmount currencyAmount={feeValue0} />}
</Text>
<CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={currency0} />
</RowFixed>
</RowBetween>
<RowBetween>
<Text fontSize={16} fontWeight={500}>
{currency1?.symbol} from fees:
</Text>
<RowFixed>
<Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
{feeValue1 && <FormattedCurrencyAmount currencyAmount={feeValue1} />}
</Text>
<CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={currency1} />
</RowFixed>
</RowBetween>
</>
) : null}
<ButtonPrimary mt="16px" onClick={burn}>
Remove
</ButtonPrimary>
</AutoColumn>
)
}
return ( return (
<AutoColumn> <AutoColumn>
<TransactionConfirmationModal <TransactionConfirmationModal
...@@ -207,19 +262,17 @@ function Remove({ tokenId }: { tokenId: BigNumber }) { ...@@ -207,19 +262,17 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
onDismiss={handleDismissConfirmation} onDismiss={handleDismissConfirmation}
attemptingTxn={attemptingTxn} attemptingTxn={attemptingTxn}
hash={txnHash ?? ''} hash={txnHash ?? ''}
content={() => <div />} content={() => (
<ConfirmationModalContent
title={'Remove Liquidity'}
onDismiss={handleDismissConfirmation}
topContent={modalHeader}
/>
)}
pendingText={pendingText} pendingText={pendingText}
/> />
<AutoRow marginBottom="20px">
<UnstyledLink to="pool">
<ButtonText opacity={'0.4'}>Pool</ButtonText>
</UnstyledLink>
<TYPE.label margin="0 10px" opacity={'0.4'}>
{' > '}
</TYPE.label>
<TYPE.label>Remove Liquidity</TYPE.label>
</AutoRow>
<AppBody> <AppBody>
<AddRemoveTabs creating={false} adding={false} />
<Wrapper> <Wrapper>
{position ? ( {position ? (
<AutoColumn gap="lg"> <AutoColumn gap="lg">
...@@ -308,8 +361,12 @@ function Remove({ tokenId }: { tokenId: BigNumber }) { ...@@ -308,8 +361,12 @@ function Remove({ tokenId }: { tokenId: BigNumber }) {
</LightCard> </LightCard>
<div style={{ display: 'flex' }}> <div style={{ display: 'flex' }}>
<AutoColumn gap="12px" style={{ flex: '1' }}> <AutoColumn gap="12px" style={{ flex: '1' }}>
<ButtonConfirmed confirmed={false} disabled={percent === 0 || !liquidityValue0} onClick={burn}> <ButtonConfirmed
{error ?? 'Remove Liquidity'} confirmed={false}
disabled={percent === 0 || !liquidityValue0}
onClick={() => setShowConfirm(true)}
>
{error ?? 'Remove'}
</ButtonConfirmed> </ButtonConfirmed>
</AutoColumn> </AutoColumn>
</div> </div>
......
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