Feat/1924: Reward details API queries refactor (#1966)
* Feat/1924: Reward details API queries refactor. Also now shows rewards of any asset type * Lint fix
This commit is contained in:
parent
113eb90469
commit
927b2a86d1
@ -1,15 +1,8 @@
|
|||||||
query Rewards($partyId: ID!) {
|
fragment RewardFields on Reward {
|
||||||
party(id: $partyId) {
|
|
||||||
id
|
|
||||||
rewardDetails {
|
|
||||||
asset {
|
|
||||||
id
|
|
||||||
symbol
|
|
||||||
}
|
|
||||||
rewards {
|
|
||||||
rewardType
|
rewardType
|
||||||
asset {
|
asset {
|
||||||
id
|
id
|
||||||
|
symbol
|
||||||
}
|
}
|
||||||
party {
|
party {
|
||||||
id
|
id
|
||||||
@ -22,14 +15,30 @@ query Rewards($partyId: ID!) {
|
|||||||
percentageOfTotal
|
percentageOfTotal
|
||||||
receivedAt
|
receivedAt
|
||||||
}
|
}
|
||||||
totalAmount
|
|
||||||
totalAmountFormatted @client
|
fragment DelegationFields on Delegation {
|
||||||
}
|
|
||||||
delegations {
|
|
||||||
amount
|
amount
|
||||||
amountFormatted @client
|
amountFormatted @client
|
||||||
epoch
|
epoch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query Rewards($partyId: ID!) {
|
||||||
|
party(id: $partyId) {
|
||||||
|
id
|
||||||
|
rewardsConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
...RewardFields
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delegationsConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
...DelegationFields
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
epoch {
|
epoch {
|
||||||
id
|
id
|
||||||
|
@ -1,174 +0,0 @@
|
|||||||
/* tslint:disable */
|
|
||||||
/* eslint-disable */
|
|
||||||
// @generated
|
|
||||||
// This file was automatically generated and should not be edited.
|
|
||||||
|
|
||||||
import { AccountType } from "@vegaprotocol/types";
|
|
||||||
|
|
||||||
// ====================================================
|
|
||||||
// GraphQL query operation: Rewards
|
|
||||||
// ====================================================
|
|
||||||
|
|
||||||
export interface Rewards_party_rewardDetails_asset {
|
|
||||||
__typename: "Asset";
|
|
||||||
/**
|
|
||||||
* The ID of the asset
|
|
||||||
*/
|
|
||||||
id: string;
|
|
||||||
/**
|
|
||||||
* The symbol of the asset (e.g: GBP)
|
|
||||||
*/
|
|
||||||
symbol: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Rewards_party_rewardDetails_rewards_asset {
|
|
||||||
__typename: "Asset";
|
|
||||||
/**
|
|
||||||
* The ID of the asset
|
|
||||||
*/
|
|
||||||
id: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Rewards_party_rewardDetails_rewards_party {
|
|
||||||
__typename: "Party";
|
|
||||||
/**
|
|
||||||
* Party identifier
|
|
||||||
*/
|
|
||||||
id: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Rewards_party_rewardDetails_rewards_epoch {
|
|
||||||
__typename: "Epoch";
|
|
||||||
/**
|
|
||||||
* Numeric sequence number used to identify the epoch
|
|
||||||
*/
|
|
||||||
id: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Rewards_party_rewardDetails_rewards {
|
|
||||||
__typename: "Reward";
|
|
||||||
/**
|
|
||||||
* The type of reward
|
|
||||||
*/
|
|
||||||
rewardType: AccountType;
|
|
||||||
/**
|
|
||||||
* The asset this reward is paid in
|
|
||||||
*/
|
|
||||||
asset: Rewards_party_rewardDetails_rewards_asset;
|
|
||||||
/**
|
|
||||||
* Party receiving the reward
|
|
||||||
*/
|
|
||||||
party: Rewards_party_rewardDetails_rewards_party;
|
|
||||||
/**
|
|
||||||
* Epoch for which this reward was distributed
|
|
||||||
*/
|
|
||||||
epoch: Rewards_party_rewardDetails_rewards_epoch;
|
|
||||||
/**
|
|
||||||
* Amount received for this reward
|
|
||||||
*/
|
|
||||||
amount: string;
|
|
||||||
/**
|
|
||||||
* The amount field formatted by the client
|
|
||||||
*/
|
|
||||||
amountFormatted: string;
|
|
||||||
/**
|
|
||||||
* Percentage out of the total distributed reward
|
|
||||||
*/
|
|
||||||
percentageOfTotal: string;
|
|
||||||
/**
|
|
||||||
* Time at which the rewards was received
|
|
||||||
*/
|
|
||||||
receivedAt: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Rewards_party_rewardDetails {
|
|
||||||
__typename: "RewardPerAssetDetail";
|
|
||||||
/**
|
|
||||||
* Asset in which the reward was paid
|
|
||||||
*/
|
|
||||||
asset: Rewards_party_rewardDetails_asset;
|
|
||||||
/**
|
|
||||||
* A list of rewards received for this asset
|
|
||||||
*/
|
|
||||||
rewards: (Rewards_party_rewardDetails_rewards | null)[] | null;
|
|
||||||
/**
|
|
||||||
* The total amount of rewards received for this asset.
|
|
||||||
*/
|
|
||||||
totalAmount: string;
|
|
||||||
/**
|
|
||||||
* The total amount field formatted by the client
|
|
||||||
*/
|
|
||||||
totalAmountFormatted: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Rewards_party_delegations {
|
|
||||||
__typename: "Delegation";
|
|
||||||
/**
|
|
||||||
* Amount delegated
|
|
||||||
*/
|
|
||||||
amount: string;
|
|
||||||
/**
|
|
||||||
* The amount field formatted by the client
|
|
||||||
*/
|
|
||||||
amountFormatted: string;
|
|
||||||
/**
|
|
||||||
* Epoch of delegation
|
|
||||||
*/
|
|
||||||
epoch: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Rewards_party {
|
|
||||||
__typename: "Party";
|
|
||||||
/**
|
|
||||||
* Party identifier
|
|
||||||
*/
|
|
||||||
id: string;
|
|
||||||
/**
|
|
||||||
* Return reward information
|
|
||||||
*/
|
|
||||||
rewardDetails: (Rewards_party_rewardDetails | null)[] | null;
|
|
||||||
delegations: Rewards_party_delegations[] | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Rewards_epoch_timestamps {
|
|
||||||
__typename: "EpochTimestamps";
|
|
||||||
/**
|
|
||||||
* RFC3339 timestamp - Vega time of epoch start, null if not started
|
|
||||||
*/
|
|
||||||
start: string | null;
|
|
||||||
/**
|
|
||||||
* RFC3339 timestamp - Vega time of epoch end, null if not ended
|
|
||||||
*/
|
|
||||||
end: string | null;
|
|
||||||
/**
|
|
||||||
* RFC3339 timestamp - Vega time of epoch expiry
|
|
||||||
*/
|
|
||||||
expiry: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Rewards_epoch {
|
|
||||||
__typename: "Epoch";
|
|
||||||
/**
|
|
||||||
* Numeric sequence number used to identify the epoch
|
|
||||||
*/
|
|
||||||
id: string;
|
|
||||||
/**
|
|
||||||
* Timestamps for start and end of epochs
|
|
||||||
*/
|
|
||||||
timestamps: Rewards_epoch_timestamps;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Rewards {
|
|
||||||
/**
|
|
||||||
* An entity that is trading on the Vega network
|
|
||||||
*/
|
|
||||||
party: Rewards_party | null;
|
|
||||||
/**
|
|
||||||
* Get data for a specific epoch, if ID omitted it gets the current epoch. If the string is 'next', fetch the next epoch
|
|
||||||
*/
|
|
||||||
epoch: Rewards_epoch;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RewardsVariables {
|
|
||||||
partyId: string;
|
|
||||||
}
|
|
@ -3,27 +3,23 @@ import { Schema as Types } from '@vegaprotocol/types';
|
|||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
import * as Apollo from '@apollo/client';
|
import * as Apollo from '@apollo/client';
|
||||||
const defaultOptions = {} as const;
|
const defaultOptions = {} as const;
|
||||||
|
export type RewardFieldsFragment = { __typename?: 'Reward', rewardType: Types.AccountType, amount: string, amountFormatted: string, percentageOfTotal: string, receivedAt: string, asset: { __typename?: 'Asset', id: string, symbol: string }, party: { __typename?: 'Party', id: string }, epoch: { __typename?: 'Epoch', id: string } };
|
||||||
|
|
||||||
|
export type DelegationFieldsFragment = { __typename?: 'Delegation', amount: string, amountFormatted: string, epoch: number };
|
||||||
|
|
||||||
export type RewardsQueryVariables = Types.Exact<{
|
export type RewardsQueryVariables = Types.Exact<{
|
||||||
partyId: Types.Scalars['ID'];
|
partyId: Types.Scalars['ID'];
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type RewardsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, rewardDetails?: Array<{ __typename?: 'RewardPerAssetDetail', totalAmount: string, totalAmountFormatted: string, asset: { __typename?: 'Asset', id: string, symbol: string }, rewards?: Array<{ __typename?: 'Reward', rewardType: Types.AccountType, amount: string, amountFormatted: string, percentageOfTotal: string, receivedAt: string, asset: { __typename?: 'Asset', id: string }, party: { __typename?: 'Party', id: string }, epoch: { __typename?: 'Epoch', id: string } } | null> | null } | null> | null, delegations?: Array<{ __typename?: 'Delegation', amount: string, amountFormatted: string, epoch: number }> | null } | null, epoch: { __typename?: 'Epoch', id: string, timestamps: { __typename?: 'EpochTimestamps', start?: string | null, end?: string | null, expiry?: string | 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, amountFormatted: string, percentageOfTotal: string, receivedAt: string, asset: { __typename?: 'Asset', id: string, symbol: string }, 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, amountFormatted: string, epoch: number } } | null> | null } | null } | null, epoch: { __typename?: 'Epoch', id: string, timestamps: { __typename?: 'EpochTimestamps', start?: string | null, end?: string | null, expiry?: string | null } } };
|
||||||
|
|
||||||
|
export const RewardFieldsFragmentDoc = gql`
|
||||||
export const RewardsDocument = gql`
|
fragment RewardFields on Reward {
|
||||||
query Rewards($partyId: ID!) {
|
|
||||||
party(id: $partyId) {
|
|
||||||
id
|
|
||||||
rewardDetails {
|
|
||||||
asset {
|
|
||||||
id
|
|
||||||
symbol
|
|
||||||
}
|
|
||||||
rewards {
|
|
||||||
rewardType
|
rewardType
|
||||||
asset {
|
asset {
|
||||||
id
|
id
|
||||||
|
symbol
|
||||||
}
|
}
|
||||||
party {
|
party {
|
||||||
id
|
id
|
||||||
@ -36,13 +32,31 @@ export const RewardsDocument = gql`
|
|||||||
percentageOfTotal
|
percentageOfTotal
|
||||||
receivedAt
|
receivedAt
|
||||||
}
|
}
|
||||||
totalAmount
|
`;
|
||||||
totalAmountFormatted @client
|
export const DelegationFieldsFragmentDoc = gql`
|
||||||
}
|
fragment DelegationFields on Delegation {
|
||||||
delegations {
|
|
||||||
amount
|
amount
|
||||||
amountFormatted @client
|
amountFormatted @client
|
||||||
epoch
|
epoch
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export const RewardsDocument = gql`
|
||||||
|
query Rewards($partyId: ID!) {
|
||||||
|
party(id: $partyId) {
|
||||||
|
id
|
||||||
|
rewardsConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
...RewardFields
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delegationsConnection {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
...DelegationFields
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
epoch {
|
epoch {
|
||||||
@ -54,7 +68,8 @@ export const RewardsDocument = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
${RewardFieldsFragmentDoc}
|
||||||
|
${DelegationFieldsFragmentDoc}`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __useRewardsQuery__
|
* __useRewardsQuery__
|
||||||
|
@ -1,168 +1 @@
|
|||||||
import { useQuery } from '@apollo/client';
|
export * from './rewards-page';
|
||||||
import { Button, Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit';
|
|
||||||
import { formatDistance } from 'date-fns';
|
|
||||||
// @ts-ignore No types available for duration-js
|
|
||||||
import Duration from 'duration-js';
|
|
||||||
import gql from 'graphql-tag';
|
|
||||||
import React from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
import { EpochCountdown } from '../../../components/epoch-countdown';
|
|
||||||
import { Heading } from '../../../components/heading';
|
|
||||||
import { SplashLoader } from '../../../components/splash-loader';
|
|
||||||
import {
|
|
||||||
AppStateActionType,
|
|
||||||
useAppState,
|
|
||||||
} from '../../../contexts/app-state/app-state-context';
|
|
||||||
import type { Rewards } from './__generated__/Rewards';
|
|
||||||
import { RewardInfo } from './reward-info';
|
|
||||||
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
|
|
||||||
import { useNetworkParams, NetworkParams } from '@vegaprotocol/react-helpers';
|
|
||||||
|
|
||||||
export const REWARDS_QUERY = gql`
|
|
||||||
query Rewards($partyId: ID!) {
|
|
||||||
party(id: $partyId) {
|
|
||||||
id
|
|
||||||
rewardDetails {
|
|
||||||
asset {
|
|
||||||
id
|
|
||||||
symbol
|
|
||||||
}
|
|
||||||
rewards {
|
|
||||||
rewardType
|
|
||||||
asset {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
party {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
epoch {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
amount
|
|
||||||
amountFormatted @client
|
|
||||||
percentageOfTotal
|
|
||||||
receivedAt
|
|
||||||
}
|
|
||||||
totalAmount
|
|
||||||
totalAmountFormatted @client
|
|
||||||
}
|
|
||||||
delegations {
|
|
||||||
amount
|
|
||||||
amountFormatted @client
|
|
||||||
epoch
|
|
||||||
}
|
|
||||||
}
|
|
||||||
epoch {
|
|
||||||
id
|
|
||||||
timestamps {
|
|
||||||
start
|
|
||||||
end
|
|
||||||
expiry
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const RewardsIndex = () => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const { pubKey, pubKeys } = useVegaWallet();
|
|
||||||
const { openVegaWalletDialog } = useVegaWalletDialogStore((store) => ({
|
|
||||||
openVegaWalletDialog: store.openVegaWalletDialog,
|
|
||||||
}));
|
|
||||||
const { appDispatch } = useAppState();
|
|
||||||
const { data, loading, error } = useQuery<Rewards>(REWARDS_QUERY, {
|
|
||||||
variables: { partyId: pubKey },
|
|
||||||
skip: !pubKey,
|
|
||||||
});
|
|
||||||
const { params } = useNetworkParams([
|
|
||||||
NetworkParams.reward_asset,
|
|
||||||
NetworkParams.reward_staking_delegation_payoutDelay,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const payoutDuration = React.useMemo(() => {
|
|
||||||
if (!params) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return new Duration(
|
|
||||||
params.reward_staking_delegation_payoutDelay
|
|
||||||
).milliseconds();
|
|
||||||
}, [params]);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return (
|
|
||||||
<section>
|
|
||||||
<p>{t('Something went wrong')}</p>
|
|
||||||
{error && <pre>{error.message}</pre>}
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loading || !params) {
|
|
||||||
return (
|
|
||||||
<Splash>
|
|
||||||
<SplashLoader />
|
|
||||||
</Splash>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<section className="rewards">
|
|
||||||
<Heading title={t('pageTitleRewards')} />
|
|
||||||
<p>{t('rewardsPara1')}</p>
|
|
||||||
<p>{t('rewardsPara2')}</p>
|
|
||||||
{payoutDuration ? (
|
|
||||||
<div className="my-8">
|
|
||||||
<Callout
|
|
||||||
title={t('rewardsCallout', {
|
|
||||||
duration: formatDistance(new Date(0), payoutDuration),
|
|
||||||
})}
|
|
||||||
headingLevel={3}
|
|
||||||
intent={Intent.Warning}
|
|
||||||
>
|
|
||||||
<p className="mb-0">{t('rewardsPara3')}</p>
|
|
||||||
</Callout>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
{!loading &&
|
|
||||||
data &&
|
|
||||||
!error &&
|
|
||||||
data.epoch.timestamps.start &&
|
|
||||||
data.epoch.timestamps.expiry && (
|
|
||||||
<section className="mb-8">
|
|
||||||
<EpochCountdown
|
|
||||||
// eslint-disable-next-line
|
|
||||||
id={data!.epoch.id}
|
|
||||||
startDate={new Date(data.epoch.timestamps.start)}
|
|
||||||
// eslint-disable-next-line
|
|
||||||
endDate={new Date(data.epoch.timestamps.expiry!)}
|
|
||||||
/>
|
|
||||||
</section>
|
|
||||||
)}
|
|
||||||
<section>
|
|
||||||
{pubKey && pubKeys?.length ? (
|
|
||||||
<RewardInfo
|
|
||||||
currVegaKey={pubKey}
|
|
||||||
data={data}
|
|
||||||
rewardAssetId={params.reward_asset}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div>
|
|
||||||
<Button
|
|
||||||
data-testid="connect-to-vega-wallet-btn"
|
|
||||||
onClick={() => {
|
|
||||||
appDispatch({
|
|
||||||
type: AppStateActionType.SET_VEGA_WALLET_OVERLAY,
|
|
||||||
isOpen: true,
|
|
||||||
});
|
|
||||||
openVegaWalletDialog();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t('connectVegaWallet')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import * as Sentry from '@sentry/react';
|
import compact from 'lodash/compact';
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -7,69 +7,53 @@ import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
|||||||
import { BigNumber } from '../../../lib/bignumber';
|
import { BigNumber } from '../../../lib/bignumber';
|
||||||
import { DATE_FORMAT_DETAILED } from '../../../lib/date-formats';
|
import { DATE_FORMAT_DETAILED } from '../../../lib/date-formats';
|
||||||
import type {
|
import type {
|
||||||
Rewards,
|
RewardsQuery,
|
||||||
Rewards_party_delegations,
|
RewardFieldsFragment,
|
||||||
Rewards_party_rewardDetails_rewards,
|
DelegationFieldsFragment,
|
||||||
} from './__generated__/Rewards';
|
} from './__generated___/Rewards';
|
||||||
|
|
||||||
interface RewardInfoProps {
|
interface RewardInfoProps {
|
||||||
data: Rewards | undefined;
|
data: RewardsQuery | undefined;
|
||||||
currVegaKey: string;
|
currVegaKey: string;
|
||||||
rewardAssetId: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RewardInfo = ({
|
export const RewardInfo = ({ data, currVegaKey }: RewardInfoProps) => {
|
||||||
data,
|
|
||||||
currVegaKey,
|
|
||||||
rewardAssetId,
|
|
||||||
}: RewardInfoProps) => {
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
// Create array of rewards per epoch
|
const rewards = React.useMemo(() => {
|
||||||
const vegaTokenRewards = React.useMemo(() => {
|
if (!data?.party || !data.party.rewardsConnection?.edges?.length) return [];
|
||||||
if (!data?.party || !data.party.rewardDetails?.length) return [];
|
|
||||||
|
|
||||||
const vegaTokenRewards = data.party.rewardDetails.find(
|
return (
|
||||||
(r) => r?.asset.id === rewardAssetId
|
compact(data.party.rewardsConnection.edges.map((edge) => edge?.node)) ||
|
||||||
|
[]
|
||||||
);
|
);
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
// We only issue rewards as Vega tokens for now so there should only be one
|
const delegations = React.useMemo(() => {
|
||||||
// item in the rewardDetails array
|
if (!data?.party || !data.party.delegationsConnection?.edges?.length) {
|
||||||
if (!vegaTokenRewards) {
|
|
||||||
const rewardAssets = data.party.rewardDetails
|
|
||||||
.map((r) => r?.asset.symbol)
|
|
||||||
.join(', ');
|
|
||||||
Sentry.captureMessage(
|
|
||||||
`Could not find VEGA token rewards ${rewardAssets}`
|
|
||||||
);
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vegaTokenRewards?.rewards?.length) return [];
|
return (
|
||||||
|
compact(
|
||||||
const sorted = Array.from(vegaTokenRewards.rewards).sort((a, b) => {
|
data.party.delegationsConnection.edges.map((edge) => edge?.node)
|
||||||
if (!a || !b) return 0;
|
) || []
|
||||||
if (a.epoch > b.epoch) return -1;
|
);
|
||||||
if (a.epoch < b.epoch) return 1;
|
}, [data]);
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
return sorted;
|
|
||||||
}, [data, rewardAssetId]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
{t('Connected Vega key')}: {currVegaKey}
|
{t('Connected Vega key')}: {currVegaKey}
|
||||||
</p>
|
</p>
|
||||||
{vegaTokenRewards.length ? (
|
{rewards.length ? (
|
||||||
vegaTokenRewards.map((reward, i) => {
|
rewards.map((reward, i) => {
|
||||||
if (!reward) return null;
|
if (!reward) return null;
|
||||||
return (
|
return (
|
||||||
<RewardTable
|
<RewardTable
|
||||||
key={i}
|
key={i}
|
||||||
reward={reward}
|
reward={reward}
|
||||||
delegations={data?.party?.delegations || []}
|
delegations={delegations || []}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@ -81,8 +65,8 @@ export const RewardInfo = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
interface RewardTableProps {
|
interface RewardTableProps {
|
||||||
reward: Rewards_party_rewardDetails_rewards;
|
reward: RewardFieldsFragment;
|
||||||
delegations: Rewards_party_delegations[];
|
delegations: DelegationFieldsFragment[] | [];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RewardTable = ({ reward, delegations }: RewardTableProps) => {
|
export const RewardTable = ({ reward, delegations }: RewardTableProps) => {
|
||||||
|
116
apps/token/src/routes/rewards/home/rewards-page.tsx
Normal file
116
apps/token/src/routes/rewards/home/rewards-page.tsx
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import { Button, Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { formatDistance } from 'date-fns';
|
||||||
|
// @ts-ignore No types available for duration-js
|
||||||
|
import Duration from 'duration-js';
|
||||||
|
import React from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import { EpochCountdown } from '../../../components/epoch-countdown';
|
||||||
|
import { Heading } from '../../../components/heading';
|
||||||
|
import { SplashLoader } from '../../../components/splash-loader';
|
||||||
|
import {
|
||||||
|
AppStateActionType,
|
||||||
|
useAppState,
|
||||||
|
} from '../../../contexts/app-state/app-state-context';
|
||||||
|
import { RewardInfo } from './reward-info';
|
||||||
|
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
|
||||||
|
import { useNetworkParams, NetworkParams } from '@vegaprotocol/react-helpers';
|
||||||
|
import { useRewardsQuery } from './__generated___/Rewards';
|
||||||
|
|
||||||
|
export const RewardsPage = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { pubKey, pubKeys } = useVegaWallet();
|
||||||
|
const { openVegaWalletDialog } = useVegaWalletDialogStore((store) => ({
|
||||||
|
openVegaWalletDialog: store.openVegaWalletDialog,
|
||||||
|
}));
|
||||||
|
const { appDispatch } = useAppState();
|
||||||
|
const { data, loading, error } = useRewardsQuery({
|
||||||
|
variables: { partyId: pubKey || '' },
|
||||||
|
skip: !pubKey,
|
||||||
|
});
|
||||||
|
const { params } = useNetworkParams([
|
||||||
|
NetworkParams.reward_staking_delegation_payoutDelay,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const payoutDuration = React.useMemo(() => {
|
||||||
|
if (!params) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return new Duration(
|
||||||
|
params.reward_staking_delegation_payoutDelay
|
||||||
|
).milliseconds();
|
||||||
|
}, [params]);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
<p>{t('Something went wrong')}</p>
|
||||||
|
{error && <pre>{error.message}</pre>}
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loading || !params) {
|
||||||
|
return (
|
||||||
|
<Splash>
|
||||||
|
<SplashLoader />
|
||||||
|
</Splash>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="rewards">
|
||||||
|
<Heading title={t('pageTitleRewards')} />
|
||||||
|
<p>{t('rewardsPara1')}</p>
|
||||||
|
<p>{t('rewardsPara2')}</p>
|
||||||
|
{payoutDuration ? (
|
||||||
|
<div className="my-8">
|
||||||
|
<Callout
|
||||||
|
title={t('rewardsCallout', {
|
||||||
|
duration: formatDistance(new Date(0), payoutDuration),
|
||||||
|
})}
|
||||||
|
headingLevel={3}
|
||||||
|
intent={Intent.Warning}
|
||||||
|
>
|
||||||
|
<p className="mb-0">{t('rewardsPara3')}</p>
|
||||||
|
</Callout>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
{!loading &&
|
||||||
|
data &&
|
||||||
|
!error &&
|
||||||
|
data.epoch.timestamps.start &&
|
||||||
|
data.epoch.timestamps.expiry && (
|
||||||
|
<section className="mb-8">
|
||||||
|
<EpochCountdown
|
||||||
|
// eslint-disable-next-line
|
||||||
|
id={data!.epoch.id}
|
||||||
|
startDate={new Date(data.epoch.timestamps.start)}
|
||||||
|
// eslint-disable-next-line
|
||||||
|
endDate={new Date(data.epoch.timestamps.expiry!)}
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
<section>
|
||||||
|
{pubKey && pubKeys?.length ? (
|
||||||
|
<RewardInfo currVegaKey={pubKey} data={data} />
|
||||||
|
) : (
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
data-testid="connect-to-vega-wallet-btn"
|
||||||
|
onClick={() => {
|
||||||
|
appDispatch({
|
||||||
|
type: AppStateActionType.SET_VEGA_WALLET_OVERLAY,
|
||||||
|
isOpen: true,
|
||||||
|
});
|
||||||
|
openVegaWalletDialog();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('connectVegaWallet')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
@ -1,11 +1,11 @@
|
|||||||
import { useDocumentTitle } from '../../hooks/use-document-title';
|
import { useDocumentTitle } from '../../hooks/use-document-title';
|
||||||
import type { RouteChildProps } from '..';
|
import type { RouteChildProps } from '..';
|
||||||
import { RewardsIndex } from './home';
|
import { RewardsPage } from './home';
|
||||||
|
|
||||||
const Rewards = ({ name }: RouteChildProps) => {
|
const Rewards = ({ name }: RouteChildProps) => {
|
||||||
useDocumentTitle(name);
|
useDocumentTitle(name);
|
||||||
|
|
||||||
return <RewardsIndex />;
|
return <RewardsPage />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Rewards;
|
export default Rewards;
|
||||||
|
Loading…
Reference in New Issue
Block a user