feat: [info] Add Liquidity and Swap buttons on PDP (#7382)

* feat: setup initial pool details page and route

* add pool data query and call on enw page

* make query dynamic to url chainId

* Get and display Header info

* add token symbols

* split header into its own file

* add helper function to not default to eth chain

* add helper function tests

* add header component tests

* add mocked test for PDP

* use valid values

* allow unsupported BE chains supported by thegraph

* typecheck

* remove useless row

* no longer needed child

* use first and last child

* move mock consts to their own file

* skele linear task

* return null

* descriptiive pool not found bool

* modify correct logo container

* update snapshots

* instantiate all chain apollo clients

* added snapshot test

* merge main and update snapshots

* Update src/pages/PoolDetails/PoolDetailsHeader.tsx

Co-authored-by: Nate Wienert <natewienert@gmail.com>

* type feeTier

* setup init stats component

* correctly query pool data for t24, t48, and tWeek timestamps

* add comments

* sanitize pool data and update tests

* correct test data

* add todo

* lint

* show correct data

* remove logs

* use formatter

* showing colored bars

* styled graph

* get muted color

* refactor: move getColor to src

* refactor useColor to use getColor function

* remove consts

* refactor files

* 1st class var support courtesy of carter

* remove logging and adds comments

* mobile styling

* move Stats to its own file

* add test cases

* add test file

* update padding

* remove old test file

* respond to feedback

* right column wrapper

* add non-functional pdp buttons

* update tests

* add button functionality

* working tokenId for position

* split buttons in their own file

* add tests

* reduce screenshots

---------

Co-authored-by: Nate Wienert <natewienert@gmail.com>
This commit is contained in:
Charles Bachmeier 2023-10-02 09:56:17 -07:00 committed by GitHub
parent 524ce49fcb
commit 81accd1864
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 520 additions and 107 deletions

@ -1,8 +1,5 @@
import { BigNumber } from '@ethersproject/bignumber'
import { ChainId, WETH9 } from '@uniswap/sdk-core'
import { FeeAmount, Pool, Position } from '@uniswap/v3-sdk'
import { USDC_MAINNET } from 'constants/tokens'
import { mocked } from 'test-utils/mocked' import { mocked } from 'test-utils/mocked'
import { owner, useMultiChainPositionsReturnValue } from 'test-utils/pools/fixtures'
import { render } from 'test-utils/render' import { render } from 'test-utils/render'
import Pools from '.' import Pools from '.'
@ -12,53 +9,6 @@ jest.mock('./useMultiChainPositions')
jest.spyOn(console, 'warn').mockImplementation() jest.spyOn(console, 'warn').mockImplementation()
const owner = '0xf5b6bb25f5beaea03dd014c6ef9fa9f3926bf36c'
const pool = new Pool(
USDC_MAINNET,
WETH9[ChainId.MAINNET],
FeeAmount.MEDIUM,
'1851127709498178402383049949138810',
'7076437181775065414',
201189
)
const position = new Position({
pool,
liquidity: 1341008833950736,
tickLower: 200040,
tickUpper: 202560,
})
const details = {
nonce: BigNumber.from('0'),
tokenId: BigNumber.from('0'),
operator: '0x0',
token0: USDC_MAINNET.address,
token1: WETH9[ChainId.MAINNET].address,
fee: FeeAmount.MEDIUM,
tickLower: -100,
tickUpper: 100,
liquidity: BigNumber.from('9000'),
feeGrowthInside0LastX128: BigNumber.from('0'),
feeGrowthInside1LastX128: BigNumber.from('0'),
tokensOwed0: BigNumber.from('0'),
tokensOwed1: BigNumber.from('0'),
}
const useMultiChainPositionsReturnValue = {
positions: [
{
owner,
chainId: ChainId.MAINNET,
position,
pool,
details,
inRange: true,
closed: false,
},
],
loading: false,
}
beforeEach(() => { beforeEach(() => {
mocked(useMultiChainPositions).mockReturnValue(useMultiChainPositionsReturnValue) mocked(useMultiChainPositions).mockReturnValue(useMultiChainPositionsReturnValue)
}) })

@ -0,0 +1,63 @@
import userEvent from '@testing-library/user-event'
import useMultiChainPositions from 'components/AccountDrawer/MiniPortfolio/Pools/useMultiChainPositions'
import { mocked } from 'test-utils/mocked'
import { useMultiChainPositionsReturnValue, validPoolToken0, validPoolToken1 } from 'test-utils/pools/fixtures'
import { act, render, screen } from 'test-utils/render'
import { PoolDetailsStatsButtons } from './PoolDetailsStatsButtons'
jest.mock('components/AccountDrawer/MiniPortfolio/Pools/useMultiChainPositions')
describe('PoolDetailsStatsButton', () => {
const mockProps = {
chainId: 1,
token0: validPoolToken0,
token1: validPoolToken1,
feeTier: 500,
}
const mockPropsTokensReversed = {
...mockProps,
token0: validPoolToken1,
token1: validPoolToken0,
}
beforeEach(() => {
mocked(useMultiChainPositions).mockReturnValue(useMultiChainPositionsReturnValue)
})
it('renders both buttons correctly', () => {
const { asFragment } = render(<PoolDetailsStatsButtons {...mockProps} />)
expect(asFragment()).toMatchSnapshot()
expect(screen.getByTestId('pool-details-add-liquidity-button')).toBeVisible()
expect(screen.getByTestId('pool-details-swap-button')).toBeVisible()
})
it('clicking swap goes to correct url', async () => {
render(<PoolDetailsStatsButtons {...mockProps} />)
await act(() => userEvent.click(screen.getByTestId('pool-details-swap-button')))
expect(global.window.location.href).toContain(
'/swap?inputCurrency=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48&outputCurrency=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'
)
})
it('clicking swap goes to correct url with tokens reversed', async () => {
render(<PoolDetailsStatsButtons {...mockPropsTokensReversed} />)
await act(() => userEvent.click(screen.getByTestId('pool-details-swap-button')))
expect(global.window.location.href).toContain(
'/swap?inputCurrency=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2&outputCurrency=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
)
})
it('clicking add liquidity goes to correct url', async () => {
render(<PoolDetailsStatsButtons {...mockPropsTokensReversed} />)
await act(() => userEvent.click(screen.getByTestId('pool-details-add-liquidity-button')))
expect(global.window.location.href).toContain(
'/increase/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/500'
)
})
})

@ -0,0 +1,89 @@
import { Trans } from '@lingui/macro'
import { useWeb3React } from '@web3-react/core'
import { PositionInfo } from 'components/AccountDrawer/MiniPortfolio/Pools/cache'
import useMultiChainPositions from 'components/AccountDrawer/MiniPortfolio/Pools/useMultiChainPositions'
import { ButtonEmphasis, ButtonSize, ThemeButton } from 'components/Button'
import Row from 'components/Row'
import { Token } from 'graphql/thegraph/__generated__/types-and-hooks'
import { useCurrency } from 'hooks/Tokens'
import { useSwitchChain } from 'hooks/useSwitchChain'
import { useNavigate } from 'react-router-dom'
import styled from 'styled-components'
import { BREAKPOINTS } from 'theme'
import { currencyId } from 'utils/currencyId'
const PoolDetailsStatsButtonsRow = styled(Row)`
gap: 12px;
@media (max-width: ${BREAKPOINTS.lg - 1}px) {
display: none;
}
`
const PoolButton = styled(ThemeButton)`
padding: 12px 16px 12px 12px;
border-radius: 900px;
width: 50%;
`
interface PoolDetailsStatsButtonsProps {
chainId?: number
token0?: Token
token1?: Token
feeTier?: number
}
function findMatchingPosition(positions: PositionInfo[], token0?: Token, token1?: Token, feeTier?: number) {
return positions?.find(
(position) =>
(position?.details.token0.toLowerCase() === token0?.id ||
position?.details.token0.toLowerCase() === token1?.id) &&
(position?.details.token1.toLowerCase() === token0?.id ||
position?.details.token1.toLowerCase() === token1?.id) &&
position?.details.fee == feeTier &&
!position.closed
)
}
export function PoolDetailsStatsButtons({ chainId, token0, token1, feeTier }: PoolDetailsStatsButtonsProps) {
const { chainId: walletChainId, connector, account } = useWeb3React()
const { positions: userOwnedPositions } = useMultiChainPositions(account ?? '', chainId ? [chainId] : undefined)
const position = userOwnedPositions && findMatchingPosition(userOwnedPositions, token0, token1, feeTier)
const tokenId = position?.details.tokenId
const switchChain = useSwitchChain()
const navigate = useNavigate()
const currency0 = useCurrency(token0?.id, chainId)
const currency1 = useCurrency(token1?.id, chainId)
const handleOnClick = async (toSwap: boolean) => {
if (currency0 && currency1) {
if (walletChainId !== chainId && chainId) await switchChain(connector, chainId)
navigate(
toSwap
? `/swap?inputCurrency=${currencyId(currency0)}&outputCurrency=${currencyId(currency1)}`
: `/increase/${currencyId(currency0)}/${currencyId(currency1)}/${feeTier}${tokenId ? `/${tokenId}` : ''}`
)
}
}
if (!currency0 || !currency1) return null
return (
<PoolDetailsStatsButtonsRow>
<PoolButton
size={ButtonSize.medium}
emphasis={ButtonEmphasis.highSoft}
onClick={() => handleOnClick(false)}
data-testid="pool-details-add-liquidity-button"
>
<Trans>Add liquidity</Trans>
</PoolButton>
<PoolButton
size={ButtonSize.medium}
emphasis={ButtonEmphasis.highSoft}
onClick={() => handleOnClick(true)}
data-testid="pool-details-swap-button"
>
<Trans>Swap</Trans>
</PoolButton>
</PoolDetailsStatsButtonsRow>
)
}

@ -0,0 +1,141 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`PoolDetailsStatsButton renders both buttons correctly 1`] = `
<DocumentFragment>
.c0 {
box-sizing: border-box;
margin: 0;
min-width: 0;
}
.c1 {
width: 100%;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
padding: 0;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: start;
-webkit-justify-content: flex-start;
-ms-flex-pack: start;
justify-content: flex-start;
}
.c6 {
background-color: transparent;
bottom: 0;
border-radius: inherit;
height: 100%;
left: 0;
position: absolute;
right: 0;
top: 0;
-webkit-transition: 150ms ease background-color;
transition: 150ms ease background-color;
width: 100%;
}
.c3 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
background-color: #FFEFFF;
border-radius: 16px;
border: 0;
color: #FC72FF;
cursor: pointer;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
font-size: 16px;
font-weight: 535;
gap: 12px;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
line-height: 20px;
padding: 10px 12px;
position: relative;
-webkit-transition: 150ms ease opacity;
transition: 150ms ease opacity;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.c3:active .c5 {
background-color: #B8C0DC3d;
}
.c3:focus .c5 {
background-color: #B8C0DC3d;
}
.c3:hover .c5 {
background-color: #98A1C014;
}
.c3:disabled {
cursor: default;
opacity: 0.6;
}
.c3:disabled:active .c5,
.c3:disabled:focus .c5,
.c3:disabled:hover .c5 {
background-color: transparent;
}
.c2 {
gap: 12px;
}
.c4 {
padding: 12px 16px 12px 12px;
border-radius: 900px;
width: 50%;
}
@media (max-width:1023px) {
.c2 {
display: none;
}
}
<div
class="c0 c1 c2"
>
<button
class="c3 c4"
data-testid="pool-details-add-liquidity-button"
size="1"
>
<div
class="c5 c6"
/>
Add liquidity
</button>
<button
class="c3 c4"
data-testid="pool-details-swap-button"
size="1"
>
<div
class="c5 c6"
/>
Swap
</button>
</div>
</DocumentFragment>
`;

@ -17,7 +17,7 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
width: max-content; width: max-content;
} }
.c26 { .c31 {
box-sizing: border-box; box-sizing: border-box;
margin: 0; margin: 0;
min-width: 0; min-width: 0;
@ -82,7 +82,7 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
gap: 8px; gap: 8px;
} }
.c27 { .c32 {
width: -webkit-max-content; width: -webkit-max-content;
width: -moz-max-content; width: -moz-max-content;
width: max-content; width: max-content;
@ -124,6 +124,78 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
justify-content: flex-start; justify-content: flex-start;
} }
.c21 {
background-color: transparent;
bottom: 0;
border-radius: inherit;
height: 100%;
left: 0;
position: absolute;
right: 0;
top: 0;
-webkit-transition: 150ms ease background-color;
transition: 150ms ease background-color;
width: 100%;
}
.c18 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
background-color: #FFEFFF;
border-radius: 16px;
border: 0;
color: #FC72FF;
cursor: pointer;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
font-size: 16px;
font-weight: 535;
gap: 12px;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
line-height: 20px;
padding: 10px 12px;
position: relative;
-webkit-transition: 150ms ease opacity;
transition: 150ms ease opacity;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.c18:active .c20 {
background-color: #B8C0DC3d;
}
.c18:focus .c20 {
background-color: #B8C0DC3d;
}
.c18:hover .c20 {
background-color: #98A1C014;
}
.c18:disabled {
cursor: default;
opacity: 0.6;
}
.c18:disabled:active .c20,
.c18:disabled:focus .c20,
.c18:disabled:hover .c20 {
background-color: transparent;
}
.c4 { .c4 {
gap: 36px; gap: 36px;
} }
@ -207,17 +279,17 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
border-radius: 50%; border-radius: 50%;
} }
.c28 { .c33 {
color: #FF5F52; color: #FF5F52;
} }
.c18 { .c23 {
font-weight: 485; font-weight: 485;
font-size: 24px; font-size: 24px;
line-height: 36px; line-height: 36px;
} }
.c17 { .c22 {
gap: 24px; gap: 24px;
padding: 20px; padding: 20px;
border-radius: 20px; border-radius: 20px;
@ -225,7 +297,7 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
width: 100%; width: 100%;
} }
.c19 { .c24 {
gap: 8px; gap: 8px;
-webkit-flex: 1; -webkit-flex: 1;
-ms-flex: 1; -ms-flex: 1;
@ -233,14 +305,14 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
min-width: 180px; min-width: 180px;
} }
.c20 { .c25 {
-webkit-box-pack: justify; -webkit-box-pack: justify;
-webkit-justify-content: space-between; -webkit-justify-content: space-between;
-ms-flex-pack: justify; -ms-flex-pack: justify;
justify-content: space-between; justify-content: space-between;
} }
.c21 { .c26 {
font-weight: 485; font-weight: 485;
font-size: 18px; font-size: 18px;
line-height: 24px; line-height: 24px;
@ -249,7 +321,7 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
width: max-content; width: max-content;
} }
.c22 { .c27 {
height: 8px; height: 8px;
width: 40.698463777008904%; width: 40.698463777008904%;
background: #2172E5; background: #2172E5;
@ -258,7 +330,7 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
border-right: 1px solid #F9F9F9; border-right: 1px solid #F9F9F9;
} }
.c23 { .c28 {
height: 8px; height: 8px;
width: 59.3015362229911%; width: 59.3015362229911%;
background: #2172E5; background: #2172E5;
@ -267,7 +339,7 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
border-left: 1px solid #F9F9F9; border-left: 1px solid #F9F9F9;
} }
.c24 { .c29 {
gap: 4px; gap: 4px;
width: 100%; width: 100%;
-webkit-align-items: flex-end; -webkit-align-items: flex-end;
@ -276,13 +348,23 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
align-items: flex-end; align-items: flex-end;
} }
.c25 { .c30 {
color: #222222; color: #222222;
font-size: 36px; font-size: 36px;
font-weight: 485; font-weight: 485;
line-height: 44px; line-height: 44px;
} }
.c17 {
gap: 12px;
}
.c19 {
padding: 12px 16px 12px 12px;
border-radius: 900px;
width: 50%;
}
.c2 { .c2 {
padding: 48px; padding: 48px;
width: 100%; width: 100%;
@ -300,13 +382,13 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
} }
@media (max-width:1023px) { @media (max-width:1023px) {
.c18 { .c23 {
width: 100%; width: 100%;
} }
} }
@media (max-width:1023px) { @media (max-width:1023px) {
.c17 { .c22 {
-webkit-flex-direction: row; -webkit-flex-direction: row;
-ms-flex-direction: row; -ms-flex-direction: row;
flex-direction: row; flex-direction: row;
@ -323,13 +405,13 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
} }
@media (max-width:640px) { @media (max-width:640px) {
.c19 { .c24 {
min-width: 150px; min-width: 150px;
} }
} }
@media (max-width:1023px) { @media (max-width:1023px) {
.c20 { .c25 {
-webkit-flex-direction: column; -webkit-flex-direction: column;
-ms-flex-direction: column; -ms-flex-direction: column;
flex-direction: column; flex-direction: column;
@ -337,7 +419,7 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
} }
@media (max-width:1023px) { @media (max-width:1023px) {
.c21 { .c26 {
font-size: 20px; font-size: 20px;
line-height: 28px; line-height: 28px;
width: 100%; width: 100%;
@ -345,7 +427,7 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
} }
@media (max-width:1023px) { @media (max-width:1023px) {
.c24 { .c29 {
-webkit-flex-direction: column; -webkit-flex-direction: column;
-ms-flex-direction: column; -ms-flex-direction: column;
flex-direction: column; flex-direction: column;
@ -358,12 +440,18 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
} }
@media (max-width:1023px) { @media (max-width:1023px) {
.c25 { .c30 {
font-size: 20px; font-size: 20px;
line-height: 28px; line-height: 28px;
} }
} }
@media (max-width:1023px) {
.c17 {
display: none;
}
}
@media (max-width:1023px) { @media (max-width:1023px) {
.c2 { .c2 {
-webkit-flex-direction: column; -webkit-flex-direction: column;
@ -485,15 +573,39 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
class="c3 c16" class="c3 c16"
> >
<div <div
class="c3 c17" class="c0 c1 c17"
>
<button
class="c18 c19"
data-testid="pool-details-add-liquidity-button"
size="1"
>
<div
class="c20 c21"
/>
Add liquidity
</button>
<button
class="c18 c19"
data-testid="pool-details-swap-button"
size="1"
>
<div
class="c20 c21"
/>
Swap
</button>
</div>
<div
class="c3 c22"
> >
<div <div
class="c18 css-vurnku" class="c23 css-vurnku"
> >
Stats Stats
</div> </div>
<div <div
class="c3 c19" class="c3 c24"
> >
<div <div
class="c6 css-1urox24" class="c6 css-1urox24"
@ -501,15 +613,15 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
Pool balances Pool balances
</div> </div>
<div <div
class="c0 c1 c20" class="c0 c1 c25"
> >
<div <div
class="c0 c1 c21" class="c0 c1 c26"
> >
90.93M USDC 90.93M USDC
</div> </div>
<div <div
class="c0 c1 c21" class="c0 c1 c26"
> >
82,526.49 WETH 82,526.49 WETH
</div> </div>
@ -519,15 +631,15 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
data-testid="pool-balance-chart" data-testid="pool-balance-chart"
> >
<div <div
class="c22" class="c27"
/> />
<div <div
class="c23" class="c28"
/> />
</div> </div>
</div> </div>
<div <div
class="c3 c19" class="c3 c24"
> >
<div <div
class="c6 css-1urox24" class="c6 css-1urox24"
@ -535,20 +647,20 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
TVL TVL
</div> </div>
<div <div
class="c0 c1 c24" class="c0 c1 c29"
> >
<div <div
class="c25 css-vurnku" class="c30 css-vurnku"
> >
$223.2M $223.2M
</div> </div>
<div <div
class="c26 c27" class="c31 c32"
width="max-content" width="max-content"
> >
<svg <svg
aria-label="down" aria-label="down"
class="c28" class="c33"
fill="none" fill="none"
height="16" height="16"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@ -569,7 +681,7 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
</div> </div>
</div> </div>
<div <div
class="c3 c19" class="c3 c24"
> >
<div <div
class="c6 css-1urox24" class="c6 css-1urox24"
@ -577,20 +689,20 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
24H volume 24H volume
</div> </div>
<div <div
class="c0 c1 c24" class="c0 c1 c29"
> >
<div <div
class="c25 css-vurnku" class="c30 css-vurnku"
> >
$233.4M $233.4M
</div> </div>
<div <div
class="c26 c27" class="c31 c32"
width="max-content" width="max-content"
> >
<svg <svg
aria-label="down" aria-label="down"
class="c28" class="c33"
fill="none" fill="none"
height="16" height="16"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@ -611,7 +723,7 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
</div> </div>
</div> </div>
<div <div
class="c3 c19" class="c3 c24"
> >
<div <div
class="c6 css-1urox24" class="c6 css-1urox24"
@ -619,10 +731,10 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
24H fees 24H fees
</div> </div>
<div <div
class="c0 c1 c24" class="c0 c1 c29"
> >
<div <div
class="c25 css-vurnku" class="c30 css-vurnku"
> >
$116.7K $116.7K
</div> </div>

@ -11,6 +11,7 @@ import { isAddress } from 'utils'
import { PoolDetailsHeader } from './PoolDetailsHeader' import { PoolDetailsHeader } from './PoolDetailsHeader'
import { PoolDetailsStats } from './PoolDetailsStats' import { PoolDetailsStats } from './PoolDetailsStats'
import { PoolDetailsStatsButtons } from './PoolDetailsStatsButtons'
const PageWrapper = styled(Row)` const PageWrapper = styled(Row)`
padding: 48px; padding: 48px;
@ -67,6 +68,7 @@ export default function PoolDetailsPage() {
toggleReversed={toggleReversed} toggleReversed={toggleReversed}
/> />
<RightColumn> <RightColumn>
<PoolDetailsStatsButtons chainId={chainId} token0={token0} token1={token1} feeTier={poolData?.feeTier} />
{poolData && <PoolDetailsStats poolData={poolData} isReversed={isReversed} chainId={chainId} />} {poolData && <PoolDetailsStats poolData={poolData} isReversed={isReversed} chainId={chainId} />}
</RightColumn> </RightColumn>
</PageWrapper> </PageWrapper>

@ -1,6 +1,76 @@
import { BigNumber } from '@ethersproject/bignumber'
import { ChainId, WETH9 } from '@uniswap/sdk-core'
import { FeeAmount, Pool, Position } from '@uniswap/v3-sdk'
import { USDC_MAINNET } from 'constants/tokens'
import { Token } from 'graphql/thegraph/__generated__/types-and-hooks' import { Token } from 'graphql/thegraph/__generated__/types-and-hooks'
export const validParams = { poolAddress: '0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640', chainName: 'ethereum' } export const validParams = { poolAddress: '0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640', chainName: 'ethereum' }
export const validPoolToken0 = {
id: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
symbol: 'USDC',
name: 'USD Coin',
decimals: '6',
derivedETH: '0.0006240873011635544626425964678706127',
__typename: 'Token',
} as Token
export const validPoolToken1 = {
id: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
symbol: 'WETH',
name: 'Wrapped Ether',
decimals: '18',
derivedETH: '1',
__typename: 'Token',
} as Token
export const owner = '0xf5b6bb25f5beaea03dd014c6ef9fa9f3926bf36c'
const pool = new Pool(
USDC_MAINNET,
WETH9[ChainId.MAINNET],
FeeAmount.MEDIUM,
'1851127709498178402383049949138810',
'7076437181775065414',
201189
)
const position = new Position({
pool,
liquidity: 1341008833950736,
tickLower: 200040,
tickUpper: 202560,
})
const details = {
nonce: BigNumber.from('0'),
tokenId: BigNumber.from('0'),
operator: '0x0',
token0: USDC_MAINNET.address,
token1: WETH9[ChainId.MAINNET].address,
fee: FeeAmount.MEDIUM,
tickLower: -100,
tickUpper: 100,
liquidity: BigNumber.from('9000'),
feeGrowthInside0LastX128: BigNumber.from('0'),
feeGrowthInside1LastX128: BigNumber.from('0'),
tokensOwed0: BigNumber.from('0'),
tokensOwed1: BigNumber.from('0'),
}
export const useMultiChainPositionsReturnValue = {
positions: [
{
owner,
chainId: ChainId.MAINNET,
position,
pool,
details,
inRange: true,
closed: false,
},
],
loading: false,
}
export const validPoolDataResponse = { export const validPoolDataResponse = {
data: { data: {
id: '0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640', id: '0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640',
@ -8,22 +78,8 @@ export const validPoolDataResponse = {
liquidity: parseFloat('26414803986874770777'), liquidity: parseFloat('26414803986874770777'),
sqrtPrice: parseFloat('1977320351696380862605029898750440'), sqrtPrice: parseFloat('1977320351696380862605029898750440'),
tick: 202508, tick: 202508,
token0: { token0: validPoolToken0,
id: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', token1: validPoolToken1,
symbol: 'USDC',
name: 'USD Coin',
decimals: '6',
derivedETH: '0.0006240873011635544626425964678706127',
__typename: 'Token',
} as Token,
token1: {
id: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
symbol: 'WETH',
name: 'Wrapped Ether',
decimals: '18',
derivedETH: '1',
__typename: 'Token',
} as Token,
token0Price: 1605.481, token0Price: 1605.481,
token1Price: 0.000622, token1Price: 0.000622,
volumeUSD: 233379442.64648438, volumeUSD: 233379442.64648438,