diff --git a/packages/app/src/sections/dashboard/RewardsTab.tsx b/packages/app/src/sections/dashboard/RewardsTab.tsx index e0101612a1..7df173ee48 100644 --- a/packages/app/src/sections/dashboard/RewardsTab.tsx +++ b/packages/app/src/sections/dashboard/RewardsTab.tsx @@ -1,5 +1,5 @@ import { ZERO_WEI } from '@kwenta/sdk/constants' -import { formatDollars, formatPercent, truncateNumbers } from '@kwenta/sdk/utils' +import { formatDollars, formatNumber, formatPercent } from '@kwenta/sdk/utils' import { wei } from '@synthetixio/wei' import { FC, useCallback, useMemo } from 'react' import { useTranslation } from 'react-i18next' @@ -13,7 +13,7 @@ import { Body, Heading } from 'components/Text' import { EXTERNAL_LINKS } from 'constants/links' import { NO_VALUE } from 'constants/placeholder' import useIsL2 from 'hooks/useIsL2' -import { TradingRewardProps, useEstimatedReward } from 'queries/staking/utils' +import { TradingRewardProps } from 'queries/staking/utils' import { StakingCard } from 'sections/dashboard/Stake/card' import { selectFuturesFees, selectFuturesFeesForAccount } from 'state/futures/selectors' import { useAppDispatch, useAppSelector } from 'state/hooks' @@ -21,6 +21,8 @@ import { claimMultipleAllRewards } from 'state/staking/actions' import { setSelectedEpoch } from 'state/staking/reducer' import { selectEpochData, + selectEstimatedKwentaRewards, + selectEstimatedOpRewards, selectKwentaRewards, selectOpRewards, selectSelectedEpoch, @@ -44,6 +46,8 @@ const RewardsTab: FC = ({ period = 0 }) => { const kwentaRewards = useAppSelector(selectKwentaRewards) const opRewards = useAppSelector(selectOpRewards) const snxOpRewards = useAppSelector(selectSnxOpRewards) + const estimatedKwentaRewards = useAppSelector(selectEstimatedKwentaRewards) + const estimatedOpRewards = useAppSelector(selectEstimatedOpRewards) const futuresFeePaid = useAppSelector(selectFuturesFeesForAccount) const totalFuturesFeePaid = useAppSelector(selectFuturesFees) @@ -51,9 +55,6 @@ const RewardsTab: FC = ({ period = 0 }) => { dispatch(claimMultipleAllRewards()) }, [dispatch]) - const estimatedKwentaReward = useEstimatedReward('epoch-current.json') - const estimatedOp = useEstimatedReward('epoch-current-op.json') - const claimDisabledAll = useMemo( () => kwentaRewards.add(opRewards).add(snxOpRewards).lte(0), [opRewards, snxOpRewards, kwentaRewards] @@ -74,7 +75,7 @@ const RewardsTab: FC = ({ period = 0 }) => { labels: [ { label: t('dashboard.stake.portfolio.rewards.title'), - value: truncateNumbers(kwentaRewards, 4), + value: formatNumber(kwentaRewards, { minDecimals: 4 }), }, { label: t('dashboard.stake.tabs.trading-rewards.fee-paid'), @@ -96,7 +97,7 @@ const RewardsTab: FC = ({ period = 0 }) => { }, { label: t('dashboard.rewards.estimated'), - value: truncateNumbers(wei(estimatedKwentaReward ?? ZERO_WEI), 4), + value: formatNumber(estimatedKwentaRewards, { minDecimals: 4 }), }, ], kwentaIcon: true, @@ -109,13 +110,13 @@ const RewardsTab: FC = ({ period = 0 }) => { labels: [ { label: t('dashboard.stake.portfolio.rewards.title'), - value: truncateNumbers(wei(opRewards ?? ZERO_WEI), 4), + value: formatNumber(opRewards, { minDecimals: 4 }), }, ], info: [ { label: t('dashboard.rewards.estimated'), - value: truncateNumbers(wei(estimatedOp ?? ZERO_WEI), 4), + value: formatNumber(estimatedOpRewards, { minDecimals: 4 }), }, ], kwentaIcon: false, @@ -128,7 +129,7 @@ const RewardsTab: FC = ({ period = 0 }) => { labels: [ { label: t('dashboard.stake.portfolio.rewards.title'), - value: truncateNumbers(wei(snxOpRewards ?? ZERO_WEI), 4), + value: formatNumber(snxOpRewards, { minDecimals: 4 }), }, ], info: [ @@ -142,8 +143,8 @@ const RewardsTab: FC = ({ period = 0 }) => { }, ], [ - estimatedKwentaReward, - estimatedOp, + estimatedKwentaRewards, + estimatedOpRewards, futuresFeePaid, kwentaRewards, opRewards, diff --git a/packages/app/src/state/staking/actions.ts b/packages/app/src/state/staking/actions.ts index 0a3ba9815b..894a23b5b1 100644 --- a/packages/app/src/state/staking/actions.ts +++ b/packages/app/src/state/staking/actions.ts @@ -102,7 +102,7 @@ export const approveKwentaToken = createAsyncThunk< monitorTransaction({ txHash: hash, onTxConfirmed: () => { - dispatch(fetchStakingData()) + dispatch(fetchStakeMigrateData()) }, }) }) @@ -118,7 +118,7 @@ export const redeemToken = createAsyncThunk { - dispatch(fetchStakingData()) + dispatch(fetchStakeMigrateData()) }, }) } @@ -160,6 +160,18 @@ export const fetchEscrowV2Data = createAsyncThunk< } }) +export const fetchEstimatedRewards = createAsyncThunk< + { estimatedKwentaRewards: string; estimatedOpRewards: string }, + void, + ThunkConfig +>('staking/fetchEstimatedRewards', async (_, { extra: { sdk } }) => { + const { estimatedKwentaRewards, estimatedOpRewards } = await sdk.kwentaToken.getEstimatedRewards() + return { + estimatedKwentaRewards: estimatedKwentaRewards.toString(), + estimatedOpRewards: estimatedOpRewards.toString(), + } +}) + export const fetchStakeMigrateData = createAsyncThunk( 'stakeMigrateData/fetch', async (_, { dispatch }) => { @@ -168,6 +180,7 @@ export const fetchStakeMigrateData = createAsyncThunk( dispatch(fetchStakingV2Data()) dispatch(fetchEscrowData()) dispatch(fetchEscrowV2Data()) + dispatch(fetchEstimatedRewards()) } ) diff --git a/packages/app/src/state/staking/reducer.ts b/packages/app/src/state/staking/reducer.ts index 7ecb2827ec..737eb1700a 100644 --- a/packages/app/src/state/staking/reducer.ts +++ b/packages/app/src/state/staking/reducer.ts @@ -18,6 +18,7 @@ import { vestEscrowedRewards, fetchStakingV2Data, fetchEscrowV2Data, + fetchEstimatedRewards, } from './actions' import { StakingState } from './types' @@ -49,6 +50,8 @@ export const STAKING_INITIAL_STATE: StakingState = { kwentaRewards: '0', opRewards: '0', snxOpRewards: '0', + estimatedKwentaRewards: '0', + estimatedOpRewards: '0', claimableKwentaRewards: [], claimableOpRewards: [], claimableSnxOpRewards: [], @@ -147,6 +150,10 @@ const stakingSlice = createSlice({ state.opRewards = action.payload.opRewards state.snxOpRewards = action.payload.snxOpRewards }) + builder.addCase(fetchEstimatedRewards.fulfilled, (state, action) => { + state.estimatedKwentaRewards = action.payload.estimatedKwentaRewards + state.estimatedOpRewards = action.payload.estimatedOpRewards + }) builder.addCase(stakeKwenta.pending, (state) => { state.stakeStatus = FetchStatus.Loading }) diff --git a/packages/app/src/state/staking/selectors.ts b/packages/app/src/state/staking/selectors.ts index a15eedb866..a2fa437f28 100644 --- a/packages/app/src/state/staking/selectors.ts +++ b/packages/app/src/state/staking/selectors.ts @@ -196,6 +196,16 @@ export const selectSnxOpRewards = createSelector( wei ) +export const selectEstimatedKwentaRewards = createSelector( + (state: RootState) => state.staking.estimatedKwentaRewards, + wei +) + +export const selectEstimatedOpRewards = createSelector( + (state: RootState) => state.staking.estimatedOpRewards, + wei +) + export const selectTotalVestable = createSelector( (state: RootState) => state.staking.totalVestable, wei diff --git a/packages/app/src/state/staking/types.ts b/packages/app/src/state/staking/types.ts index 51c4200755..cd9e557f37 100644 --- a/packages/app/src/state/staking/types.ts +++ b/packages/app/src/state/staking/types.ts @@ -30,6 +30,8 @@ export type StakingState = { kwentaRewards: string opRewards: string snxOpRewards: string + estimatedKwentaRewards: string + estimatedOpRewards: string claimableKwentaRewards: ClaimParams[][] claimableOpRewards: ClaimParams[] claimableSnxOpRewards: ClaimParams[] diff --git a/packages/sdk/src/services/kwentaToken.ts b/packages/sdk/src/services/kwentaToken.ts index fe20ae1de6..c128015318 100644 --- a/packages/sdk/src/services/kwentaToken.ts +++ b/packages/sdk/src/services/kwentaToken.ts @@ -500,6 +500,32 @@ export default class KwentaTokenService { return this.performStakeAction('unstake', amount, { escrow: true, version: 2 }) } + public async getEstimatedRewards() { + const { networkId, walletAddress } = this.sdk.context + const fileNames = ['', '-op'].map( + (i) => `trading-rewards-snapshots/${networkId === 420 ? 'goerli-' : ''}epoch-current${i}.json` + ) + + const responses: EpochData[] = await Promise.all( + fileNames.map(async (fileName) => { + const response = await client.get(fileName) + return { ...response.data } + }) + ) + + const [estimatedKwentaRewards, estimatedOpRewards] = responses.map((d) => { + const reward = d.claims[walletAddress] + + if (reward) { + return weiFromWei(reward.amount) + } + + return ZERO_WEI + }) + + return { estimatedKwentaRewards, estimatedOpRewards } + } + public async getClaimableRewards(epochPeriod: number, isOldDistributor: boolean = true) { const { MultipleMerkleDistributor, MultipleMerkleDistributorPerpsV2 } = this.sdk.context.multicallContracts