From c43edbdfa59c1d57c551affe61d60f838fd6e999 Mon Sep 17 00:00:00 2001 From: Oleksandr Khlopiachyi Date: Tue, 28 May 2024 11:16:00 +0300 Subject: [PATCH] feat: update queries for validators to handle all validators (#97) --- apps/web-coreum/package.json | 2 +- .../src/graphql/types/general_types.ts | 120 +++++++++-------- .../ui/src/graphql/types/general_types.ts | 124 ++++++++++-------- packages/ui/src/recoil/validators/hooks.ts | 58 ++++++-- .../proposals/components/list/index.tsx | 1 - .../validators/components/list/hooks.ts | 46 ++++++- .../validators/components/list/types.ts | 1 + 7 files changed, 231 insertions(+), 121 deletions(-) diff --git a/apps/web-coreum/package.json b/apps/web-coreum/package.json index 2cf4cd95e0..174af01ecc 100644 --- a/apps/web-coreum/package.json +++ b/apps/web-coreum/package.json @@ -1,6 +1,6 @@ { "name": "web-coreum", - "version": "2.19.3-104", + "version": "2.19.3-105", "license": "Apache-2.0", "private": true, "scripts": { diff --git a/apps/web-coreum/src/graphql/types/general_types.ts b/apps/web-coreum/src/graphql/types/general_types.ts index 342fb84ef0..ed9eaa6bab 100644 --- a/apps/web-coreum/src/graphql/types/general_types.ts +++ b/apps/web-coreum/src/graphql/types/general_types.ts @@ -11890,7 +11890,10 @@ export type ValidatorUndelegationsQueryVariables = Exact<{ export type ValidatorUndelegationsQuery = { undelegations?: { __typename?: 'ActionUnbondingDelegationResponse', pagination?: any | null, undelegations?: Array | null } | null }; -export type ValidatorsQueryVariables = Exact<{ [key: string]: never; }>; +export type ValidatorsQueryVariables = Exact<{ + limit?: InputMaybe; + offset?: InputMaybe; +}>; export type ValidatorsQuery = { stakingPool: Array<{ __typename?: 'staking_pool', bondedTokens: any }>, validator: Array<{ __typename?: 'validator', validatorStatuses: Array<{ __typename?: 'validator_status', status: number, jailed: boolean, height: any }>, validatorSigningInfos: Array<{ __typename?: 'validator_signing_info', tombstoned: boolean, missedBlocksCounter: any }>, validatorInfo?: { __typename?: 'validator_info', operatorAddress: string, selfDelegateAddress?: string | null } | null, validatorVotingPowers: Array<{ __typename?: 'validator_voting_power', votingPower: any }>, validatorCommissions: Array<{ __typename?: 'validator_commission', commission: any }> }>, slashingParams: Array<{ __typename?: 'slashing_params', params: any }> }; @@ -11900,7 +11903,10 @@ export type ValidatorsAddressListQueryVariables = Exact<{ [key: string]: never; export type ValidatorsAddressListQuery = { validator: Array<{ __typename?: 'validator', validatorInfo?: { __typename?: 'validator_info', operatorAddress: string, selfDelegateAddress?: string | null, consensusAddress: string } | null, validatorDescriptions: Array<{ __typename?: 'validator_description', moniker?: string | null, identity?: string | null, avatarUrl?: string | null }> }> }; -export type ValidatorAddressesQueryVariables = Exact<{ [key: string]: never; }>; +export type ValidatorAddressesQueryVariables = Exact<{ + limit?: InputMaybe; + offset?: InputMaybe; +}>; export type ValidatorAddressesQuery = { validator: Array<{ __typename?: 'validator', validatorInfo?: { __typename?: 'validator_info', operatorAddress: string, selfDelegateAddress?: string | null, consensusAddress: string } | null, validatorDescriptions: Array<{ __typename?: 'validator_description', moniker?: string | null, avatarUrl?: string | null }> }> }; @@ -13574,49 +13580,52 @@ export type ValidatorUndelegationsQueryHookResult = ReturnType; export type ValidatorUndelegationsQueryResult = Apollo.QueryResult; export const ValidatorsDocument = gql` - query Validators { - stakingPool: staking_pool(limit: 1, order_by: {height: desc}) { - bondedTokens: bonded_tokens - } - validator { - validatorStatuses: validator_statuses(order_by: {height: desc}, limit: 1) { - status - jailed - height - } - validatorSigningInfos: validator_signing_infos( - order_by: {height: desc} - limit: 1 - ) { - missedBlocksCounter: missed_blocks_counter - tombstoned - } - validatorInfo: validator_info { - operatorAddress: operator_address - selfDelegateAddress: self_delegate_address + query Validators($limit: Int = 100, $offset: Int = 0) { + stakingPool: staking_pool(limit: 1, order_by: {height: desc}) { + bondedTokens: bonded_tokens } - validatorVotingPowers: validator_voting_powers( - offset: 0 - limit: 1 - order_by: {height: desc} + validator: validator( + limit: $limit + offset: $offset ) { - votingPower: voting_power - } - validatorCommissions: validator_commissions(order_by: {height: desc}, limit: 1) { - commission + validatorStatuses: validator_statuses(order_by: {height: desc}, limit: 1) { + status + jailed + height + } + validatorSigningInfos: validator_signing_infos( + order_by: {height: desc} + limit: 1 + ) { + missedBlocksCounter: missed_blocks_counter + tombstoned + } + validatorInfo: validator_info { + operatorAddress: operator_address + selfDelegateAddress: self_delegate_address + } + validatorVotingPowers: validator_voting_powers( + offset: 0 + limit: 1 + order_by: {height: desc} + ) { + votingPower: voting_power + } + validatorCommissions: validator_commissions(order_by: {height: desc}, limit: 1) { + commission + } + validatorSigningInfos: validator_signing_infos( + order_by: {height: desc} + limit: 1 + ) { + missedBlocksCounter: missed_blocks_counter + } } - validatorSigningInfos: validator_signing_infos( - order_by: {height: desc} - limit: 1 - ) { - missedBlocksCounter: missed_blocks_counter + slashingParams: slashing_params(order_by: {height: desc}, limit: 1) { + params } } - slashingParams: slashing_params(order_by: {height: desc}, limit: 1) { - params - } -} - `; +`; /** * __useValidatorsQuery__ @@ -13691,23 +13700,26 @@ export type ValidatorsAddressListQueryHookResult = ReturnType; export type ValidatorsAddressListQueryResult = Apollo.QueryResult; export const ValidatorAddressesDocument = gql` - query ValidatorAddresses { - validator { - validatorInfo: validator_info { - operatorAddress: operator_address - selfDelegateAddress: self_delegate_address - consensusAddress: consensus_address - } - validatorDescriptions: validator_descriptions( - limit: 1 - order_by: {height: desc} + query ValidatorAddresses($limit: Int = 100, $offset: Int = 0) { + validator: validator( + limit: $limit + offset: $offset ) { - moniker - avatarUrl: avatar_url + validatorInfo: validator_info { + operatorAddress: operator_address + selfDelegateAddress: self_delegate_address + consensusAddress: consensus_address + } + validatorDescriptions: validator_descriptions( + limit: 1 + order_by: {height: desc} + ) { + moniker + avatarUrl: avatar_url + } } } -} - `; +`; /** * __useValidatorAddressesQuery__ diff --git a/packages/ui/src/graphql/types/general_types.ts b/packages/ui/src/graphql/types/general_types.ts index 1aa9d79978..00ccc7a0d3 100644 --- a/packages/ui/src/graphql/types/general_types.ts +++ b/packages/ui/src/graphql/types/general_types.ts @@ -11892,7 +11892,10 @@ export type ValidatorUndelegationsQueryVariables = Exact<{ export type ValidatorUndelegationsQuery = { undelegations?: { __typename?: 'ActionUnbondingDelegationResponse', pagination?: any | null, undelegations?: Array | null } | null }; -export type ValidatorsQueryVariables = Exact<{ [key: string]: never; }>; +export type ValidatorsQueryVariables = Exact<{ + limit?: InputMaybe; + offset?: InputMaybe; +}>; export type ValidatorsQuery = { stakingPool: Array<{ __typename?: 'staking_pool', bondedTokens: any }>, validator: Array<{ __typename?: 'validator', validatorStatuses: Array<{ __typename?: 'validator_status', status: number, jailed: boolean, height: any }>, validatorSigningInfos: Array<{ __typename?: 'validator_signing_info', tombstoned: boolean, missedBlocksCounter: any }>, validatorInfo?: { __typename?: 'validator_info', operatorAddress: string, selfDelegateAddress?: string | null } | null, validatorVotingPowers: Array<{ __typename?: 'validator_voting_power', votingPower: any }>, validatorCommissions: Array<{ __typename?: 'validator_commission', commission: any }> }>, slashingParams: Array<{ __typename?: 'slashing_params', params: any }> }; @@ -11902,7 +11905,10 @@ export type ValidatorsAddressListQueryVariables = Exact<{ [key: string]: never; export type ValidatorsAddressListQuery = { validator: Array<{ __typename?: 'validator', validatorInfo?: { __typename?: 'validator_info', operatorAddress: string, selfDelegateAddress?: string | null, consensusAddress: string } | null, validatorDescriptions: Array<{ __typename?: 'validator_description', moniker?: string | null, identity?: string | null, avatarUrl?: string | null }> }> }; -export type ValidatorAddressesQueryVariables = Exact<{ [key: string]: never; }>; +export type ValidatorAddressesQueryVariables = Exact<{ + limit?: InputMaybe; + offset?: InputMaybe; +}>; export type ValidatorAddressesQuery = { validator: Array<{ __typename?: 'validator', validatorInfo?: { __typename?: 'validator_info', operatorAddress: string, selfDelegateAddress?: string | null, consensusAddress: string } | null, validatorDescriptions: Array<{ __typename?: 'validator_description', moniker?: string | null, identity?: string | null, avatarUrl?: string | null }> }> }; @@ -13562,53 +13568,58 @@ export function useValidatorUndelegationsLazyQuery(baseOptions?: Apollo.LazyQuer const options = {...defaultOptions, ...baseOptions} return Apollo.useLazyQuery(ValidatorUndelegationsDocument, options); } + export type ValidatorUndelegationsQueryHookResult = ReturnType; export type ValidatorUndelegationsLazyQueryHookResult = ReturnType; export type ValidatorUndelegationsQueryResult = Apollo.QueryResult; + export const ValidatorsDocument = gql` - query Validators { - stakingPool: staking_pool(limit: 1, order_by: {height: desc}) { - bondedTokens: bonded_tokens - } - validator { - validatorStatuses: validator_statuses(order_by: {height: desc}, limit: 1) { - status - jailed - height - } - validatorSigningInfos: validator_signing_infos( - order_by: {height: desc} - limit: 1 - ) { - missedBlocksCounter: missed_blocks_counter - tombstoned - } - validatorInfo: validator_info { - operatorAddress: operator_address - selfDelegateAddress: self_delegate_address + query Validators($limit: Int = 100, $offset: Int = 0) { + stakingPool: staking_pool(limit: 1, order_by: {height: desc}) { + bondedTokens: bonded_tokens } - validatorVotingPowers: validator_voting_powers( - offset: 0 - limit: 1 - order_by: {height: desc} + validator: validator( + limit: $limit + offset: $offset ) { - votingPower: voting_power - } - validatorCommissions: validator_commissions(order_by: {height: desc}, limit: 1) { - commission + validatorStatuses: validator_statuses(order_by: {height: desc}, limit: 1) { + status + jailed + height + } + validatorSigningInfos: validator_signing_infos( + order_by: {height: desc} + limit: 1 + ) { + missedBlocksCounter: missed_blocks_counter + tombstoned + } + validatorInfo: validator_info { + operatorAddress: operator_address + selfDelegateAddress: self_delegate_address + } + validatorVotingPowers: validator_voting_powers( + offset: 0 + limit: 1 + order_by: {height: desc} + ) { + votingPower: voting_power + } + validatorCommissions: validator_commissions(order_by: {height: desc}, limit: 1) { + commission + } + validatorSigningInfos: validator_signing_infos( + order_by: {height: desc} + limit: 1 + ) { + missedBlocksCounter: missed_blocks_counter + } } - validatorSigningInfos: validator_signing_infos( - order_by: {height: desc} - limit: 1 - ) { - missedBlocksCounter: missed_blocks_counter + slashingParams: slashing_params(order_by: {height: desc}, limit: 1) { + params } } - slashingParams: slashing_params(order_by: {height: desc}, limit: 1) { - params - } -} - `; +`; /** * __useValidatorsQuery__ @@ -13683,24 +13694,27 @@ export type ValidatorsAddressListQueryHookResult = ReturnType; export type ValidatorsAddressListQueryResult = Apollo.QueryResult; export const ValidatorAddressesDocument = gql` - query ValidatorAddresses { - validator { - validatorInfo: validator_info { - operatorAddress: operator_address - selfDelegateAddress: self_delegate_address - consensusAddress: consensus_address - } - validatorDescriptions: validator_descriptions( - limit: 1 - order_by: {height: desc} + query ValidatorAddresses($limit: Int = 100, $offset: Int = 0) { + validator: validator( + limit: $limit + offset: $offset ) { - moniker - identity - avatarUrl: avatar_url + validatorInfo: validator_info { + operatorAddress: operator_address + selfDelegateAddress: self_delegate_address + consensusAddress: consensus_address + } + validatorDescriptions: validator_descriptions( + limit: 1 + order_by: {height: desc} + ) { + moniker + identity + avatarUrl: avatar_url + } } } -} - `; +`; /** * __useValidatorAddressesQuery__ diff --git a/packages/ui/src/recoil/validators/hooks.ts b/packages/ui/src/recoil/validators/hooks.ts index f8c56904d3..18eea5d296 100644 --- a/packages/ui/src/recoil/validators/hooks.ts +++ b/packages/ui/src/recoil/validators/hooks.ts @@ -1,4 +1,4 @@ -import { useEffect } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import { useRecoilCallback } from 'recoil'; import { AtomState as ValidatorAtomState } from 'ui/recoil/validators'; import { useValidatorAddressesQuery } from '@/graphql/types/general_types'; @@ -7,7 +7,50 @@ import type { AtomState as ProfileAtomState } from '@/recoil/profiles/types'; import { atomFamilyState as validatorAtomState } from '@/recoil/validators/atom'; export const useValidatorRecoil = () => { - const { loading: loadingValidator, data } = useValidatorAddressesQuery(); + const [validatorAddresses, setValidatorsAddresses] = useState([]); + const [isLoading, setIsLoading] = useState(true); + const [isAllDataLoaded, setIsAllDataLoaded] = useState(false); + + const validatorAddressesQuery = useValidatorAddressesQuery({ + variables: {}, + onCompleted: (response) => { + setValidatorsAddresses(response.validator); + setIsLoading(false); + + if (response.validator.length < 100) { + setIsAllDataLoaded(true); + } + }, + onError: () => { + setValidatorsAddresses([]); + setIsLoading(false); + }, + }); + + const loadMoreItems = useCallback(async () => { + await validatorAddressesQuery + .fetchMore({ + variables: { + offset: validatorAddresses.length || 0, + }, + }) + .then(({ data: responseData }) => { + const itemsLength = responseData.validator.length || 0; + + if (itemsLength < 100) { + setIsAllDataLoaded(true); + } + + setValidatorsAddresses((prevValue) => prevValue.concat(responseData.validator)); + }); + }, [validatorAddresses.length, validatorAddressesQuery]); + + useEffect(() => { + if (!isAllDataLoaded && !isLoading) { + loadMoreItems(); + } + }, [isAllDataLoaded, isLoading, loadMoreItems]); + const setValidatorAtomState = useRecoilCallback( ({ set }) => (consensusAddress: string, newState: ValidatorAtomState) => @@ -15,9 +58,8 @@ export const useValidatorRecoil = () => { [] ); useEffect(() => { - if (!data?.validator) return; const map = new Map( - data.validator + validatorAddresses .filter((x) => x.validatorInfo?.consensusAddress) .map((x) => [x.validatorInfo?.consensusAddress ?? '', x]) ); @@ -27,7 +69,7 @@ export const useValidatorRecoil = () => { validator: x.validatorInfo?.consensusAddress ?? '', }); }); - }, [data, setValidatorAtomState]); + }, [validatorAddresses, setValidatorAtomState]); const setProfileAtomFamilyState = useRecoilCallback( ({ set }) => @@ -43,7 +85,7 @@ export const useValidatorRecoil = () => { ); useEffect(() => { - data?.validator?.forEach((validator) => { + validatorAddresses.forEach((validator) => { if (!validator.validatorInfo?.selfDelegateAddress) return; setProfileAtomFamilyState(validator.validatorInfo?.selfDelegateAddress, { @@ -51,9 +93,9 @@ export const useValidatorRecoil = () => { imageUrl: validator.validatorDescriptions?.[0]?.avatarUrl || '', }); }); - }, [data?.validator, setProfileAtomFamilyState]); + }, [validatorAddresses, setProfileAtomFamilyState]); return { - loading: loadingValidator, + loading: isLoading, }; }; diff --git a/packages/ui/src/screens/proposals/components/list/index.tsx b/packages/ui/src/screens/proposals/components/list/index.tsx index ed2077cb17..afc3a3c63b 100644 --- a/packages/ui/src/screens/proposals/components/list/index.tsx +++ b/packages/ui/src/screens/proposals/components/list/index.tsx @@ -87,7 +87,6 @@ const ProposalsList: FC = ({
- {/* */}
diff --git a/packages/ui/src/screens/validators/components/list/hooks.ts b/packages/ui/src/screens/validators/components/list/hooks.ts index 054a2bdea2..645a7218f3 100644 --- a/packages/ui/src/screens/validators/components/list/hooks.ts +++ b/packages/ui/src/screens/validators/components/list/hooks.ts @@ -1,7 +1,7 @@ import Big from 'big.js'; import numeral from 'numeral'; import * as R from 'ramda'; -import { SyntheticEvent, useCallback, useState } from 'react'; +import { SyntheticEvent, useCallback, useEffect, useState } from 'react'; import chainConfig from '@/chainConfig'; import { useValidatorsQuery, ValidatorsQuery } from '@/graphql/types/general_types'; import { SlashingParams } from '@/models'; @@ -91,6 +91,7 @@ export const useValidators = () => { tab: 0, sortKey: 'votingPower', sortDirection: 'desc', + allItemsLoaded: false, }); const handleSetState = useCallback( @@ -106,7 +107,10 @@ export const useValidators = () => { // ========================== // Fetch Data // ========================== - useValidatorsQuery({ + const validatorsQuery = useValidatorsQuery({ + variables: { + offset: 0, + }, onCompleted: (data) => { handleSetState((prevState) => ({ ...prevState, @@ -123,6 +127,44 @@ export const useValidators = () => { }, }); + const loadNextPage = useCallback(async () => { + // handleSetState((prevState) => ({ ...prevState, loading: true })); + // refetch query + await validatorsQuery + .fetchMore({ + variables: { + offset: state.items.length, + }, + }) + .then(({ data }) => { + const validators = formatValidators(data); + const itemsLength = validators.items?.length || 0; + + if (validators.items) { + const newItems = state.items.concat(validators.items); + + handleSetState((prevState) => ({ + ...prevState, + items: newItems, + // loading: false, + allItemsLoaded: itemsLength < 99, + })); + } else { + handleSetState((prevState) => ({ + ...prevState, + // loading: false, + allItemsLoaded: true, + })); + } + }); + }, [handleSetState, state.items, validatorsQuery]); + + useEffect(() => { + if (!state.allItemsLoaded && !state.loading) { + loadNextPage(); + } + }, [state.allItemsLoaded, state.loading, loadNextPage]); + const handleTabChange = useCallback( (_event: SyntheticEvent, newValue: number) => { setState((prevState) => ({ diff --git a/packages/ui/src/screens/validators/components/list/types.ts b/packages/ui/src/screens/validators/components/list/types.ts index bc9adfd50c..e3d0aa27b5 100644 --- a/packages/ui/src/screens/validators/components/list/types.ts +++ b/packages/ui/src/screens/validators/components/list/types.ts @@ -18,6 +18,7 @@ export interface ValidatorsState { sortDirection: 'asc' | 'desc'; votingPowerOverall: number; items: ValidatorType[]; + allItemsLoaded: boolean; } export type ItemType = Override;