Commit 2d7642ed authored by Noah Zinsmeister's avatar Noah Zinsmeister

simplify range ui

parent c3ad1296
...@@ -2,7 +2,7 @@ import React, { useMemo } from 'react' ...@@ -2,7 +2,7 @@ import React, { useMemo } from 'react'
import { Position } from '@uniswap/v3-sdk' import { Position } from '@uniswap/v3-sdk'
import Badge, { BadgeVariant } from 'components/Badge' import Badge, { BadgeVariant } from 'components/Badge'
import DoubleCurrencyLogo from 'components/DoubleLogo' import DoubleCurrencyLogo from 'components/DoubleLogo'
import { PoolState, usePool } from 'hooks/usePools' import { usePool } from 'hooks/usePools'
import { useToken } from 'hooks/Tokens' import { useToken } from 'hooks/Tokens'
import { AlertTriangle } from 'react-feather' import { AlertTriangle } from 'react-feather'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
...@@ -11,11 +11,12 @@ import styled from 'styled-components' ...@@ -11,11 +11,12 @@ import styled from 'styled-components'
import { MEDIA_WIDTHS } from 'theme' import { MEDIA_WIDTHS } from 'theme'
import { PositionDetails } from 'types/position' import { PositionDetails } from 'types/position'
import { basisPointsToPercent } from 'utils' import { basisPointsToPercent } from 'utils'
import { TokenAmount } from '@uniswap/sdk-core' import { TokenAmount, WETH9, Price, Token } from '@uniswap/sdk-core'
import { formatPrice, formatTokenAmount } from 'utils/formatTokenAmount' import { formatPrice, formatTokenAmount } from 'utils/formatTokenAmount'
import Loader from 'components/Loader' import Loader from 'components/Loader'
import { unwrappedToken } from 'utils/wrappedCurrency' import { unwrappedToken } from 'utils/wrappedCurrency'
import { useV3PositionFees } from 'hooks/useV3PositionFees' import { useV3PositionFees } from 'hooks/useV3PositionFees'
import { DAI, USDC, USDT, WBTC } from '../../constants'
const ActiveDot = styled.span` const ActiveDot = styled.span`
background-color: ${({ theme }) => theme.success}; background-color: ${({ theme }) => theme.success};
...@@ -123,6 +124,62 @@ export interface PositionListItemProps { ...@@ -123,6 +124,62 @@ export interface PositionListItemProps {
positionDetails: PositionDetails positionDetails: PositionDetails
} }
export function getPriceOrderingFromPositionForUI(
position?: Position
): {
priceLower?: Price
priceUpper?: Price
quote?: Token
base?: Token
} {
if (!position) {
return {}
}
const token0 = position.amount0.token
const token1 = position.amount1.token
// if token0 is a dollar-stable asset, set it as the quote token
const stables = [DAI, USDC, USDT]
if (stables.some((stable) => stable.equals(token0))) {
return {
priceLower: position.token0PriceUpper.invert(),
priceUpper: position.token0PriceLower.invert(),
quote: token0,
base: token1,
}
}
// if token1 is an ETH-/BTC-stable asset, set it as the base token
const bases = [...Object.values(WETH9), WBTC]
if (bases.some((base) => base.equals(token1))) {
return {
priceLower: position.token0PriceUpper.invert(),
priceUpper: position.token0PriceLower.invert(),
quote: token0,
base: token1,
}
}
// if both prices are below 1, invert
if (position.token0PriceUpper.lessThan(1)) {
return {
priceLower: position.token0PriceUpper.invert(),
priceUpper: position.token0PriceLower.invert(),
quote: token0,
base: token1,
}
}
// otherwise, just return the default
return {
priceLower: position.token0PriceUpper.invert(),
priceUpper: position.token0PriceLower.invert(),
quote: token1,
base: token0,
}
}
export default function PositionListItem({ positionDetails }: PositionListItemProps) { export default function PositionListItem({ positionDetails }: PositionListItemProps) {
const { t } = useTranslation() const { t } = useTranslation()
...@@ -142,7 +199,8 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr ...@@ -142,7 +199,8 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr
const currency1 = token1 ? unwrappedToken(token1) : undefined const currency1 = token1 ? unwrappedToken(token1) : undefined
// construct Position from details returned // construct Position from details returned
const [poolState, pool] = usePool(currency0 ?? undefined, currency1 ?? undefined, feeAmount) const [, pool] = usePool(currency0 ?? undefined, currency1 ?? undefined, feeAmount)
const position = useMemo(() => { const position = useMemo(() => {
if (pool) { if (pool) {
return new Position({ pool, liquidity: liquidity.toString(), tickLower, tickUpper }) return new Position({ pool, liquidity: liquidity.toString(), tickLower, tickUpper })
...@@ -150,8 +208,6 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr ...@@ -150,8 +208,6 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr
return undefined return undefined
}, [liquidity, pool, tickLower, tickUpper]) }, [liquidity, pool, tickLower, tickUpper])
const poolLoading = poolState === PoolState.LOADING
// liquidity amounts in tokens // liquidity amounts in tokens
const amount0: TokenAmount | undefined = position?.amount0 const amount0: TokenAmount | undefined = position?.amount0
const amount1: TokenAmount | undefined = position?.amount1 const amount1: TokenAmount | undefined = position?.amount1
...@@ -159,10 +215,10 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr ...@@ -159,10 +215,10 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr
const formattedAmount1 = formatTokenAmount(amount1, 4) const formattedAmount1 = formatTokenAmount(amount1, 4)
// prices // prices
const price0Lower = position?.token0PriceLower const { priceLower, priceUpper, base } = getPriceOrderingFromPositionForUI(position)
const price0Upper = position?.token0PriceUpper const inverted = token1 ? base?.equals(token1) : undefined
const price1Lower = price0Lower?.invert() const currencyQuote = inverted ? currency0 : currency1
const price1Upper = price0Upper?.invert() const currencyBase = inverted ? currency1 : currency0
// fees // fees
const [feeValue0, feeValue1] = useV3PositionFees(pool ?? undefined, positionDetails) const [feeValue0, feeValue1] = useV3PositionFees(pool ?? undefined, positionDetails)
...@@ -176,9 +232,9 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr ...@@ -176,9 +232,9 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr
<Row to={positionSummaryLink}> <Row to={positionSummaryLink}>
<LabelData> <LabelData>
<PrimaryPositionIdData> <PrimaryPositionIdData>
<DoubleCurrencyLogo currency0={currency0 ?? undefined} currency1={currency1 ?? undefined} size={16} margin /> <DoubleCurrencyLogo currency0={currencyBase} currency1={currencyQuote} size={16} margin />
<DataText> <DataText>
&nbsp;{currency0?.symbol}&nbsp;/&nbsp;{currency1?.symbol} &nbsp;{currencyQuote?.symbol}&nbsp;/&nbsp;{currencyBase?.symbol}
</DataText> </DataText>
&nbsp; &nbsp;
<Badge> <Badge>
...@@ -201,17 +257,13 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr ...@@ -201,17 +257,13 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr
</BadgeWrapper> </BadgeWrapper>
</LabelData> </LabelData>
<RangeData> <RangeData>
{price0Lower && price1Lower && price0Upper && price1Upper ? ( {priceLower && priceUpper ? (
<> <>
<DataLineItem> <DataLineItem>
{formatPrice(price0Lower, 4)} <DoubleArrow></DoubleArrow> {formatPrice(price0Upper, 4)}{' '} {formatPrice(priceLower, 4)} <DoubleArrow></DoubleArrow> {formatPrice(priceUpper, 4)}{' '}
{currency1?.symbol}&nbsp;/&nbsp; {currencyQuote?.symbol}
{currency0?.symbol} &nbsp;/&nbsp;
</DataLineItem> {currencyBase?.symbol}
<DataLineItem>
{formatPrice(price1Lower, 4)} <DoubleArrow></DoubleArrow> {formatPrice(price1Upper, 4)}{' '}
{currency0?.symbol}&nbsp;/&nbsp;
{currency1?.symbol}
</DataLineItem> </DataLineItem>
</> </>
) : ( ) : (
...@@ -219,13 +271,13 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr ...@@ -219,13 +271,13 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr
)} )}
</RangeData> </RangeData>
<AmountData> <AmountData>
{!poolLoading ? ( {formattedAmount0 && formattedAmount1 ? (
<> <>
<DataLineItem> <DataLineItem>
{formattedAmount0}&nbsp;{currency0?.symbol} {inverted ? formattedAmount0 : formattedAmount1}&nbsp;{currencyQuote?.symbol}
</DataLineItem> </DataLineItem>
<DataLineItem> <DataLineItem>
{formattedAmount1}&nbsp;{currency1?.symbol} {inverted ? formattedAmount1 : formattedAmount0}&nbsp;{currencyBase?.symbol}
</DataLineItem> </DataLineItem>
</> </>
) : ( ) : (
...@@ -236,10 +288,10 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr ...@@ -236,10 +288,10 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr
{feeValue0 && feeValue1 ? ( {feeValue0 && feeValue1 ? (
<> <>
<DataLineItem> <DataLineItem>
{formatTokenAmount(feeValue0, 4)}&nbsp;{currency0?.symbol} {formatTokenAmount(inverted ? feeValue0 : feeValue1, 4)}&nbsp;{currencyQuote?.symbol}
</DataLineItem> </DataLineItem>
<DataLineItem> <DataLineItem>
{formatTokenAmount(feeValue1, 4)}&nbsp;{currency1?.symbol} {formatTokenAmount(inverted ? feeValue1 : feeValue0, 4)}&nbsp;{currencyBase?.symbol}
</DataLineItem> </DataLineItem>
</> </>
) : ( ) : (
......
...@@ -10,13 +10,13 @@ import styled from 'styled-components' ...@@ -10,13 +10,13 @@ import styled from 'styled-components'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
import { RowBetween, RowFixed } from 'components/Row' import { RowBetween, RowFixed } from 'components/Row'
import DoubleCurrencyLogo from 'components/DoubleLogo' import DoubleCurrencyLogo from 'components/DoubleLogo'
import { TYPE } from 'theme' import { ButtonText, TYPE } from 'theme'
import Badge, { BadgeVariant } from 'components/Badge' import Badge, { BadgeVariant } from 'components/Badge'
import { basisPointsToPercent } from 'utils' import { basisPointsToPercent } from 'utils'
import { ButtonConfirmed, ButtonPrimary } from 'components/Button' import { ButtonConfirmed, ButtonPrimary } from 'components/Button'
import { DarkCard, DarkGreyCard } from 'components/Card' import { DarkCard, DarkGreyCard } from 'components/Card'
import CurrencyLogo from 'components/CurrencyLogo' import CurrencyLogo from 'components/CurrencyLogo'
import { AlertTriangle } from 'react-feather' import { AlertTriangle, ToggleLeft, ToggleRight } from 'react-feather'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { currencyId } from 'utils/currencyId' import { currencyId } from 'utils/currencyId'
import { formatTokenAmount } from 'utils/formatTokenAmount' import { formatTokenAmount } from 'utils/formatTokenAmount'
...@@ -30,6 +30,7 @@ import { useIsTransactionPending, useTransactionAdder } from 'state/transactions ...@@ -30,6 +30,7 @@ import { useIsTransactionPending, useTransactionAdder } from 'state/transactions
import ReactGA from 'react-ga' import ReactGA from 'react-ga'
import { TransactionResponse } from '@ethersproject/providers' import { TransactionResponse } from '@ethersproject/providers'
import { Dots } from 'components/swap/styleds' import { Dots } from 'components/swap/styleds'
import { getPriceOrderingFromPositionForUI } from '../../components/PositionListItem'
const PageWrapper = styled.div` const PageWrapper = styled.div`
min-width: 800px; min-width: 800px;
...@@ -122,10 +123,15 @@ export function PositionPage({ ...@@ -122,10 +123,15 @@ export function PositionPage({
return undefined return undefined
}, [liquidity, pool, tickLower, tickUpper]) }, [liquidity, pool, tickLower, tickUpper])
const price0Lower = position?.token0PriceLower let { priceLower, priceUpper, base, quote } = getPriceOrderingFromPositionForUI(position)
const price0Upper = position?.token0PriceUpper const [manuallyInverted, setManuallyInverted] = useState(false)
const price1Lower = price0Lower?.invert() // handle manual inversion
const price1Upper = price0Upper?.invert() if (manuallyInverted) {
;[priceLower, priceUpper, base, quote] = [priceUpper?.invert(), priceLower?.invert(), quote, base]
}
const inverted = token1 ? base?.equals(token1) : undefined
const currencyQuote = inverted ? currency0 : currency1
const currencyBase = inverted ? currency1 : currency0
// check if price is within range // check if price is within range
const outOfRange: boolean = const outOfRange: boolean =
...@@ -225,9 +231,9 @@ export function PositionPage({ ...@@ -225,9 +231,9 @@ export function PositionPage({
<AutoColumn gap="sm"> <AutoColumn gap="sm">
<RowBetween> <RowBetween>
<RowFixed> <RowFixed>
<DoubleCurrencyLogo currency0={currency0} currency1={currency1} size={20} margin={true} /> <DoubleCurrencyLogo currency0={currencyBase} currency1={currencyQuote} size={20} margin={true} />
<TYPE.label fontSize={'20px'} mr="10px"> <TYPE.label fontSize={'20px'} mr="10px">
&nbsp;{currency0?.symbol}&nbsp;/&nbsp;{currency1?.symbol} &nbsp;{currencyQuote?.symbol}&nbsp;/&nbsp;{currencyBase?.symbol}
</TYPE.label> </TYPE.label>
<Badge> <Badge>
<BadgeText>{basisPointsToPercent(feeAmount / 100).toSignificant()}%</BadgeText> <BadgeText>{basisPointsToPercent(feeAmount / 100).toSignificant()}%</BadgeText>
...@@ -290,75 +296,93 @@ export function PositionPage({ ...@@ -290,75 +296,93 @@ export function PositionPage({
<AutoColumn gap="lg"> <AutoColumn gap="lg">
<ResponsiveGrid> <ResponsiveGrid>
<Label>Tokens</Label> <Label>Tokens</Label>
<Label end={true}>Amount Deposited</Label> <Label end={true}>Liquidity</Label>
<Label end={true}>Fees</Label> <Label end={true}>Fees</Label>
</ResponsiveGrid> </ResponsiveGrid>
<ResponsiveGrid> <ResponsiveGrid>
<RowFixed> <RowFixed>
<CurrencyLogo currency={currency0} /> <CurrencyLogo currency={currencyQuote} />
<TYPE.label ml="10px">{currency0?.symbol}</TYPE.label> <TYPE.label ml="10px">{currencyQuote?.symbol}</TYPE.label>
</RowFixed> </RowFixed>
<Label end={true}>{position?.amount0.toSignificant(4)}</Label> <Label end={true}>
<Label end={true}>{feeValue0 ? formatTokenAmount(feeValue0, 4) : '-'}</Label> {inverted ? position?.amount0.toSignificant(4) : position?.amount1.toSignificant(4)}
</Label>
<Label end={true}>
{inverted
? feeValue0
? formatTokenAmount(feeValue0, 4)
: '-'
: feeValue1
? formatTokenAmount(feeValue1, 4)
: '-'}
</Label>
</ResponsiveGrid> </ResponsiveGrid>
<ResponsiveGrid> <ResponsiveGrid>
<RowFixed> <RowFixed>
<CurrencyLogo currency={currency1} /> <CurrencyLogo currency={currencyBase} />
<TYPE.label ml="10px">{currency1?.symbol}</TYPE.label> <TYPE.label ml="10px">{currencyBase?.symbol}</TYPE.label>
</RowFixed> </RowFixed>
<Label end={true}>{position?.amount1.toSignificant(4)}</Label> <Label end={true}>
<Label end={true}>{feeValue1 ? formatTokenAmount(feeValue1, 4) : '-'}</Label> {inverted ? position?.amount1.toSignificant(4) : position?.amount0.toSignificant(4)}
</Label>
<Label end={true}>
{inverted
? feeValue1
? formatTokenAmount(feeValue1, 4)
: '-'
: feeValue0
? formatTokenAmount(feeValue0, 4)
: '-'}
</Label>
</ResponsiveGrid> </ResponsiveGrid>
</AutoColumn> </AutoColumn>
</DarkCard> </DarkCard>
<DarkCard> <DarkCard>
<AutoColumn gap="lg"> <AutoColumn gap="lg">
<TYPE.label>Position Limits</TYPE.label> <TYPE.label display="flex">
Position Limits
<ButtonText style={{ marginLeft: '10px', color: 'inherit' }}>
{manuallyInverted ? (
<ToggleLeft onClick={() => setManuallyInverted(false)} />
) : (
<ToggleRight onClick={() => setManuallyInverted(true)} />
)}
</ButtonText>
</TYPE.label>
<RowBetween> <RowBetween>
<DarkGreyCard width="49%"> <DarkGreyCard width="48%">
<AutoColumn gap="sm" justify="flex-start"> <AutoColumn gap="sm" justify="flex-start">
<TYPE.main>Lower Limit</TYPE.main> <TYPE.main>Lower</TYPE.main>
<RowFixed>
<TYPE.label>{price0Lower?.toSignificant(4)}</TYPE.label>
<TYPE.label ml="10px">
{currency0?.symbol} / {currency1?.symbol}
</TYPE.label>
</RowFixed>
<RowFixed> <RowFixed>
<TYPE.label>{price1Lower?.toSignificant(4)}</TYPE.label> <TYPE.label>
<TYPE.label ml="10px"> {priceLower?.toSignificant(4)} {currencyQuote?.symbol} / 1 {currencyBase?.symbol}
{currency1?.symbol} / {currency0?.symbol}
</TYPE.label> </TYPE.label>
</RowFixed> </RowFixed>
<DarkBadge> <DarkBadge>
<RowFixed> <RowFixed>
<TYPE.label mr="6px">100%</TYPE.label> <TYPE.label mr="6px">100%</TYPE.label>
<CurrencyLogo currency={currency0} size="16px" /> <CurrencyLogo currency={inverted ? currency1 : currency0} size="16px" />
<TYPE.label ml="4px">{currency0?.symbol}</TYPE.label> <TYPE.label ml="4px">{inverted ? currency1?.symbol : currency0?.symbol}</TYPE.label>
</RowFixed> </RowFixed>
</DarkBadge> </DarkBadge>
</AutoColumn> </AutoColumn>
</DarkGreyCard> </DarkGreyCard>
<DarkGreyCard width="49%">
<DarkGreyCard width="48%">
<AutoColumn gap="sm" justify="flex-start"> <AutoColumn gap="sm" justify="flex-start">
<TYPE.main>Upper Limit</TYPE.main> <TYPE.main>Upper</TYPE.main>
<RowFixed>
<TYPE.label>{price0Upper?.toSignificant(4)}</TYPE.label>
<TYPE.label ml="10px">
{currency0?.symbol} / {currency1?.symbol}
</TYPE.label>
</RowFixed>
<RowFixed> <RowFixed>
<TYPE.label>{price1Upper?.toSignificant(4)}</TYPE.label> <TYPE.label>
<TYPE.label ml="10px"> {priceUpper?.toSignificant(4)} {currencyQuote?.symbol} / 1 {currencyBase?.symbol}
{currency1?.symbol} / {currency0?.symbol}
</TYPE.label> </TYPE.label>
</RowFixed> </RowFixed>
<DarkBadge> <DarkBadge>
<RowFixed> <RowFixed>
<TYPE.label mr="6px">100%</TYPE.label> <TYPE.label mr="6px">100%</TYPE.label>
<CurrencyLogo currency={currency1} size="16px" /> <CurrencyLogo currency={inverted ? currency0 : currency1} size="16px" />
<TYPE.label ml="4px">{currency1?.symbol}</TYPE.label> <TYPE.label ml="4px">{inverted ? currency0?.symbol : currency1?.symbol}</TYPE.label>
</RowFixed> </RowFixed>
</DarkBadge> </DarkBadge>
</AutoColumn> </AutoColumn>
......
...@@ -67,6 +67,7 @@ const loadingAnimation = keyframes` ...@@ -67,6 +67,7 @@ const loadingAnimation = keyframes`
export const LoadingRows = styled.div` export const LoadingRows = styled.div`
display: grid; display: grid;
min-width: 75%;
grid-column-gap: 0.5em; grid-column-gap: 0.5em;
grid-row-gap: 0.8em; grid-row-gap: 0.8em;
grid-template-columns: repeat(3, 1fr); grid-template-columns: repeat(3, 1fr);
......
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