Skip to content
This repository has been archived by the owner on Jun 24, 2022. It is now read-only.

Commit

Permalink
feat(pool): add liquidity distribution range slider and update add li…
Browse files Browse the repository at this point in the history
…quidity layout (#1829)

* first iteration of useTicks and useActiveLiquidity

* feat(pools): add liquidity depth chart (#1835)

* cleanup

* use area chart instead of bar chart

* check for undefined rather than falsy

* feat: range buttons based on fee amount (#1870)

* range buttons based on fee amount

* hardcode percentages as ticks

* increase blocksperfect

* feat: optimize add liquidity charts (#1880)

* ignore syncing state

* remove surrounding ticks

* avoid processing price1 as it is unused

* cleanup

* feat: add zoom buttons to liquidity depth chart (#1882)

* ignore syncing state

* remove surrounding ticks

* avoid processing price1 as it is unused

* cleanup

* first pass at +/- zoom buttons

* remove console.log, cleanup

* use real price for price line

* updated brush handles to latest spec

* added % labels to handles

* round tick to nearest usable tick

* first pass at brushable area chart with d3

* first pass at brushable area chart with d3

* rework

* address PR comments

* add brush handles

* address PR comments

* further improvements

* feat(pools): improve full range support + capital efficiency warning (#1903)

* handle min and max prices in add liquidity

* cleaned up

* use flag to denote full range

* reset inputs on fee select

* fixed merge conflict

* handle full range in positions preview

* fixed invalid range when tokens are reversed

* use formatTickData

* updated layout

* cleaned up layout

* fixed address

* avoid re-rendering deposit amounts

* added zoom behavior and more styling

* renamed chart

* renamed main chart file;

* add brush tooltips

* remove chart title

* added accents to brush handles

* more work

* moved to file

* modularize chart components

* fix maximum depth

* added brush labels

* cleanup

* cleanup

* set up zoom

* added new components

* improved brush and zoom integration

* cleaned up clip path

* fixed clip paths

* integrated with the graph changes

* adjust fee selector

* fix data error

* add bar chart

* polish

* merged

* clean up error

* cleaned up after merge

* visual improvements

* moved +/- buttons to the right/left

* removed margin bottom

* removed unsused

* fix brush labels % change

* use d3.axisBottom

* updated labels

* improve brush range

* fix one brush change only

* adjust zoom and clippath

* use bars

* use area

* adjust axis bottom to mocks;

* improved bars

* show bar colors

* better handle full range

* adjust colors for light mode

* updated to mocks

* adjusted handles for visibility

* switch to area

* add react ga events

* adjusted to mocks

* memo brush domain to avoid re-renders

* fix inputstepcounter color

* adjust handles

* rely on the graph sorting tickidx

* use curvestepafter

* updated polish

* merged main

* add clamping and other fixes

* highlight selected area using a mask

* use price instead of % for labels

* delete unused

* refine ux

* relayout

* improve hooks

* adjust layout for mobile

* fixed card color

* adjust padding

* preent tick overflow

* flip handles sooner

* delete bars.tsx
  • Loading branch information
Justin Domingue authored Jul 8, 2021
1 parent 2db29f2 commit ffbd2d1
Show file tree
Hide file tree
Showing 19 changed files with 997 additions and 470 deletions.
22 changes: 21 additions & 1 deletion src/components/Button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ export const ButtonOutlined = styled(Base)`
border: 1px solid ${({ theme }) => theme.bg2};
background-color: transparent;
color: ${({ theme }) => theme.text1};
&:focus {
box-shadow: 0 0 0 1px ${({ theme }) => theme.bg4};
}
Expand All @@ -169,6 +168,27 @@ export const ButtonOutlined = styled(Base)`
}
`

export const ButtonYellow = styled(Base)`
background-color: ${({ theme }) => theme.yellow3};
color: white;
&:focus {
box-shadow: 0 0 0 1pt ${({ theme }) => darken(0.05, theme.yellow3)};
background-color: ${({ theme }) => darken(0.05, theme.yellow3)};
}
&:hover {
background-color: ${({ theme }) => darken(0.05, theme.yellow3)};
}
&:active {
box-shadow: 0 0 0 1pt ${({ theme }) => darken(0.1, theme.yellow3)};
background-color: ${({ theme }) => darken(0.1, theme.yellow3)};
}
&:disabled {
background-color: ${({ theme }) => theme.yellow3};
opacity: 50%;
cursor: auto;
}
`

export const ButtonEmpty = styled(Base)`
background-color: transparent;
color: ${({ theme }) => theme.primary1};
Expand Down
2 changes: 1 addition & 1 deletion src/components/FeeSelector/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ export default function FeeSelector({
onClick={() => handleFeePoolSelectWithEvent(FeeAmount.LOW)}
>
<AutoColumn gap="sm" justify="flex-start">
<AutoColumn justify="flex-start" gap="4px">
<AutoColumn justify="flex-start" gap="6px">
<ResponsiveText>
<Trans>0.05% fee</Trans>
</ResponsiveText>
Expand Down
91 changes: 52 additions & 39 deletions src/components/InputStepCounter/InputStepCounter.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { useState, useCallback, useEffect, ReactNode } from 'react'
import { LightCard } from 'components/Card'
import { RowBetween } from 'components/Row'
import { OutlineCard } from 'components/Card'
import { Input as NumericalInput } from '../NumericalInput'
import styled, { keyframes } from 'styled-components/macro'
import { TYPE } from 'theme'
import { AutoColumn } from 'components/Column'
import { ButtonPrimary } from 'components/Button'
import { ButtonGray } from 'components/Button'
import { FeeAmount } from '@uniswap/v3-sdk'
import { formattedFeeAmount } from 'utils'
import { Trans } from '@lingui/macro'
import { Plus, Minus } from 'react-feather'

const pulse = (color: string) => keyframes`
0% {
Expand All @@ -24,25 +23,29 @@ const pulse = (color: string) => keyframes`
}
`

const SmallButton = styled(ButtonPrimary)`
/* background-color: ${({ theme }) => theme.bg2}; */
const InputRow = styled.div`
display: grid;
grid-template-columns: 30px 1fr 30px;
`

const SmallButton = styled(ButtonGray)`
border-radius: 8px;
padding: 4px 6px;
width: 48%;
padding: 4px;
`

const FocusedOutlineCard = styled(LightCard)<{ active?: boolean; pulsing?: boolean }>`
const FocusedOutlineCard = styled(OutlineCard)<{ active?: boolean; pulsing?: boolean }>`
border-color: ${({ active, theme }) => active && theme.blue1};
padding: 12px;
animation: ${({ pulsing, theme }) => pulsing && pulse(theme.blue1)} 0.8s linear;
`

const StyledInput = styled(NumericalInput)<{ usePercent?: boolean }>`
/* background-color: ${({ theme }) => theme.bg0}; */
background-color: transparent;
text-align: center;
margin-right: 12px;
width: 100%;
font-weight: 500;
padding: 0 10px;
`

const InputTitle = styled(TYPE.small)`
Expand All @@ -51,11 +54,17 @@ const InputTitle = styled(TYPE.small)`
font-weight: 500;
`

const ButtonLabel = styled(TYPE.white)<{ disabled: boolean }>`
color: ${({ theme, disabled }) => (disabled ? theme.text2 : theme.text1)} !important;
`

interface StepCounterProps {
value: string
onUserInput: (value: string) => void
decrement: () => string
increment: () => string
decrementDisabled?: boolean
incrementDisabled?: boolean
feeAmount?: FeeAmount
label?: string
width?: string
Expand All @@ -69,7 +78,8 @@ const StepCounter = ({
value,
decrement,
increment,
feeAmount,
decrementDisabled = false,
incrementDisabled = false,
width,
locked,
onUserInput,
Expand All @@ -87,9 +97,6 @@ const StepCounter = ({
// animation if parent value updates local value
const [pulsing, setPulsing] = useState<boolean>(false)

// format fee amount
const feeAmountFormatted = feeAmount ? formattedFeeAmount(feeAmount * 2) : ''

const handleOnFocus = () => {
setUseLocalValue(true)
setActive(true)
Expand Down Expand Up @@ -126,39 +133,45 @@ const StepCounter = ({

return (
<FocusedOutlineCard pulsing={pulsing} active={active} onFocus={handleOnFocus} onBlur={handleOnBlur} width={width}>
<AutoColumn gap="6px" style={{ marginBottom: '12px' }}>
<AutoColumn gap="6px">
<InputTitle fontSize={12} textAlign="center">
{title}
</InputTitle>
<StyledInput
className="rate-input-0"
value={localValue}
fontSize="20px"
disabled={locked}
onUserInput={(val) => {
setLocalValue(val)
}}
/>

<InputRow>
{!locked && (
<SmallButton onClick={handleDecrement} disabled={decrementDisabled}>
<ButtonLabel disabled={decrementDisabled} fontSize="12px">
<Minus size={18} />
</ButtonLabel>
</SmallButton>
)}

<StyledInput
className="rate-input-0"
value={localValue}
fontSize="20px"
disabled={locked}
onUserInput={(val) => {
setLocalValue(val)
}}
/>

{!locked && (
<SmallButton onClick={handleIncrement} disabled={incrementDisabled}>
<ButtonLabel disabled={incrementDisabled} fontSize="12px">
<Plus size={18} />
</ButtonLabel>
</SmallButton>
)}
</InputRow>

<InputTitle fontSize={12} textAlign="center">
<Trans>
{tokenB} per {tokenA}
</Trans>
</InputTitle>
</AutoColumn>
{!locked ? (
<RowBetween>
<SmallButton onClick={handleDecrement}>
<TYPE.white fontSize="12px">
<Trans>-{feeAmountFormatted}%</Trans>
</TYPE.white>
</SmallButton>
<SmallButton onClick={handleIncrement}>
<TYPE.white fontSize="12px">
<Trans>+{feeAmountFormatted}%</Trans>
</TYPE.white>
</SmallButton>
</RowBetween>
) : null}
</FocusedOutlineCard>
)
}
Expand Down
26 changes: 23 additions & 3 deletions src/components/NavigationTabs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { resetMintState } from 'state/mint/actions'
import { resetMintState as resetMintV3State } from 'state/mint/v3/actions'
import { TYPE } from 'theme'
import useTheme from 'hooks/useTheme'
import { ReactNode } from 'react'
import { Box } from 'rebass'

const Tabs = styled.div`
${({ theme }) => theme.flexRowNoWrap}
Expand Down Expand Up @@ -49,6 +51,15 @@ const StyledNavLink = styled(NavLink).attrs({
}
`

const StyledHistoryLink = styled(HistoryLink)<{ flex: string | undefined }>`
flex: ${({ flex }) => flex ?? 'none'};
${({ theme }) => theme.mediaWidth.upToMedium`
flex: none;
margin-right: 10px;
`};
`

const ActiveText = styled.div`
font-weight: 500;
font-size: 20px;
Expand Down Expand Up @@ -91,11 +102,14 @@ export function AddRemoveTabs({
creating,
defaultSlippage,
positionID,
children,
}: {
adding: boolean
creating: boolean
defaultSlippage: Percent
positionID?: string | undefined
showBackLink?: boolean
children?: ReactNode | undefined
}) {
const theme = useTheme()
// reset states on back
Expand All @@ -110,7 +124,7 @@ export function AddRemoveTabs({
return (
<Tabs>
<RowBetween style={{ padding: '1rem 1rem 0 1rem' }}>
<HistoryLink
<StyledHistoryLink
to={poolLink}
onClick={() => {
if (adding) {
Expand All @@ -119,10 +133,15 @@ export function AddRemoveTabs({
dispatch(resetMintV3State())
}
}}
flex={children ? '1' : undefined}
>
<StyledArrowLeft stroke={theme.text2} />
</HistoryLink>
<TYPE.mediumHeader fontWeight={500} fontSize={20}>
</StyledHistoryLink>
<TYPE.mediumHeader
fontWeight={500}
fontSize={20}
style={{ flex: '1', margin: 'auto', textAlign: children ? 'start' : 'center' }}
>
{creating ? (
<Trans>Create a pair</Trans>
) : adding ? (
Expand All @@ -131,6 +150,7 @@ export function AddRemoveTabs({
<Trans>Remove Liquidity</Trans>
)}
</TYPE.mediumHeader>
<Box style={{ marginRight: '.5rem' }}>{children}</Box>
<SettingsTab placeholderSlippage={defaultSlippage} />
</RowBetween>
</Tabs>
Expand Down
14 changes: 9 additions & 5 deletions src/components/PositionListItem/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ import styled from 'styled-components/macro'
import { HideSmall, MEDIA_WIDTHS, SmallOnly } from 'theme'
import { PositionDetails } from 'types/position'
import { Price, Token, Percent } from '@uniswap/sdk-core'
import { formatPrice } from 'utils/formatCurrencyAmount'
import { formatTickPrice } from 'utils/formatTickPrice'
import Loader from 'components/Loader'
import { unwrappedToken } from 'utils/unwrappedToken'
import RangeBadge from 'components/Badge/RangeBadge'
import { RowFixed } from 'components/Row'
import HoverInlineText from 'components/HoverInlineText'
import { DAI, USDC, USDT, WBTC, WETH9_EXTENDED } from '../../constants/tokens'
import { Trans } from '@lingui/macro'
import useIsTickAtLimit from 'hooks/useIsTickAtLimit'
import { Bound } from 'state/mint/v3/actions'

const LinkRow = styled(Link)`
align-items: center;
Expand Down Expand Up @@ -201,6 +203,8 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr
return undefined
}, [liquidity, pool, tickLower, tickUpper])

const tickAtLimit = useIsTickAtLimit(feeAmount, tickLower, tickUpper)

// prices
const { priceLower, priceUpper, quote, base } = getPriceOrderingFromPositionForUI(position)

Expand Down Expand Up @@ -239,8 +243,8 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr
<Trans>Min: </Trans>
</ExtentsText>
<Trans>
{formatPrice(priceLower, 5)} <HoverInlineText text={currencyQuote?.symbol} /> per{' '}
<HoverInlineText text={currencyBase?.symbol ?? ''} />
{formatTickPrice(priceLower, tickAtLimit, Bound.LOWER)} <HoverInlineText text={currencyQuote?.symbol} />{' '}
per <HoverInlineText text={currencyBase?.symbol ?? ''} />
</Trans>
</RangeText>{' '}
<HideSmall>
Expand All @@ -254,8 +258,8 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr
<Trans>Max:</Trans>
</ExtentsText>
<Trans>
{formatPrice(priceUpper, 5)} <HoverInlineText text={currencyQuote?.symbol} /> per{' '}
<HoverInlineText maxCharacters={10} text={currencyBase?.symbol} />
{formatTickPrice(priceUpper, tickAtLimit, Bound.UPPER)} <HoverInlineText text={currencyQuote?.symbol} />{' '}
per <HoverInlineText maxCharacters={10} text={currencyBase?.symbol} />
</Trans>
</RangeText>
</RangeLineItem>
Expand Down
16 changes: 14 additions & 2 deletions src/components/PositionPreview/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,21 @@ import DoubleCurrencyLogo from 'components/DoubleLogo'
import RangeBadge from 'components/Badge/RangeBadge'
import { ThemeContext } from 'styled-components/macro'
import JSBI from 'jsbi'
import { Bound } from 'state/mint/v3/actions'
import { formatTickPrice } from 'utils/formatTickPrice'

export const PositionPreview = ({
position,
title,
inRange,
baseCurrencyDefault,
ticksAtLimit,
}: {
position: Position
title?: ReactNode
inRange: boolean
baseCurrencyDefault?: Currency | undefined
ticksAtLimit: { [bound: string]: boolean | undefined }
}) => {
const theme = useContext(ThemeContext)

Expand Down Expand Up @@ -121,7 +125,11 @@ export const PositionPreview = ({
<TYPE.main fontSize="12px">
<Trans>Min Price</Trans>
</TYPE.main>
<TYPE.mediumHeader textAlign="center">{`${priceLower.toSignificant(5)}`}</TYPE.mediumHeader>
<TYPE.mediumHeader textAlign="center">{`${formatTickPrice(
priceLower,
ticksAtLimit,
Bound.LOWER
)}`}</TYPE.mediumHeader>
<TYPE.main textAlign="center" fontSize="12px">
<Trans>
{quoteCurrency.symbol} per {baseCurrency.symbol}
Expand All @@ -138,7 +146,11 @@ export const PositionPreview = ({
<TYPE.main fontSize="12px">
<Trans>Max Price</Trans>
</TYPE.main>
<TYPE.mediumHeader textAlign="center">{`${priceUpper.toSignificant(5)}`}</TYPE.mediumHeader>
<TYPE.mediumHeader textAlign="center">{`${formatTickPrice(
priceUpper,
ticksAtLimit,
Bound.UPPER
)}`}</TYPE.mediumHeader>
<TYPE.main textAlign="center" fontSize="12px">
<Trans>
{quoteCurrency.symbol} per {baseCurrency.symbol}
Expand Down
Loading

0 comments on commit ffbd2d1

Please sign in to comment.