Skip to content

Commit

Permalink
fix(trading): rewards page updates (#5437)
Browse files Browse the repository at this point in the history
Co-authored-by: Matthew Russell <[email protected]>
  • Loading branch information
MadalinaRaicu and mattrussell36 authored Dec 6, 2023
1 parent a52e60d commit 3cd393d
Show file tree
Hide file tree
Showing 5 changed files with 328 additions and 53 deletions.
171 changes: 130 additions & 41 deletions apps/trading/components/rewards-container/rewards-container.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import groupBy from 'lodash/groupBy';
import uniq from 'lodash/uniq';
import type { Account } from '@vegaprotocol/accounts';
import { useAccounts } from '@vegaprotocol/accounts';
import {
Expand Down Expand Up @@ -31,6 +32,12 @@ import { ViewType, useSidebar } from '../sidebar';
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
import { RewardsHistoryContainer } from './rewards-history';
import { useT } from '../../lib/use-t';
import { useAssetsMapProvider } from '@vegaprotocol/assets';

const ASSETS_WITH_INCORRECT_VESTING_REWARD_DATA = [
'bf1e88d19db4b3ca0d1d5bdb73718a01686b18cf731ca26adedf3c8b83802bba', // USDT mainnet
'8ba0b10971f0c4747746cd01ff05a53ae75ca91eba1d4d050b527910c983e27e', // USDT testnet
];

export const RewardsContainer = () => {
const t = useT();
Expand All @@ -40,34 +47,67 @@ export const RewardsContainer = () => {
NetworkParams.rewards_activityStreak_benefitTiers,
NetworkParams.rewards_vesting_baseRate,
]);

const { data: accounts, loading: accountsLoading } = useAccounts(pubKey);

const { data: assetMap } = useAssetsMapProvider();

const { data: epochData } = useRewardsEpochQuery();

// No need to specify the fromEpoch as it will by default give you the last
// Note activityStreak in query will fail
const { data: rewardsData, loading: rewardsLoading } = useRewardsPageQuery({
variables: {
partyId: pubKey || '',
},
// Inclusion of activity streak in query currently fails
errorPolicy: 'ignore',
});

if (!epochData?.epoch) return null;
if (!epochData?.epoch || !assetMap) return null;

const loading = paramsLoading || accountsLoading || rewardsLoading;

const rewardAccounts = accounts
? accounts.filter((a) =>
[
AccountType.ACCOUNT_TYPE_VESTED_REWARDS,
AccountType.ACCOUNT_TYPE_VESTING_REWARDS,
].includes(a.type)
? accounts
.filter((a) =>
[
AccountType.ACCOUNT_TYPE_VESTED_REWARDS,
AccountType.ACCOUNT_TYPE_VESTING_REWARDS,
].includes(a.type)
)
.filter((a) => new BigNumber(a.balance).isGreaterThan(0))
: [];

const rewardAccountsAssetMap = groupBy(rewardAccounts, 'asset.id');

const lockedBalances = rewardsData?.party?.vestingBalancesSummary
.lockedBalances
? rewardsData.party.vestingBalancesSummary.lockedBalances.filter((b) =>
new BigNumber(b.balance).isGreaterThan(0)
)
: [];
const lockedAssetMap = groupBy(lockedBalances, 'asset.id');

const rewardAssetsMap = groupBy(
rewardAccounts.filter((a) => a.asset.id !== params.reward_asset),
'asset.id'
);
const vestingBalances = rewardsData?.party?.vestingBalancesSummary
.vestingBalances
? rewardsData.party.vestingBalancesSummary.vestingBalances.filter((b) =>
new BigNumber(b.balance).isGreaterThan(0)
)
: [];
const vestingAssetMap = groupBy(vestingBalances, 'asset.id');

// each asset reward pot is made up of:
// available to withdraw - ACCOUNT_TYPE_VESTED_REWARDS
// vesting - vestingBalancesSummary.vestingBalances
// locked - vestingBalancesSummary.lockedBalances
//
// there can be entires for the same asset in each list so we need a uniq list of assets
const assets = uniq([
...Object.keys(rewardAccountsAssetMap),
...Object.keys(lockedAssetMap),
...Object.keys(vestingAssetMap),
]);

return (
<div className="grid auto-rows-min grid-cols-6 gap-3">
Expand Down Expand Up @@ -117,28 +157,72 @@ export const RewardsContainer = () => {
</Card>

{/* Show all other reward pots, most of the time users will not have other rewards */}
{Object.keys(rewardAssetsMap).map((assetId) => {
const asset = rewardAssetsMap[assetId][0].asset;
return (
<Card
key={assetId}
title={t('{{assetSymbol}} Reward pot', {
assetSymbol: asset.symbol,
})}
className="lg:col-span-3 xl:col-span-2"
loading={loading}
>
<RewardPot
pubKey={pubKey}
accounts={accounts}
assetId={assetId}
vestingBalancesSummary={
rewardsData?.party?.vestingBalancesSummary
}
/>
</Card>
);
})}
{assets
.filter((assetId) => assetId !== params.reward_asset)
.map((assetId) => {
const asset = assetMap ? assetMap[assetId] : null;

if (!asset) return null;

// Following code is for mitigating an issue due to a core bug where locked and vesting
// balances were incorrectly increased for infrastructure rewards for USDT on mainnet
//
// We don't want to incorrectly show the wring locked/vesting values, but we DO want to
// show the user that they have rewards available to withdraw
if (ASSETS_WITH_INCORRECT_VESTING_REWARD_DATA.includes(asset.id)) {
const accountsForAsset = rewardAccountsAssetMap[asset.id];
const vestedAccount = accountsForAsset?.find(
(a) => a.type === AccountType.ACCOUNT_TYPE_VESTED_REWARDS
);

// No vested rewards available to withdraw, so skip over USDT
if (!vestedAccount || Number(vestedAccount.balance) <= 0) {
return null;
}

return (
<Card
key={assetId}
title={t('{{assetSymbol}} Reward pot', {
assetSymbol: asset.symbol,
})}
className="lg:col-span-3 xl:col-span-2"
loading={loading}
>
<RewardPot
pubKey={pubKey}
accounts={accounts}
assetId={assetId}
// Ensure that these values are shown as 0
vestingBalancesSummary={{
lockedBalances: [],
vestingBalances: [],
}}
/>
</Card>
);
}

return (
<Card
key={assetId}
title={t('{{assetSymbol}} Reward pot', {
assetSymbol: asset.symbol,
})}
className="lg:col-span-3 xl:col-span-2"
loading={loading}
>
<RewardPot
pubKey={pubKey}
accounts={accounts}
assetId={assetId}
vestingBalancesSummary={
rewardsData?.party?.vestingBalancesSummary
}
/>
</Card>
);
})}
<Card
title={t('Rewards history')}
className="lg:col-span-full"
Expand All @@ -147,6 +231,7 @@ export const RewardsContainer = () => {
<RewardsHistoryContainer
epoch={Number(epochData?.epoch.id)}
pubKey={pubKey}
assets={assetMap}
/>
</Card>
</div>
Expand Down Expand Up @@ -313,14 +398,14 @@ export const RewardPot = ({
export const Vesting = ({
pubKey,
baseRate,
multiplier = '1',
multiplier,
}: {
pubKey: string | null;
baseRate: string;
multiplier?: string;
}) => {
const t = useT();
const rate = new BigNumber(baseRate).times(multiplier);
const rate = new BigNumber(baseRate).times(multiplier || 1);
const rateFormatted = formatPercentage(Number(rate));
const baseRateFormatted = formatPercentage(Number(baseRate));

Expand All @@ -335,7 +420,7 @@ export const Vesting = ({
{pubKey && (
<tr>
<CardTableTH>{t('Vesting multiplier')}</CardTableTH>
<CardTableTD>{multiplier}x</CardTableTD>
<CardTableTD>{multiplier ? `${multiplier}x` : '-'}</CardTableTD>
</tr>
)}
</CardTable>
Expand All @@ -345,16 +430,16 @@ export const Vesting = ({

export const Multipliers = ({
pubKey,
streakMultiplier = '1',
hoarderMultiplier = '1',
streakMultiplier,
hoarderMultiplier,
}: {
pubKey: string | null;
streakMultiplier?: string;
hoarderMultiplier?: string;
}) => {
const t = useT();
const combinedMultiplier = new BigNumber(streakMultiplier).times(
hoarderMultiplier
const combinedMultiplier = new BigNumber(streakMultiplier || 1).times(
hoarderMultiplier || 1
);

if (!pubKey) {
Expand All @@ -375,11 +460,15 @@ export const Multipliers = ({
<CardTable>
<tr>
<CardTableTH>{t('Streak reward multiplier')}</CardTableTH>
<CardTableTD>{streakMultiplier}x</CardTableTD>
<CardTableTD>
{streakMultiplier ? `${streakMultiplier}x` : '-'}
</CardTableTD>
</tr>
<tr>
<CardTableTH>{t('Hoarder reward multiplier')}</CardTableTH>
<CardTableTD>{hoarderMultiplier}x</CardTableTD>
<CardTableTD>
{hoarderMultiplier ? `${hoarderMultiplier}x` : '-'}
</CardTableTD>
</tr>
</CardTable>
</div>
Expand Down
26 changes: 22 additions & 4 deletions apps/trading/components/rewards-container/rewards-history.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ const rewardSummaries = [
rewardType: AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
},
},
{
node: {
epoch: 7,
assetId: assets.asset2.id,
amount: '300',
rewardType: AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
},
},
];

const getCell = (cells: HTMLElement[], colId: string) => {
Expand All @@ -69,7 +77,7 @@ const getCell = (cells: HTMLElement[], colId: string) => {
);
};

describe('RewarsHistoryTable', () => {
describe('RewardsHistoryTable', () => {
const props = {
epochRewardSummaries: {
edges: rewardSummaries,
Expand All @@ -88,7 +96,7 @@ describe('RewarsHistoryTable', () => {
loading: false,
};

it('Renders table with accounts summed up by asset', () => {
it('renders table with accounts summed up by asset', () => {
render(<RewardHistoryTable {...props} />);

const container = within(
Expand All @@ -110,17 +118,27 @@ describe('RewarsHistoryTable', () => {
assets.asset2.name
);

// First row
const marketCreationCell = getCell(cells, 'marketCreation');
expect(
marketCreationCell.getByTestId('stack-cell-primary')
).toHaveTextContent('300');
expect(
marketCreationCell.getByTestId('stack-cell-secondary')
).toHaveTextContent('100.00%');
).toHaveTextContent('50.00%');

const infrastructureFeesCell = getCell(cells, 'infrastructureFees');
expect(
infrastructureFeesCell.getByTestId('stack-cell-primary')
).toHaveTextContent('300');
expect(
infrastructureFeesCell.getByTestId('stack-cell-secondary')
).toHaveTextContent('50.00%');

let totalCell = getCell(cells, 'total');
expect(totalCell.getByText('300.00')).toBeInTheDocument();
expect(totalCell.getByText('600.00')).toBeInTheDocument();

// Second row
row = within(rows[1]);
cells = row.getAllByRole('gridcell');

Expand Down
16 changes: 10 additions & 6 deletions apps/trading/components/rewards-container/rewards-history.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ import debounce from 'lodash/debounce';
import { useMemo, useState } from 'react';
import BigNumber from 'bignumber.js';
import type { ColDef, ValueFormatterFunc } from 'ag-grid-community';
import {
useAssetsMapProvider,
type AssetFieldsFragment,
} from '@vegaprotocol/assets';
import { type AssetFieldsFragment } from '@vegaprotocol/assets';
import {
addDecimalsFormatNumberQuantum,
formatNumberPercentage,
Expand All @@ -26,17 +23,17 @@ import { useT } from '../../lib/use-t';
export const RewardsHistoryContainer = ({
epoch,
pubKey,
assets,
}: {
pubKey: string | null;
epoch: number;
assets: Record<string, AssetFieldsFragment>;
}) => {
const [epochVariables, setEpochVariables] = useState(() => ({
from: epoch - 1,
to: epoch,
}));

const { data: assets } = useAssetsMapProvider();

// No need to specify the fromEpoch as it will by default give you the last
const { refetch, data, loading } = useRewardsHistoryQuery({
variables: {
Expand Down Expand Up @@ -154,10 +151,12 @@ export const RewardHistoryTable = ({
const rewardValueFormatter: ValueFormatterFunc<RewardRow> = ({
data,
value,
...rest
}) => {
if (!value || !data) {
return '-';
}

return addDecimalsFormatNumberQuantum(
value,
data.asset.decimals,
Expand Down Expand Up @@ -197,6 +196,11 @@ export const RewardHistoryTable = ({
},
sort: 'desc',
},
{
field: 'infrastructureFees',
valueFormatter: rewardValueFormatter,
cellRenderer: rewardCellRenderer,
},
{
field: 'staking',
valueFormatter: rewardValueFormatter,
Expand Down
Loading

0 comments on commit 3cd393d

Please sign in to comment.