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:
parent
524ce49fcb
commit
81accd1864
@ -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 { owner, useMultiChainPositionsReturnValue } from 'test-utils/pools/fixtures'
|
||||
import { render } from 'test-utils/render'
|
||||
|
||||
import Pools from '.'
|
||||
@ -12,53 +9,6 @@ jest.mock('./useMultiChainPositions')
|
||||
|
||||
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(() => {
|
||||
mocked(useMultiChainPositions).mockReturnValue(useMultiChainPositionsReturnValue)
|
||||
})
|
||||
|
63
src/pages/PoolDetails/PoolDetailsStatsButtons.test.tsx
Normal file
63
src/pages/PoolDetails/PoolDetailsStatsButtons.test.tsx
Normal file
@ -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'
|
||||
)
|
||||
})
|
||||
})
|
89
src/pages/PoolDetails/PoolDetailsStatsButtons.tsx
Normal file
89
src/pages/PoolDetails/PoolDetailsStatsButtons.tsx
Normal file
@ -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;
|
||||
}
|
||||
|
||||
.c26 {
|
||||
.c31 {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
min-width: 0;
|
||||
@ -82,7 +82,7 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.c27 {
|
||||
.c32 {
|
||||
width: -webkit-max-content;
|
||||
width: -moz-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;
|
||||
}
|
||||
|
||||
.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 {
|
||||
gap: 36px;
|
||||
}
|
||||
@ -207,17 +279,17 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.c28 {
|
||||
.c33 {
|
||||
color: #FF5F52;
|
||||
}
|
||||
|
||||
.c18 {
|
||||
.c23 {
|
||||
font-weight: 485;
|
||||
font-size: 24px;
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.c17 {
|
||||
.c22 {
|
||||
gap: 24px;
|
||||
padding: 20px;
|
||||
border-radius: 20px;
|
||||
@ -225,7 +297,7 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.c19 {
|
||||
.c24 {
|
||||
gap: 8px;
|
||||
-webkit-flex: 1;
|
||||
-ms-flex: 1;
|
||||
@ -233,14 +305,14 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
|
||||
min-width: 180px;
|
||||
}
|
||||
|
||||
.c20 {
|
||||
.c25 {
|
||||
-webkit-box-pack: justify;
|
||||
-webkit-justify-content: space-between;
|
||||
-ms-flex-pack: justify;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.c21 {
|
||||
.c26 {
|
||||
font-weight: 485;
|
||||
font-size: 18px;
|
||||
line-height: 24px;
|
||||
@ -249,7 +321,7 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
.c22 {
|
||||
.c27 {
|
||||
height: 8px;
|
||||
width: 40.698463777008904%;
|
||||
background: #2172E5;
|
||||
@ -258,7 +330,7 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
|
||||
border-right: 1px solid #F9F9F9;
|
||||
}
|
||||
|
||||
.c23 {
|
||||
.c28 {
|
||||
height: 8px;
|
||||
width: 59.3015362229911%;
|
||||
background: #2172E5;
|
||||
@ -267,7 +339,7 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
|
||||
border-left: 1px solid #F9F9F9;
|
||||
}
|
||||
|
||||
.c24 {
|
||||
.c29 {
|
||||
gap: 4px;
|
||||
width: 100%;
|
||||
-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;
|
||||
}
|
||||
|
||||
.c25 {
|
||||
.c30 {
|
||||
color: #222222;
|
||||
font-size: 36px;
|
||||
font-weight: 485;
|
||||
line-height: 44px;
|
||||
}
|
||||
|
||||
.c17 {
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.c19 {
|
||||
padding: 12px 16px 12px 12px;
|
||||
border-radius: 900px;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.c2 {
|
||||
padding: 48px;
|
||||
width: 100%;
|
||||
@ -300,13 +382,13 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
|
||||
}
|
||||
|
||||
@media (max-width:1023px) {
|
||||
.c18 {
|
||||
.c23 {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width:1023px) {
|
||||
.c17 {
|
||||
.c22 {
|
||||
-webkit-flex-direction: row;
|
||||
-ms-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) {
|
||||
.c19 {
|
||||
.c24 {
|
||||
min-width: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width:1023px) {
|
||||
.c20 {
|
||||
.c25 {
|
||||
-webkit-flex-direction: column;
|
||||
-ms-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) {
|
||||
.c21 {
|
||||
.c26 {
|
||||
font-size: 20px;
|
||||
line-height: 28px;
|
||||
width: 100%;
|
||||
@ -345,7 +427,7 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
|
||||
}
|
||||
|
||||
@media (max-width:1023px) {
|
||||
.c24 {
|
||||
.c29 {
|
||||
-webkit-flex-direction: column;
|
||||
-ms-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) {
|
||||
.c25 {
|
||||
.c30 {
|
||||
font-size: 20px;
|
||||
line-height: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width:1023px) {
|
||||
.c17 {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width:1023px) {
|
||||
.c2 {
|
||||
-webkit-flex-direction: column;
|
||||
@ -485,15 +573,39 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
|
||||
class="c3 c16"
|
||||
>
|
||||
<div
|
||||
class="c3 c17"
|
||||
class="c0 c1 c17"
|
||||
>
|
||||
<button
|
||||
class="c18 c19"
|
||||
data-testid="pool-details-add-liquidity-button"
|
||||
size="1"
|
||||
>
|
||||
<div
|
||||
class="c18 css-vurnku"
|
||||
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
|
||||
class="c23 css-vurnku"
|
||||
>
|
||||
Stats
|
||||
</div>
|
||||
<div
|
||||
class="c3 c19"
|
||||
class="c3 c24"
|
||||
>
|
||||
<div
|
||||
class="c6 css-1urox24"
|
||||
@ -501,15 +613,15 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
|
||||
Pool balances
|
||||
</div>
|
||||
<div
|
||||
class="c0 c1 c20"
|
||||
class="c0 c1 c25"
|
||||
>
|
||||
<div
|
||||
class="c0 c1 c21"
|
||||
class="c0 c1 c26"
|
||||
>
|
||||
90.93M USDC
|
||||
</div>
|
||||
<div
|
||||
class="c0 c1 c21"
|
||||
class="c0 c1 c26"
|
||||
>
|
||||
82,526.49 WETH
|
||||
</div>
|
||||
@ -519,15 +631,15 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
|
||||
data-testid="pool-balance-chart"
|
||||
>
|
||||
<div
|
||||
class="c22"
|
||||
class="c27"
|
||||
/>
|
||||
<div
|
||||
class="c23"
|
||||
class="c28"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="c3 c19"
|
||||
class="c3 c24"
|
||||
>
|
||||
<div
|
||||
class="c6 css-1urox24"
|
||||
@ -535,20 +647,20 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
|
||||
TVL
|
||||
</div>
|
||||
<div
|
||||
class="c0 c1 c24"
|
||||
class="c0 c1 c29"
|
||||
>
|
||||
<div
|
||||
class="c25 css-vurnku"
|
||||
class="c30 css-vurnku"
|
||||
>
|
||||
$223.2M
|
||||
</div>
|
||||
<div
|
||||
class="c26 c27"
|
||||
class="c31 c32"
|
||||
width="max-content"
|
||||
>
|
||||
<svg
|
||||
aria-label="down"
|
||||
class="c28"
|
||||
class="c33"
|
||||
fill="none"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
@ -569,7 +681,7 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="c3 c19"
|
||||
class="c3 c24"
|
||||
>
|
||||
<div
|
||||
class="c6 css-1urox24"
|
||||
@ -577,20 +689,20 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
|
||||
24H volume
|
||||
</div>
|
||||
<div
|
||||
class="c0 c1 c24"
|
||||
class="c0 c1 c29"
|
||||
>
|
||||
<div
|
||||
class="c25 css-vurnku"
|
||||
class="c30 css-vurnku"
|
||||
>
|
||||
$233.4M
|
||||
</div>
|
||||
<div
|
||||
class="c26 c27"
|
||||
class="c31 c32"
|
||||
width="max-content"
|
||||
>
|
||||
<svg
|
||||
aria-label="down"
|
||||
class="c28"
|
||||
class="c33"
|
||||
fill="none"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
@ -611,7 +723,7 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="c3 c19"
|
||||
class="c3 c24"
|
||||
>
|
||||
<div
|
||||
class="c6 css-1urox24"
|
||||
@ -619,10 +731,10 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
|
||||
24H fees
|
||||
</div>
|
||||
<div
|
||||
class="c0 c1 c24"
|
||||
class="c0 c1 c29"
|
||||
>
|
||||
<div
|
||||
class="c25 css-vurnku"
|
||||
class="c30 css-vurnku"
|
||||
>
|
||||
$116.7K
|
||||
</div>
|
||||
|
@ -11,6 +11,7 @@ import { isAddress } from 'utils'
|
||||
|
||||
import { PoolDetailsHeader } from './PoolDetailsHeader'
|
||||
import { PoolDetailsStats } from './PoolDetailsStats'
|
||||
import { PoolDetailsStatsButtons } from './PoolDetailsStatsButtons'
|
||||
|
||||
const PageWrapper = styled(Row)`
|
||||
padding: 48px;
|
||||
@ -67,6 +68,7 @@ export default function PoolDetailsPage() {
|
||||
toggleReversed={toggleReversed}
|
||||
/>
|
||||
<RightColumn>
|
||||
<PoolDetailsStatsButtons chainId={chainId} token0={token0} token1={token1} feeTier={poolData?.feeTier} />
|
||||
{poolData && <PoolDetailsStats poolData={poolData} isReversed={isReversed} chainId={chainId} />}
|
||||
</RightColumn>
|
||||
</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'
|
||||
|
||||
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 = {
|
||||
data: {
|
||||
id: '0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640',
|
||||
@ -8,22 +78,8 @@ export const validPoolDataResponse = {
|
||||
liquidity: parseFloat('26414803986874770777'),
|
||||
sqrtPrice: parseFloat('1977320351696380862605029898750440'),
|
||||
tick: 202508,
|
||||
token0: {
|
||||
id: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
||||
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,
|
||||
token0: validPoolToken0,
|
||||
token1: validPoolToken1,
|
||||
token0Price: 1605.481,
|
||||
token1Price: 0.000622,
|
||||
volumeUSD: 233379442.64648438,
|
||||
|
Loading…
Reference in New Issue
Block a user