diff --git a/apps/trading/components/card/card.tsx b/apps/trading/components/card/card.tsx index 9a40b257f..fc507afb0 100644 --- a/apps/trading/components/card/card.tsx +++ b/apps/trading/components/card/card.tsx @@ -1,3 +1,4 @@ +import { Tooltip } from '@vegaprotocol/ui-toolkit'; import classNames from 'classnames'; import type { ReactNode } from 'react'; @@ -17,10 +18,10 @@ export const Card = ({ className={classNames( 'p-4 bg-vega-clight-800 dark:bg-vega-cdark-800 col-span-full lg:col-auto', 'rounded-lg', - className + className, )} > -

{title}

+

{title}

{loading ? : children} ); @@ -34,3 +35,51 @@ export const CardLoader = () => { ); }; + +export const CardStat = ({ + value, + text, + highlight, + description, +}: { + value: ReactNode; + text?: string; + highlight?: boolean; + description?: ReactNode; +}) => { + const val = ( + + {value} + + ); + + return ( +

+ {description ? {val} : val} + {text && ( + {text} + )} +

+ ); +}; + +export const CardTable = ({ children }: { children: ReactNode }) => { + return ( + + {children} +
+ ); +}; + +export const CardTableTH = ({ children }: { children: ReactNode }) => { + return {children}; +}; + +export const CardTableTD = ({ children }: { children: ReactNode }) => { + return {children}; +}; diff --git a/apps/trading/components/card/index.ts b/apps/trading/components/card/index.ts index 48b675389..a4b7d3b15 100644 --- a/apps/trading/components/card/index.ts +++ b/apps/trading/components/card/index.ts @@ -1 +1 @@ -export { Card } from './card'; +export { Card, CardStat, CardTable, CardTableTH, CardTableTD } from './card'; diff --git a/apps/trading/components/fees-container/fees-container.tsx b/apps/trading/components/fees-container/fees-container.tsx index 1bd07de70..8dacf1858 100644 --- a/apps/trading/components/fees-container/fees-container.tsx +++ b/apps/trading/components/fees-container/fees-container.tsx @@ -253,7 +253,7 @@ export const TradingFees = ({ : `${formatPercentage(adjustedTotal)}%`}

- + {t('Total fee before discount')} {minTotal !== undefined && maxTotal !== undefined diff --git a/apps/trading/components/rewards-container/Rewards.graphql b/apps/trading/components/rewards-container/Rewards.graphql new file mode 100644 index 000000000..d28c47fb3 --- /dev/null +++ b/apps/trading/components/rewards-container/Rewards.graphql @@ -0,0 +1,15 @@ +query RewardsPage($partyId: ID!) { + party(id: $partyId) { + id + activityStreak { + isActive + activeFor + inactiveFor + rewardDistributionMultiplier + rewardVestingMultiplier + epoch + tradedVolume + openVolume + } + } +} diff --git a/apps/trading/components/rewards-container/__generated__/Rewards.ts b/apps/trading/components/rewards-container/__generated__/Rewards.ts new file mode 100644 index 000000000..7fb5ec6cc --- /dev/null +++ b/apps/trading/components/rewards-container/__generated__/Rewards.ts @@ -0,0 +1,58 @@ +import * as Types from '@vegaprotocol/types'; + +import { gql } from '@apollo/client'; +import * as Apollo from '@apollo/client'; +const defaultOptions = {} as const; +export type RewardsPageQueryVariables = Types.Exact<{ + partyId: Types.Scalars['ID']; +}>; + + +export type RewardsPageQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, activityStreak?: { __typename?: 'PartyActivityStreak', isActive: boolean, activeFor: number, inactiveFor: number, rewardDistributionMultiplier: string, rewardVestingMultiplier: string, epoch: number, tradedVolume: string, openVolume: string } | null } | null }; + + +export const RewardsPageDocument = gql` + query RewardsPage($partyId: ID!) { + party(id: $partyId) { + id + activityStreak { + isActive + activeFor + inactiveFor + rewardDistributionMultiplier + rewardVestingMultiplier + epoch + tradedVolume + openVolume + } + } +} + `; + +/** + * __useRewardsPageQuery__ + * + * To run a query within a React component, call `useRewardsPageQuery` and pass it any options that fit your needs. + * When your component renders, `useRewardsPageQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useRewardsPageQuery({ + * variables: { + * partyId: // value for 'partyId' + * }, + * }); + */ +export function useRewardsPageQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(RewardsPageDocument, options); + } +export function useRewardsPageLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(RewardsPageDocument, options); + } +export type RewardsPageQueryHookResult = ReturnType; +export type RewardsPageLazyQueryHookResult = ReturnType; +export type RewardsPageQueryResult = Apollo.QueryResult; \ No newline at end of file diff --git a/apps/trading/components/rewards-container/rewards-container.tsx b/apps/trading/components/rewards-container/rewards-container.tsx index 0720bab9f..26780e679 100644 --- a/apps/trading/components/rewards-container/rewards-container.tsx +++ b/apps/trading/components/rewards-container/rewards-container.tsx @@ -1,18 +1,26 @@ -import type { Account} from '@vegaprotocol/accounts'; +import type { Account } from '@vegaprotocol/accounts'; import { useAccounts } from '@vegaprotocol/accounts'; import { t } from '@vegaprotocol/i18n'; import { NetworkParams, - useNetworkParam, + useNetworkParams, } from '@vegaprotocol/network-parameters'; import { AccountType } from '@vegaprotocol/types'; -import { TradingAnchorButton, TradingButton } from '@vegaprotocol/ui-toolkit'; import { useVegaWallet } from '@vegaprotocol/wallet'; import { Links } from '../../lib/links'; import BigNumber from 'bignumber.js'; import { Link } from 'react-router-dom'; -import { Card } from '../card/card'; +import { + Card, + CardStat, + CardTable, + CardTableTD, + CardTableTH, +} from '../card/card'; import { getQuantumValue } from '@vegaprotocol/assets'; +import { useRewardsPageQuery } from './__generated__/Rewards'; +import { TradingButton } from '@vegaprotocol/ui-toolkit'; +import { formatPercentage } from '../fees-container/utils'; const REWARD_ACCOUNT_TYPES = [ AccountType.ACCOUNT_TYPE_VESTED_REWARDS, @@ -21,36 +29,50 @@ const REWARD_ACCOUNT_TYPES = [ export const RewardsContainer = () => { const { pubKey } = useVegaWallet(); - const { param, loading: paramsLoading } = useNetworkParam( - NetworkParams.rewards_activityStreak_benefitTiers - ); + const { params, loading: paramsLoading } = useNetworkParams([ + NetworkParams.reward_asset, + NetworkParams.rewards_activityStreak_benefitTiers, + NetworkParams.rewards_vesting_baseRate, + ]); const { data: accounts, loading: accountsLoading } = useAccounts(pubKey); + const { data: rewardsData, loading: rewardsLoading } = useRewardsPageQuery({ + variables: { + partyId: pubKey || '', + }, + skip: !pubKey, + }); - const loading = paramsLoading || accountsLoading; + const loading = paramsLoading || accountsLoading || rewardsLoading; return (

Rewards

- - - - - TODO: - - - TODO: - - + + + + + + + + + {/* + + TODO: TODO: + */} TODO: @@ -59,15 +81,17 @@ export const RewardsContainer = () => { ); }; -export const RewardPot = ({ accounts }: { accounts: Account[] | null }) => { +export const RewardPot = ({ + accounts, + rewardAssetId, +}: { + accounts: Account[] | null; + rewardAssetId: string; // VEGA +}) => { const rewardAccounts = accounts ? accounts.filter((a) => REWARD_ACCOUNT_TYPES.includes(a.type)) : []; - const vestedRewardAccounts = accounts - ? accounts.filter((a) => a.type === AccountType.ACCOUNT_TYPE_VESTED_REWARDS) - : []; - const totalRewards = BigNumber.sum.apply( null, rewardAccounts.length @@ -75,28 +99,110 @@ export const RewardPot = ({ accounts }: { accounts: Account[] | null }) => { : [0] ); - const totalVestedRewards = BigNumber.sum.apply( + const rewardAssetAccounts = accounts + ? accounts.filter((a) => { + return a.asset.id === rewardAssetId; + }) + : []; + + const vestedRewardAssetAccounts = rewardAssetAccounts.filter( + (a) => a.type === AccountType.ACCOUNT_TYPE_VESTED_REWARDS + ); + + const vestingRewardAssetAccounts = rewardAssetAccounts.filter( + (a) => a.type === AccountType.ACCOUNT_TYPE_VESTED_REWARDS + ); + + const totalVestedRewardsByRewardAsset = BigNumber.sum.apply( null, - vestedRewardAccounts.length - ? vestedRewardAccounts.map((a) => - getQuantumValue(a.balance, a.asset.quantum) - ) + vestedRewardAssetAccounts.length + ? vestedRewardAssetAccounts.map((a) => a.balance) : [0] ); + const totalVestingRewardsByRewardAsset = BigNumber.sum.apply( + null, + vestingRewardAssetAccounts.length + ? vestingRewardAssetAccounts.map((a) => a.balance) + : [0] + ); + + const totalRewardAsset = totalVestedRewardsByRewardAsset.plus( + totalVestingRewardsByRewardAsset + ); + return (
-

- {totalRewards.toString()} {t('qUSD')} -

-

- {totalVestedRewards.toString()} {t('qUSD')} -

- {t('Redeem')} +
+ + {totalRewardAsset.toString()} {t('VEGA')} +

+ } + /> + + {totalRewards.toString()} {t('qUSD')} +

+ } + /> +
+
+ + + {t('Locked VEGA')} + FOO + + + {t('Vesting VEGA')} + + {totalVestingRewardsByRewardAsset.toString()} + + + + {t('Available to withdraw this epoch')} + + {totalVestedRewardsByRewardAsset.toString()} + + + + + {t('Redeem')} + +
); }; -const ActivityStreak = () => { - return
ActivityStreak
; +const Vesting = ({ baseRate }: { baseRate: string }) => { + const baseRateFormatted = formatPercentage(Number(baseRate)); + return ( +
+ + + + {t('Base rate')} + {baseRateFormatted}% + + + {t('Vesting multiplier')} + 0% + + + {t('Available to withdraw next epoch')} + 0% + + +
+ ); +}; + +const Multipliers = () => { + return ( +
+

{t('No active reward bonuses')}

+
+ ); }; diff --git a/libs/network-parameters/src/use-network-params.ts b/libs/network-parameters/src/use-network-params.ts index 7639e3e19..68d1aff54 100644 --- a/libs/network-parameters/src/use-network-params.ts +++ b/libs/network-parameters/src/use-network-params.ts @@ -8,6 +8,7 @@ import { export const NetworkParams = { blockchains_ethereumConfig: 'blockchains_ethereumConfig', reward_asset: 'reward_asset', + rewards_activityStreak_benefitTiers: 'rewards_activityStreak_benefitTiers', rewards_marketCreationQuantumMultiple: 'rewards_marketCreationQuantumMultiple', reward_staking_delegation_payoutDelay: @@ -178,7 +179,6 @@ export const NetworkParams = { transfer_fee_factor: 'transfer_fee_factor', transfer_minTransferQuantumMultiple: 'transfer_minTransferQuantumMultiple', network_validators_incumbentBonus: 'network_validators_incumbentBonus', - rewards_activityStreak_benefitTiers: 'rewards_activityStreak_benefitTiers', } as const; type Params = typeof NetworkParams;