Commit 408c9078 authored by Justin Domingue's avatar Justin Domingue Committed by GitHub

feat: add support for 0.01% tier (#2769)

* chore: add support for 0.01% tier

* only show 1bps on mainnet

* rename VERY_LOW to LOWEST

* upgrade to v3-sdk 3.7.0

* add snapshot testing for lowest tier

* fix integration test

* fix integration test

* use ALL_SUPPORTED_CHAIN_IDS over string all

* consider 0.01% tier in pool (#2770)

* merge main and only consider lowest tier for mainnet
parent 8a99bad7
...@@ -5,6 +5,11 @@ ...@@ -5,6 +5,11 @@
} }
}, },
"asToken0": [ "asToken0": [
{
"feeTier": "100",
"totalValueLockedToken0": "0",
"totalValueLockedToken1": "3"
},
{ {
"feeTier": "500", "feeTier": "500",
"totalValueLockedToken0": "0", "totalValueLockedToken0": "0",
...@@ -13,7 +18,7 @@ ...@@ -13,7 +18,7 @@
{ {
"feeTier": "3000", "feeTier": "3000",
"totalValueLockedToken0": "0", "totalValueLockedToken0": "0",
"totalValueLockedToken1": "7" "totalValueLockedToken1": "4"
}, },
{ {
"feeTier": "10000", "feeTier": "10000",
......
...@@ -58,7 +58,7 @@ describe('Add Liquidity', () => { ...@@ -58,7 +58,7 @@ describe('Add Liquidity', () => {
cy.wait('@feeTierDistributionQuery') cy.wait('@feeTierDistributionQuery')
cy.get('#add-liquidity-selected-fee .selected-fee-label').should('contain.text', '0.3% fee tier') cy.get('#add-liquidity-selected-fee .selected-fee-label').should('contain.text', '0.3% fee tier')
cy.get('#add-liquidity-selected-fee .selected-fee-percentage').should('contain.text', '70%') cy.get('#add-liquidity-selected-fee .selected-fee-percentage').should('contain.text', '40%')
}) })
}) })
}) })
...@@ -315,8 +315,8 @@ const ActiveOutlined = styled(ButtonOutlined)` ...@@ -315,8 +315,8 @@ const ActiveOutlined = styled(ButtonOutlined)`
` `
const Circle = styled.div` const Circle = styled.div`
height: 20px; height: 17px;
width: 20px; width: 17px;
border-radius: 50%; border-radius: 50%;
background-color: ${({ theme }) => theme.primary1}; background-color: ${({ theme }) => theme.primary1};
display: flex; display: flex;
...@@ -325,11 +325,11 @@ const Circle = styled.div` ...@@ -325,11 +325,11 @@ const Circle = styled.div`
` `
const CheckboxWrapper = styled.div` const CheckboxWrapper = styled.div`
width: 30px; width: 20px;
padding: 0 10px; padding: 0 10px;
position: absolute; position: absolute;
top: 10px; top: 11px;
right: 10px; right: 15px;
` `
const ResponsiveCheck = styled(Check)` const ResponsiveCheck = styled(Check)`
......
import { Trans } from '@lingui/macro'
import { FeeAmount } from '@uniswap/v3-sdk'
import { ButtonRadioChecked } from 'components/Button'
import { AutoColumn } from 'components/Column'
import { useFeeTierDistribution } from 'hooks/useFeeTierDistribution'
import { PoolState } from 'hooks/usePools'
import React from 'react'
import styled from 'styled-components/macro'
import { TYPE } from 'theme'
import { FeeTierPercentageBadge } from './FeeTierPercentageBadge'
import { FEE_AMOUNT_DETAIL } from './shared'
const ResponsiveText = styled(TYPE.label)`
line-height: 16px;
font-size: 14px;
${({ theme }) => theme.mediaWidth.upToSmall`
font-size: 12px;
line-height: 12px;
`};
`
interface FeeOptionProps {
feeAmount: FeeAmount
active: boolean
distributions: ReturnType<typeof useFeeTierDistribution>['distributions']
poolState: PoolState
onClick: () => void
}
export function FeeOption({ feeAmount, active, poolState, distributions, onClick }: FeeOptionProps) {
return (
<ButtonRadioChecked active={active} onClick={onClick}>
<AutoColumn gap="sm" justify="flex-start">
<AutoColumn justify="flex-start" gap="6px">
<ResponsiveText>
<Trans>{FEE_AMOUNT_DETAIL[feeAmount].label}%</Trans>
</ResponsiveText>
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
{FEE_AMOUNT_DETAIL[feeAmount].description}
</TYPE.main>
</AutoColumn>
{distributions && (
<FeeTierPercentageBadge distributions={distributions} feeAmount={feeAmount} poolState={poolState} />
)}
</AutoColumn>
</ButtonRadioChecked>
)
}
import { Trans } from '@lingui/macro'
import { FeeAmount } from '@uniswap/v3-sdk'
import Badge from 'components/Badge'
import { useFeeTierDistribution } from 'hooks/useFeeTierDistribution'
import { PoolState } from 'hooks/usePools'
import React from 'react'
import { TYPE } from 'theme'
export function FeeTierPercentageBadge({
feeAmount,
distributions,
poolState,
}: {
feeAmount: FeeAmount
distributions: ReturnType<typeof useFeeTierDistribution>['distributions']
poolState: PoolState
}) {
return (
<Badge>
<TYPE.label fontSize={11}>
{!distributions || poolState === PoolState.NOT_EXISTS || poolState === PoolState.INVALID ? (
<Trans>Not created</Trans>
) : distributions[feeAmount] !== undefined ? (
<Trans>{distributions[feeAmount]?.toFixed(0)}% select</Trans>
) : (
<Trans>No data</Trans>
)}
</TYPE.label>
</Badge>
)
}
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { Currency } from '@uniswap/sdk-core' import { Currency } from '@uniswap/sdk-core'
import { FeeAmount } from '@uniswap/v3-sdk' import { FeeAmount } from '@uniswap/v3-sdk'
import Badge from 'components/Badge' import { ButtonGray } from 'components/Button'
import { ButtonGray, ButtonRadioChecked } from 'components/Button'
import Card from 'components/Card' import Card from 'components/Card'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
import { RowBetween } from 'components/Row' import { RowBetween } from 'components/Row'
import { useFeeTierDistribution } from 'hooks/useFeeTierDistribution' import { useFeeTierDistribution } from 'hooks/useFeeTierDistribution'
import { PoolState, usePools } from 'hooks/usePools' import { PoolState, usePools } from 'hooks/usePools'
import usePrevious from 'hooks/usePrevious' import usePrevious from 'hooks/usePrevious'
import { useActiveWeb3React } from 'hooks/web3'
import { DynamicSection } from 'pages/AddLiquidity/styled' import { DynamicSection } from 'pages/AddLiquidity/styled'
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import ReactGA from 'react-ga' import ReactGA from 'react-ga'
...@@ -16,6 +16,10 @@ import { Box } from 'rebass' ...@@ -16,6 +16,10 @@ import { Box } from 'rebass'
import styled, { keyframes } from 'styled-components/macro' import styled, { keyframes } from 'styled-components/macro'
import { TYPE } from 'theme' import { TYPE } from 'theme'
import { FeeOption } from './FeeOption'
import { FeeTierPercentageBadge } from './FeeTierPercentageBadge'
import { FEE_AMOUNT_DETAIL } from './shared'
const pulse = (color: string) => keyframes` const pulse = (color: string) => keyframes`
0% { 0% {
box-shadow: 0 0 0 0 ${color}; box-shadow: 0 0 0 0 ${color};
...@@ -29,60 +33,18 @@ const pulse = (color: string) => keyframes` ...@@ -29,60 +33,18 @@ const pulse = (color: string) => keyframes`
box-shadow: 0 0 0 0 ${color}; box-shadow: 0 0 0 0 ${color};
} }
` `
const ResponsiveText = styled(TYPE.label)`
line-height: 16px;
${({ theme }) => theme.mediaWidth.upToSmall`
font-size: 12px;
line-height: 12px;
`};
`
const FocusedOutlineCard = styled(Card)<{ pulsing: boolean }>` const FocusedOutlineCard = styled(Card)<{ pulsing: boolean }>`
border: 1px solid ${({ theme }) => theme.bg2}; border: 1px solid ${({ theme }) => theme.bg2};
animation: ${({ pulsing, theme }) => pulsing && pulse(theme.primary1)} 0.6s linear; animation: ${({ pulsing, theme }) => pulsing && pulse(theme.primary1)} 0.6s linear;
align-self: center; align-self: center;
` `
const FeeAmountLabel = { const Select = styled.div`
[FeeAmount.LOW]: { align-items: flex-start;
label: '0.05', display: grid;
description: <Trans>Best for stable pairs.</Trans>, grid-auto-flow: column;
}, grid-gap: 8px;
[FeeAmount.MEDIUM]: { `
label: '0.3',
description: <Trans>Best for most pairs.</Trans>,
},
[FeeAmount.HIGH]: {
label: '1',
description: <Trans>Best for exotic pairs.</Trans>,
},
}
function FeeTierPercentageBadge({
feeAmount,
distributions,
poolState,
}: {
feeAmount: FeeAmount
distributions: ReturnType<typeof useFeeTierDistribution>['distributions']
poolState: PoolState
}) {
return (
<Badge>
<TYPE.label fontSize={12}>
{!distributions || poolState === PoolState.NOT_EXISTS || poolState === PoolState.INVALID ? (
<Trans>Not created</Trans>
) : distributions[feeAmount] !== undefined ? (
<Trans>{distributions[feeAmount]?.toFixed(0)}% select</Trans>
) : (
<Trans>No data</Trans>
)}
</TYPE.label>
</Badge>
)
}
export default function FeeSelector({ export default function FeeSelector({
disabled = false, disabled = false,
...@@ -97,16 +59,19 @@ export default function FeeSelector({ ...@@ -97,16 +59,19 @@ export default function FeeSelector({
currencyA?: Currency | undefined currencyA?: Currency | undefined
currencyB?: Currency | undefined currencyB?: Currency | undefined
}) { }) {
const { chainId } = useActiveWeb3React()
const { isLoading, isError, largestUsageFeeTier, distributions } = useFeeTierDistribution(currencyA, currencyB) const { isLoading, isError, largestUsageFeeTier, distributions } = useFeeTierDistribution(currencyA, currencyB)
// get pool data on-chain for latest states // get pool data on-chain for latest states
const pools = usePools([ const pools = usePools([
[currencyA, currencyB, FeeAmount.LOWEST],
[currencyA, currencyB, FeeAmount.LOW], [currencyA, currencyB, FeeAmount.LOW],
[currencyA, currencyB, FeeAmount.MEDIUM], [currencyA, currencyB, FeeAmount.MEDIUM],
[currencyA, currencyB, FeeAmount.HIGH], [currencyA, currencyB, FeeAmount.HIGH],
]) ])
const poolsByFeeTier = useMemo( const poolsByFeeTier: Record<FeeAmount, PoolState> = useMemo(
() => () =>
pools.reduce( pools.reduce(
(acc, [curPoolState, curPool]) => { (acc, [curPoolState, curPool]) => {
...@@ -118,6 +83,7 @@ export default function FeeSelector({ ...@@ -118,6 +83,7 @@ export default function FeeSelector({
}, },
{ {
// default all states to NOT_EXISTS // default all states to NOT_EXISTS
[FeeAmount.LOWEST]: PoolState.NOT_EXISTS,
[FeeAmount.LOW]: PoolState.NOT_EXISTS, [FeeAmount.LOW]: PoolState.NOT_EXISTS,
[FeeAmount.MEDIUM]: PoolState.NOT_EXISTS, [FeeAmount.MEDIUM]: PoolState.NOT_EXISTS,
[FeeAmount.HIGH]: PoolState.NOT_EXISTS, [FeeAmount.HIGH]: PoolState.NOT_EXISTS,
...@@ -134,7 +100,7 @@ export default function FeeSelector({ ...@@ -134,7 +100,7 @@ export default function FeeSelector({
const recommended = useRef(false) const recommended = useRef(false)
const handleFeePoolSelectWithEvent = useCallback( const handleFeePoolSelectWithEvent = useCallback(
(fee) => { (fee: FeeAmount) => {
ReactGA.event({ ReactGA.event({
category: 'FeePoolSelect', category: 'FeePoolSelect',
action: 'Manual', action: 'Manual',
...@@ -193,7 +159,7 @@ export default function FeeSelector({ ...@@ -193,7 +159,7 @@ export default function FeeSelector({
) : ( ) : (
<> <>
<TYPE.label className="selected-fee-label"> <TYPE.label className="selected-fee-label">
<Trans>{FeeAmountLabel[feeAmount].label}% fee tier</Trans> <Trans>{FEE_AMOUNT_DETAIL[feeAmount].label}% fee tier</Trans>
</TYPE.label> </TYPE.label>
<Box style={{ width: 'fit-content', marginTop: '8px' }} className="selected-fee-percentage"> <Box style={{ width: 'fit-content', marginTop: '8px' }} className="selected-fee-percentage">
{distributions && ( {distributions && (
...@@ -214,81 +180,25 @@ export default function FeeSelector({ ...@@ -214,81 +180,25 @@ export default function FeeSelector({
</RowBetween> </RowBetween>
</FocusedOutlineCard> </FocusedOutlineCard>
{showOptions && ( {chainId && showOptions && (
<RowBetween> <Select>
<ButtonRadioChecked {[FeeAmount.LOWEST, FeeAmount.LOW, FeeAmount.MEDIUM, FeeAmount.HIGH].map((_feeAmount, i) => {
width="32%" const { supportedChains } = FEE_AMOUNT_DETAIL[_feeAmount]
active={feeAmount === FeeAmount.LOW} if (supportedChains.includes(chainId)) {
onClick={() => handleFeePoolSelectWithEvent(FeeAmount.LOW)} return (
> <FeeOption
<AutoColumn gap="sm" justify="flex-start"> feeAmount={_feeAmount}
<AutoColumn justify="flex-start" gap="6px"> active={feeAmount === _feeAmount}
<ResponsiveText> onClick={() => handleFeePoolSelectWithEvent(_feeAmount)}
<Trans>0.05% fee</Trans>
</ResponsiveText>
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
<Trans>Best for stable pairs.</Trans>
</TYPE.main>
</AutoColumn>
{distributions && (
<FeeTierPercentageBadge
distributions={distributions} distributions={distributions}
feeAmount={FeeAmount.LOW} poolState={poolsByFeeTier[_feeAmount]}
poolState={poolsByFeeTier[FeeAmount.LOW]} key={i}
/> />
)} )
</AutoColumn> }
</ButtonRadioChecked> return null
<ButtonRadioChecked })}
width="32%" </Select>
active={feeAmount === FeeAmount.MEDIUM}
onClick={() => handleFeePoolSelectWithEvent(FeeAmount.MEDIUM)}
>
<AutoColumn gap="sm" justify="flex-start">
<AutoColumn justify="flex-start" gap="4px">
<ResponsiveText>
<Trans>0.3% fee</Trans>
</ResponsiveText>
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
<Trans>Best for most pairs.</Trans>
</TYPE.main>
</AutoColumn>
{distributions && (
<FeeTierPercentageBadge
distributions={distributions}
feeAmount={FeeAmount.MEDIUM}
poolState={poolsByFeeTier[FeeAmount.MEDIUM]}
/>
)}
</AutoColumn>
</ButtonRadioChecked>
<ButtonRadioChecked
width="32%"
active={feeAmount === FeeAmount.HIGH}
onClick={() => handleFeePoolSelectWithEvent(FeeAmount.HIGH)}
>
<AutoColumn gap="sm" justify="flex-start">
<AutoColumn justify="flex-start" gap="4px">
<ResponsiveText>
<Trans>1% fee</Trans>
</ResponsiveText>
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
<Trans>Best for exotic pairs.</Trans>
</TYPE.main>
</AutoColumn>
{distributions && (
<FeeTierPercentageBadge
distributions={distributions}
feeAmount={FeeAmount.HIGH}
poolState={poolsByFeeTier[FeeAmount.HIGH]}
/>
)}
</AutoColumn>
</ButtonRadioChecked>
</RowBetween>
)} )}
</DynamicSection> </DynamicSection>
</AutoColumn> </AutoColumn>
......
import { Trans } from '@lingui/macro'
import { FeeAmount } from '@uniswap/v3-sdk'
import { ALL_SUPPORTED_CHAIN_IDS, SupportedChainId } from 'constants/chains'
import { ReactNode } from 'react'
export const FEE_AMOUNT_DETAIL: Record<
FeeAmount,
{ label: string; description: ReactNode; supportedChains: SupportedChainId[] }
> = {
[FeeAmount.LOWEST]: {
label: '0.01',
description: <Trans>Best for very stable pairs.</Trans>,
supportedChains: [SupportedChainId.MAINNET],
},
[FeeAmount.LOW]: {
label: '0.05',
description: <Trans>Best for stable pairs.</Trans>,
supportedChains: ALL_SUPPORTED_CHAIN_IDS,
},
[FeeAmount.MEDIUM]: {
label: '0.3',
description: <Trans>Best for most pairs.</Trans>,
supportedChains: ALL_SUPPORTED_CHAIN_IDS,
},
[FeeAmount.HIGH]: {
label: '1',
description: <Trans>Best for exotic pairs.</Trans>,
supportedChains: ALL_SUPPORTED_CHAIN_IDS,
},
}
...@@ -20,6 +20,12 @@ import { useDensityChartData } from './hooks' ...@@ -20,6 +20,12 @@ import { useDensityChartData } from './hooks'
import { ZoomLevels } from './types' import { ZoomLevels } from './types'
const ZOOM_LEVELS: Record<FeeAmount, ZoomLevels> = { const ZOOM_LEVELS: Record<FeeAmount, ZoomLevels> = {
[FeeAmount.LOWEST]: {
initialMin: 0.999,
initialMax: 1.001,
min: 0.00001,
max: 1.5,
},
[FeeAmount.LOW]: { [FeeAmount.LOW]: {
initialMin: 0.999, initialMin: 0.999,
initialMax: 1.001, initialMax: 1.001,
......
...@@ -10,7 +10,7 @@ const percent = (strings: TemplateStringsArray) => new Percent(parseInt(strings[ ...@@ -10,7 +10,7 @@ const percent = (strings: TemplateStringsArray) => new Percent(parseInt(strings[
const singleRoute: RoutingDiagramEntry = { percent: percent`100`, path: [[USDC, DAI, FeeAmount.LOW]] } const singleRoute: RoutingDiagramEntry = { percent: percent`100`, path: [[USDC, DAI, FeeAmount.LOW]] }
const multiRoute: RoutingDiagramEntry[] = [ const multiRoute: RoutingDiagramEntry[] = [
{ percent: percent`75`, path: [[USDC, DAI, FeeAmount.LOW]] }, { percent: percent`75`, path: [[USDC, DAI, FeeAmount.LOWEST]] },
{ {
percent: percent`25`, percent: percent`25`,
path: [ path: [
......
...@@ -47,7 +47,7 @@ exports[`renders multi route 1`] = ` ...@@ -47,7 +47,7 @@ exports[`renders multi route 1`] = `
<div <div
class="theme__TextWrapper-sc-18nh1jk-0 cWOfab css-15li2d9" class="theme__TextWrapper-sc-18nh1jk-0 cWOfab css-15li2d9"
> >
0.05% 0.01%
</div> </div>
</div> </div>
</div> </div>
......
...@@ -19,11 +19,7 @@ interface FeeTierDistribution { ...@@ -19,11 +19,7 @@ interface FeeTierDistribution {
largestUsageFeeTier?: FeeAmount | undefined largestUsageFeeTier?: FeeAmount | undefined
// distributions as percentages of overall liquidity // distributions as percentages of overall liquidity
distributions?: { distributions?: Record<FeeAmount, number | undefined>
[FeeAmount.LOW]: number | undefined
[FeeAmount.MEDIUM]: number | undefined
[FeeAmount.HIGH]: number | undefined
}
} }
export function useFeeTierDistribution( export function useFeeTierDistribution(
...@@ -36,6 +32,7 @@ export function useFeeTierDistribution( ...@@ -36,6 +32,7 @@ export function useFeeTierDistribution(
) )
// fetch all pool states to determine pool state // fetch all pool states to determine pool state
const [poolStateVeryLow] = usePool(currencyA, currencyB, FeeAmount.LOWEST)
const [poolStateLow] = usePool(currencyA, currencyB, FeeAmount.LOW) const [poolStateLow] = usePool(currencyA, currencyB, FeeAmount.LOW)
const [poolStateMedium] = usePool(currencyA, currencyB, FeeAmount.MEDIUM) const [poolStateMedium] = usePool(currencyA, currencyB, FeeAmount.MEDIUM)
const [poolStateHigh] = usePool(currencyA, currencyB, FeeAmount.HIGH) const [poolStateHigh] = usePool(currencyA, currencyB, FeeAmount.HIGH)
...@@ -58,10 +55,13 @@ export function useFeeTierDistribution( ...@@ -58,10 +55,13 @@ export function useFeeTierDistribution(
!isLoading && !isLoading &&
!isError && !isError &&
distributions && distributions &&
poolStateVeryLow !== PoolState.LOADING &&
poolStateLow !== PoolState.LOADING && poolStateLow !== PoolState.LOADING &&
poolStateMedium !== PoolState.LOADING && poolStateMedium !== PoolState.LOADING &&
poolStateHigh !== PoolState.LOADING poolStateHigh !== PoolState.LOADING
? { ? {
[FeeAmount.LOWEST]:
poolStateVeryLow === PoolState.EXISTS ? (distributions[FeeAmount.LOWEST] ?? 0) * 100 : undefined,
[FeeAmount.LOW]: poolStateLow === PoolState.EXISTS ? (distributions[FeeAmount.LOW] ?? 0) * 100 : undefined, [FeeAmount.LOW]: poolStateLow === PoolState.EXISTS ? (distributions[FeeAmount.LOW] ?? 0) * 100 : undefined,
[FeeAmount.MEDIUM]: [FeeAmount.MEDIUM]:
poolStateMedium === PoolState.EXISTS ? (distributions[FeeAmount.MEDIUM] ?? 0) * 100 : undefined, poolStateMedium === PoolState.EXISTS ? (distributions[FeeAmount.MEDIUM] ?? 0) * 100 : undefined,
...@@ -76,7 +76,17 @@ export function useFeeTierDistribution( ...@@ -76,7 +76,17 @@ export function useFeeTierDistribution(
distributions: percentages, distributions: percentages,
largestUsageFeeTier: largestUsageFeeTier === -1 ? undefined : largestUsageFeeTier, largestUsageFeeTier: largestUsageFeeTier === -1 ? undefined : largestUsageFeeTier,
} }
}, [isLoading, isFetching, isUninitialized, isError, distributions, poolStateLow, poolStateMedium, poolStateHigh]) }, [
isLoading,
isFetching,
isUninitialized,
isError,
distributions,
poolStateVeryLow,
poolStateLow,
poolStateMedium,
poolStateHigh,
])
} }
function usePoolTVL(token0: Token | undefined, token1: Token | undefined) { function usePoolTVL(token0: Token | undefined, token1: Token | undefined) {
...@@ -124,10 +134,11 @@ function usePoolTVL(token0: Token | undefined, token1: Token | undefined) { ...@@ -124,10 +134,11 @@ function usePoolTVL(token0: Token | undefined, token1: Token | undefined) {
return acc return acc
}, },
{ {
[FeeAmount.LOWEST]: [undefined, undefined],
[FeeAmount.LOW]: [undefined, undefined], [FeeAmount.LOW]: [undefined, undefined],
[FeeAmount.MEDIUM]: [undefined, undefined], [FeeAmount.MEDIUM]: [undefined, undefined],
[FeeAmount.HIGH]: [undefined, undefined], [FeeAmount.HIGH]: [undefined, undefined],
} } as Record<FeeAmount, [number | undefined, number | undefined]>
) )
// sum total tvl for token0 and token1 // sum total tvl for token0 and token1
...@@ -144,7 +155,13 @@ function usePoolTVL(token0: Token | undefined, token1: Token | undefined) { ...@@ -144,7 +155,13 @@ function usePoolTVL(token0: Token | undefined, token1: Token | undefined) {
const mean = (tvl0: number | undefined, sumTvl0: number, tvl1: number | undefined, sumTvl1: number) => const mean = (tvl0: number | undefined, sumTvl0: number, tvl1: number | undefined, sumTvl1: number) =>
tvl0 === undefined && tvl1 === undefined ? undefined : ((tvl0 ?? 0) + (tvl1 ?? 0)) / (sumTvl0 + sumTvl1) || 0 tvl0 === undefined && tvl1 === undefined ? undefined : ((tvl0 ?? 0) + (tvl1 ?? 0)) / (sumTvl0 + sumTvl1) || 0
const distributions = { const distributions: Record<FeeAmount, number | undefined> = {
[FeeAmount.LOWEST]: mean(
tvlByFeeTier[FeeAmount.LOWEST][0],
sumToken0Tvl,
tvlByFeeTier[FeeAmount.LOWEST][1],
sumToken1Tvl
),
[FeeAmount.LOW]: mean(tvlByFeeTier[FeeAmount.LOW][0], sumToken0Tvl, tvlByFeeTier[FeeAmount.LOW][1], sumToken1Tvl), [FeeAmount.LOW]: mean(tvlByFeeTier[FeeAmount.LOW][0], sumToken0Tvl, tvlByFeeTier[FeeAmount.LOW][1], sumToken1Tvl),
[FeeAmount.MEDIUM]: mean( [FeeAmount.MEDIUM]: mean(
tvlByFeeTier[FeeAmount.MEDIUM][0], tvlByFeeTier[FeeAmount.MEDIUM][0],
......
import { Currency, Token } from '@uniswap/sdk-core' import { Currency, Token } from '@uniswap/sdk-core'
import { FeeAmount, Pool } from '@uniswap/v3-sdk' import { FeeAmount, Pool } from '@uniswap/v3-sdk'
import { SupportedChainId } from 'constants/chains'
import { useMemo } from 'react' import { useMemo } from 'react'
import { useAllCurrencyCombinations } from './useAllCurrencyCombinations' import { useAllCurrencyCombinations } from './useAllCurrencyCombinations'
import { PoolState, usePools } from './usePools' import { PoolState, usePools } from './usePools'
import { useActiveWeb3React } from './web3'
/** /**
* Returns all the existing pools that should be considered for swapping between an input currency and an output currency * Returns all the existing pools that should be considered for swapping between an input currency and an output currency
...@@ -17,18 +19,27 @@ export function useV3SwapPools( ...@@ -17,18 +19,27 @@ export function useV3SwapPools(
pools: Pool[] pools: Pool[]
loading: boolean loading: boolean
} { } {
const { chainId } = useActiveWeb3React()
const allCurrencyCombinations = useAllCurrencyCombinations(currencyIn, currencyOut) const allCurrencyCombinations = useAllCurrencyCombinations(currencyIn, currencyOut)
const allCurrencyCombinationsWithAllFees: [Token, Token, FeeAmount][] = useMemo( const allCurrencyCombinationsWithAllFees: [Token, Token, FeeAmount][] = useMemo(
() => () =>
allCurrencyCombinations.reduce<[Token, Token, FeeAmount][]>((list, [tokenA, tokenB]) => { allCurrencyCombinations.reduce<[Token, Token, FeeAmount][]>((list, [tokenA, tokenB]) => {
return list.concat([ return chainId === SupportedChainId.MAINNET
[tokenA, tokenB, FeeAmount.LOW], ? list.concat([
[tokenA, tokenB, FeeAmount.MEDIUM], [tokenA, tokenB, FeeAmount.LOW],
[tokenA, tokenB, FeeAmount.HIGH], [tokenA, tokenB, FeeAmount.MEDIUM],
]) [tokenA, tokenB, FeeAmount.HIGH],
])
: list.concat([
[tokenA, tokenB, FeeAmount.LOWEST],
[tokenA, tokenB, FeeAmount.LOW],
[tokenA, tokenB, FeeAmount.MEDIUM],
[tokenA, tokenB, FeeAmount.HIGH],
])
}, []), }, []),
[allCurrencyCombinations] [allCurrencyCombinations, chainId]
) )
const pools = usePools(allCurrencyCombinationsWithAllFees) const pools = usePools(allCurrencyCombinationsWithAllFees)
......
...@@ -4666,10 +4666,10 @@ ...@@ -4666,10 +4666,10 @@
base64-sol "1.0.1" base64-sol "1.0.1"
hardhat-watcher "^2.1.1" hardhat-watcher "^2.1.1"
"@uniswap/v3-sdk@3.6.3": "@uniswap/v3-sdk@^3.7.1":
version "3.6.3" version "3.7.1"
resolved "https://registry.yarnpkg.com/@uniswap/v3-sdk/-/v3-sdk-3.6.3.tgz#f2fca86cfde1450976581028195fc0ee4b11036d" resolved "https://registry.yarnpkg.com/@uniswap/v3-sdk/-/v3-sdk-3.7.1.tgz#8a3740ff6302d8069e7ce4a38b7588721398048b"
integrity sha512-nepNTZMpM1uwLJAlQaUUEDMFrSujS1sOqyVD739zoPWsVHAUPvqVAKQN0GlgZcLXOqeCMKjO3lteaNHEXef1XA== integrity sha512-/0FBsrRijfAEOVO0ejCQX36MwaKzjKCaInUA1dNqFyDNZ5dthvv6jUhMADYuNXZnhN6NcSdIj6xhlc/cpgPm9Q==
dependencies: dependencies:
"@ethersproject/abi" "^5.0.12" "@ethersproject/abi" "^5.0.12"
"@ethersproject/solidity" "^5.0.9" "@ethersproject/solidity" "^5.0.9"
......
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