diff --git a/src/components/EarningPieChart/index.tsx b/src/components/EarningPieChart/index.tsx index 82c35d204a..604f3ab20b 100644 --- a/src/components/EarningPieChart/index.tsx +++ b/src/components/EarningPieChart/index.tsx @@ -2,6 +2,7 @@ import { ChainId } from '@kyberswap/ks-sdk-core' import { Trans, t } from '@lingui/macro' import { darken, rgba } from 'polished' import { useCallback, useMemo, useState } from 'react' +import { HelpCircle } from 'react-feather' import { PieChart, pieChartDefaultProps } from 'react-minimal-pie-chart' import { Flex, Text } from 'rebass' import styled from 'styled-components' @@ -133,18 +134,7 @@ const Legend: React.FC = ({ justifyContent: 'center', }} > - {logoUrl ? ( - - ) : ( - - )} + {logoUrl ? : } {chainId && ( = ({ poolEarning, chainId }) => {
{myLiquidityBalance}} - disabled={poolEarning.liquidityTokenBalance === '0'} + disabled={poolEarning.liquidityTokenBalanceIncludingStake === '0'} text={
@@ -199,11 +199,24 @@ const Position: React.FC = ({ poolEarning, chainId }) => { } /> - + - + - + ) diff --git a/src/pages/MyEarnings/ClassicPools/SinglePool/index.tsx b/src/pages/MyEarnings/ClassicPools/SinglePool/index.tsx index f6050cec5c..6de5550890 100644 --- a/src/pages/MyEarnings/ClassicPools/SinglePool/index.tsx +++ b/src/pages/MyEarnings/ClassicPools/SinglePool/index.tsx @@ -125,9 +125,10 @@ const SinglePool: React.FC = ({ poolEarning, chainId }) => { visibleCurrency1?.symbol || poolEarning.pool.token1.symbol, ) const myLiquidityBalance = - poolEarning.liquidityTokenBalance !== '0' && poolEarning.pool.totalSupply !== '0' + poolEarning.liquidityTokenBalanceIncludingStake !== '0' && poolEarning.pool.totalSupply !== '0' ? formatDollarAmount( - (+poolEarning.liquidityTokenBalance * +poolEarning.pool.reserveUSD) / +poolEarning.pool.totalSupply, + (+poolEarning.liquidityTokenBalanceIncludingStake * +poolEarning.pool.reserveUSD) / + +poolEarning.pool.totalSupply, ) : '--' @@ -198,8 +199,10 @@ const SinglePool: React.FC = ({ poolEarning, chainId }) => { = ({ poolEarning, chainId }) => { }} > - + + + {NETWORKS_INFO[chainId].name} + = ({ poolEarning, chainId }) => { gap: '8px', }} > - - {visibleCurrency0Symbol} - {visibleCurrency1Symbol} + + + + {visibleCurrency0Symbol} - {visibleCurrency1Symbol} + + - AMP {+poolEarning.pool.amp / 10000} + + + AMP {+poolEarning.pool.amp / 10000} + {isFarmingPool && ( = ({ isLoading, data, className, horizontalLayout }) => { const theme = useTheme() const numberOfTokens = data?.breakdowns.length || 0 + const [tokens, setTokens] = useState<{ [chainId: string]: { [address: string]: WrappedTokenInfo } }>({}) + + const missingTokensByChainId = useMemo(() => { + return ( + data?.breakdowns + .filter(item => (item.address && item.chainId ? item.symbol === '' : false)) + .reduce( + (acc, cur) => { + if (!cur.chainId || !cur.address) return acc + if (acc[cur.chainId]) { + acc[cur.chainId].push(cur as Token) + } else acc[cur.chainId] = [cur as Token] + return acc + }, + {} as { + [key: string]: Array + }, + ) || {} + ) + }, [data]) + + useEffect(() => { + const getData = async () => { + const chainIds = Object.keys(missingTokensByChainId) + const res = await Promise.all( + chainIds.map(chain => { + const missingTokens = missingTokensByChainId[chain].map(item => item.address) + return fetchListTokenByAddresses(missingTokens, +chain) + }), + ) + + setTokens( + chainIds.reduce((acc, id, idx) => { + acc[id] = res[idx].reduce( + (ac, item: WrappedTokenInfo) => ({ ...ac, [item.address]: item }), + {} as { [tokenAddress: string]: WrappedTokenInfo }, + ) + + return acc + }, {} as { [chainId: string]: { [address: string]: WrappedTokenInfo } }), + ) + } + + getData() + }, [missingTokensByChainId]) return ( 5 ? 2 : 1}> @@ -73,7 +130,17 @@ const EarningsBreakdownPanel: React.FC = ({ isLoading, data, className, h ) : ( ({ + ...item, + logoUrl: + item.chainId && item.address && !item.logoUrl + ? tokens[item.chainId]?.[item.address].logoURI + : item.logoUrl, + symbol: + item.chainId && item.address && !item.symbol + ? tokens[item.chainId]?.[item.address].symbol || '' + : item.symbol, + }))} totalValue={formatUSDValue(data.totalValue, true)} /> )} diff --git a/src/pages/MyEarnings/ElasticPools/SinglePosition/EarningView.tsx b/src/pages/MyEarnings/ElasticPools/SinglePosition/EarningView.tsx index 4287084d73..2440eb796d 100644 --- a/src/pages/MyEarnings/ElasticPools/SinglePosition/EarningView.tsx +++ b/src/pages/MyEarnings/ElasticPools/SinglePosition/EarningView.tsx @@ -29,7 +29,12 @@ const EarningView: React.FC = props => { // format pool value const ticks: EarningStatsTick[] | undefined = useMemo(() => { - return calculateEarningStatsTick({ data: positionEarning.historicalEarning, chainId, tokensByChainId, nativeLogo }) + return calculateEarningStatsTick({ + data: positionEarning.historicalEarning, + chainId, + tokensByChainId: tokensByChainId[chainId], + nativeLogo, + }) }, [chainId, positionEarning.historicalEarning, tokensByChainId, nativeLogo]) const earningToday = ticks?.[0] diff --git a/src/pages/MyEarnings/PoolEarningsSection.tsx b/src/pages/MyEarnings/PoolEarningsSection.tsx index 7d936728ed..c508398d40 100644 --- a/src/pages/MyEarnings/PoolEarningsSection.tsx +++ b/src/pages/MyEarnings/PoolEarningsSection.tsx @@ -175,8 +175,13 @@ const PoolEarningsSection: React.FC = ({ historicalEarning, chainId }) => // format pool value const ticks: EarningStatsTick[] | undefined = useMemo(() => { - return calculateEarningStatsTick({ data: historicalEarning, chainId, tokensByChainId, nativeLogo }) - }, [chainId, historicalEarning, tokensByChainId, nativeLogo]) + return calculateEarningStatsTick({ + data: historicalEarning, + chainId, + tokensByChainId: { ...tokensByChainId[chainId], ...tokens }, + nativeLogo, + }) + }, [chainId, historicalEarning, tokensByChainId, nativeLogo, tokens]) if (upToExtraSmall) { return ( diff --git a/src/pages/MyEarnings/styled.tsx b/src/pages/MyEarnings/styled.tsx index 2aba73d535..c85e29ecf4 100644 --- a/src/pages/MyEarnings/styled.tsx +++ b/src/pages/MyEarnings/styled.tsx @@ -44,6 +44,7 @@ export const Row = styled.div` padding: 12px; font-size: 14px; font-weight: 500; + gap: 8px; display: grid; grid-template-columns: 3fr repeat(7, 1fr); diff --git a/src/pages/MyEarnings/utils.ts b/src/pages/MyEarnings/utils.ts index 37eb4abc8e..4ff4819e13 100644 --- a/src/pages/MyEarnings/utils.ts +++ b/src/pages/MyEarnings/utils.ts @@ -10,9 +10,11 @@ import { TokenEarning, } from 'services/earning/types' -import { NETWORKS_INFO, SUPPORTED_NETWORKS_FOR_MY_EARNINGS } from 'constants/networks' +import { ZERO_ADDRESS } from 'constants/index' +import { MAINNET_NETWORKS, NETWORKS_INFO } from 'constants/networks' import { NativeCurrencies } from 'constants/tokens' import { TokenAddressMap } from 'state/lists/reducer' +import { WrappedTokenInfo } from 'state/lists/wrappedTokenInfo' import { EarningStatsTick, EarningsBreakdown } from 'types/myEarnings' import { isAddress } from 'utils' @@ -114,7 +116,7 @@ const fillHistoricalEarningsForTicks = (ticks: EarningStatsTick[] | undefined): return results } -export const chainIdByRoute: Record = SUPPORTED_NETWORKS_FOR_MY_EARNINGS.map(chainId => ({ +export const chainIdByRoute: Record = MAINNET_NETWORKS.map(chainId => ({ route: NETWORKS_INFO[chainId].aggregatorRoute, chainId, })).reduce((acc, { route, chainId }) => { @@ -134,7 +136,7 @@ export const calculateEarningStatsTick = ({ }: { data: HistoricalEarning['historicalEarning'] chainId: ChainId - tokensByChainId: TokenAddressMap + tokensByChainId: { [tokenAddress: string]: WrappedTokenInfo } nativeLogo: string }): EarningStatsTick[] | undefined => { if (!data?.length) { @@ -153,18 +155,22 @@ export const calculateEarningStatsTick = ({ farmRewardsValue: farmRewardsValueUSD, totalValue: poolRewardsValueUSD + farmRewardsValueUSD, tokens: (singlePointData.total || []) - .filter(tokenEarning => { + .map(tokenEarning => { const tokenAddress = isAddress(chainId, tokenEarning.token) - if (!tokenAddress) { - return false + const currency = + tokenEarning.token === ZERO_ADDRESS ? NativeCurrencies[chainId] : tokensByChainId[String(tokenAddress)] + + if (!currency) { + return { + logoUrl: '', + amount: Number(tokenEarning.amountFloat), + amountUSD: Number(tokenEarning.amountUSD), + symbol: '', + chainId, + address: String(tokenAddress), + } } - const currency = tokensByChainId[chainId][tokenAddress] - return !!currency - }) - .map(tokenEarning => { - const tokenAddress = isAddress(chainId, tokenEarning.token) - const currency = tokensByChainId[chainId][String(tokenAddress)] const isNative = currency.isNative || tokenAddress === WETH[chainId].address const symbol = (isNative ? NativeCurrencies[chainId].symbol : currency.symbol) || 'NO SYMBOL' const logoUrl = (isNative ? nativeLogo : currency.logoURI) || '' @@ -204,13 +210,13 @@ export const calculateEarningStatsTick = ({ return ticks } -const mergeTokenEarnings = (earnings: Array): Array => { +const mergeTokenEarnings = (earnings: Array, chainId: ChainId): Array => { const earningByTokenId: Record = {} earnings.forEach(earning => { - const tokenId = earning.token + const tokenId = earning.token === ZERO_ADDRESS ? WETH[chainId].address.toLowerCase() : earning.token if (!earningByTokenId[tokenId]) { - earningByTokenId[tokenId] = cloneDeep(earning) + earningByTokenId[tokenId] = cloneDeep({ ...earning, token: tokenId }) } else { earningByTokenId[tokenId].amountFloat = String( Number(earningByTokenId[tokenId].amountFloat) + Number(earning.amountFloat), @@ -224,7 +230,10 @@ const mergeTokenEarnings = (earnings: Array): Array return Object.values(earningByTokenId) } -const mergeHistoricalEarningsByDay = (historicalData: HistoricalSingleData[]): HistoricalSingleData[] => { +const mergeHistoricalEarningsByDay = ( + historicalData: HistoricalSingleData[], + chainId: ChainId, +): HistoricalSingleData[] => { const dataByDay: Record = {} historicalData.forEach(singlePointData => { @@ -232,8 +241,11 @@ const mergeHistoricalEarningsByDay = (historicalData: HistoricalSingleData[]): H if (!dataByDay[day]) { dataByDay[day] = cloneDeep(singlePointData) } else { - const fees = mergeTokenEarnings([...(dataByDay[day].fees || []), ...(singlePointData.fees || [])]) - const rewards = mergeTokenEarnings([...(dataByDay[day].rewards || []), ...(singlePointData.rewards || [])]) + const fees = mergeTokenEarnings([...(dataByDay[day].fees || []), ...(singlePointData.fees || [])], chainId) + const rewards = mergeTokenEarnings( + [...(dataByDay[day].rewards || []), ...(singlePointData.rewards || [])], + chainId, + ) dataByDay[day].fees = fees dataByDay[day].rewards = rewards @@ -245,7 +257,10 @@ const mergeHistoricalEarningsByDay = (historicalData: HistoricalSingleData[]): H .sort((d1, d2) => d2 - d1) return days.map(day => { - dataByDay[day].total = mergeTokenEarnings([...(dataByDay[day].fees || []), ...(dataByDay[day].rewards || [])]) + dataByDay[day].total = mergeTokenEarnings( + [...(dataByDay[day].fees || []), ...(dataByDay[day].rewards || [])], + chainId, + ) return dataByDay[day] }) } @@ -315,15 +330,16 @@ export const aggregatePositionEarnings = < const chains = Object.keys(draft) chains.forEach(chain => { + const chainId = chainIdByRoute[chain] const { positions } = draft[chain] positions.forEach(position => { const earnings = position.historicalEarning || [] earnings.forEach(earning => { - const fees = mergeTokenEarnings(earning.fees || []) - const rewards = mergeTokenEarnings(earning.rewards || []) - const total = mergeTokenEarnings([...fees, ...rewards]) + const fees = mergeTokenEarnings(earning.fees || [], chainId) + const rewards = mergeTokenEarnings(earning.rewards || [], chainId) + const total = mergeTokenEarnings([...fees, ...rewards], chainId) earning.fees = fees earning.rewards = rewards earning.total = total @@ -346,6 +362,7 @@ export const aggregatePoolEarnings = ( const chains = Object.keys(draft) chains.forEach(chain => { + const chainId = chainIdByRoute[chain] const { positions } = draft[chain] // historical earning data only const byPool: Record = {} @@ -366,7 +383,7 @@ export const aggregatePoolEarnings = ( const poolIds = Object.keys(byPool) const pools = poolIds.map(poolId => { const historicalEarning = fillHistoricalEarningsForEmptyDays( - mergeHistoricalEarningsByDay(byPool[poolId].historicalEarning), + mergeHistoricalEarningsByDay(byPool[poolId].historicalEarning, chainId), ) byPool[poolId].historicalEarning = historicalEarning @@ -401,6 +418,7 @@ export const aggregateAccountEarnings = < chains.forEach(chain => { const { positions } = draft[chain] + const chainId = chainIdByRoute[chain] const byDay: Record = {} positions.forEach(position => { @@ -426,9 +444,9 @@ export const aggregateAccountEarnings = < Object.keys(byDay).forEach(day => { const earning = byDay[day] - const fees = mergeTokenEarnings(earning.fees || []) - const rewards = mergeTokenEarnings(earning.rewards || []) - const total = mergeTokenEarnings([...fees, ...rewards]) + const fees = mergeTokenEarnings(earning.fees || [], chainId) + const rewards = mergeTokenEarnings(earning.rewards || [], chainId) + const total = mergeTokenEarnings([...fees, ...rewards], chainId) earning.fees = fees earning.rewards = rewards earning.total = total @@ -525,18 +543,20 @@ export const calculateTicksOfAccountEarningsInMultipleChains = ( farmRewardsValue: farmRewardsValueUSD, totalValue: poolRewardsValueUSD + farmRewardsValueUSD, tokens: (singleDataPoint.total || []) - .filter(tokenEarning => { - const tokenAddress = isAddress(chainId, tokenEarning.token) - if (!tokenAddress) { - return false - } - - const currency = tokensByChainId[chainId][tokenAddress] - return !!currency - }) .map(tokenEarning => { const tokenAddress = isAddress(chainId, tokenEarning.token) const currency = tokensByChainId[chainId][String(tokenAddress)] + if (!currency) { + return { + logoUrl: '', + amount: Number(tokenEarning.amountFloat), + amountUSD: Number(tokenEarning.amountUSD), + symbol: '', + chainId, + address: String(tokenAddress), + } + } + const isNative = currency.isNative || tokenAddress === WETH[chainId].address const symbol = (isNative ? NativeCurrencies[chainId].symbol : currency.symbol) || 'NO SYMBOL' const logoUrl = (isNative ? NETWORKS_INFO[chainId].nativeToken.logo : currency.logoURI) || '' @@ -602,6 +622,7 @@ export const calculateEarningBreakdowns = ( const breakdowns: EarningsBreakdown['breakdowns'] = tokens.length <= 10 ? tokens.map(data => ({ + address: data.address, chainId: data.chainId, logoUrl: data.logoUrl, symbol: data.symbol, @@ -610,6 +631,7 @@ export const calculateEarningBreakdowns = ( })) : [ ...tokens.slice(0, 9).map(data => ({ + address: data.address, chainId: data.chainId, logoUrl: data.logoUrl, symbol: data.symbol, diff --git a/src/types/myEarnings.ts b/src/types/myEarnings.ts index 89e3a8ec69..5cd19e1e3e 100644 --- a/src/types/myEarnings.ts +++ b/src/types/myEarnings.ts @@ -3,6 +3,7 @@ import { ChainId } from '@kyberswap/ks-sdk-core' export type EarningsBreakdown = { totalValue: number breakdowns: Array<{ + address?: string chainId?: ChainId logoUrl?: string symbol: string