diff --git a/apps/explorer/src/app/routes/parties/id/__generated__/PartyAssetsQuery.ts b/apps/explorer/src/app/routes/parties/id/__generated__/PartyAssetsQuery.ts index 052dda376..0a5e18f85 100644 --- a/apps/explorer/src/app/routes/parties/id/__generated__/PartyAssetsQuery.ts +++ b/apps/explorer/src/app/routes/parties/id/__generated__/PartyAssetsQuery.ts @@ -9,31 +9,6 @@ import { AccountType } from "@vegaprotocol/types"; // GraphQL query operation: PartyAssetsQuery // ==================================================== -export interface PartyAssetsQuery_party_delegations_node { - __typename: "Node"; - /** - * The node URL eg n01.vega.xyz - */ - id: string; - name: string; -} - -export interface PartyAssetsQuery_party_delegations { - __typename: "Delegation"; - /** - * Amount delegated - */ - amount: string; - /** - * URL of node you are delegating to - */ - node: PartyAssetsQuery_party_delegations_node; - /** - * Epoch of delegation - */ - epoch: number; -} - export interface PartyAssetsQuery_party_stakingSummary { __typename: "StakingSummary"; /** @@ -102,7 +77,6 @@ export interface PartyAssetsQuery_party { * Party identifier */ id: string; - delegations: PartyAssetsQuery_party_delegations[] | null; /** * The staking information for this Party */ diff --git a/apps/explorer/src/app/routes/parties/id/index.tsx b/apps/explorer/src/app/routes/parties/id/index.tsx index b84c5ba07..c5f381d37 100644 --- a/apps/explorer/src/app/routes/parties/id/index.tsx +++ b/apps/explorer/src/app/routes/parties/id/index.tsx @@ -27,14 +27,6 @@ const PARTY_ASSETS_QUERY = gql` query PartyAssetsQuery($partyId: ID!) { party(id: $partyId) { id - delegations { - amount - node { - id - name - } - epoch - } stakingSummary { currentStakeAvailable } diff --git a/apps/token/src/components/vega-wallet/Delegations.graphql b/apps/token/src/components/vega-wallet/Delegations.graphql index 9425fb405..851c321e5 100644 --- a/apps/token/src/components/vega-wallet/Delegations.graphql +++ b/apps/token/src/components/vega-wallet/Delegations.graphql @@ -1,17 +1,25 @@ +fragment WalletDelegationFields on Delegation { + amountFormatted @client + amount + node { + id + name + } + epoch +} + query Delegations($partyId: ID!) { epoch { id } party(id: $partyId) { id - delegations { - amountFormatted @client - amount - node { - id - name + delegationsConnection { + edges { + node { + ...WalletDelegationFields + } } - epoch } stakingSummary { currentStakeAvailable diff --git a/apps/token/src/components/vega-wallet/__generated__/Delegations.ts b/apps/token/src/components/vega-wallet/__generated__/Delegations.ts index 5c3fc39d1..6cddf9ec8 100644 --- a/apps/token/src/components/vega-wallet/__generated__/Delegations.ts +++ b/apps/token/src/components/vega-wallet/__generated__/Delegations.ts @@ -17,7 +17,7 @@ export interface Delegations_epoch { id: string; } -export interface Delegations_party_delegations_node { +export interface Delegations_party_delegationsConnection_edges_node_node { __typename: "Node"; /** * The node URL eg n01.vega.xyz @@ -26,7 +26,7 @@ export interface Delegations_party_delegations_node { name: string; } -export interface Delegations_party_delegations { +export interface Delegations_party_delegationsConnection_edges_node { __typename: "Delegation"; /** * The amount field formatted by the client @@ -39,13 +39,29 @@ export interface Delegations_party_delegations { /** * URL of node you are delegating to */ - node: Delegations_party_delegations_node; + node: Delegations_party_delegationsConnection_edges_node_node; /** * Epoch of delegation */ epoch: number; } +export interface Delegations_party_delegationsConnection_edges { + __typename: "DelegationEdge"; + /** + * The delegation information + */ + node: Delegations_party_delegationsConnection_edges_node; +} + +export interface Delegations_party_delegationsConnection { + __typename: "DelegationsConnection"; + /** + * The delegation information available on this connection + */ + edges: (Delegations_party_delegationsConnection_edges | null)[] | null; +} + export interface Delegations_party_stakingSummary { __typename: "StakingSummary"; /** @@ -114,7 +130,7 @@ export interface Delegations_party { * Party identifier */ id: string; - delegations: Delegations_party_delegations[] | null; + delegationsConnection: Delegations_party_delegationsConnection | null; /** * The staking information for this Party */ diff --git a/apps/token/src/components/vega-wallet/__generated___/Delegations.ts b/apps/token/src/components/vega-wallet/__generated___/Delegations.ts index 26cb13e22..a5b8bbacc 100644 --- a/apps/token/src/components/vega-wallet/__generated___/Delegations.ts +++ b/apps/token/src/components/vega-wallet/__generated___/Delegations.ts @@ -3,14 +3,26 @@ 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 DelegationsQueryVariables = Types.Exact<{ partyId: Types.Scalars['ID']; }>; -export type DelegationsQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string }, party?: { __typename?: 'Party', id: string, delegations?: Array<{ __typename?: 'Delegation', amountFormatted: string, amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } }> | null, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string }, accounts?: Array<{ __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 }; - +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 }, accounts?: Array<{ __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 }; +export const WalletDelegationFieldsFragmentDoc = gql` + fragment WalletDelegationFields on Delegation { + amountFormatted @client + amount + node { + id + name + } + epoch +} + `; export const DelegationsDocument = gql` query Delegations($partyId: ID!) { epoch { @@ -18,14 +30,12 @@ export const DelegationsDocument = gql` } party(id: $partyId) { id - delegations { - amountFormatted @client - amount - node { - id - name + delegationsConnection { + edges { + node { + ...WalletDelegationFields + } } - epoch } stakingSummary { currentStakeAvailable @@ -48,7 +58,7 @@ export const DelegationsDocument = gql` } } } - `; + ${WalletDelegationFieldsFragmentDoc}`; /** * __useDelegationsQuery__ diff --git a/apps/token/src/components/vega-wallet/hooks.ts b/apps/token/src/components/vega-wallet/hooks.ts index ea611cc65..79ad79b87 100644 --- a/apps/token/src/components/vega-wallet/hooks.ts +++ b/apps/token/src/components/vega-wallet/hooks.ts @@ -4,6 +4,7 @@ import keyBy from 'lodash/keyBy'; import uniq from 'lodash/uniq'; import React from 'react'; import { useTranslation } from 'react-i18next'; +import compact from 'lodash/compact'; import noIcon from '../../images/token-no-icon.png'; import vegaBlack from '../../images/vega_black.png'; @@ -11,7 +12,7 @@ import { BigNumber } from '../../lib/bignumber'; import type { WalletCardAssetProps } from '../wallet-card'; import type { Delegations, - Delegations_party_delegations, + Delegations_party_delegationsConnection_edges_node, DelegationsVariables, } from './__generated__/Delegations'; import { useVegaWallet } from '@vegaprotocol/wallet'; @@ -30,14 +31,18 @@ const DELEGATIONS_QUERY = gql` } party(id: $partyId) { id - delegations { - amountFormatted @client - amount - node { - id - name + delegationsConnection { + edges { + node { + amountFormatted @client + amount + node { + id + name + } + epoch + } } - epoch } stakingSummary { currentStakeAvailable @@ -72,7 +77,7 @@ export const usePollForDelegations = () => { const { pubKey } = useVegaWallet(); const client = useApolloClient(); const [delegations, setDelegations] = React.useState< - Delegations_party_delegations[] + Delegations_party_delegationsConnection_edges_node[] >([]); const [delegatedNodes, setDelegatedNodes] = React.useState< { @@ -103,8 +108,11 @@ export const usePollForDelegations = () => { }) .then((res) => { if (!mounted) return; + const canonisedDelegations = compact( + res.data.party?.delegationsConnection?.edges + ).map(({ node }) => node); const filter = - res.data.party?.delegations?.filter((d) => { + canonisedDelegations.filter((d) => { return d.epoch.toString() === res.data.epoch.id; }) || []; const sortedDelegations = [...filter].sort((a, b) => { @@ -164,13 +172,13 @@ export const usePollForDelegations = () => { }) ); const delegatedNextEpoch = keyBy( - res.data.party?.delegations?.filter((d) => { + canonisedDelegations.filter((d) => { return d.epoch === Number(res.data.epoch.id) + 1; }) || [], 'node.id' ); const delegatedThisEpoch = keyBy( - res.data.party?.delegations?.filter((d) => { + canonisedDelegations.filter((d) => { return d.epoch === Number(res.data.epoch.id); }) || [], 'node.id' diff --git a/apps/token/src/routes/staking/node/PartyDelegations.graphql b/apps/token/src/routes/staking/node/PartyDelegations.graphql index c083a9a40..6ae421bd9 100644 --- a/apps/token/src/routes/staking/node/PartyDelegations.graphql +++ b/apps/token/src/routes/staking/node/PartyDelegations.graphql @@ -1,13 +1,21 @@ +fragment StakingDelegationsFields on Delegation { + amount + amountFormatted @client + node { + id + } + epoch +} + query PartyDelegations($partyId: ID!) { party(id: $partyId) { id - delegations { - amount - amountFormatted @client - node { - id + delegationsConnection { + edges { + node { + ...StakingDelegationsFields + } } - epoch } } epoch { diff --git a/apps/token/src/routes/staking/node/Staking.graphql b/apps/token/src/routes/staking/node/Staking.graphql index f64179085..1ac0a5e35 100644 --- a/apps/token/src/routes/staking/node/Staking.graphql +++ b/apps/token/src/routes/staking/node/Staking.graphql @@ -1,15 +1,49 @@ +fragment StakingNodeFields on Node { + id + name + pubkey + infoUrl + location + ethereumAddress + stakedByOperator + stakedByDelegates + stakedTotal + pendingStake + stakedByOperatorFormatted @client + stakedByDelegatesFormatted @client + stakedTotalFormatted @client + pendingStakeFormatted @client + epochData { + total + offline + online + } + status + rankingScore { + rankingScore + stakeScore + performanceScore + votingPower + stakeScore + } +} + query Staking($partyId: ID!) { party(id: $partyId) { id stakingSummary { currentStakeAvailable } - delegations { - amount - amountFormatted @client - epoch - node { - id + delegationsConnection { + edges { + node { + amount + amountFormatted @client + epoch + node { + id + } + } } } } @@ -24,33 +58,7 @@ query Staking($partyId: ID!) { nodesConnection { edges { node { - id - name - pubkey - infoUrl - location - ethereumAddress - stakedByOperator - stakedByDelegates - stakedTotal - pendingStake - stakedByOperatorFormatted @client - stakedByDelegatesFormatted @client - stakedTotalFormatted @client - pendingStakeFormatted @client - epochData { - total - offline - online - } - status - rankingScore { - rankingScore - stakeScore - performanceScore - votingPower - stakeScore - } + ...StakingNodeFields } } } diff --git a/apps/token/src/routes/staking/node/__generated__/PartyDelegations.ts b/apps/token/src/routes/staking/node/__generated__/PartyDelegations.ts deleted file mode 100644 index 0a82c1232..000000000 --- a/apps/token/src/routes/staking/node/__generated__/PartyDelegations.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// @generated -// This file was automatically generated and should not be edited. - -// ==================================================== -// GraphQL query operation: PartyDelegations -// ==================================================== - -export interface PartyDelegations_party_delegations_node { - __typename: "Node"; - /** - * The node URL eg n01.vega.xyz - */ - id: string; -} - -export interface PartyDelegations_party_delegations { - __typename: "Delegation"; - /** - * Amount delegated - */ - amount: string; - /** - * The amount field formatted by the client - */ - amountFormatted: string; - /** - * URL of node you are delegating to - */ - node: PartyDelegations_party_delegations_node; - /** - * Epoch of delegation - */ - epoch: number; -} - -export interface PartyDelegations_party { - __typename: "Party"; - /** - * Party identifier - */ - id: string; - delegations: PartyDelegations_party_delegations[] | null; -} - -export interface PartyDelegations_epoch { - __typename: "Epoch"; - /** - * Numeric sequence number used to identify the epoch - */ - id: string; -} - -export interface PartyDelegations { - /** - * An entity that is trading on the Vega network - */ - party: PartyDelegations_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: PartyDelegations_epoch; -} - -export interface PartyDelegationsVariables { - partyId: string; -} diff --git a/apps/token/src/routes/staking/node/__generated__/Staking.ts b/apps/token/src/routes/staking/node/__generated__/Staking.ts deleted file mode 100644 index 8cbcace6e..000000000 --- a/apps/token/src/routes/staking/node/__generated__/Staking.ts +++ /dev/null @@ -1,259 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// @generated -// This file was automatically generated and should not be edited. - -import { NodeStatus } from "@vegaprotocol/types"; - -// ==================================================== -// GraphQL query operation: Staking -// ==================================================== - -export interface Staking_party_stakingSummary { - __typename: "StakingSummary"; - /** - * The stake currently available for the party - */ - currentStakeAvailable: string; -} - -export interface Staking_party_delegations_node { - __typename: "Node"; - /** - * The node URL eg n01.vega.xyz - */ - id: string; -} - -export interface Staking_party_delegations { - __typename: "Delegation"; - /** - * Amount delegated - */ - amount: string; - /** - * The amount field formatted by the client - */ - amountFormatted: string; - /** - * Epoch of delegation - */ - epoch: number; - /** - * URL of node you are delegating to - */ - node: Staking_party_delegations_node; -} - -export interface Staking_party { - __typename: "Party"; - /** - * Party identifier - */ - id: string; - /** - * The staking information for this Party - */ - stakingSummary: Staking_party_stakingSummary; - delegations: Staking_party_delegations[] | null; -} - -export interface Staking_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 Staking_epoch { - __typename: "Epoch"; - /** - * Numeric sequence number used to identify the epoch - */ - id: string; - /** - * Timestamps for start and end of epochs - */ - timestamps: Staking_epoch_timestamps; -} - -export interface Staking_nodesConnection_edges_node_epochData { - __typename: "EpochData"; - /** - * Total number of epochs since node was created - */ - total: number; - /** - * Total number of offline epochs since node was created - */ - offline: number; - /** - * Total number of online epochs since node was created - */ - online: number; -} - -export interface Staking_nodesConnection_edges_node_rankingScore { - __typename: "RankingScore"; - /** - * The ranking score of the validator - */ - rankingScore: string; - /** - * The stake based score of the validator (no anti-whaling) - */ - stakeScore: string; - /** - * The performance score of the validator - */ - performanceScore: string; - /** - * The Tendermint voting power of the validator (uint32) - */ - votingPower: string; -} - -export interface Staking_nodesConnection_edges_node { - __typename: "Node"; - /** - * The node URL eg n01.vega.xyz - */ - id: string; - name: string; - /** - * Public key of the node operator - */ - pubkey: string; - /** - * URL from which you can get more info about the node. - */ - infoUrl: string; - /** - * Country code for the location of the node - */ - location: string; - /** - * Ethereum public key of the node - */ - ethereumAddress: string; - /** - * The amount of stake the node has put up themselves - */ - stakedByOperator: string; - /** - * The amount of stake that has been delegated by token holders - */ - stakedByDelegates: string; - /** - * Total amount staked on node - */ - stakedTotal: string; - /** - * Amount of stake on the next epoch - */ - pendingStake: string; - /** - * The stakes by operator field formatted by the client - */ - stakedByOperatorFormatted: string; - /** - * The stakes by delegates field formatted by the client - */ - stakedByDelegatesFormatted: string; - /** - * The total staked field formatted by the client - */ - stakedTotalFormatted: string; - /** - * The pending staked field formatted by the client - */ - pendingStakeFormatted: string; - /** - * Summary of epoch data across all nodes - */ - epochData: Staking_nodesConnection_edges_node_epochData | null; - /** - * Validator status of the node - */ - status: NodeStatus; - /** - * Ranking scores and status for the validator for the current epoch - */ - rankingScore: Staking_nodesConnection_edges_node_rankingScore; -} - -export interface Staking_nodesConnection_edges { - __typename: "NodeEdge"; - /** - * The node - */ - node: Staking_nodesConnection_edges_node; -} - -export interface Staking_nodesConnection { - __typename: "NodesConnection"; - /** - * List of nodes available for the connection - */ - edges: (Staking_nodesConnection_edges | null)[] | null; -} - -export interface Staking_nodeData { - __typename: "NodeData"; - /** - * Total staked amount across all nodes - */ - stakedTotal: string; - /** - * The total staked field formatted by the client - */ - stakedTotalFormatted: string; - /** - * Total number of nodes - */ - totalNodes: number; - /** - * Number of inactive nodes - */ - inactiveNodes: number; - /** - * Number of nodes validating - */ - validatingNodes: number; - /** - * Total uptime for all epochs across all nodes. Or specify a number of epochs - */ - uptime: number; -} - -export interface Staking { - /** - * An entity that is trading on the Vega network - */ - party: Staking_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: Staking_epoch; - /** - * All known network nodes - */ - nodesConnection: Staking_nodesConnection; - /** - * Returns information about nodes - */ - nodeData: Staking_nodeData | null; -} - -export interface StakingVariables { - partyId: string; -} diff --git a/apps/token/src/routes/staking/node/__generated___/PartyDelegations.ts b/apps/token/src/routes/staking/node/__generated___/PartyDelegations.ts index 0914c78b1..a42326ad2 100644 --- a/apps/token/src/routes/staking/node/__generated___/PartyDelegations.ts +++ b/apps/token/src/routes/staking/node/__generated___/PartyDelegations.ts @@ -3,32 +3,42 @@ 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 PartyDelegationsQueryVariables = Types.Exact<{ partyId: Types.Scalars['ID']; }>; -export type PartyDelegationsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, delegations?: Array<{ __typename?: 'Delegation', amount: string, amountFormatted: string, epoch: number, node: { __typename?: 'Node', id: string } }> | 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, amountFormatted: 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 + } + epoch +} + `; export const PartyDelegationsDocument = gql` query PartyDelegations($partyId: ID!) { party(id: $partyId) { id - delegations { - amount - amountFormatted @client - node { - id + delegationsConnection { + edges { + node { + ...StakingDelegationsFields + } } - epoch } } epoch { id } } - `; + ${StakingDelegationsFieldsFragmentDoc}`; /** * __usePartyDelegationsQuery__ diff --git a/apps/token/src/routes/staking/node/__generated___/Staking.ts b/apps/token/src/routes/staking/node/__generated___/Staking.ts index e36010dea..1d1622d60 100644 --- a/apps/token/src/routes/staking/node/__generated___/Staking.ts +++ b/apps/token/src/routes/staking/node/__generated___/Staking.ts @@ -3,14 +3,46 @@ import { Schema as Types } from '@vegaprotocol/types'; import { gql } from '@apollo/client'; import * as Apollo from '@apollo/client'; const defaultOptions = {} as const; +export type StakingNodeFieldsFragment = { __typename?: 'Node', id: string, name: string, pubkey: string, infoUrl: string, location: string, ethereumAddress: string, stakedByOperator: string, stakedByDelegates: string, stakedTotal: string, pendingStake: string, stakedByOperatorFormatted: string, stakedByDelegatesFormatted: string, stakedTotalFormatted: string, pendingStakeFormatted: string, status: Types.NodeStatus, epochData?: { __typename?: 'EpochData', total: number, offline: number, online: number } | null, rankingScore: { __typename?: 'RankingScore', rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string } }; + export type StakingQueryVariables = Types.Exact<{ partyId: Types.Scalars['ID']; }>; -export type StakingQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string }, delegations?: Array<{ __typename?: 'Delegation', amount: string, amountFormatted: string, epoch: number, node: { __typename?: 'Node', id: string } }> | null } | null, 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', id: string, name: string, pubkey: string, infoUrl: string, location: string, ethereumAddress: string, stakedByOperator: string, stakedByDelegates: string, stakedTotal: string, pendingStake: string, stakedByOperatorFormatted: string, stakedByDelegatesFormatted: string, stakedTotalFormatted: string, pendingStakeFormatted: string, status: Types.NodeStatus, epochData?: { __typename?: 'EpochData', total: number, offline: number, online: number } | null, rankingScore: { __typename?: 'RankingScore', rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string } } } | null> | null }, nodeData?: { __typename?: 'NodeData', stakedTotal: string, stakedTotalFormatted: string, totalNodes: number, inactiveNodes: number, validatingNodes: number, uptime: number } | null }; - +export type StakingQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: 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, timestamps: { __typename?: 'EpochTimestamps', start?: string | null, end?: string | null, expiry?: string | null } }, nodesConnection: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', id: string, name: string, pubkey: string, infoUrl: string, location: string, ethereumAddress: string, stakedByOperator: string, stakedByDelegates: string, stakedTotal: string, pendingStake: string, stakedByOperatorFormatted: string, stakedByDelegatesFormatted: string, stakedTotalFormatted: string, pendingStakeFormatted: string, status: Types.NodeStatus, epochData?: { __typename?: 'EpochData', total: number, offline: number, online: number } | null, rankingScore: { __typename?: 'RankingScore', rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string } } } | null> | null }, nodeData?: { __typename?: 'NodeData', stakedTotal: string, stakedTotalFormatted: string, totalNodes: number, inactiveNodes: number, validatingNodes: number, uptime: number } | null }; +export const StakingNodeFieldsFragmentDoc = gql` + fragment StakingNodeFields on Node { + id + name + pubkey + infoUrl + location + ethereumAddress + stakedByOperator + stakedByDelegates + stakedTotal + pendingStake + stakedByOperatorFormatted @client + stakedByDelegatesFormatted @client + stakedTotalFormatted @client + pendingStakeFormatted @client + epochData { + total + offline + online + } + status + rankingScore { + rankingScore + stakeScore + performanceScore + votingPower + stakeScore + } +} + `; export const StakingDocument = gql` query Staking($partyId: ID!) { party(id: $partyId) { @@ -18,12 +50,16 @@ export const StakingDocument = gql` stakingSummary { currentStakeAvailable } - delegations { - amount - amountFormatted @client - epoch - node { - id + delegationsConnection { + edges { + node { + amount + amountFormatted @client + epoch + node { + id + } + } } } } @@ -38,33 +74,7 @@ export const StakingDocument = gql` nodesConnection { edges { node { - id - name - pubkey - infoUrl - location - ethereumAddress - stakedByOperator - stakedByDelegates - stakedTotal - pendingStake - stakedByOperatorFormatted @client - stakedByDelegatesFormatted @client - stakedTotalFormatted @client - pendingStakeFormatted @client - epochData { - total - offline - online - } - status - rankingScore { - rankingScore - stakeScore - performanceScore - votingPower - stakeScore - } + ...StakingNodeFields } } } @@ -77,7 +87,7 @@ export const StakingDocument = gql` uptime } } - `; + ${StakingNodeFieldsFragmentDoc}`; /** * __useStakingQuery__ diff --git a/apps/token/src/routes/staking/node/node.tsx b/apps/token/src/routes/staking/node/node.tsx index 4d922f35e..7c88afbed 100644 --- a/apps/token/src/routes/staking/node/node.tsx +++ b/apps/token/src/routes/staking/node/node.tsx @@ -4,7 +4,6 @@ import { useParams } from 'react-router-dom'; import { EpochCountdown } from '../../../components/epoch-countdown'; import { BigNumber } from '../../../lib/bignumber'; -import type { Staking as StakingQueryResult } from './__generated__/Staking'; import { ConnectToVega } from '../../../components/connect-to-vega/connect-to-vega'; import { StakingForm } from './staking-form'; import { ValidatorTable } from './validator-table'; @@ -14,9 +13,10 @@ import { useVegaWallet } from '@vegaprotocol/wallet'; import { useAppState } from '../../../contexts/app-state/app-state-context'; import { toBigNum } from '@vegaprotocol/react-helpers'; import compact from 'lodash/compact'; +import type { StakingQuery } from './__generated___/Staking'; interface StakingNodeProps { - data?: StakingQueryResult; + data?: StakingQuery; } export const StakingNode = ({ data }: StakingNodeProps) => { @@ -27,26 +27,32 @@ export const StakingNode = ({ data }: StakingNodeProps) => { const { node } = useParams<{ node: string }>(); const { t } = useTranslation(); const nodeInfo = React.useMemo(() => { - return compact(data?.nodesConnection?.edges).find( - ({ node: { id } }) => id === node - )?.node; + const canonisedNodes = + compact(data?.nodesConnection?.edges?.map((edge) => edge?.node)) || []; + return canonisedNodes.find(({ id }) => id === node); }, [node, data]); const currentEpoch = React.useMemo(() => { return data?.epoch.id; }, [data?.epoch.id]); + const delegations = React.useMemo( + () => + compact( + data?.party?.delegationsConnection?.edges?.map((edge) => edge?.node) + ) || [], + [data?.party?.delegationsConnection?.edges] + ); + const stakeThisEpoch = React.useMemo(() => { - const delegations = data?.party?.delegations || []; const amountsThisEpoch = delegations .filter((d) => d.node.id === node) .filter((d) => d.epoch === Number(currentEpoch)) .map((d) => new BigNumber(d.amountFormatted)); return BigNumber.sum.apply(null, [new BigNumber(0), ...amountsThisEpoch]); - }, [data?.party?.delegations, node, currentEpoch]); + }, [delegations, node, currentEpoch]); const stakeNextEpoch = React.useMemo(() => { - const delegations = data?.party?.delegations || []; const amountsNextEpoch = delegations .filter((d) => d.node.id === node) .filter((d) => d.epoch === Number(currentEpoch) + 1) @@ -56,15 +62,15 @@ export const StakingNode = ({ data }: StakingNodeProps) => { return stakeThisEpoch; } return BigNumber.sum.apply(null, [new BigNumber(0), ...amountsNextEpoch]); - }, [currentEpoch, data?.party?.delegations, node, stakeThisEpoch]); + }, [currentEpoch, delegations, node, stakeThisEpoch]); const currentDelegationAmount = React.useMemo(() => { - if (!data?.party?.delegations) return new BigNumber(0); - const amounts = data.party.delegations + if (delegations.length < 1) return new BigNumber(0); + const amounts = delegations .filter((d) => d.epoch === Number(currentEpoch) + 1) .map((d) => new BigNumber(d.amountFormatted)); return BigNumber.sum.apply(null, [new BigNumber(0), ...amounts]); - }, [currentEpoch, data?.party?.delegations]); + }, [currentEpoch, delegations]); const unstaked = React.useMemo(() => { const value = toBigNum( diff --git a/apps/token/src/routes/staking/node/nodes-container.tsx b/apps/token/src/routes/staking/node/nodes-container.tsx index 4e0c29395..21f3bebfe 100644 --- a/apps/token/src/routes/staking/node/nodes-container.tsx +++ b/apps/token/src/routes/staking/node/nodes-container.tsx @@ -1,96 +1,26 @@ -import { gql, useQuery } from '@apollo/client'; import { Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit'; import { useVegaWallet } from '@vegaprotocol/wallet'; import React from 'react'; import { useTranslation } from 'react-i18next'; +import { useStakingQuery } from './__generated___/Staking'; import { SplashLoader } from '../../../components/splash-loader'; -import type { Staking as StakingQueryResult } from './__generated__/Staking'; +import type { StakingQuery } from './__generated___/Staking'; // TODO should only request a single node. When migrating from deprecated APIs we should address this. -export const STAKING_QUERY = gql` - query Staking($partyId: ID!) { - party(id: $partyId) { - id - stakingSummary { - currentStakeAvailable - } - delegations { - amount - amountFormatted @client - epoch - node { - id - } - } - } - epoch { - id - timestamps { - start - end - expiry - } - } - nodesConnection { - edges { - node { - id - name - pubkey - infoUrl - location - ethereumAddress - stakedByOperator - stakedByDelegates - stakedTotal - pendingStake - stakedByOperatorFormatted @client - stakedByDelegatesFormatted @client - stakedTotalFormatted @client - pendingStakeFormatted @client - epochData { - total - offline - online - } - status - rankingScore { - rankingScore - stakeScore - performanceScore - votingPower - stakeScore - } - } - } - } - nodeData { - stakedTotal - stakedTotalFormatted @client - totalNodes - inactiveNodes - validatingNodes - uptime - } - } -`; const RPC_ERROR = 'rpc error: code = NotFound desc = NotFound error'; export const NodeContainer = ({ children, }: { - children: ({ data }: { data?: StakingQueryResult }) => React.ReactElement; + children: ({ data }: { data?: StakingQuery }) => React.ReactElement; }) => { const { t } = useTranslation(); const { pubKey } = useVegaWallet(); - const { data, loading, error, refetch } = useQuery( - STAKING_QUERY, - { - variables: { partyId: pubKey || '' }, - } - ); + const { data, loading, error, refetch } = useStakingQuery({ + variables: { partyId: pubKey || '' }, + }); React.useEffect(() => { const interval = setInterval(() => { diff --git a/apps/token/src/routes/staking/node/staking-form.tsx b/apps/token/src/routes/staking/node/staking-form.tsx index 07dd75100..cb2c21379 100644 --- a/apps/token/src/routes/staking/node/staking-form.tsx +++ b/apps/token/src/routes/staking/node/staking-form.tsx @@ -1,17 +1,15 @@ -import { gql, useApolloClient } from '@apollo/client'; +import { useApolloClient } from '@apollo/client'; import * as Sentry from '@sentry/react'; +import compact from 'lodash/compact'; import React, { useCallback, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; +import { usePartyDelegationsLazyQuery } from './__generated___/PartyDelegations'; import { TokenInput } from '../../../components/token-input'; import { useAppState } from '../../../contexts/app-state/app-state-context'; import { useSearchParams } from '../../../hooks/use-search-params'; import { BigNumber } from '../../../lib/bignumber'; -import type { - PartyDelegations, - PartyDelegationsVariables, -} from './__generated__/PartyDelegations'; import { StakingFormTxStatuses } from './staking-form-tx-statuses'; import { ButtonLink, @@ -31,25 +29,6 @@ import { addDecimal, } from '@vegaprotocol/react-helpers'; -export const PARTY_DELEGATIONS_QUERY = gql` - query PartyDelegations($partyId: ID!) { - party(id: $partyId) { - id - delegations { - amount - amountFormatted @client - node { - id - } - epoch - } - } - epoch { - id - } - } -`; - export enum FormState { Default, Requested, @@ -159,6 +138,13 @@ export const StakingForm = ({ } } + const [delegationSearch, { data, error }] = usePartyDelegationsLazyQuery({ + variables: { + partyId: pubKey, + }, + fetchPolicy: 'network-only', + }); + React.useEffect(() => { // eslint-disable-next-line let interval: any; @@ -166,33 +152,31 @@ export const StakingForm = ({ if (formState === FormState.Pending) { // start polling for delegation interval = setInterval(() => { - client - .query({ - query: PARTY_DELEGATIONS_QUERY, - variables: { partyId: pubKey }, - fetchPolicy: 'network-only', - }) - .then((res) => { - const delegation = res.data.party?.delegations?.find((d) => { - return ( - d.node.id === nodeId && - d.epoch === Number(res.data.epoch.id) + 1 - ); - }); + delegationSearch(); - if (delegation) { - setFormState(FormState.Success); - clearInterval(interval); - } - }) - .catch((err) => { - Sentry.captureException(err); + if (data) { + const delegation = compact( + data.party?.delegationsConnection?.edges?.map((edge) => edge?.node) + ).find((d) => { + return ( + d.node.id === nodeId && d.epoch === Number(data.epoch.id) + 1 + ); }); + + if (delegation) { + setFormState(FormState.Success); + clearInterval(interval); + } + } + + if (error) { + Sentry.captureException(error); + } }, 1000); } return () => clearInterval(interval); - }, [formState, client, pubKey, nodeId]); + }, [formState, client, pubKey, nodeId, delegationSearch, data, error]); const toggleDialog = useCallback(() => { setIsDialogVisible(!isDialogVisible); diff --git a/apps/token/src/routes/staking/node/validator-table.tsx b/apps/token/src/routes/staking/node/validator-table.tsx index bf81d4064..9a920c182 100644 --- a/apps/token/src/routes/staking/node/validator-table.tsx +++ b/apps/token/src/routes/staking/node/validator-table.tsx @@ -6,7 +6,7 @@ import { useEnvironment } from '@vegaprotocol/environment'; import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit'; import { BigNumber } from '../../../lib/bignumber'; import { formatNumber } from '../../../lib/format-number'; -import type { Staking_nodesConnection_edges_node } from './__generated__/Staking'; +import type { StakingNodeFieldsFragment } from './__generated___/Staking'; const ValidatorTableCell = ({ children, @@ -21,7 +21,7 @@ const ValidatorTableCell = ({ ); export interface ValidatorTableProps { - node: Staking_nodesConnection_edges_node; + node: StakingNodeFieldsFragment; stakedTotal: string; stakeThisEpoch: BigNumber; }