86 lines
3.4 KiB
TypeScript
86 lines
3.4 KiB
TypeScript
|
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]
|
||
|
}
|