diff --git a/apps/token-e2e/src/integration/flow/staking-flow.cy.js b/apps/token-e2e/src/integration/flow/staking-flow.cy.js index db17b4fa4..f4bc50109 100644 --- a/apps/token-e2e/src/integration/flow/staking-flow.cy.js +++ b/apps/token-e2e/src/integration/flow/staking-flow.cy.js @@ -96,7 +96,7 @@ context( .contains(2.0, epochTimeout) .should('be.visible'); - cy.get(nominatedStake).should('have.text', '2.000000000000000000'); // 2001-STKE-017 2002-SINC-007 + cy.get(nominatedStake).should('have.text', '2.00'); // 2001-STKE-017 2002-SINC-007 cy.navigate_to('staking'); diff --git a/apps/token/client.graphql b/apps/token/client.graphql deleted file mode 100644 index d1e892861..000000000 --- a/apps/token/client.graphql +++ /dev/null @@ -1,38 +0,0 @@ -extend type Delegation { - "The amount field formatted by the client" - amountFormatted: String! -} - -extend type NodeData { - "The total staked field formatted by the client" - stakedTotalFormatted: String! -} - -extend type Node { - "The total staked field formatted by the client" - stakedTotalFormatted: String! - - "The pending staked field formatted by the client" - pendingStakeFormatted: String! - - "The stakes by operator field formatted by the client" - stakedByOperatorFormatted: String! - - "The stakes by delegates field formatted by the client" - stakedByDelegatesFormatted: String! -} - -extend type Reward { - "The amount field formatted by the client" - amountFormatted: String! -} - -extend type RewardPerAssetDetail { - "The total amount field formatted by the client" - totalAmountFormatted: String! -} - -extend type AccountBalance { - "The balance field formatted by the client" - balanceFormatted: String! -} diff --git a/apps/token/src/app.tsx b/apps/token/src/app.tsx index 32a976725..3c04e4678 100644 --- a/apps/token/src/app.tsx +++ b/apps/token/src/app.tsx @@ -28,44 +28,12 @@ import { } from '@vegaprotocol/environment'; import { createConnectors } from './lib/web3-connectors'; import { ENV } from './config/env'; -import type { - FieldFunctionOptions, - InMemoryCacheConfig, - Reference, -} from '@apollo/client'; - -import { addDecimal } from '@vegaprotocol/react-helpers'; - -const formatUintToNumber = (amount: string, decimals = 18) => - addDecimal(amount, decimals).toString(); - -const createReadField = (fieldName: string) => ({ - [`${fieldName}Formatted`]: { - read(_: string, options: FieldFunctionOptions) { - const amount = options.readField(fieldName) as string; - return amount ? formatUintToNumber(amount) : '0'; - }, - }, -}); +import type { InMemoryCacheConfig } from '@apollo/client'; const cache: InMemoryCacheConfig = { typePolicies: { Account: { keyFields: false, - fields: { - balanceFormatted: { - read(_: string, options: FieldFunctionOptions) { - const balance = options.readField('balance'); - const asset = options.readField('asset'); - const decimals = options.readField('decimals', asset as Reference); - if (typeof balance !== 'string') return '0'; - if (typeof decimals !== 'number') return '0'; - return balance && decimals - ? formatUintToNumber(balance, decimals) - : '0'; - }, - }, - }, }, Delegation: { keyFields: false, @@ -73,61 +41,20 @@ const cache: InMemoryCacheConfig = { merge(_, incoming) { return incoming; }, - fields: { - ...createReadField('amount'), - }, }, Reward: { keyFields: false, - fields: { - ...createReadField('amount'), - }, }, RewardPerAssetDetail: { keyFields: false, - fields: { - ...createReadField('totalAmount'), - }, }, Node: { keyFields: false, - fields: { - ...createReadField('pendingStake'), - ...createReadField('stakedByOperator'), - ...createReadField('stakedByDelegates'), - ...createReadField('stakedTotal'), - }, }, NodeData: { merge: (existing = {}, incoming) => { return { ...existing, ...incoming }; }, - fields: { - ...createReadField('stakedTotal'), - }, - }, - Party: { - fields: { - stake: { - merge(existing, incoming) { - return { - ...existing, - ...incoming, - }; - }, - read(stake) { - if (stake) { - return { - ...stake, - currentStakeAvailableFormatted: formatUintToNumber( - stake.currentStakeAvailable - ), - }; - } - return stake; - }, - }, - }, }, Withdrawal: { fields: { diff --git a/apps/token/src/components/vega-wallet/Delegations.graphql b/apps/token/src/components/vega-wallet/Delegations.graphql index 877350da8..dc1347e93 100644 --- a/apps/token/src/components/vega-wallet/Delegations.graphql +++ b/apps/token/src/components/vega-wallet/Delegations.graphql @@ -1,5 +1,4 @@ fragment WalletDelegationFields on Delegation { - amountFormatted @client amount node { id diff --git a/apps/token/src/components/vega-wallet/__generated___/Delegations.ts b/apps/token/src/components/vega-wallet/__generated___/Delegations.ts index 1193de991..f795723d3 100644 --- a/apps/token/src/components/vega-wallet/__generated___/Delegations.ts +++ b/apps/token/src/components/vega-wallet/__generated___/Delegations.ts @@ -3,18 +3,17 @@ import { Schema as Types } from '@vegaprotocol/types'; import { gql } from '@apollo/client'; import * as Apollo from '@apollo/client'; const defaultOptions = {} as const; -export type WalletDelegationFieldsFragment = { __typename?: 'Delegation', amountFormatted: string, amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } }; +export type WalletDelegationFieldsFragment = { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } }; export type DelegationsQueryVariables = Types.Exact<{ partyId: Types.Scalars['ID']; }>; -export type DelegationsQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string }, party?: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amountFormatted: string, amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } } } | null> | null } | null, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } } } } | null> | null } | null } | null }; +export type DelegationsQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string }, party?: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } } } | null> | null } | null, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } } } } | null> | null } | null } | null }; export const WalletDelegationFieldsFragmentDoc = gql` fragment WalletDelegationFields on Delegation { - amountFormatted @client amount node { id diff --git a/apps/token/src/components/vega-wallet/hooks.ts b/apps/token/src/components/vega-wallet/hooks.ts index bde7dab4f..9bfd7ec38 100644 --- a/apps/token/src/components/vega-wallet/hooks.ts +++ b/apps/token/src/components/vega-wallet/hooks.ts @@ -74,8 +74,8 @@ export const usePollForDelegations = () => { return d.epoch.toString() === res.data.epoch.id; }) || []; const sortedDelegations = [...filter].sort((a, b) => { - return new BigNumber(b.amountFormatted) - .minus(a.amountFormatted) + return toBigNum(b.amount, decimals) + .minus(toBigNum(a.amount, decimals)) .toNumber(); }); setDelegations(sortedDelegations); @@ -157,18 +157,18 @@ export const usePollForDelegations = () => { delegatedThisEpoch[d]?.node?.name || delegatedNextEpoch[d]?.node?.name, hasStakePending: !!( - (delegatedThisEpoch[d]?.amountFormatted || - delegatedNextEpoch[d]?.amountFormatted) && - delegatedThisEpoch[d]?.amountFormatted !== - delegatedNextEpoch[d]?.amountFormatted && + (delegatedThisEpoch[d]?.amount || + delegatedNextEpoch[d]?.amount) && + delegatedThisEpoch[d]?.amount !== + delegatedNextEpoch[d]?.amount && delegatedNextEpoch[d] !== undefined ), currentEpochStake: delegatedThisEpoch[d] && - new BigNumber(delegatedThisEpoch[d].amountFormatted), + toBigNum(delegatedThisEpoch[d].amount, decimals), nextEpochStake: delegatedNextEpoch[d] && - new BigNumber(delegatedNextEpoch[d].amountFormatted), + toBigNum(delegatedNextEpoch[d].amount, decimals), })) .sort((a, b) => { if ( diff --git a/apps/token/src/components/vega-wallet/vega-wallet.tsx b/apps/token/src/components/vega-wallet/vega-wallet.tsx index 9e7895972..affe842a2 100644 --- a/apps/token/src/components/vega-wallet/vega-wallet.tsx +++ b/apps/token/src/components/vega-wallet/vega-wallet.tsx @@ -24,6 +24,7 @@ import { DownloadWalletPrompt } from './download-wallet-prompt'; import { usePollForDelegations } from './hooks'; import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet'; import { Button, ButtonLink } from '@vegaprotocol/ui-toolkit'; +import { toBigNum } from '@vegaprotocol/react-helpers'; export const VegaWallet = () => { const { t } = useTranslation(); @@ -128,11 +129,11 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => { const unstaked = React.useMemo(() => { const totalDelegated = delegations.reduce( - (acc, cur) => acc.plus(cur.amountFormatted), + (acc, cur) => acc.plus(toBigNum(cur.amount, decimals)), new BigNumber(0) ); return BigNumber.max(currentStakeAvailable.minus(totalDelegated), 0); - }, [currentStakeAvailable, delegations]); + }, [currentStakeAvailable, decimals, delegations]); const footer = (
diff --git a/apps/token/src/contexts/app-state/app-state-provider.tsx b/apps/token/src/contexts/app-state/app-state-provider.tsx index f63921e73..760ac3904 100644 --- a/apps/token/src/contexts/app-state/app-state-provider.tsx +++ b/apps/token/src/contexts/app-state/app-state-provider.tsx @@ -6,6 +6,7 @@ import type { AppState, AppStateAction } from './app-state-context'; interface AppStateProviderProps { children: React.ReactNode; + initialState?: Partial; } const initialAppState: AppState = { @@ -149,8 +150,14 @@ function appStateReducer(state: AppState, action: AppStateAction): AppState { } } -export function AppStateProvider({ children }: AppStateProviderProps) { - const [state, dispatch] = React.useReducer(appStateReducer, initialAppState); +export function AppStateProvider({ + children, + initialState, +}: AppStateProviderProps) { + const [state, dispatch] = React.useReducer(appStateReducer, { + ...initialAppState, + ...initialState, + }); return ( ; -export type NodeDataQuery = { __typename?: 'Query', nodeData?: { __typename?: 'NodeData', stakedTotal: string, stakedTotalFormatted: string } | null }; +export type NodeDataQuery = { __typename?: 'Query', nodeData?: { __typename?: 'NodeData', stakedTotal: string } | null }; export const NodeDataDocument = gql` query NodeData { nodeData { stakedTotal - stakedTotalFormatted @client } } `; diff --git a/apps/token/src/routes/home/index.tsx b/apps/token/src/routes/home/index.tsx index b29a1da95..a7319b9cb 100644 --- a/apps/token/src/routes/home/index.tsx +++ b/apps/token/src/routes/home/index.tsx @@ -6,11 +6,11 @@ import { Heading } from '../../components/heading'; import { ExternalLinks } from '@vegaprotocol/react-helpers'; import { useAppState } from '../../contexts/app-state/app-state-context'; import { useDocumentTitle } from '../../hooks/use-document-title'; -import { BigNumber } from '../../lib/bignumber'; import type { RouteChildProps } from '..'; import Routes from '../routes'; import { TokenDetails } from './token-details'; import { Button } from '@vegaprotocol/ui-toolkit'; +import { toBigNum } from '@vegaprotocol/react-helpers'; import { useNodeDataQuery } from './__generated___/NodeData'; const Home = ({ name }: RouteChildProps) => { @@ -19,8 +19,8 @@ const Home = ({ name }: RouteChildProps) => { const { appState } = useAppState(); const { data } = useNodeDataQuery(); const totalAssociated = React.useMemo(() => { - return new BigNumber(data?.nodeData?.stakedTotalFormatted || '0'); - }, [data]); + return toBigNum(data?.nodeData?.stakedTotal || '0', appState.decimals); + }, [appState.decimals, data?.nodeData?.stakedTotal]); return ( <> diff --git a/apps/token/src/routes/rewards/home/Rewards.graphql b/apps/token/src/routes/rewards/home/Rewards.graphql index e9e842e24..1f91efc43 100644 --- a/apps/token/src/routes/rewards/home/Rewards.graphql +++ b/apps/token/src/routes/rewards/home/Rewards.graphql @@ -11,14 +11,12 @@ fragment RewardFields on Reward { id } amount - amountFormatted @client percentageOfTotal receivedAt } fragment DelegationFields on Delegation { amount - amountFormatted @client epoch } diff --git a/apps/token/src/routes/rewards/home/__generated___/Rewards.ts b/apps/token/src/routes/rewards/home/__generated___/Rewards.ts index 08edba4a6..2c85138b3 100644 --- a/apps/token/src/routes/rewards/home/__generated___/Rewards.ts +++ b/apps/token/src/routes/rewards/home/__generated___/Rewards.ts @@ -3,16 +3,16 @@ import { Schema as Types } from '@vegaprotocol/types'; import { gql } from '@apollo/client'; import * as Apollo from '@apollo/client'; 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 RewardFieldsFragment = { __typename?: 'Reward', rewardType: Types.AccountType, amount: 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 DelegationFieldsFragment = { __typename?: 'Delegation', amount: string, epoch: number }; export type RewardsQueryVariables = Types.Exact<{ partyId: Types.Scalars['ID']; }>; -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 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: 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, 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` fragment RewardFields on Reward { @@ -28,7 +28,6 @@ export const RewardFieldsFragmentDoc = gql` id } amount - amountFormatted @client percentageOfTotal receivedAt } @@ -36,7 +35,6 @@ export const RewardFieldsFragmentDoc = gql` export const DelegationFieldsFragmentDoc = gql` fragment DelegationFields on Delegation { amount - amountFormatted @client epoch } `; diff --git a/apps/token/src/routes/rewards/home/reward-info.tsx b/apps/token/src/routes/rewards/home/reward-info.tsx index 14abd0b2a..edd141786 100644 --- a/apps/token/src/routes/rewards/home/reward-info.tsx +++ b/apps/token/src/routes/rewards/home/reward-info.tsx @@ -11,6 +11,8 @@ import type { RewardFieldsFragment, DelegationFieldsFragment, } from './__generated___/Rewards'; +import { formatNumber, toBigNum } from '@vegaprotocol/react-helpers'; +import { useAppState } from '../../../contexts/app-state/app-state-context'; interface RewardInfoProps { data: RewardsQuery | undefined; @@ -71,6 +73,9 @@ interface RewardTableProps { export const RewardTable = ({ reward, delegations }: RewardTableProps) => { const { t } = useTranslation(); + const { + appState: { decimals }, + } = useAppState(); // Get your stake for epoch in which you have rewards const stakeForEpoch = React.useMemo(() => { @@ -78,7 +83,7 @@ export const RewardTable = ({ reward, delegations }: RewardTableProps) => { const delegationsForEpoch = delegations .filter((d) => d.epoch.toString() === reward.epoch.id) - .map((d) => new BigNumber(d.amountFormatted)); + .map((d) => toBigNum(d.amount, decimals)); if (delegationsForEpoch.length) { return BigNumber.sum.apply(null, [ @@ -88,7 +93,7 @@ export const RewardTable = ({ reward, delegations }: RewardTableProps) => { } return new BigNumber(0); - }, [delegations, reward.epoch]); + }, [decimals, delegations, reward.epoch.id]); return (
@@ -107,7 +112,7 @@ export const RewardTable = ({ reward, delegations }: RewardTableProps) => { {t('reward')} - {reward.amountFormatted} {t('VEGA')} + {formatNumber(toBigNum(reward.amount, decimals))} {t('VEGA')} diff --git a/apps/token/src/routes/staking/home/Nodes.graphql b/apps/token/src/routes/staking/home/Nodes.graphql index 1fc91a2ca..d387cc0a9 100644 --- a/apps/token/src/routes/staking/home/Nodes.graphql +++ b/apps/token/src/routes/staking/home/Nodes.graphql @@ -4,9 +4,7 @@ fragment NodesFragment on Node { name pubkey stakedTotal - stakedTotalFormatted @client pendingStake - pendingStakeFormatted @client rankingScore { rankingScore stakeScore @@ -34,6 +32,5 @@ query Nodes { } nodeData { stakedTotal - stakedTotalFormatted @client } } diff --git a/apps/token/src/routes/staking/home/__generated___/Nodes.ts b/apps/token/src/routes/staking/home/__generated___/Nodes.ts index cf40abf42..a3d62d593 100644 --- a/apps/token/src/routes/staking/home/__generated___/Nodes.ts +++ b/apps/token/src/routes/staking/home/__generated___/Nodes.ts @@ -3,12 +3,12 @@ import { Schema as Types } from '@vegaprotocol/types'; import { gql } from '@apollo/client'; import * as Apollo from '@apollo/client'; const defaultOptions = {} as const; -export type NodesFragmentFragment = { __typename?: 'Node', avatarUrl?: string | null, id: string, name: string, pubkey: string, stakedTotal: string, stakedTotalFormatted: string, pendingStake: string, pendingStakeFormatted: string, rankingScore: { __typename?: 'RankingScore', rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string, status: Types.ValidatorStatus } }; +export type NodesFragmentFragment = { __typename?: 'Node', avatarUrl?: string | null, id: string, name: string, pubkey: string, stakedTotal: string, pendingStake: string, rankingScore: { __typename?: 'RankingScore', rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string, status: Types.ValidatorStatus } }; export type NodesQueryVariables = Types.Exact<{ [key: string]: never; }>; -export type NodesQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, timestamps: { __typename?: 'EpochTimestamps', start?: string | null, end?: string | null, expiry?: string | null } }, nodesConnection: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', avatarUrl?: string | null, id: string, name: string, pubkey: string, stakedTotal: string, stakedTotalFormatted: string, pendingStake: string, pendingStakeFormatted: string, rankingScore: { __typename?: 'RankingScore', rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string, status: Types.ValidatorStatus } } } | null> | null }, nodeData?: { __typename?: 'NodeData', stakedTotal: string, stakedTotalFormatted: string } | null }; +export type NodesQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, timestamps: { __typename?: 'EpochTimestamps', start?: string | null, end?: string | null, expiry?: string | null } }, nodesConnection: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', avatarUrl?: string | null, id: string, name: string, pubkey: string, stakedTotal: string, pendingStake: string, rankingScore: { __typename?: 'RankingScore', rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string, status: Types.ValidatorStatus } } } | null> | null }, nodeData?: { __typename?: 'NodeData', stakedTotal: string } | null }; export const NodesFragmentFragmentDoc = gql` fragment NodesFragment on Node { @@ -17,9 +17,7 @@ export const NodesFragmentFragmentDoc = gql` name pubkey stakedTotal - stakedTotalFormatted @client pendingStake - pendingStakeFormatted @client rankingScore { rankingScore stakeScore @@ -48,7 +46,6 @@ export const NodesDocument = gql` } nodeData { stakedTotal - stakedTotalFormatted @client } } ${NodesFragmentFragmentDoc}`; diff --git a/apps/token/src/routes/staking/home/node-list.spec.tsx b/apps/token/src/routes/staking/home/node-list.spec.tsx index b3bab1b74..45dc90245 100644 --- a/apps/token/src/routes/staking/home/node-list.spec.tsx +++ b/apps/token/src/routes/staking/home/node-list.spec.tsx @@ -3,11 +3,11 @@ import merge from 'lodash/merge'; import { NodeList } from './node-list'; import { MockedProvider } from '@apollo/client/testing'; import { MemoryRouter } from 'react-router-dom'; -import { addDecimal } from '@vegaprotocol/react-helpers'; import type { PartialDeep } from 'type-fest'; import type { NodesFragmentFragment } from './__generated___/Nodes'; import { NodesDocument } from './__generated___/Nodes'; import { Schema } from '@vegaprotocol/types'; +import { AppStateProvider } from '../../../contexts/app-state/app-state-provider'; jest.mock('../../../components/epoch-countdown', () => ({ EpochCountdown: () =>
, @@ -20,9 +20,7 @@ const nodeFactory = (overrides?: PartialDeep) => { avatarUrl: 'https://upload.wikimedia.org/wikipedia/en/2/25/Marvin-TV-3.jpg', pubkey: '6abc23391a9f888ab240415bf63d6844b03fc360be822f4a1d2cd832d87b2917', stakedTotal: '14182454495731682635157', - stakedTotalFormatted: addDecimal('14182454495731682635157', 18), pendingStake: '0', - pendingStakeFormatted: addDecimal('0', 18), rankingScore: { rankingScore: '0.67845061012234727427532760837568', stakeScore: '0.3392701644525644', @@ -48,7 +46,6 @@ const MOCK_NODES = { pubkey: 'ccc3b8362c25b09d20df8ea407b0a476d6b24a0e72bc063d0033c8841652ddd4', stakedTotal: '9618711883996159534058', - stakedTotalFormatted: addDecimal('9618711883996159534058', 18), rankingScore: { rankingScore: '0.4601942440481428', stakeScore: '0.2300971220240714', @@ -64,7 +61,6 @@ const MOCK_NODES = { pubkey: '0931a8fd8cc935458f470e435a05414387cea6f329d648be894fcd44bd517a2b', stakedTotal: '4041343338923442976709', - stakedTotalFormatted: addDecimal('4041343338923442976709', 18), pendingStake: '0', rankingScore: { rankingScore: '0.1932810100133910357676209647912', @@ -79,7 +75,6 @@ const MOCK_NODES = { }, nodeData: { stakedTotal: '27842509718651285145924', - stakedTotalFormatted: addDecimal('27842509718651285145924', 18), totalNodes: 3, inactiveNodes: 0, validatingNodes: 3, @@ -100,18 +95,20 @@ const MOCK_NODES = { const renderNodeList = (data = MOCK_NODES) => { return render( - - - - - + + + + + + + ); }; @@ -165,7 +162,6 @@ describe('Nodes list', () => { pubkey: 'ccc3b8362c25b09d20df8ea407b0a476d6b24a0e72bc063d0033c8841652ddd4', stakedTotal: '9618711883996159534058', - stakedTotalFormatted: addDecimal('9618711883996159534058', 18), rankingScore: { rankingScore: '0.4601942440481428', stakeScore: '0.2300971220240714', @@ -179,7 +175,6 @@ describe('Nodes list', () => { }, nodeData: { stakedTotal: '9618711883996159534058', - stakedTotalFormatted: addDecimal('9618711883996159534058', 18), totalNodes: 1, inactiveNodes: 0, validatingNodes: 1, diff --git a/apps/token/src/routes/staking/home/node-list.tsx b/apps/token/src/routes/staking/home/node-list.tsx index f728081f9..c775c8c8c 100644 --- a/apps/token/src/routes/staking/home/node-list.tsx +++ b/apps/token/src/routes/staking/home/node-list.tsx @@ -10,10 +10,11 @@ import { } from '@vegaprotocol/ui-toolkit'; import { EpochCountdown } from '../../../components/epoch-countdown'; import { BigNumber } from '../../../lib/bignumber'; -import { formatNumber } from '@vegaprotocol/react-helpers'; +import { formatNumber, toBigNum } from '@vegaprotocol/react-helpers'; import { Schema } from '@vegaprotocol/types'; -import { useNodesQuery } from './__generated___/Nodes'; import type { ColDef } from 'ag-grid-community'; +import { useNodesQuery } from './__generated___/Nodes'; +import { useAppState } from '../../../contexts/app-state/app-state-context'; const VALIDATOR = 'validator'; const STATUS = 'status'; @@ -89,6 +90,9 @@ export const NodeList = () => { // errorPolicy due to vegaprotocol/vega issue 5898 const { data, error, loading, refetch } = useNodesQuery(); const navigate = useNavigate(); + const { + appState: { decimals }, + } = useAppState(); const [hideTopThird, setHideTopThird] = useState(true); useEffect(() => { @@ -117,7 +121,7 @@ export const NodeList = () => { id, name, avatarUrl, - stakedTotalFormatted, + stakedTotal, rankingScore: { rankingScore, stakeScore, @@ -125,18 +129,22 @@ export const NodeList = () => { performanceScore, votingPower, }, - pendingStakeFormatted, + pendingStake, }, }) => { - const stakedTotal = new BigNumber( - data?.nodeData?.stakedTotalFormatted || 0 + const stakedTotalNum = toBigNum( + data?.nodeData?.stakedTotal || 0, + decimals ); - const stakedOnNode = new BigNumber(stakedTotalFormatted); + const stakedOnNode = toBigNum(stakedTotal, decimals); const stakedTotalPercentage = - stakedTotal.isEqualTo(0) || stakedOnNode.isEqualTo(0) + stakedTotalNum.isEqualTo(0) || stakedOnNode.isEqualTo(0) ? '-' - : stakedOnNode.dividedBy(stakedTotal).times(100).dp(2).toString() + - '%'; + : stakedOnNode + .dividedBy(stakedTotalNum) + .times(100) + .dp(2) + .toString() + '%'; const translatedStatus = t(statusTranslationKey(status)); return { @@ -146,10 +154,13 @@ export const NodeList = () => { name, }, [STATUS]: translatedStatus, - [TOTAL_STAKE_THIS_EPOCH]: formatNumber(stakedTotalFormatted, 2), + [TOTAL_STAKE_THIS_EPOCH]: formatNumber( + toBigNum(stakedTotal, decimals), + 2 + ), [SHARE]: stakedTotalPercentage, [VALIDATOR_STAKE]: formatNumber(stakedOnNode, 2), - [PENDING_STAKE]: formatNumber(pendingStakeFormatted, 2), + [PENDING_STAKE]: formatNumber(toBigNum(pendingStake, decimals), 2), [RANKING_SCORE]: formatNumber(new BigNumber(rankingScore), 5), [STAKE_SCORE]: formatNumber(new BigNumber(stakeScore), 5), [PERFORMANCE_SCORE]: formatNumber(new BigNumber(performanceScore), 5), @@ -190,8 +201,9 @@ export const NodeList = () => { return removeTopThirdOfStakeScores.remaining; }, [ - data?.nodeData?.stakedTotalFormatted, + data?.nodeData?.stakedTotal, data?.nodesConnection.edges, + decimals, hideTopThird, t, ]); diff --git a/apps/token/src/routes/staking/node/PartyDelegations.graphql b/apps/token/src/routes/staking/node/PartyDelegations.graphql index 6ae421bd9..80dd2114f 100644 --- a/apps/token/src/routes/staking/node/PartyDelegations.graphql +++ b/apps/token/src/routes/staking/node/PartyDelegations.graphql @@ -1,6 +1,5 @@ fragment StakingDelegationsFields on Delegation { amount - amountFormatted @client node { id } diff --git a/apps/token/src/routes/staking/node/Staking.graphql b/apps/token/src/routes/staking/node/Staking.graphql index d3cdc21ae..35a9857bf 100644 --- a/apps/token/src/routes/staking/node/Staking.graphql +++ b/apps/token/src/routes/staking/node/Staking.graphql @@ -9,10 +9,6 @@ fragment StakingNodeFields on Node { stakedByDelegates stakedTotal pendingStake - stakedByOperatorFormatted @client - stakedByDelegatesFormatted @client - stakedTotalFormatted @client - pendingStakeFormatted @client epochData { total offline @@ -37,7 +33,6 @@ query Staking($partyId: ID!) { edges { node { amount - amountFormatted @client epoch node { id @@ -63,7 +58,6 @@ query Staking($partyId: ID!) { } nodeData { stakedTotal - stakedTotalFormatted @client totalNodes inactiveNodes validatingNodes diff --git a/apps/token/src/routes/staking/node/__generated___/PartyDelegations.ts b/apps/token/src/routes/staking/node/__generated___/PartyDelegations.ts index a42326ad2..17ba74bac 100644 --- a/apps/token/src/routes/staking/node/__generated___/PartyDelegations.ts +++ b/apps/token/src/routes/staking/node/__generated___/PartyDelegations.ts @@ -3,19 +3,18 @@ import { Schema as Types } from '@vegaprotocol/types'; import { gql } from '@apollo/client'; import * as Apollo from '@apollo/client'; const defaultOptions = {} as const; -export type StakingDelegationsFieldsFragment = { __typename?: 'Delegation', amount: string, amountFormatted: string, epoch: number, node: { __typename?: 'Node', id: string } }; +export type StakingDelegationsFieldsFragment = { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string } }; export type PartyDelegationsQueryVariables = Types.Exact<{ partyId: Types.Scalars['ID']; }>; -export type PartyDelegationsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, amountFormatted: string, epoch: number, node: { __typename?: 'Node', id: string } } } | null> | null } | null } | null, epoch: { __typename?: 'Epoch', id: string } }; +export type PartyDelegationsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string } } } | null> | null } | null } | null, epoch: { __typename?: 'Epoch', id: string } }; export const StakingDelegationsFieldsFragmentDoc = gql` fragment StakingDelegationsFields on Delegation { amount - amountFormatted @client node { id } diff --git a/apps/token/src/routes/staking/node/__generated___/Staking.ts b/apps/token/src/routes/staking/node/__generated___/Staking.ts index 3083d8918..efbb710e3 100644 --- a/apps/token/src/routes/staking/node/__generated___/Staking.ts +++ b/apps/token/src/routes/staking/node/__generated___/Staking.ts @@ -24,10 +24,6 @@ export const StakingNodeFieldsFragmentDoc = gql` stakedByDelegates stakedTotal pendingStake - stakedByOperatorFormatted @client - stakedByDelegatesFormatted @client - stakedTotalFormatted @client - pendingStakeFormatted @client epochData { total offline @@ -53,7 +49,6 @@ export const StakingDocument = gql` edges { node { amount - amountFormatted @client epoch node { id @@ -79,7 +74,6 @@ export const StakingDocument = gql` } nodeData { stakedTotal - stakedTotalFormatted @client totalNodes inactiveNodes validatingNodes diff --git a/apps/token/src/routes/staking/node/node.tsx b/apps/token/src/routes/staking/node/node.tsx index 7c88afbed..574749283 100644 --- a/apps/token/src/routes/staking/node/node.tsx +++ b/apps/token/src/routes/staking/node/node.tsx @@ -11,7 +11,7 @@ import { YourStake } from './your-stake'; import NodeContainer from './nodes-container'; import { useVegaWallet } from '@vegaprotocol/wallet'; import { useAppState } from '../../../contexts/app-state/app-state-context'; -import { toBigNum } from '@vegaprotocol/react-helpers'; +import { addDecimal, toBigNum } from '@vegaprotocol/react-helpers'; import compact from 'lodash/compact'; import type { StakingQuery } from './__generated___/Staking'; @@ -48,29 +48,29 @@ export const StakingNode = ({ data }: StakingNodeProps) => { const amountsThisEpoch = delegations .filter((d) => d.node.id === node) .filter((d) => d.epoch === Number(currentEpoch)) - .map((d) => new BigNumber(d.amountFormatted)); + .map((d) => toBigNum(d.amount, decimals)); return BigNumber.sum.apply(null, [new BigNumber(0), ...amountsThisEpoch]); - }, [delegations, node, currentEpoch]); + }, [delegations, node, currentEpoch, decimals]); const stakeNextEpoch = React.useMemo(() => { const amountsNextEpoch = delegations .filter((d) => d.node.id === node) .filter((d) => d.epoch === Number(currentEpoch) + 1) - .map((d) => new BigNumber(d.amountFormatted)); + .map((d) => toBigNum(d.amount, decimals)); if (!amountsNextEpoch.length) { return stakeThisEpoch; } return BigNumber.sum.apply(null, [new BigNumber(0), ...amountsNextEpoch]); - }, [currentEpoch, delegations, node, stakeThisEpoch]); + }, [currentEpoch, decimals, delegations, node, stakeThisEpoch]); const currentDelegationAmount = React.useMemo(() => { if (delegations.length < 1) return new BigNumber(0); const amounts = delegations .filter((d) => d.epoch === Number(currentEpoch) + 1) - .map((d) => new BigNumber(d.amountFormatted)); + .map((d) => toBigNum(d.amount, decimals)); return BigNumber.sum.apply(null, [new BigNumber(0), ...amounts]); - }, [currentEpoch, delegations]); + }, [currentEpoch, decimals, delegations]); const unstaked = React.useMemo(() => { const value = toBigNum( @@ -102,7 +102,7 @@ export const StakingNode = ({ data }: StakingNodeProps) => {
diff --git a/apps/token/src/routes/staking/node/validator-table.tsx b/apps/token/src/routes/staking/node/validator-table.tsx index 4b9a647f5..88fb654d3 100644 --- a/apps/token/src/routes/staking/node/validator-table.tsx +++ b/apps/token/src/routes/staking/node/validator-table.tsx @@ -8,6 +8,8 @@ import { BigNumber } from '../../../lib/bignumber'; import { formatNumber } from '../../../lib/format-number'; import { statusTranslationKey } from '../home/node-list'; import type { StakingNodeFieldsFragment } from './__generated___/Staking'; +import { toBigNum } from '@vegaprotocol/react-helpers'; +import { useAppState } from '../../../contexts/app-state/app-state-context'; const ValidatorTableCell = ({ children, @@ -34,15 +36,18 @@ export const ValidatorTable = ({ }: ValidatorTableProps) => { const { ETHERSCAN_URL } = useEnvironment(); const { t } = useTranslation(); + const { + appState: { decimals }, + } = useAppState(); const stakePercentage = React.useMemo(() => { const total = new BigNumber(stakedTotal); - const stakedOnNode = new BigNumber(node.stakedTotalFormatted); + const stakedOnNode = toBigNum(node.stakedTotal, decimals); const stakedTotalPercentage = total.isEqualTo(0) || stakedOnNode.isEqualTo(0) ? '-' : stakedOnNode.dividedBy(total).times(100).dp(2).toString() + '%'; return stakedTotalPercentage; - }, [node.stakedTotalFormatted, stakedTotal]); + }, [decimals, node.stakedTotal, stakedTotal]); return ( @@ -86,22 +91,26 @@ export const ValidatorTable = ({
{t('TOTAL STAKE')} - {node.stakedTotalFormatted} + + {formatNumber(toBigNum(node.stakedTotal, decimals))} + {t('PENDING STAKE')} - {node.pendingStakeFormatted} + + {formatNumber(toBigNum(node.pendingStake, decimals))} + {t('STAKED BY OPERATOR')} - {node.stakedByOperatorFormatted} + {formatNumber(toBigNum(node.stakedByOperator, decimals))} {t('STAKED BY DELEGATES')} - {node.stakedByDelegatesFormatted} + {formatNumber(toBigNum(node.stakedByDelegates, 18))} @@ -115,7 +124,7 @@ export const ValidatorTable = ({ {t('NOMINATED (THIS EPOCH)')} - {node.stakedByDelegatesFormatted} + {formatNumber(toBigNum(node.stakedByDelegates, decimals))} diff --git a/libs/types/src/__generated__/types.ts b/libs/types/src/__generated__/types.ts index 08ed5625d..f99bb374e 100644 --- a/libs/types/src/__generated__/types.ts +++ b/libs/types/src/__generated__/types.ts @@ -21,8 +21,6 @@ export type AccountBalance = { asset: Asset; /** Balance as string - current account balance (approx. as balances can be updated several times per second) */ balance: Scalars['String']; - /** The balance field formatted by the client */ - balanceFormatted: Scalars['String']; /** Market (only relevant to margin accounts) */ market?: Maybe; /** Owner of the account */ @@ -596,8 +594,6 @@ export type Delegation = { __typename?: 'Delegation'; /** Amount delegated */ amount: Scalars['String']; - /** The amount field formatted by the client */ - amountFormatted: Scalars['String']; /** Epoch of delegation */ epoch: Scalars['Int']; /** URL of node you are delegating to */ @@ -1906,8 +1902,6 @@ export type Node = { name: Scalars['String']; /** Amount of stake on the next epoch */ pendingStake: Scalars['String']; - /** The pending staked field formatted by the client */ - pendingStakeFormatted: Scalars['String']; /** Public key of the node operator */ pubkey: Scalars['String']; /** Ranking scores and status for the validator for the current epoch */ @@ -1916,16 +1910,10 @@ export type Node = { rewardScore?: Maybe; /** The amount of stake that has been delegated by token holders */ stakedByDelegates: Scalars['String']; - /** The stakes by delegates field formatted by the client */ - stakedByDelegatesFormatted: Scalars['String']; /** The amount of stake the node has put up themselves */ stakedByOperator: Scalars['String']; - /** The stakes by operator field formatted by the client */ - stakedByOperatorFormatted: Scalars['String']; /** Total amount staked on node */ stakedTotal: Scalars['String']; - /** The total staked field formatted by the client */ - stakedTotalFormatted: Scalars['String']; /** Validator status of the node */ status: NodeStatus; /** Tendermint public key of the node */ @@ -1955,8 +1943,6 @@ export type NodeData = { inactiveNodes: Scalars['Int']; /** Total staked amount across all nodes */ stakedTotal: Scalars['String']; - /** The total staked field formatted by the client */ - stakedTotalFormatted: Scalars['String']; /** Total number of nodes */ totalNodes: Scalars['Int']; /** Total uptime for all epochs across all nodes. Or specify a number of epochs */ @@ -3916,8 +3902,6 @@ export type Reward = { __typename?: 'Reward'; /** Amount received for this reward */ amount: Scalars['String']; - /** The amount field formatted by the client */ - amountFormatted: Scalars['String']; /** The asset this reward is paid in */ asset: Asset; /** Epoch for which this reward was distributed */ @@ -3957,8 +3941,6 @@ export type RewardPerAssetDetail = { rewards?: Maybe>>; /** The total amount of rewards received for this asset. */ totalAmount: Scalars['String']; - /** The total amount field formatted by the client */ - totalAmountFormatted: Scalars['String']; }; export type RewardScore = {