diff --git a/src/abis/staking-rewards.ts b/src/abis/staking-rewards.ts index c551eb8534..53975d2d9c 100644 --- a/src/abis/staking-rewards.ts +++ b/src/abis/staking-rewards.ts @@ -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 } diff --git a/src/components/PositionListItem/index.tsx b/src/components/PositionListItem/index.tsx index 2fcd499b0b..e96be50e81 100644 --- a/src/components/PositionListItem/index.tsx +++ b/src/components/PositionListItem/index.tsx @@ -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' diff --git a/src/constants/index.ts b/src/constants/index.ts index 98cc803335..e3601963c8 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -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], diff --git a/src/data/Pools.ts b/src/data/Pools.ts deleted file mode 100644 index 937aaadf1e..0000000000 --- a/src/data/Pools.ts +++ /dev/null @@ -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, - ]) -} diff --git a/src/hooks/useDerivedPositionInfo.ts b/src/hooks/useDerivedPositionInfo.ts index f20caf14f3..4a72098271 100644 --- a/src/hooks/useDerivedPositionInfo.ts +++ b/src/hooks/useDerivedPositionInfo.ts @@ -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' diff --git a/src/hooks/usePools.ts b/src/hooks/usePools.ts new file mode 100644 index 0000000000..3aa22e7546 --- /dev/null +++ b/src/hooks/usePools.ts @@ -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] +} diff --git a/src/pages/MigrateV2/MigrateV2Pair.tsx b/src/pages/MigrateV2/MigrateV2Pair.tsx index f6e99a0a84..5cb32a9fed 100644 --- a/src/pages/MigrateV2/MigrateV2Pair.tsx +++ b/src/pages/MigrateV2/MigrateV2Pair.tsx @@ -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' diff --git a/src/pages/Pool/PositionPage.tsx b/src/pages/Pool/PositionPage.tsx index 454c4780f0..8e288a3514 100644 --- a/src/pages/Pool/PositionPage.tsx +++ b/src/pages/Pool/PositionPage.tsx @@ -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' diff --git a/src/state/burn/v3/hooks.ts b/src/state/burn/v3/hooks.ts index 6b67f99467..98ceb4bdb9 100644 --- a/src/state/burn/v3/hooks.ts +++ b/src/state/burn/v3/hooks.ts @@ -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' diff --git a/src/state/claim/hooks.ts b/src/state/claim/hooks.ts index 9ac1db1f25..689b6c305e 100644 --- a/src/state/claim/hooks.ts +++ b/src/state/claim/hooks.ts @@ -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 diff --git a/src/state/mint/hooks.ts b/src/state/mint/hooks.ts index 4a8c6217bb..11ae0dac90 100644 --- a/src/state/mint/hooks.ts +++ b/src/state/mint/hooks.ts @@ -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((state) => state.mint)