diff --git a/src/pages/account/Rewards/Rewards.tsx b/src/pages/account/Rewards/Rewards.tsx index 06d9cc855..5635dc5b0 100644 --- a/src/pages/account/Rewards/Rewards.tsx +++ b/src/pages/account/Rewards/Rewards.tsx @@ -9,7 +9,12 @@ import { TokenAmount } from '@components/TokenAmount'; import { Spinner, Typography } from '@subql/components'; import { TableTitle } from '@subql/components'; import { GetEraRewardsByIndexerAndPageQuery } from '@subql/network-query'; -import { renderAsync, useGetEraRewardsByIndexerAndPageLazyQuery, useGetRewardsQuery } from '@subql/react-hooks'; +import { + renderAsync, + useGetEraRewardsByIndexerAndPageLazyQuery, + useGetFilteredDelegationsQuery, + useGetRewardsQuery, +} from '@subql/react-hooks'; import { ExcludeNull, formatEther, notEmpty } from '@utils'; import { useMount, useUpdate } from 'ahooks'; import { Table, TableProps, Tag, Tooltip } from 'antd'; @@ -17,12 +22,15 @@ import dayjs from 'dayjs'; import { BigNumber } from 'ethers'; import { useAccount } from 'wagmi'; +import { useWeb3Store } from 'src/stores'; + import { ClaimRewards } from './ClaimRewards'; import styles from './Rewards.module.css'; export const Rewards: React.FC = () => { const { address: account } = useAccount(); + const { contracts } = useWeb3Store(); const update = useUpdate(); const filterParams = { address: account || '' }; const rewards = useGetRewardsQuery({ variables: filterParams, fetchPolicy: 'network-only' }); @@ -110,6 +118,64 @@ export const Rewards: React.FC = () => { update(); }; + // this is a hotfix for unclaimed rewards. + const [unClaimedRewardsFromContracts, setUnClaimedRewardsFromContracts] = React.useState<{ + indexers: string[]; + amount: BigNumber; + }>({ + indexers: [], + amount: BigNumber.from(0), + }); + const delegations = useGetFilteredDelegationsQuery({ + variables: { delegator: account ?? '', filterIndexer: account ?? '', offset: 0 }, + }); + const indexerIds = React.useMemo(() => { + return delegations.data?.delegations?.nodes + .map((i) => i?.indexerId) + .filter((i) => !unclaimedRewards?.indexers.includes(i)); + }, [delegations.data?.delegations, unclaimedRewards]); + const getUnclaimedRewards = async () => { + if (!account || !contracts || !indexerIds?.length) return; + + const inner = async (indexerId: string | undefined) => { + if (!indexerId) return true; + const res = await contracts?.rewardsDistributor.userRewards(indexerId, account); + return [res, indexerId]; + }; + + const res = await Promise.allSettled(indexerIds.map((indexer) => inner(indexer))); + + const unClaimedRewardsIndexers = res + .map((i) => { + if (i.status === 'fulfilled') { + const [amount, indexerAddress] = i.value as [BigNumber, string]; + + if (!amount.eq(0)) return indexerAddress; + } + + return undefined; + }) + .filter((i) => i); + const unClaimedRewardsAmount = res.reduce((cur, add) => { + if (add.status === 'fulfilled') { + const [amount] = add.value as [BigNumber, string]; + + return cur.add(amount); + } + return cur; + }, BigNumber.from(0)); + + setUnClaimedRewardsFromContracts({ + indexers: unClaimedRewardsIndexers as string[], + amount: unClaimedRewardsAmount, + }); + }; + + React.useEffect(() => { + getUnclaimedRewards(); + }, [indexerIds, account, unclaimedRewards]); + // the above codes is a hotfix + React.useEffect(() => { if (!account) return; queryParams.current.offset = 0; @@ -135,12 +201,19 @@ export const Rewards: React.FC = () => { {t('rewards.info')} - {totalUnclaimedRewards > 0 && unclaimedRewards?.indexers && ( + {(totalUnclaimedRewards > 0 && unclaimedRewards?.indexers) || + unClaimedRewardsFromContracts.indexers.length ? ( + ) : ( + '' )}
@@ -153,7 +226,7 @@ export const Rewards: React.FC = () => { columns={columns} dataSource={filterEmptyData || []} scroll={{ x: 600 }} - rowKey="id" + rowKey={(record) => `${record.eraId}${record.delegatorId}${record.indexerId}`} pagination={{ current: Math.floor(queryParams.current.offset / queryParams.current.pageSize) + 1, pageSize: queryParams.current.pageSize,