diff --git a/apps/trading/components/rewards-container/active-rewards.tsx b/apps/trading/components/rewards-container/active-rewards.tsx index 40db0e296..bf281f5dd 100644 --- a/apps/trading/components/rewards-container/active-rewards.tsx +++ b/apps/trading/components/rewards-container/active-rewards.tsx @@ -1,5 +1,5 @@ import { useT } from '../../lib/use-t'; -import { addDecimalsFormatNumber } from '@vegaprotocol/utils'; +import { addDecimalsFormatNumber, formatNumber } from '@vegaprotocol/utils'; import classNames from 'classnames'; import { type VegaIconSize, @@ -24,6 +24,9 @@ import { type DispatchStrategy, IndividualScopeMapping, IndividualScopeDescriptionMapping, + AccountType, + DistributionStrategy, + IndividualScope, type Asset, } from '@vegaprotocol/types'; import { Card } from '../card/card'; @@ -62,22 +65,27 @@ export const applyFilter = ( filter: Filter ) => { const { transfer } = node; - if ( - transfer.kind.__typename !== 'RecurringTransfer' || - !transfer.kind.dispatchStrategy?.dispatchMetric - ) { + + // if the transfer is a staking reward then it should be displayed + if (transfer.toAccountType === AccountType.ACCOUNT_TYPE_GLOBAL_REWARD) { + return true; + } + + if (transfer.kind.__typename !== 'RecurringTransfer') { return false; } if ( - DispatchMetricLabels[transfer.kind.dispatchStrategy.dispatchMetric] - .toLowerCase() - .includes(filter.searchTerm.toLowerCase()) || + (transfer.kind.dispatchStrategy?.dispatchMetric && + DispatchMetricLabels[transfer.kind.dispatchStrategy.dispatchMetric] + .toLowerCase() + .includes(filter.searchTerm.toLowerCase())) || transfer.asset?.symbol .toLowerCase() .includes(filter.searchTerm.toLowerCase()) || ( - EntityScopeLabelMapping[transfer.kind.dispatchStrategy.entityScope] || + (transfer.kind.dispatchStrategy && + EntityScopeLabelMapping[transfer.kind.dispatchStrategy.entityScope]) || 'Unspecified' ) .toLowerCase() @@ -93,6 +101,7 @@ export const applyFilter = ( ) { return true; } + return false; }; @@ -174,6 +183,29 @@ export const ActiveRewardCard = ({ return null; } + if ( + !transferNode.transfer.kind.dispatchStrategy && + transferNode.transfer.toAccountType === + AccountType.ACCOUNT_TYPE_GLOBAL_REWARD + ) { + return ( + + ); + } + let colour = DispatchMetricColourMap[ transferNode.transfer.kind.dispatchStrategy.dispatchMetric @@ -318,7 +350,7 @@ const RewardCard = ({ - + {/** DISPATCH METRIC */} {dispatchMetricInfo ? ( dispatchMetricInfo @@ -355,11 +387,11 @@ const RewardCard = ({ {/** DISPATCH METRIC DESCRIPTION */} {dispatchStrategy?.dispatchMetric && ( - +

{t(DispatchMetricDescription[dispatchStrategy?.dispatchMetric])} - +

)} - + {/** REQUIREMENTS */} {dispatchStrategy && ( { + const t = useT(); + return ( +
+
+
+
+ {/** ENTITY SCOPE */} +
+ + { + + {EntityScopeLabelMapping[ + EntityScope.ENTITY_SCOPE_INDIVIDUALS + ] || t('Unspecified')} + + } +
+ + {/** AMOUNT AND DISTRIBUTION STRATEGY */} +
+ {/** AMOUNT */} +

+ + {rewardAmount} + + + {rewardAsset?.symbol || ''} +

+ + {/** DISTRIBUTION STRATEGY */} + + + { + DistributionStrategyMapping[ + DistributionStrategy.DISTRIBUTION_STRATEGY_PRO_RATA + ] + } + + +
+ + {/** DISTRIBUTION DELAY */} +
+ + + {t('numberEpochs', '{{count}} epochs', { + count: 0, + })} + +
+
+ + + {/** DISPATCH METRIC */} + { + + {t('Staking rewards')} + + } +
+ {/** ENDS IN */} + {endsIn != null && ( + + {t('Ends in')} + + {endsIn >= 0 + ? t('numberEpochs', '{{count}} epochs', { + count: endsIn, + }) + : t('Ended')} + + + )} + + {/** WINDOW LENGTH */} + + {t('Assessed over')} + + {t('numberEpochs', '{{count}} epochs', { + count: 1, + })} + + +
+ {/** DISPATCH METRIC DESCRIPTION */} + { +

+ {t( + 'Global staking reward for staking $VEGA on the network via the Governance app' + )} +

+ } + + {/** REQUIREMENTS */} +
+
+
+ {t('Team scope')} +
+
+ + {t('Individual')} + +
+
+ +
+
+ {t('Staked VEGA')} +
+
+ {formatNumber(1, 2)} +
+
+ +
+
+ {t('Average position')} +
+
+ {formatNumber(0, 2)} +
+
+
+
+
+
+ ); +}; + export const DispatchMetricInfo = ({ reward, }: { diff --git a/apps/trading/lib/hooks/use-rewards.ts b/apps/trading/lib/hooks/use-rewards.ts index 69908f01e..59cb6045d 100644 --- a/apps/trading/lib/hooks/use-rewards.ts +++ b/apps/trading/lib/hooks/use-rewards.ts @@ -16,6 +16,7 @@ import { EntityScope, IndividualScope, MarketState, + AccountType, } from '@vegaprotocol/types'; import { type ApolloError } from '@apollo/client'; import compact from 'lodash/compact'; @@ -46,8 +47,9 @@ export type EnrichedRewardTransfer = RewardTransfer & { */ export const isReward = (node: TransferNode): node is RewardTransfer => { if ( - node.transfer.kind.__typename === 'RecurringTransfer' && - node.transfer.kind.dispatchStrategy != null + (node.transfer.kind.__typename === 'RecurringTransfer' && + node.transfer.kind.dispatchStrategy != null) || + node.transfer.toAccountType === AccountType.ACCOUNT_TYPE_GLOBAL_REWARD ) { return true; } @@ -79,13 +81,13 @@ export const isActiveReward = (node: RewardTransfer, currentEpoch: number) => { */ export const isScopedToTeams = (node: EnrichedRewardTransfer) => // scoped to teams - node.transfer.kind.dispatchStrategy.entityScope === + node.transfer.kind.dispatchStrategy?.entityScope === EntityScope.ENTITY_SCOPE_TEAMS || // or to individuals - (node.transfer.kind.dispatchStrategy.entityScope === + (node.transfer.kind.dispatchStrategy?.entityScope === EntityScope.ENTITY_SCOPE_INDIVIDUALS && // but they have to be in a team - node.transfer.kind.dispatchStrategy.individualScope === + node.transfer.kind.dispatchStrategy?.individualScope === IndividualScope.INDIVIDUAL_SCOPE_IN_TEAM); /** Retrieves rewards (transfers) */ @@ -142,6 +144,7 @@ export const useRewards = ({ .filter((node) => (scopeToTeams ? isScopedToTeams(node) : true)) // enrich with dispatch asset and markets in scope details .map((node) => { + if (!node.transfer.kind.dispatchStrategy) return node; const dispatchAsset = (assets && assets[node.transfer.kind.dispatchStrategy.dispatchMetricAssetId]) || @@ -170,7 +173,7 @@ export const useRewards = ({ ...node, dispatchAsset, isAssetTraded: isAssetTraded != null ? isAssetTraded : undefined, - markets: marketsInScope.length > 0 ? marketsInScope : undefined, + markets: marketsInScope?.length > 0 ? marketsInScope : undefined, }; }); diff --git a/libs/i18n/src/locales/en/trading.json b/libs/i18n/src/locales/en/trading.json index 79c2f819d..f7eb93483 100644 --- a/libs/i18n/src/locales/en/trading.json +++ b/libs/i18n/src/locales/en/trading.json @@ -136,6 +136,7 @@ "Governance vote for this market is valid and has been accepted": "Governance vote for this market is valid and has been accepted", "Governance vote has passed and market is awaiting opening auction exit": "Governance vote has passed and market is awaiting opening auction exit", "Governance vote passed to close the market": "Governance vote passed to close the market", + "Global staking reward for staking $VEGA on the network via the Governance app": "Global staking reward for staking $VEGA on the network via the Governance app", "Help identify bugs and improve the service by sharing anonymous usage data.": "Help identify bugs and improve the service by sharing anonymous usage data.", "Help us identify bugs and improve Vega Governance by sharing anonymous usage data.": "Help us identify bugs and improve Vega Governance by sharing anonymous usage data.", "Hide closed markets": "Hide closed markets", @@ -368,12 +369,12 @@ "TradingView": "TradingView", "Transfer": "Transfer", "Type": "Type", + "Staking rewards": "Staking rewards", "Unknown": "Unknown", "Unknown settlement date": "Unknown settlement date", "Update team": "Update team", "URL": "URL", "Use a comma separated list to allow only specific public keys to join the team": "Use a comma separated list to allow only specific public keys to join the team", - "Vega chart": "Vega chart", "Vega Reward pot": "Vega Reward pot", "Vega Wallet <0>full featured": "Vega Wallet <0>full featured", "Vega chart": "Vega chart",