fix(governance): earned by me reward percentage (#4093)
This commit is contained in:
parent
35896a9cf5
commit
0089920d4c
@ -48,15 +48,22 @@ export const EpochIndividualRewards = ({
|
|||||||
return removePaginationWrapper(data.party.rewardsConnection.edges);
|
return removePaginationWrapper(data.party.rewardsConnection.edges);
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
|
const epochRewardSummaries = useMemo(() => {
|
||||||
|
if (!data?.epochRewardSummaries) return [];
|
||||||
|
|
||||||
|
return removePaginationWrapper(data.epochRewardSummaries.edges);
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
const epochIndividualRewardSummaries = useMemo(() => {
|
const epochIndividualRewardSummaries = useMemo(() => {
|
||||||
if (!data?.party) return [];
|
if (!data?.party) return [];
|
||||||
return generateEpochIndividualRewardsList({
|
return generateEpochIndividualRewardsList({
|
||||||
rewards,
|
rewards,
|
||||||
epochId,
|
epochId,
|
||||||
|
epochRewardSummaries,
|
||||||
page,
|
page,
|
||||||
size: EPOCHS_PAGE_SIZE,
|
size: EPOCHS_PAGE_SIZE,
|
||||||
});
|
});
|
||||||
}, [data?.party, epochId, page, rewards]);
|
}, [data?.party, epochId, epochRewardSummaries, page, rewards]);
|
||||||
|
|
||||||
const refetchData = useCallback(
|
const refetchData = useCallback(
|
||||||
async (toPage?: number) => {
|
async (toPage?: number) => {
|
||||||
|
@ -65,7 +65,11 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
|
|
||||||
it('should return an empty array if no rewards are provided', () => {
|
it('should return an empty array if no rewards are provided', () => {
|
||||||
expect(
|
expect(
|
||||||
generateEpochIndividualRewardsList({ rewards: [], epochId: 1 })
|
generateEpochIndividualRewardsList({
|
||||||
|
rewards: [],
|
||||||
|
epochId: 1,
|
||||||
|
epochRewardSummaries: [],
|
||||||
|
})
|
||||||
).toEqual([
|
).toEqual([
|
||||||
{
|
{
|
||||||
epoch: 1,
|
epoch: 1,
|
||||||
@ -78,6 +82,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
const result = generateEpochIndividualRewardsList({
|
const result = generateEpochIndividualRewardsList({
|
||||||
rewards: [rewardWrongType],
|
rewards: [rewardWrongType],
|
||||||
epochId: 1,
|
epochId: 1,
|
||||||
|
epochRewardSummaries: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(result).toEqual([
|
||||||
@ -92,6 +97,15 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
const result = generateEpochIndividualRewardsList({
|
const result = generateEpochIndividualRewardsList({
|
||||||
rewards: [reward1],
|
rewards: [reward1],
|
||||||
epochId: 1,
|
epochId: 1,
|
||||||
|
epochRewardSummaries: [
|
||||||
|
{
|
||||||
|
__typename: 'EpochRewardSummary',
|
||||||
|
epoch: 1,
|
||||||
|
assetId: 'usd',
|
||||||
|
amount: '100000',
|
||||||
|
rewardType: AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result[0]).toEqual({
|
expect(result[0]).toEqual({
|
||||||
@ -134,7 +148,11 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
|
|
||||||
it('should return an array sorted by epoch descending', () => {
|
it('should return an array sorted by epoch descending', () => {
|
||||||
const rewards = [reward1, reward2, reward3, reward4];
|
const rewards = [reward1, reward2, reward3, reward4];
|
||||||
const result1 = generateEpochIndividualRewardsList({ rewards, epochId: 2 });
|
const result1 = generateEpochIndividualRewardsList({
|
||||||
|
rewards,
|
||||||
|
epochId: 2,
|
||||||
|
epochRewardSummaries: [],
|
||||||
|
});
|
||||||
|
|
||||||
expect(result1[0].epoch).toEqual(2);
|
expect(result1[0].epoch).toEqual(2);
|
||||||
expect(result1[1].epoch).toEqual(1);
|
expect(result1[1].epoch).toEqual(1);
|
||||||
@ -143,6 +161,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
const result2 = generateEpochIndividualRewardsList({
|
const result2 = generateEpochIndividualRewardsList({
|
||||||
rewards: reorderedRewards,
|
rewards: reorderedRewards,
|
||||||
epochId: 2,
|
epochId: 2,
|
||||||
|
epochRewardSummaries: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result2[0].epoch).toEqual(2);
|
expect(result2[0].epoch).toEqual(2);
|
||||||
@ -151,7 +170,11 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
|
|
||||||
it('correctly calculates the total value of rewards for an asset', () => {
|
it('correctly calculates the total value of rewards for an asset', () => {
|
||||||
const rewards = [reward1, reward4];
|
const rewards = [reward1, reward4];
|
||||||
const result = generateEpochIndividualRewardsList({ rewards, epochId: 1 });
|
const result = generateEpochIndividualRewardsList({
|
||||||
|
rewards,
|
||||||
|
epochId: 1,
|
||||||
|
epochRewardSummaries: [],
|
||||||
|
});
|
||||||
|
|
||||||
expect(result[0].rewards[0].totalAmount).toEqual('200');
|
expect(result[0].rewards[0].totalAmount).toEqual('200');
|
||||||
});
|
});
|
||||||
@ -159,7 +182,11 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
it('returns data in the expected shape', () => {
|
it('returns data in the expected shape', () => {
|
||||||
// Just sanity checking the whole structure here
|
// Just sanity checking the whole structure here
|
||||||
const rewards = [reward1, reward2, reward3, reward4];
|
const rewards = [reward1, reward2, reward3, reward4];
|
||||||
const result = generateEpochIndividualRewardsList({ rewards, epochId: 2 });
|
const result = generateEpochIndividualRewardsList({
|
||||||
|
rewards,
|
||||||
|
epochId: 2,
|
||||||
|
epochRewardSummaries: [],
|
||||||
|
});
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(result).toEqual([
|
||||||
{
|
{
|
||||||
@ -273,6 +300,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
const resultPageOne = generateEpochIndividualRewardsList({
|
const resultPageOne = generateEpochIndividualRewardsList({
|
||||||
rewards,
|
rewards,
|
||||||
epochId: 3,
|
epochId: 3,
|
||||||
|
epochRewardSummaries: [],
|
||||||
page: 1,
|
page: 1,
|
||||||
size: 2,
|
size: 2,
|
||||||
});
|
});
|
||||||
@ -386,6 +414,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
const resultPageTwo = generateEpochIndividualRewardsList({
|
const resultPageTwo = generateEpochIndividualRewardsList({
|
||||||
rewards,
|
rewards,
|
||||||
epochId: 3,
|
epochId: 3,
|
||||||
|
epochRewardSummaries: [],
|
||||||
page: 2,
|
page: 2,
|
||||||
size: 2,
|
size: 2,
|
||||||
});
|
});
|
||||||
@ -429,4 +458,69 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('correctly calculates the percentage of two or more rewards by referencing the total rewards amount', () => {
|
||||||
|
const result = generateEpochIndividualRewardsList({
|
||||||
|
rewards: [
|
||||||
|
// reward1 is 100 usd, which is 10% of the total rewards amount
|
||||||
|
reward1,
|
||||||
|
{
|
||||||
|
rewardType: AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
|
||||||
|
amount: '200',
|
||||||
|
percentageOfTotal: '0.2',
|
||||||
|
receivedAt: new Date(),
|
||||||
|
asset: { id: 'usd', symbol: 'USD', name: 'USD', decimals: 6 },
|
||||||
|
party: { id: 'blah' },
|
||||||
|
epoch: { id: '1' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
epochId: 1,
|
||||||
|
epochRewardSummaries: [
|
||||||
|
{
|
||||||
|
__typename: 'EpochRewardSummary',
|
||||||
|
epoch: 1,
|
||||||
|
assetId: 'usd',
|
||||||
|
amount: '1000',
|
||||||
|
rewardType: AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result[0]).toEqual({
|
||||||
|
epoch: 1,
|
||||||
|
rewards: [
|
||||||
|
{
|
||||||
|
asset: 'USD',
|
||||||
|
decimals: 6,
|
||||||
|
totalAmount: '300',
|
||||||
|
rewardTypes: {
|
||||||
|
[AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE]: {
|
||||||
|
amount: '0',
|
||||||
|
percentageOfTotal: '0',
|
||||||
|
},
|
||||||
|
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
||||||
|
amount: '0',
|
||||||
|
percentageOfTotal: '0',
|
||||||
|
},
|
||||||
|
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
|
||||||
|
amount: '300',
|
||||||
|
percentageOfTotal: '30',
|
||||||
|
},
|
||||||
|
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES]: {
|
||||||
|
amount: '0',
|
||||||
|
percentageOfTotal: '0',
|
||||||
|
},
|
||||||
|
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES]: {
|
||||||
|
amount: '0',
|
||||||
|
percentageOfTotal: '0',
|
||||||
|
},
|
||||||
|
[AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS]: {
|
||||||
|
amount: '0',
|
||||||
|
percentageOfTotal: '0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import { BigNumber } from '../../../lib/bignumber';
|
import { BigNumber } from '../../../lib/bignumber';
|
||||||
import { RowAccountTypes } from '../shared-rewards-table-assets/shared-rewards-table-assets';
|
import { RowAccountTypes } from '../shared-rewards-table-assets/shared-rewards-table-assets';
|
||||||
import type { RewardFieldsFragment } from '../home/__generated__/Rewards';
|
import type {
|
||||||
|
EpochRewardSummaryFieldsFragment,
|
||||||
|
RewardFieldsFragment,
|
||||||
|
} from '../home/__generated__/Rewards';
|
||||||
import type { AccountType } from '@vegaprotocol/types';
|
import type { AccountType } from '@vegaprotocol/types';
|
||||||
import { calculateEpochOffset } from '../../../lib/epoch-pagination';
|
import { calculateEpochOffset } from '../../../lib/epoch-pagination';
|
||||||
|
|
||||||
@ -32,11 +35,13 @@ const emptyRowAccountTypes = accountTypes.map((type) => [
|
|||||||
export const generateEpochIndividualRewardsList = ({
|
export const generateEpochIndividualRewardsList = ({
|
||||||
rewards,
|
rewards,
|
||||||
epochId,
|
epochId,
|
||||||
|
epochRewardSummaries,
|
||||||
page = 1,
|
page = 1,
|
||||||
size = 10,
|
size = 10,
|
||||||
}: {
|
}: {
|
||||||
rewards: RewardFieldsFragment[];
|
rewards: RewardFieldsFragment[];
|
||||||
epochId: number;
|
epochId: number;
|
||||||
|
epochRewardSummaries: EpochRewardSummaryFieldsFragment[];
|
||||||
page?: number;
|
page?: number;
|
||||||
size?: number;
|
size?: number;
|
||||||
}) => {
|
}) => {
|
||||||
@ -54,6 +59,7 @@ export const generateEpochIndividualRewardsList = ({
|
|||||||
const epochIndividualRewards = rewards.reduce((acc, reward) => {
|
const epochIndividualRewards = rewards.reduce((acc, reward) => {
|
||||||
const epochId = reward.epoch.id;
|
const epochId = reward.epoch.id;
|
||||||
const assetName = reward.asset.name;
|
const assetName = reward.asset.name;
|
||||||
|
const assetId = reward.asset.id;
|
||||||
const assetDecimals = reward.asset.decimals;
|
const assetDecimals = reward.asset.decimals;
|
||||||
const rewardType = reward.rewardType;
|
const rewardType = reward.rewardType;
|
||||||
const amount = reward.amount;
|
const amount = reward.amount;
|
||||||
@ -70,6 +76,14 @@ export const generateEpochIndividualRewardsList = ({
|
|||||||
|
|
||||||
const epoch = acc.get(epochId);
|
const epoch = acc.get(epochId);
|
||||||
|
|
||||||
|
// matchingTotalReward is the total awarded for all users for the reward type in the epoch of the asset
|
||||||
|
const matchingTotalRewardAmount = epochRewardSummaries.find(
|
||||||
|
(summary) =>
|
||||||
|
summary.epoch === Number(epochId) &&
|
||||||
|
summary.assetId === assetId &&
|
||||||
|
summary.rewardType === rewardType
|
||||||
|
)?.amount;
|
||||||
|
|
||||||
let asset = epoch?.rewards.find((r) => r.asset === assetName);
|
let asset = epoch?.rewards.find((r) => r.asset === assetName);
|
||||||
|
|
||||||
if (!asset) {
|
if (!asset) {
|
||||||
@ -86,22 +100,24 @@ export const generateEpochIndividualRewardsList = ({
|
|||||||
asset.rewardTypes[rewardType] = { amount, percentageOfTotal };
|
asset.rewardTypes[rewardType] = { amount, percentageOfTotal };
|
||||||
} else {
|
} else {
|
||||||
const previousAmount = asset.rewardTypes[rewardType]?.amount;
|
const previousAmount = asset.rewardTypes[rewardType]?.amount;
|
||||||
const previousPercentageOfTotal =
|
const newAmount = previousAmount
|
||||||
asset.rewardTypes[rewardType]?.percentageOfTotal;
|
? new BigNumber(previousAmount).plus(amount).toString()
|
||||||
|
: amount;
|
||||||
|
|
||||||
asset.rewardTypes[rewardType] = {
|
asset.rewardTypes[rewardType] = {
|
||||||
amount: previousAmount
|
amount: newAmount,
|
||||||
? new BigNumber(previousAmount).plus(amount).toString()
|
percentageOfTotal: matchingTotalRewardAmount
|
||||||
: amount,
|
? new BigNumber(newAmount)
|
||||||
percentageOfTotal: previousPercentageOfTotal
|
.dividedBy(matchingTotalRewardAmount)
|
||||||
? new BigNumber(previousPercentageOfTotal)
|
.multipliedBy(100)
|
||||||
.plus(percentageOfTotal)
|
|
||||||
.toString()
|
.toString()
|
||||||
: percentageOfTotal,
|
: // this should never be reached, if there's an individual reward there should
|
||||||
|
// always be a reward total from the api too, but set it as a fallback just in case
|
||||||
|
percentageOfTotal,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// totalAmount is the sum of all rewardTypes amounts
|
// totalAmount is the sum of all individual rewardTypes amounts
|
||||||
asset.totalAmount = Object.values(asset.rewardTypes).reduce(
|
asset.totalAmount = Object.values(asset.rewardTypes).reduce(
|
||||||
(sum, rewardType) => {
|
(sum, rewardType) => {
|
||||||
return new BigNumber(sum).plus(rewardType.amount).toString();
|
return new BigNumber(sum).plus(rewardType.amount).toString();
|
||||||
|
@ -22,6 +22,13 @@ fragment DelegationFields on Delegation {
|
|||||||
epoch
|
epoch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fragment EpochRewardSummaryFields on EpochRewardSummary {
|
||||||
|
epoch
|
||||||
|
assetId
|
||||||
|
amount
|
||||||
|
rewardType
|
||||||
|
}
|
||||||
|
|
||||||
query Rewards(
|
query Rewards(
|
||||||
$partyId: ID!
|
$partyId: ID!
|
||||||
$fromEpoch: Int
|
$fromEpoch: Int
|
||||||
@ -50,13 +57,16 @@ query Rewards(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
epochRewardSummaries(
|
||||||
|
filter: { fromEpoch: $fromEpoch, toEpoch: $toEpoch }
|
||||||
fragment EpochRewardSummaryFields on EpochRewardSummary {
|
pagination: $rewardsPagination
|
||||||
epoch
|
) {
|
||||||
assetId
|
edges {
|
||||||
amount
|
node {
|
||||||
rewardType
|
...EpochRewardSummaryFields
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
query EpochAssetsRewards(
|
query EpochAssetsRewards(
|
||||||
|
@ -7,6 +7,8 @@ export type RewardFieldsFragment = { __typename?: 'Reward', rewardType: Types.Ac
|
|||||||
|
|
||||||
export type DelegationFieldsFragment = { __typename?: 'Delegation', amount: string, epoch: number };
|
export type DelegationFieldsFragment = { __typename?: 'Delegation', amount: string, epoch: number };
|
||||||
|
|
||||||
|
export type EpochRewardSummaryFieldsFragment = { __typename?: 'EpochRewardSummary', epoch: number, assetId: string, amount: string, rewardType: Types.AccountType };
|
||||||
|
|
||||||
export type RewardsQueryVariables = Types.Exact<{
|
export type RewardsQueryVariables = Types.Exact<{
|
||||||
partyId: Types.Scalars['ID'];
|
partyId: Types.Scalars['ID'];
|
||||||
fromEpoch?: Types.InputMaybe<Types.Scalars['Int']>;
|
fromEpoch?: Types.InputMaybe<Types.Scalars['Int']>;
|
||||||
@ -16,9 +18,7 @@ export type RewardsQueryVariables = Types.Exact<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type RewardsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, rewardsConnection?: { __typename?: 'RewardsConnection', edges?: Array<{ __typename?: 'RewardEdge', node: { __typename?: 'Reward', rewardType: Types.AccountType, amount: string, percentageOfTotal: string, receivedAt: any, asset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, party: { __typename?: 'Party', id: string }, epoch: { __typename?: 'Epoch', id: string } } } | null> | null } | null, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number } } | null> | null } | null } | null };
|
export type RewardsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, rewardsConnection?: { __typename?: 'RewardsConnection', edges?: Array<{ __typename?: 'RewardEdge', node: { __typename?: 'Reward', rewardType: Types.AccountType, amount: string, percentageOfTotal: string, receivedAt: any, asset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, party: { __typename?: 'Party', id: string }, epoch: { __typename?: 'Epoch', id: string } } } | null> | null } | null, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number } } | null> | null } | null } | null, epochRewardSummaries?: { __typename?: 'EpochRewardSummaryConnection', edges?: Array<{ __typename?: 'EpochRewardSummaryEdge', node: { __typename?: 'EpochRewardSummary', epoch: number, assetId: string, amount: string, rewardType: Types.AccountType } } | null> | null } | null };
|
||||||
|
|
||||||
export type EpochRewardSummaryFieldsFragment = { __typename?: 'EpochRewardSummary', epoch: number, assetId: string, amount: string, rewardType: Types.AccountType };
|
|
||||||
|
|
||||||
export type EpochAssetsRewardsQueryVariables = Types.Exact<{
|
export type EpochAssetsRewardsQueryVariables = Types.Exact<{
|
||||||
epochRewardSummariesFilter?: Types.InputMaybe<Types.RewardSummaryFilter>;
|
epochRewardSummariesFilter?: Types.InputMaybe<Types.RewardSummaryFilter>;
|
||||||
@ -102,9 +102,20 @@ export const RewardsDocument = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
epochRewardSummaries(
|
||||||
|
filter: {fromEpoch: $fromEpoch, toEpoch: $toEpoch}
|
||||||
|
pagination: $rewardsPagination
|
||||||
|
) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
...EpochRewardSummaryFields
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
${RewardFieldsFragmentDoc}
|
${RewardFieldsFragmentDoc}
|
||||||
${DelegationFieldsFragmentDoc}`;
|
${DelegationFieldsFragmentDoc}
|
||||||
|
${EpochRewardSummaryFieldsFragmentDoc}`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __useRewardsQuery__
|
* __useRewardsQuery__
|
||||||
|
Loading…
Reference in New Issue
Block a user