diff --git a/src/components/YieldPools/FarmingPoolAPRCell.tsx b/src/components/YieldPools/FarmingPoolAPRCell.tsx index 83c1d376a6..c2406faf64 100644 --- a/src/components/YieldPools/FarmingPoolAPRCell.tsx +++ b/src/components/YieldPools/FarmingPoolAPRCell.tsx @@ -189,7 +189,7 @@ const FarmingPoolAPRCell: React.FC = ({ } + text={} > {formatDisplayNumber((poolAPR + maxFarmAPR) / 100, { style: 'percent', fractionDigits: 2 })} diff --git a/src/constants/networks.ts b/src/constants/networks.ts index 1d2f7068c3..51149291d8 100644 --- a/src/constants/networks.ts +++ b/src/constants/networks.ts @@ -130,21 +130,6 @@ export function isSupportedChainId(chainId?: number): chainId is ChainId { } export const FAUCET_NETWORKS = [ChainId.BTTC] -export const CHAINS_SUPPORT_NEW_POOL_FARM_API: readonly ChainId[] = [ - ChainId.MAINNET, - // ChainId.MUMBAI, - // ChainId.MATIC, - // ChainId.BSCTESTNET, - ChainId.BSCMAINNET, - // ChainId.AVAXTESTNET, - ChainId.AVAXMAINNET, - ChainId.FANTOM, - ChainId.CRONOS, - ChainId.BTTC, - ChainId.ARBITRUM, - ChainId.AURORA, - ChainId.OPTIMISM, -] // Fee options instead of dynamic fee export const STATIC_FEE_OPTIONS: { [chainId: number]: number[] | undefined } = { @@ -197,6 +182,9 @@ export const SUPPORTED_NETWORKS_FOR_MY_EARNINGS = [ ChainId.ARBITRUM, ChainId.OPTIMISM, ChainId.MATIC, + ChainId.LINEA, + ChainId.BASE, + ChainId.ZKSYNC, ChainId.BSCMAINNET, ChainId.AVAXMAINNET, ChainId.FANTOM, diff --git a/src/hooks/useKyberSwapConfig.ts b/src/hooks/useKyberSwapConfig.ts index 24501dfb8a..7aaa9dfae9 100644 --- a/src/hooks/useKyberSwapConfig.ts +++ b/src/hooks/useKyberSwapConfig.ts @@ -37,8 +37,8 @@ const parseResponse = ( return { rpc, - prochart: data?.prochart || false, isEnableBlockService: data?.isEnableBlockService || false, + isEnableKNProtocol: data?.isEnableKNProtocol || false, blockClient: isEVM(defaultChainId) ? createClient(data?.blockSubgraph || NETWORKS_INFO[defaultChainId].defaultBlockSubgraph) : createClient(ethereumInfo.defaultBlockSubgraph), diff --git a/src/hooks/useMixpanel.ts b/src/hooks/useMixpanel.ts index d7e6ac6e7e..cda967d80e 100644 --- a/src/hooks/useMixpanel.ts +++ b/src/hooks/useMixpanel.ts @@ -1739,6 +1739,7 @@ export const useGlobalMixpanelEvents = () => { 'notification-center': 'Notification', [APP_PATHS.KYBERAI_ABOUT]: 'KyberAI About', [APP_PATHS.KYBERDAO_KNC_UTILITY]: 'Gas refund - KNC Utility', + [APP_PATHS.MY_EARNINGS]: 'Earning Dashboard', } const protectedPaths: { [key: string]: string } = { [APP_PATHS.KYBERAI_RANKINGS]: 'KyberAI Rankings', diff --git a/src/pages/App.tsx b/src/pages/App.tsx index 0d636745c7..06a7ec8e40 100644 --- a/src/pages/App.tsx +++ b/src/pages/App.tsx @@ -24,7 +24,7 @@ import Snowfall from 'components/Snowflake/Snowfall' import Web3ReactManager from 'components/Web3ReactManager' import { ENV_LEVEL } from 'constants/env' import { APP_PATHS, BLACKLIST_WALLETS, CHAINS_SUPPORT_CROSS_CHAIN } from 'constants/index' -import { CLASSIC_NOT_SUPPORTED, NETWORKS_INFO, SUPPORTED_NETWORKS } from 'constants/networks' +import { CLASSIC_NOT_SUPPORTED, ELASTIC_NOT_SUPPORTED, NETWORKS_INFO, SUPPORTED_NETWORKS } from 'constants/networks' import { ENV_TYPE } from 'constants/type' import { useActiveWeb3React } from 'hooks' import { useAutoLogin } from 'hooks/useLogin' @@ -191,15 +191,19 @@ const RoutesWithNetworkPrefix = () => { )} - } - /> - } - /> - } /> + {!ELASTIC_NOT_SUPPORTED[chainId] && ( + <> + } + /> + } + /> + } /> + + )} } /> diff --git a/src/pages/Farm/ElasticFarmv2/components/FarmCard.tsx b/src/pages/Farm/ElasticFarmv2/components/FarmCard.tsx index 0e6452da34..c9dd8006fa 100644 --- a/src/pages/Farm/ElasticFarmv2/components/FarmCard.tsx +++ b/src/pages/Farm/ElasticFarmv2/components/FarmCard.tsx @@ -262,34 +262,9 @@ function FarmCard({ - - - - {farm.tvlToken0.toSignificant(6)} {farm.token0.symbol} - - - - - {farm.tvlToken1.toSignificant(6)} {farm.token1.symbol} - - - ) : ( - '' - ) - } - > - - {farm.tvl ? formatDollarAmount(farm.tvl) : '--'} - - - {!!farm.tvl && } - - + + {farm.tvl ? formatDollarAmount(farm.tvl) : '--'} + {isEnded || farm.isSettled ? ( isEnded ? ( diff --git a/src/pages/MyEarnings/ElasticPools/SinglePosition/CollectFeesPanel.tsx b/src/pages/MyEarnings/ElasticPools/SinglePosition/CollectFeesPanel.tsx index f5d1d35766..417ba4dc86 100644 --- a/src/pages/MyEarnings/ElasticPools/SinglePosition/CollectFeesPanel.tsx +++ b/src/pages/MyEarnings/ElasticPools/SinglePosition/CollectFeesPanel.tsx @@ -13,6 +13,7 @@ import { ButtonOutlined } from 'components/Button' import CurrencyLogo from 'components/CurrencyLogo' import { MouseoverTooltip } from 'components/Tooltip' import PROMM_FARM_ABI from 'constants/abis/v2/farm.json' +import FarmV2ABI from 'constants/abis/v2/farmv2.json' import { useActiveWeb3React, useWeb3React } from 'hooks' import { useProAmmNFTPositionManagerContract } from 'hooks/useContract' import { config } from 'hooks/useElasticLegacy' @@ -31,6 +32,7 @@ import { formatDollarAmount } from 'utils/numbers' type Props = { nftId: string + fId: string feeValue0: CurrencyAmount feeValue1: CurrencyAmount feeUsd: number @@ -43,9 +45,11 @@ type Props = { } const FarmInterface = new Interface(PROMM_FARM_ABI) +const FarmV2Interface = new Interface(FarmV2ABI) const CollectFeesPanel: React.FC = ({ nftId, + fId, chainId, feeUsd, feeValue0, @@ -140,14 +144,19 @@ const CollectFeesPanel: React.FC = ({ const amount0Min = feeValue0.subtract(feeValue0.multiply(basisPointsToPercent(allowedSlippage))) const amount1Min = feeValue1.subtract(feeValue1.multiply(basisPointsToPercent(allowedSlippage))) try { - const encoded = FarmInterface.encodeFunctionData('claimFee', [ - [nftId], - amount0Min.quotient.toString(), - amount1Min.quotient.toString(), - poolAddress, - true, - deadline?.toString(), - ]) + const encoded = (fId ? FarmV2Interface : FarmInterface).encodeFunctionData( + 'claimFee', + fId + ? [fId, [nftId], amount0Min.quotient.toString(), amount1Min.quotient.toString(), deadline?.toString(), true] + : [ + [nftId], + amount0Min.quotient.toString(), + amount1Min.quotient.toString(), + poolAddress, + true, + deadline?.toString(), + ], + ) sendTransaction({ to: farmAddress, diff --git a/src/pages/MyEarnings/ElasticPools/SinglePosition/PositionView.tsx b/src/pages/MyEarnings/ElasticPools/SinglePosition/PositionView.tsx index b51b52c3e7..77daf9abe8 100644 --- a/src/pages/MyEarnings/ElasticPools/SinglePosition/PositionView.tsx +++ b/src/pages/MyEarnings/ElasticPools/SinglePosition/PositionView.tsx @@ -15,6 +15,7 @@ import Divider from 'components/Divider' import FormattedCurrencyAmount from 'components/FormattedCurrencyAmount' import { MouseoverTooltip } from 'components/Tooltip' import PROMM_FARM_ABI from 'constants/abis/v2/farm.json' +import FarmV2ABI from 'constants/abis/v2/farmv2.json' import { VERSION } from 'constants/v2' import { useActiveWeb3React, useWeb3React } from 'hooks' import { useAllTokens } from 'hooks/Tokens' @@ -39,6 +40,7 @@ import { formatDisplayNumber } from 'utils/numbers' import ActionButtons from './ActionButtons' const FarmInterface = new Interface(PROMM_FARM_ABI) +const FarmV2Interface = new Interface(FarmV2ABI) const PositionView: React.FC = props => { const { positionEarning, position, pendingFee, tokenPrices: prices, chainId, currency0, currency1 } = props @@ -65,9 +67,14 @@ const PositionView: React.FC = props => { parseFloat(position.amount0.toExact() || '0') * prices[currency0.wrapped.address || ''] + parseFloat(position.amount1.toExact() || '0') * prices[currency1.wrapped.address || ''] + const stakedLiqFarmv2 = positionEarning.farmV2DepositedPositions?.[0]?.liquidity || '0' + const weight = positionEarning.farmV2DepositedPositions?.[0]?.range?.weight || '1' + const stakedPosition = new Position({ pool: position.pool, - liquidity: positionEarning.joinedPositions?.[0]?.liquidity || '0', + liquidity: + positionEarning.joinedPositions?.[0]?.liquidity || + BigNumber.from(stakedLiqFarmv2).div(BigNumber.from(weight)).toString(), tickLower: position.tickLower, tickUpper: position.tickUpper, }) @@ -114,35 +121,61 @@ const PositionView: React.FC = props => { const theme = useTheme() const tokens = useAllTokens(true, chainId) - const farmRewards = positionEarning.joinedPositions?.[0]?.farmingPool?.rewardTokensIds?.map((rwId, index) => { - const token = tokens[rwId] || new Token(chainId, rwId, 18, '', '') + let farmRewards = + positionEarning.joinedPositions?.[0]?.farmingPool?.rewardTokensIds?.map((rwId, index) => { + const token = tokens[rwId] || new Token(chainId, rwId, 18, '', '') - return CurrencyAmount.fromRawAmount(token, positionEarning.joinedPositions?.[0]?.pendingRewards?.[index] || '0') - }) + return CurrencyAmount.fromRawAmount(token, positionEarning.joinedPositions?.[0]?.pendingRewards?.[index] || '0') + }) || [] + + const farmV2Rewards = + positionEarning.farmV2DepositedPositions?.[0].pendingRewards.map((amount, index) => { + const tokenId = positionEarning.farmV2DepositedPositions?.[0].farmV2.rewards[index].tokenID || '' + const token = tokens[tokenId] || new Token(chainId, tokenId, 18, '', '') + + return CurrencyAmount.fromRawAmount(token, amount) + }) || [] + + farmRewards = farmRewards.concat(farmV2Rewards) + + const disabledHarvest = + !positionEarning.joinedPositions?.[0]?.pendingRewards?.some(item => item !== '0') && + !positionEarning.farmV2DepositedPositions?.[0].pendingRewards?.some(item => item !== '0') const addTransactionWithType = useTransactionAdder() const handleHarvest = () => { - const farmContract = positionEarning.joinedPositions?.[0]?.farmId + const farmContract = + positionEarning.joinedPositions?.[0]?.farmId || + positionEarning.farmV2DepositedPositions?.[0].farmV2.id.split('_')[0] + const isInFarmV2 = !!positionEarning.farmV2DepositedPositions?.[0] const pId = positionEarning.joinedPositions?.[0]?.pid + const fId = positionEarning?.farmV2DepositedPositions?.[0].farmV2.id.split('_')[1] + const library = libraryRef.current dispatch(setShowPendingModal(MODAL_PENDING_TEXTS.HARVEST)) dispatch(setAttemptingTxn(true)) - if (!library || !pId || !farmContract) { + if (!library || (isInFarmV2 ? !fId : !pId) || !farmContract) { dispatch(setAttemptingTxn(false)) dispatch(setTxError('Something went wrong!')) return } - const encodedPid = defaultAbiCoder.encode(['tupple(uint256[] pIds)'], [{ pIds: [pId] }]) - const encodedData = FarmInterface.encodeFunctionData('harvestMultiplePools', [[positionEarning.id], [encodedPid]]) + let encodedData = '' + if (isInFarmV2) { + encodedData = FarmV2Interface.encodeFunctionData('claimReward', [fId, [positionEarning.id]]) + } else { + const encodedPid = defaultAbiCoder.encode(['tupple(uint256[] pIds)'], [{ pIds: [pId] }]) + encodedData = FarmInterface.encodeFunctionData('harvestMultiplePools', [[positionEarning.id], [encodedPid]]) + } const txn = { to: farmContract, data: encodedData, } + library .getSigner() .estimateGas(txn) @@ -253,12 +286,17 @@ const PositionView: React.FC = props => { = props => { - + Farm Rewards @@ -303,7 +341,7 @@ const PositionView: React.FC = props => { item !== '0')} + disabled={disabledHarvest} style={{ height: '36px', width: 'fit-content', diff --git a/src/pages/MyEarnings/ElasticPools/SinglePosition/PriceRangeChart.tsx b/src/pages/MyEarnings/ElasticPools/SinglePosition/PriceRangeChart.tsx index 0edaf23c05..b4c334da86 100644 --- a/src/pages/MyEarnings/ElasticPools/SinglePosition/PriceRangeChart.tsx +++ b/src/pages/MyEarnings/ElasticPools/SinglePosition/PriceRangeChart.tsx @@ -75,6 +75,11 @@ const PriceRangeChart: React.FC = ({ position, disabled }) => { overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis', + ':hover': { + overflow: 'visible', + whiteSpace: 'normal', + height: 'auto', + }, }} > Current Price: diff --git a/src/pages/Pools/index.tsx b/src/pages/Pools/index.tsx index 579f84aaf4..5d41df8e1c 100644 --- a/src/pages/Pools/index.tsx +++ b/src/pages/Pools/index.tsx @@ -33,6 +33,7 @@ import { Instruction } from 'pages/Pools/InstructionAndGlobalData' import ProAmmPoolList from 'pages/ProAmmPools' import { ApplicationModal } from 'state/application/actions' import { useOpenModal } from 'state/application/hooks' +import ElasticFarmV2Updater from 'state/farms/elasticv2/updater' import { Field } from 'state/pair/actions' import { MEDIA_WIDTHS } from 'theme' import { currencyId } from 'utils/currencyId' @@ -370,6 +371,7 @@ const Pools = () => { )} + ) } diff --git a/src/pages/ProAmmPools/ListItem.tsx b/src/pages/ProAmmPools/ListItem.tsx index 0c8b990b02..cd65570d58 100644 --- a/src/pages/ProAmmPools/ListItem.tsx +++ b/src/pages/ProAmmPools/ListItem.tsx @@ -128,7 +128,7 @@ export default function ProAmmPoolListItem({ pool, onShared, userPositions }: Li .find(farm => farm.poolAddress.toLowerCase() === pool.address.toLowerCase()) const isFarmV2 = !!farmV2 - const isFarmingPool = isFarmV1 || isFarmV2 + const isFarmingPool = isFarmV1 || isFarmV2 || !!pool.farmAPR const maxFarmV2Apr = Math.max(...(farmV2?.ranges.map(item => item.apr || 0) || []), 0) @@ -145,14 +145,7 @@ export default function ProAmmPoolListItem({ pool, onShared, userPositions }: Li ) } - return ( - - {pool.apr.toFixed(2)}% - - ) + return {pool.apr.toFixed(2)}% } return ( @@ -190,7 +183,7 @@ export default function ProAmmPoolListItem({ pool, onShared, userPositions }: Li Fee {(pool.feeTier * 100) / ELASTIC_BASE_FEE_UNIT}% - {isFarmingPool && } + {isFarmingPool && } diff --git a/src/pages/ProAmmPools/index.tsx b/src/pages/ProAmmPools/index.tsx index 0284ba8d9c..236af8b042 100644 --- a/src/pages/ProAmmPools/index.tsx +++ b/src/pages/ProAmmPools/index.tsx @@ -19,7 +19,6 @@ import { ApplicationModal } from 'state/application/actions' import { useModalOpen, useOpenModal } from 'state/application/hooks' import { FarmUpdater, useElasticFarms } from 'state/farms/elastic/hooks' import { useElasticFarmsV2 } from 'state/farms/elasticv2/hooks' -import ElasticFarmV2Updater from 'state/farms/elasticv2/updater' import { Field } from 'state/mint/proamm/type' import { useTopPoolAddresses, useUserProMMPositions } from 'state/prommPools/hooks' import useGetElasticPools from 'state/prommPools/useGetElasticPools' @@ -472,7 +471,6 @@ export default function ProAmmPoolList({ title={sharedPoolId ? t`Share this pool with your friends!` : t`Share this list of pools with your friends`} /> - ) } diff --git a/src/services/earning/index.ts b/src/services/earning/index.ts index d8e77c9d4b..d7fd8ffc0e 100644 --- a/src/services/earning/index.ts +++ b/src/services/earning/index.ts @@ -55,6 +55,7 @@ const earningApi = createApi({ const positionData: GetElasticEarningResponse = (positionsRes?.data as any).data as GetElasticEarningResponse const aggregateData = Object.keys(positionData).reduce((acc, chainName) => { + if (!positionData?.[chainName]) return acc return { ...acc, [chainName]: { diff --git a/src/services/earning/types.ts b/src/services/earning/types.ts index 3813e85228..93b6e775cb 100644 --- a/src/services/earning/types.ts +++ b/src/services/earning/types.ts @@ -85,6 +85,18 @@ export type ElasticPositionEarningWithDetails = { pendingRewardUSD: string[] liquidity: string }[] + + farmV2DepositedPositions: { + farmV2: { + id: string + rewards: Array<{ amount: string; index: number; tokenID: string }> + } + pendingRewards: Array + liquidity: string + range: { + weight: string + } + }[] } & HistoricalEarning export type ClassicPositionEarningWithDetails = { diff --git a/src/services/knprotocol.ts b/src/services/knprotocol.ts new file mode 100644 index 0000000000..fe1d7c0ee7 --- /dev/null +++ b/src/services/knprotocol.ts @@ -0,0 +1,24 @@ +import { ChainId } from '@kyberswap/ks-sdk-core' +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' + +import { POOL_FARM_BASE_URL } from 'constants/env' +import { NETWORKS_INFO } from 'constants/networks' +import { EVMNetworkInfo } from 'constants/networks/type' +import { SubgraphFarmV2 } from 'state/farms/elasticv2/types' + +const knProtocolApi = createApi({ + reducerPath: 'knProtocol', + baseQuery: fetchBaseQuery({ baseUrl: POOL_FARM_BASE_URL }), + endpoints: builder => ({ + getFarmV2: builder.query<{ data: { data: SubgraphFarmV2[] } }, ChainId>({ + query: (chainId: ChainId) => ({ + url: `/${ + (NETWORKS_INFO[chainId] as EVMNetworkInfo).poolFarmRoute + }/api/v1/elastic-new/farm-v2?perPage=1000&page=1`, + }), + }), + }), +}) + +export default knProtocolApi +export const { useLazyGetFarmV2Query } = knProtocolApi diff --git a/src/services/ksSetting.ts b/src/services/ksSetting.ts index 9a20c38b0d..4e93177ee4 100644 --- a/src/services/ksSetting.ts +++ b/src/services/ksSetting.ts @@ -11,8 +11,8 @@ import { TopToken } from 'state/topTokens/type' export type KyberSwapConfig = { rpc: string - prochart: boolean isEnableBlockService: boolean + isEnableKNProtocol: boolean blockClient: ApolloClient classicClient: ApolloClient elasticClient: ApolloClient @@ -23,8 +23,8 @@ export type KyberSwapConfig = { export type KyberSwapConfigResponse = { rpc: string - prochart: boolean isEnableBlockService: boolean + isEnableKNProtocol: boolean blockSubgraph: string classicSubgraph: string elasticSubgraph: string diff --git a/src/state/application/hooks.ts b/src/state/application/hooks.ts index 62a76749e0..1572fc41fe 100644 --- a/src/state/application/hooks.ts +++ b/src/state/application/hooks.ts @@ -414,7 +414,7 @@ function getDefaultConfig(chainId: ChainId): KyberSwapConfigResponse { const evm = isEVM(chainId) return { rpc: NETWORKS_INFO[chainId].defaultRpcUrl, - prochart: false, + isEnableKNProtocol: false, isEnableBlockService: false, blockSubgraph: (evm ? NETWORKS_INFO[chainId] : ethereumInfo).defaultBlockSubgraph, elasticSubgraph: (evm ? NETWORKS_INFO[chainId] : ethereumInfo).elastic.defaultSubgraph, @@ -449,8 +449,8 @@ export const useKyberSwapConfig = (customChainId?: ChainId): KyberSwapConfig => return { rpc: config.rpc, isEnableBlockService: config.isEnableBlockService, + isEnableKNProtocol: config.isEnableKNProtocol, readProvider, - prochart: config.prochart, blockClient, elasticClient, classicClient, @@ -460,7 +460,7 @@ export const useKyberSwapConfig = (customChainId?: ChainId): KyberSwapConfig => }, [ config.rpc, config.isEnableBlockService, - config.prochart, + config.isEnableKNProtocol, config.commonTokens, readProvider, blockClient, diff --git a/src/state/application/reducer.ts b/src/state/application/reducer.ts index 2aa47c8bb3..fc7534ad81 100644 --- a/src/state/application/reducer.ts +++ b/src/state/application/reducer.ts @@ -172,6 +172,7 @@ export default createReducer(initialState, builder => const data = action.payload.data.config const rpc = data?.rpc || NETWORKS_INFO[chainId].defaultRpcUrl const isEnableBlockService = data?.isEnableBlockService ?? false + const isEnableKNProtocol = data?.isEnableKNProtocol ?? false const blockSubgraph = evm ? data?.blockSubgraph || NETWORKS_INFO[chainId].defaultBlockSubgraph @@ -191,7 +192,7 @@ export default createReducer(initialState, builder => [chainId]: { rpc, isEnableBlockService, - prochart: data?.prochart || false, + isEnableKNProtocol, blockSubgraph, elasticSubgraph, classicSubgraph, diff --git a/src/state/farms/elastic/updaters/index.tsx b/src/state/farms/elastic/updaters/index.tsx index 2dfa4e23a0..426e4dda50 100644 --- a/src/state/farms/elastic/updaters/index.tsx +++ b/src/state/farms/elastic/updaters/index.tsx @@ -1,5 +1,4 @@ -import { CHAINS_SUPPORT_NEW_POOL_FARM_API } from 'constants/networks' -import { useActiveWeb3React } from 'hooks' +import { useKyberSwapConfig } from 'state/application/hooks' import useGetUserFarmingInfo from './useGetUserElasticFarmInfo' import FarmUpdaterV1 from './v1' @@ -10,15 +9,11 @@ export type CommonProps = { } const FarmUpdater: React.FC = ({ interval = true }) => { - const { chainId } = useActiveWeb3React() + const { isEnableKNProtocol } = useKyberSwapConfig() useGetUserFarmingInfo(interval) - if (!chainId) { - return null - } - - if (CHAINS_SUPPORT_NEW_POOL_FARM_API.includes(chainId)) { + if (isEnableKNProtocol) { return } else { return diff --git a/src/state/farms/elasticv2/types.ts b/src/state/farms/elasticv2/types.ts index 7ee3b293ea..658062c1b1 100644 --- a/src/state/farms/elasticv2/types.ts +++ b/src/state/farms/elasticv2/types.ts @@ -27,8 +27,6 @@ export interface ElasticFarmV2 { token0: Currency token1: Currency tvl: number - tvlToken0: CurrencyAmount - tvlToken1: CurrencyAmount totalRewards: Array> ranges: Array } @@ -62,7 +60,8 @@ export interface SubgraphFarmV2 { endTime: string isSettled: boolean liquidity: string - depositedPositions: Array<{ + stakedTvl?: string + depositedPositions?: Array<{ id: string position: { id: string diff --git a/src/state/farms/elasticv2/updater.tsx b/src/state/farms/elasticv2/updater.tsx index b6aaa41b27..3327c123b2 100644 --- a/src/state/farms/elasticv2/updater.tsx +++ b/src/state/farms/elasticv2/updater.tsx @@ -6,7 +6,8 @@ import { CurrencyAmount, Token, WETH } from '@kyberswap/ks-sdk-core' import { FeeAmount, Pool, Position } from '@kyberswap/ks-sdk-elastic' import { BigNumber } from 'ethers' import { Interface } from 'ethers/lib/utils' -import { useEffect } from 'react' +import { useEffect, useMemo, useRef } from 'react' +import { useLazyGetFarmV2Query } from 'services/knprotocol' import FarmV2QuoterABI from 'constants/abis/farmv2Quoter.json' import NFTPositionManagerABI from 'constants/abis/v2/ProAmmNFTPositionManager.json' @@ -107,6 +108,7 @@ export default function ElasticFarmV2Updater({ interval = true }: { interval?: b const { networkInfo, isEVM, chainId, account } = useActiveWeb3React() const elasticFarm = useAppSelector(state => state.elasticFarmV2[chainId] || defaultChainData) const { elasticClient } = useKyberSwapConfig() + const isEnableKNProtocol = true const multicallContract = useMulticallContract() const farmv2QuoterContract = useContract( @@ -114,30 +116,53 @@ export default function ElasticFarmV2Updater({ interval = true }: { interval?: b FarmV2QuoterABI, ) - const [getElasticFarmV2, { data, error }] = useLazyQuery(queryFarms, { + const [getElasticFarmV2, { data: subgraphData, error: subgraphError }] = useLazyQuery(queryFarms, { client: elasticClient, fetchPolicy: 'network-only', }) + const [getElasticFarmV2FromKnProtocol, { data: knProtocolData, error: knProtocolError }] = useLazyGetFarmV2Query() + + const latestKnProtocolData = useRef(knProtocolData) + + const data = useMemo(() => { + if (isEnableKNProtocol) { + return { + farmV2S: knProtocolData?.data?.data || latestKnProtocolData.current?.data?.data || [], + } + } else return subgraphData + }, [isEnableKNProtocol, knProtocolData, subgraphData]) + + const error = useMemo(() => { + if (isEnableKNProtocol) return knProtocolError + return subgraphError + }, [isEnableKNProtocol, subgraphError, knProtocolError]) + useEffect(() => { if (isEVM && !elasticFarm?.farms && !elasticFarm?.loading) { dispatch(setLoading({ chainId, loading: true })) - getElasticFarmV2().finally(() => { - dispatch(setLoading({ chainId, loading: false })) - }) + if (isEnableKNProtocol) { + getElasticFarmV2FromKnProtocol(chainId).finally(() => { + dispatch(setLoading({ chainId, loading: false })) + }) + } else + getElasticFarmV2().finally(() => { + dispatch(setLoading({ chainId, loading: false })) + }) } - }, [isEVM, chainId, dispatch, getElasticFarmV2, elasticFarm]) + }, [isEVM, chainId, dispatch, getElasticFarmV2, elasticFarm, getElasticFarmV2FromKnProtocol, isEnableKNProtocol]) useEffect(() => { const i = interval ? setInterval(() => { - getElasticFarmV2() + if (isEnableKNProtocol) getElasticFarmV2FromKnProtocol(chainId) + else getElasticFarmV2() }, 10_000) : undefined return () => { i && clearInterval(i) } - }, [interval, dispatch, getElasticFarmV2]) + }, [interval, chainId, dispatch, getElasticFarmV2, getElasticFarmV2FromKnProtocol, isEnableKNProtocol]) useEffect(() => { if (error && chainId) { @@ -150,7 +175,7 @@ export default function ElasticFarmV2Updater({ interval = true }: { interval?: b useEffect(() => { const getData = async () => { - if (data?.farmV2S && chainId) { + if (data?.farmV2S.length && chainId) { const tokens = [ ...new Set( data.farmV2S @@ -193,23 +218,29 @@ export default function ElasticFarmV2Updater({ interval = true }: { interval?: b farm.pool.reinvestL, Number(farm.pool.tick), ) - let tvlToken0 = CurrencyAmount.fromRawAmount(token0.wrapped, 0) - let tvlToken1 = CurrencyAmount.fromRawAmount(token1.wrapped, 0) - - farm.depositedPositions.forEach(pos => { - const position = new Position({ - pool: p, - liquidity: pos.position.liquidity, - tickLower: Number(pos.position.tickLower.tickIdx), - tickUpper: Number(pos.position.tickUpper.tickIdx), - }) - tvlToken0 = tvlToken0.add(position.amount0) - tvlToken1 = tvlToken1.add(position.amount1) - }) - const tvl = - Number(tvlToken0.toExact() || '0') * (prices[farm.pool.token0.id] || 0) + - Number(tvlToken1.toExact() || '0') * (prices[farm.pool.token1.id] || 0) + let tvl = 0 + if (farm.stakedTvl) { + tvl = +farm.stakedTvl + } else { + let tvlToken0 = CurrencyAmount.fromRawAmount(token0.wrapped, 0) + let tvlToken1 = CurrencyAmount.fromRawAmount(token1.wrapped, 0) + + farm.depositedPositions?.forEach(pos => { + const position = new Position({ + pool: p, + liquidity: pos.position.liquidity, + tickLower: Number(pos.position.tickLower.tickIdx), + tickUpper: Number(pos.position.tickUpper.tickIdx), + }) + + tvlToken0 = tvlToken0.add(position.amount0) + tvlToken1 = tvlToken1.add(position.amount1) + }) + tvl = + Number(tvlToken0.toExact() || '0') * (prices[farm.pool.token0.id] || 0) + + Number(tvlToken1.toExact() || '0') * (prices[farm.pool.token1.id] || 0) + } const totalRewards = farm.rewards.map(item => CurrencyAmount.fromRawAmount(getToken(item.token, true), item.amount), @@ -227,8 +258,6 @@ export default function ElasticFarmV2Updater({ interval = true }: { interval?: b token0, token1, totalRewards, - tvlToken0, - tvlToken1, tvl, ranges: farm.ranges.map(r => { // https://www.notion.so/kybernetwork/LM-v2-APR-Formula-15b8606e820745b59a5a3aded8bf46e0 diff --git a/src/state/index.ts b/src/state/index.ts index 2d505c263e..caffdcdc0c 100644 --- a/src/state/index.ts +++ b/src/state/index.ts @@ -16,6 +16,7 @@ import crosschainApi from '../services/crossChain' import earningApi from '../services/earning' import geckoTerminalApi from '../services/geckoTermial' import identifyApi from '../services/identity' +import knProtocolApi from '../services/knprotocol' import ksSettingApi from '../services/ksSetting' import kyberDAO from '../services/kyberDAO' import limitOrderApi from '../services/limitOrder' @@ -118,6 +119,7 @@ const store = configureStore({ [tokenApi.reducerPath]: tokenApi.reducer, [socialApi.reducerPath]: socialApi.reducer, [blockServiceApi.reducerPath]: blockServiceApi.reducer, + [knProtocolApi.reducerPath]: knProtocolApi.reducer, }, middleware: getDefaultMiddleware => getDefaultMiddleware({ thunk: true, immutableCheck: false, serializableCheck: false }) @@ -138,7 +140,8 @@ const store = configureStore({ .concat(earningApi.middleware) .concat(socialApi.middleware) .concat(tokenApi.middleware) - .concat(blockServiceApi.middleware), + .concat(blockServiceApi.middleware) + .concat(knProtocolApi.middleware), preloadedState, }) diff --git a/src/state/prommPools/useGetElasticPools/index.ts b/src/state/prommPools/useGetElasticPools/index.ts index f78f657c1f..127cda4f38 100644 --- a/src/state/prommPools/useGetElasticPools/index.ts +++ b/src/state/prommPools/useGetElasticPools/index.ts @@ -1,5 +1,4 @@ -import { CHAINS_SUPPORT_NEW_POOL_FARM_API } from 'constants/networks' -import { useActiveWeb3React } from 'hooks' +import { useKyberSwapConfig } from 'state/application/hooks' import { ElasticPoolDetail } from 'types/pool' import useGetElasticPoolsV1 from './useGetElasticPoolsV1' @@ -14,13 +13,12 @@ export type CommonReturn = { } const useGetElasticPools = (poolAddresses: string[]): CommonReturn => { - const { chainId } = useActiveWeb3React() + const { isEnableKNProtocol } = useKyberSwapConfig() - const shouldRunV2 = CHAINS_SUPPORT_NEW_POOL_FARM_API.includes(chainId) - const responseV1 = useGetElasticPoolsV1(poolAddresses, shouldRunV2) + const responseV1 = useGetElasticPoolsV1(poolAddresses) const responseV2 = useGetElasticPoolsV2() - if (shouldRunV2) { + if (isEnableKNProtocol) { return responseV2 } diff --git a/src/state/prommPools/useGetElasticPools/useGetElasticPoolsV1.ts b/src/state/prommPools/useGetElasticPools/useGetElasticPoolsV1.ts index 790ca9f6bc..512f9120f9 100644 --- a/src/state/prommPools/useGetElasticPools/useGetElasticPoolsV1.ts +++ b/src/state/prommPools/useGetElasticPools/useGetElasticPoolsV1.ts @@ -124,15 +124,15 @@ const parsedPoolData = ( return formatted } -const useGetElasticPoolsV1 = (poolAddresses: string[], skip?: boolean): CommonReturn => { - const { elasticClient } = useKyberSwapConfig() +const useGetElasticPoolsV1 = (poolAddresses: string[]): CommonReturn => { + const { elasticClient, isEnableKNProtocol } = useKyberSwapConfig() const { blockLast24h } = usePoolBlocks() const { loading, error, data } = useQuery(PROMM_POOLS_BULK(undefined, poolAddresses), { client: elasticClient, fetchPolicy: 'no-cache', - skip, + skip: isEnableKNProtocol, }) const { @@ -142,7 +142,7 @@ const useGetElasticPoolsV1 = (poolAddresses: string[], skip?: boolean): CommonRe } = useQuery(PROMM_POOLS_BULK(blockLast24h, poolAddresses), { client: elasticClient, fetchPolicy: 'no-cache', - skip, + skip: isEnableKNProtocol, }) const anyError = error24?.message.includes('Failed to decode `block.number`') diff --git a/src/state/prommPools/useGetElasticPools/useGetElasticPoolsV2.ts b/src/state/prommPools/useGetElasticPools/useGetElasticPoolsV2.ts index cdd34eeede..f071b96f8a 100644 --- a/src/state/prommPools/useGetElasticPools/useGetElasticPoolsV2.ts +++ b/src/state/prommPools/useGetElasticPools/useGetElasticPoolsV2.ts @@ -1,8 +1,9 @@ import useSWRImmutable from 'swr/immutable' import { POOL_FARM_BASE_URL } from 'constants/env' -import { CHAINS_SUPPORT_NEW_POOL_FARM_API, NETWORKS_INFO, isEVM } from 'constants/networks' +import { NETWORKS_INFO, isEVM } from 'constants/networks' import { useActiveWeb3React } from 'hooks' +import { useKyberSwapConfig } from 'state/application/hooks' import { ElasticPoolDetail } from 'types/pool' import { CommonReturn } from '.' @@ -50,20 +51,20 @@ type PoolAccumulator = { [address: string]: ElasticPoolDetail } const useGetElasticPoolsV2 = (): CommonReturn => { const { chainId } = useActiveWeb3React() + const { isEnableKNProtocol } = useKyberSwapConfig() - const shouldSkip = !isEVM(chainId) || !CHAINS_SUPPORT_NEW_POOL_FARM_API.includes(chainId) const chainRoute = !isEVM(chainId) || NETWORKS_INFO[chainId].poolFarmRoute const { isValidating, error, data } = useSWRImmutable( - `${POOL_FARM_BASE_URL}/${chainRoute}/api/v1/elastic-new/pools?includeLowTvl=true&page=1&perPage=10000`, + `${POOL_FARM_BASE_URL}/${chainRoute}/api/v1/elastic-new/pools?includeLowTvl=true&page=1&perPage=10000&thisParamToForceRefresh=${isEnableKNProtocol}`, async (url: string) => { - if (shouldSkip) { + if (!isEnableKNProtocol) { return Promise.resolve({}) } return fetch(url).then(resp => resp.json()) }, { - refreshInterval: shouldSkip ? 0 : 60_000, + refreshInterval: isEnableKNProtocol ? 0 : 60_000, }, ) diff --git a/src/utils/tokenInfo.ts b/src/utils/tokenInfo.ts index bfeb5844cd..53328f997e 100644 --- a/src/utils/tokenInfo.ts +++ b/src/utils/tokenInfo.ts @@ -59,6 +59,8 @@ export const getTokenSymbolWithHardcode = ( return 'mKNC' } if (chainId === ChainId.ARBITRUM && formatAddress === '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8') return 'USDC.e' + if (chainId === ChainId.ARBITRUM && formatAddress === '0x9cfb13e6c11054ac9fcb92ba89644f30775436e4') + return 'axl.wstETH' return defaultSymbol ?? '' }