allow fetching multiple pools via usePools.ts
This commit is contained in:
parent
644ecdbd32
commit
b69f08cbe1
@ -1,9 +1,6 @@
|
||||
import { Interface } from '@ethersproject/abi'
|
||||
import { abi as STAKING_REWARDS_ABI } from '@uniswap/liquidity-staker/build/StakingRewards.json'
|
||||
import { abi as STAKING_REWARDS_FACTORY_ABI } from '@uniswap/liquidity-staker/build/StakingRewardsFactory.json'
|
||||
|
||||
const STAKING_REWARDS_INTERFACE = new Interface(STAKING_REWARDS_ABI)
|
||||
|
||||
const STAKING_REWARDS_FACTORY_INTERFACE = new Interface(STAKING_REWARDS_FACTORY_ABI)
|
||||
|
||||
export { STAKING_REWARDS_FACTORY_INTERFACE, STAKING_REWARDS_INTERFACE }
|
||||
export { STAKING_REWARDS_INTERFACE }
|
||||
|
@ -2,7 +2,7 @@ import React, { useMemo } from 'react'
|
||||
import { Position } from '@uniswap/v3-sdk'
|
||||
import Badge, { BadgeVariant } from 'components/Badge'
|
||||
import DoubleCurrencyLogo from 'components/DoubleLogo'
|
||||
import { PoolState, usePool } from 'data/Pools'
|
||||
import { PoolState, usePool } from 'hooks/usePools'
|
||||
import { useToken } from 'hooks/Tokens'
|
||||
import { AlertTriangle } from 'react-feather'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
@ -85,8 +85,8 @@ export const BASES_TO_CHECK_TRADES_AGAINST: ChainTokenList = {
|
||||
|
||||
export const ADDITIONAL_BASES: { [chainId in ChainId]?: { [tokenAddress: string]: Token[] } } = {
|
||||
[ChainId.MAINNET]: {
|
||||
'0xA948E86885e12Fb09AfEF8C52142EBDbDf73cD18': [new Token(ChainId.MAINNET, UNI_ADDRESS, 18, 'UNI', 'Uniswap')],
|
||||
'0x561a4717537ff4AF5c687328c0f7E90a319705C0': [new Token(ChainId.MAINNET, UNI_ADDRESS, 18, 'UNI', 'Uniswap')],
|
||||
'0xA948E86885e12Fb09AfEF8C52142EBDbDf73cD18': [UNI[ChainId.MAINNET]],
|
||||
'0x561a4717537ff4AF5c687328c0f7E90a319705C0': [UNI[ChainId.MAINNET]],
|
||||
[FEI.address]: [TRIBE],
|
||||
[TRIBE.address]: [FEI],
|
||||
[FRAX.address]: [FXS],
|
||||
|
@ -1,97 +0,0 @@
|
||||
import { computePoolAddress } from '@uniswap/v3-sdk'
|
||||
import { ZERO_ADDRESS } from './../constants/index'
|
||||
import { Currency } from '@uniswap/sdk-core'
|
||||
import { useMemo } from 'react'
|
||||
import { useActiveWeb3React } from '../hooks'
|
||||
import { useSingleCallResult } from '../state/multicall/hooks'
|
||||
import { wrappedCurrency } from '../utils/wrappedCurrency'
|
||||
import { Pool, FeeAmount } from '@uniswap/v3-sdk'
|
||||
import { useV3Factory, useV3Pool } from 'hooks/useContract'
|
||||
import { V3_CORE_FACTORY_ADDRESSES } from 'constants/v3'
|
||||
|
||||
export enum PoolState {
|
||||
LOADING = 'LOADING',
|
||||
NOT_EXISTS = 'NOT_EXISTS',
|
||||
EXISTS = 'EXISTS',
|
||||
INVALID = 'INVALID',
|
||||
}
|
||||
|
||||
export function usePool(currencyA?: Currency, currencyB?: Currency, feeAmount?: FeeAmount): [PoolState, Pool | null] {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
const factoryContract = useV3Factory()
|
||||
|
||||
const tokenA = wrappedCurrency(currencyA, chainId)
|
||||
const tokenB = wrappedCurrency(currencyB, chainId)
|
||||
|
||||
// sorted version
|
||||
const [token0, token1] = useMemo(
|
||||
() =>
|
||||
tokenA && tokenB && !tokenA.equals(tokenB)
|
||||
? tokenA.sortsBefore(tokenB)
|
||||
? [tokenA, tokenB]
|
||||
: [tokenB, tokenA]
|
||||
: [undefined, undefined],
|
||||
[tokenA, tokenB]
|
||||
)
|
||||
|
||||
// fetch all generated addresses for pools
|
||||
const poolAddress = useMemo(() => {
|
||||
try {
|
||||
const addr = chainId && V3_CORE_FACTORY_ADDRESSES[chainId]
|
||||
return addr && tokenA && tokenB && feeAmount && !tokenA.equals(tokenB)
|
||||
? computePoolAddress({
|
||||
factoryAddress: addr,
|
||||
tokenA,
|
||||
tokenB,
|
||||
fee: feeAmount,
|
||||
})
|
||||
: undefined
|
||||
} catch {
|
||||
return undefined
|
||||
}
|
||||
}, [chainId, feeAmount, tokenA, tokenB])
|
||||
|
||||
// check factory if pools exists
|
||||
const addressParams = token0 && token1 && feeAmount ? [token0.address, token1.address, feeAmount] : undefined
|
||||
const addressFromFactory = useSingleCallResult(addressParams ? factoryContract : undefined, 'getPool', addressParams)
|
||||
const { result: addressesResult, loading: addressesLoading } = addressFromFactory
|
||||
const poolAddressFromFactory = addressesResult?.[0]
|
||||
|
||||
const poolContract = useV3Pool(poolAddress)
|
||||
|
||||
// attempt to fetch pool metadata
|
||||
const slot0Datas = useSingleCallResult(poolContract, 'slot0')
|
||||
|
||||
// fetch additional data to instantiate pools
|
||||
const liquidityDatas = useSingleCallResult(poolContract, 'liquidity')
|
||||
|
||||
const { result: slot0, loading: slot0Loading } = slot0Datas
|
||||
const { result: liquidityResult, loading: liquidityLoading } = liquidityDatas
|
||||
|
||||
const liquidity = liquidityResult?.[0]
|
||||
|
||||
return useMemo(() => {
|
||||
// still loading data
|
||||
if (slot0Loading || addressesLoading || liquidityLoading) return [PoolState.LOADING, null]
|
||||
|
||||
// invalid pool setup
|
||||
if (!tokenA || !tokenB || !feeAmount || tokenA.equals(tokenB)) return [PoolState.INVALID, null]
|
||||
|
||||
// pool has not been created or not initialized yet
|
||||
if (poolAddressFromFactory === ZERO_ADDRESS || !slot0 || !liquidity || slot0.sqrtPriceX96 === 0) {
|
||||
return [PoolState.NOT_EXISTS, null]
|
||||
}
|
||||
|
||||
return [PoolState.EXISTS, new Pool(tokenA, tokenB, feeAmount, slot0.sqrtPriceX96, liquidity, slot0.tick)]
|
||||
}, [
|
||||
addressesLoading,
|
||||
feeAmount,
|
||||
liquidity,
|
||||
liquidityLoading,
|
||||
poolAddressFromFactory,
|
||||
slot0,
|
||||
slot0Loading,
|
||||
tokenA,
|
||||
tokenB,
|
||||
])
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import { Pool, Position } from '@uniswap/v3-sdk'
|
||||
import { usePool } from 'data/Pools'
|
||||
import { usePool } from 'hooks/usePools'
|
||||
import { PositionDetails } from 'types/position'
|
||||
import { useCurrency } from './Tokens'
|
||||
|
||||
|
85
src/hooks/usePools.ts
Normal file
85
src/hooks/usePools.ts
Normal file
@ -0,0 +1,85 @@
|
||||
import { computePoolAddress } from '@uniswap/v3-sdk'
|
||||
import { IUniswapV3PoolStateInterface } from '../types/v3/IUniswapV3PoolState'
|
||||
import { Token, Currency } from '@uniswap/sdk-core'
|
||||
import { useMemo } from 'react'
|
||||
import { useActiveWeb3React } from './index'
|
||||
import { useMultipleContractSingleData } from '../state/multicall/hooks'
|
||||
import { wrappedCurrency } from '../utils/wrappedCurrency'
|
||||
import { Pool, FeeAmount } from '@uniswap/v3-sdk'
|
||||
import { V3_CORE_FACTORY_ADDRESSES } from 'constants/v3'
|
||||
import { abi as IUniswapV3PoolStateABI } from '@uniswap/v3-core/artifacts/contracts/interfaces/pool/IUniswapV3PoolState.sol/IUniswapV3PoolState.json'
|
||||
import { Interface } from '@ethersproject/abi'
|
||||
|
||||
const POOL_STATE_INTERFACE = new Interface(IUniswapV3PoolStateABI) as IUniswapV3PoolStateInterface
|
||||
|
||||
export enum PoolState {
|
||||
LOADING = 'LOADING',
|
||||
NOT_EXISTS = 'NOT_EXISTS',
|
||||
EXISTS = 'EXISTS',
|
||||
INVALID = 'INVALID',
|
||||
}
|
||||
|
||||
export function usePools(
|
||||
poolKeys: [Currency | undefined, Currency | undefined, FeeAmount | undefined][]
|
||||
): [PoolState, Pool | null][] {
|
||||
const { chainId } = useActiveWeb3React()
|
||||
|
||||
const transformed: ([Token, Token, FeeAmount] | null)[] = useMemo(() => {
|
||||
return poolKeys.map(([currencyA, currencyB, feeAmount]) => {
|
||||
if (!chainId || !currencyA || !currencyB || !feeAmount) return null
|
||||
|
||||
const tokenA = wrappedCurrency(currencyA, chainId)
|
||||
const tokenB = wrappedCurrency(currencyB, chainId)
|
||||
if (!tokenA || !tokenB || tokenA.equals(tokenB)) return null
|
||||
const [token0, token1] = tokenA.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA]
|
||||
return [token0, token1, feeAmount]
|
||||
})
|
||||
}, [chainId, poolKeys])
|
||||
|
||||
const poolAddresses: (string | undefined)[] = useMemo(() => {
|
||||
const v3CoreFactoryAddress = chainId && V3_CORE_FACTORY_ADDRESSES[chainId]
|
||||
|
||||
return transformed.map((value) => {
|
||||
if (!v3CoreFactoryAddress || !value) return undefined
|
||||
return computePoolAddress({
|
||||
factoryAddress: v3CoreFactoryAddress,
|
||||
tokenA: value[0],
|
||||
tokenB: value[1],
|
||||
fee: value[2],
|
||||
})
|
||||
})
|
||||
}, [chainId, transformed])
|
||||
|
||||
const slot0s = useMultipleContractSingleData(poolAddresses, POOL_STATE_INTERFACE, 'slot0')
|
||||
const liquidities = useMultipleContractSingleData(poolAddresses, POOL_STATE_INTERFACE, 'liquidity')
|
||||
|
||||
return useMemo(() => {
|
||||
return poolKeys.map((_key, index) => {
|
||||
const [token0, token1, fee] = transformed[index] ?? []
|
||||
if (!token0 || !token1 || !fee) return [PoolState.INVALID, null]
|
||||
|
||||
const { result: slot0, loading: slot0Loading, valid: slot0Valid } = slot0s[index]
|
||||
const { result: liquidity, loading: liquidityLoading, valid: liquidityValid } = liquidities[index]
|
||||
|
||||
if (!slot0Valid || !liquidityValid) return [PoolState.INVALID, null]
|
||||
if (slot0Loading || liquidityLoading) return [PoolState.LOADING, null]
|
||||
|
||||
if (!slot0 || !liquidity) return [PoolState.NOT_EXISTS, null]
|
||||
|
||||
return [PoolState.EXISTS, new Pool(token0, token1, fee, slot0.sqrtPriceX96, liquidity[0], slot0.tick)]
|
||||
})
|
||||
}, [liquidities, poolKeys, slot0s, transformed])
|
||||
}
|
||||
|
||||
export function usePool(
|
||||
currencyA: Currency | undefined,
|
||||
currencyB: Currency | undefined,
|
||||
feeAmount: FeeAmount | undefined
|
||||
): [PoolState, Pool | null] {
|
||||
const poolKeys: [Currency | undefined, Currency | undefined, FeeAmount | undefined][] = useMemo(
|
||||
() => [[currencyA, currencyB, feeAmount]],
|
||||
[currencyA, currencyB, feeAmount]
|
||||
)
|
||||
|
||||
return usePools(poolKeys)[0]
|
||||
}
|
@ -18,7 +18,7 @@ import { BackArrow, ExternalLink, TYPE } from '../../theme'
|
||||
import { getEtherscanLink, isAddress } from '../../utils'
|
||||
import { BodyWrapper } from '../AppBody'
|
||||
import { V2_MIGRATOR_ADDRESSES } from 'constants/v3'
|
||||
import { PoolState, usePool } from 'data/Pools'
|
||||
import { PoolState, usePool } from 'hooks/usePools'
|
||||
import { FeeAmount, Pool, Position, priceToClosestTick, TickMath } from '@uniswap/v3-sdk'
|
||||
import { LightCard, PinkCard, YellowCard } from 'components/Card'
|
||||
import { ApprovalState, useApproveCallback } from 'hooks/useApproveCallback'
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import { Position } from '@uniswap/v3-sdk'
|
||||
import { PoolState, usePool } from 'data/Pools'
|
||||
import { PoolState, usePool } from 'hooks/usePools'
|
||||
import { useToken } from 'hooks/Tokens'
|
||||
import { useV3PositionFromTokenId } from 'hooks/useV3Positions'
|
||||
import { Link, RouteComponentProps } from 'react-router-dom'
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { TokenAmount } from '@uniswap/sdk-core'
|
||||
import { Position } from '@uniswap/v3-sdk'
|
||||
import { usePool } from 'data/Pools'
|
||||
import { usePool } from 'hooks/usePools'
|
||||
import { useActiveWeb3React } from 'hooks'
|
||||
import { useToken } from 'hooks/Tokens'
|
||||
import { useV3PositionFees } from 'hooks/useV3PositionFees'
|
||||
|
@ -97,7 +97,7 @@ export function useClaimCallback(
|
||||
const claimData = useUserClaimData(account)
|
||||
|
||||
// used for popup summary
|
||||
const unClaimedAmount: TokenAmount | undefined = useUserUnclaimedAmount(account)
|
||||
const unclaimedAmount: TokenAmount | undefined = useUserUnclaimedAmount(account)
|
||||
const addTransaction = useTransactionAdder()
|
||||
const distributorContract = useMerkleDistributorContract()
|
||||
|
||||
@ -111,7 +111,7 @@ export function useClaimCallback(
|
||||
.claim(...args, { value: null, gasLimit: calculateGasMargin(estimatedGasLimit) })
|
||||
.then((response: TransactionResponse) => {
|
||||
addTransaction(response, {
|
||||
summary: `Claimed ${unClaimedAmount?.toSignificant(4)} UNI`,
|
||||
summary: `Claimed ${unclaimedAmount?.toSignificant(4)} UNI`,
|
||||
claim: { recipient: account },
|
||||
})
|
||||
return response.hash
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { BIG_INT_ZERO } from './../../constants/index'
|
||||
import { getTickToPrice } from 'utils/getTickToPrice'
|
||||
import JSBI from 'jsbi'
|
||||
import { PoolState } from './../../data/Pools'
|
||||
import { PoolState } from '../../hooks/usePools'
|
||||
import { Pool, FeeAmount, Position, priceToClosestTick, TickMath } from '@uniswap/v3-sdk/dist/'
|
||||
import { Currency, CurrencyAmount, ETHER, Price } from '@uniswap/sdk-core'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
@ -13,7 +13,7 @@ import { tryParseAmount } from '../swap/hooks'
|
||||
import { useCurrencyBalances } from '../wallet/hooks'
|
||||
import { Field, Bound, typeInput, typeLowerRangeInput, typeUpperRangeInput, typeStartPriceInput } from './actions'
|
||||
import { tryParseTick } from './utils'
|
||||
import { usePool } from 'data/Pools'
|
||||
import { usePool } from 'hooks/usePools'
|
||||
|
||||
export function useMintState(): AppState['mint'] {
|
||||
return useSelector<AppState, AppState['mint']>((state) => state.mint)
|
||||
|
Loading…
Reference in New Issue
Block a user