From 463a906bba85b4039e29aa0baec94be34ca00d49 Mon Sep 17 00:00:00 2001 From: Brian Li Date: Tue, 20 Aug 2024 15:27:15 -0400 Subject: [PATCH] Batch delegation nodes API call (#784) * Batch delegation nodes API call * Fix copy * Fix lint --- src/api/index.ts | 13 +++ src/pages/Account/Error.tsx | 4 +- src/pages/DelegatoryValidator/Title.tsx | 4 +- src/pages/DelegatoryValidator/utils.tsx | 5 +- .../Validators/DelegationValidatorsTable.tsx | 86 +++++++++++-------- 5 files changed, 71 insertions(+), 41 deletions(-) diff --git a/src/api/index.ts b/src/api/index.ts index b9bd9a71..50637f00 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -304,3 +304,16 @@ export async function getValidatorState( }; return withResponseError(client.view(payload)); } + +export async function getValidatorCommisionAndState( + client: AptosClient, + validatorAddresses: Types.Address[], +): Promise { + const payload: Types.ViewRequest = { + function: + "0x7a5c34e80f796fe58c336812f80e15a86a2086c75640270a11207b911d512aba::helpers::pool_address_info", + type_arguments: [], + arguments: [validatorAddresses], + }; + return withResponseError(client.view(payload)); +} diff --git a/src/pages/Account/Error.tsx b/src/pages/Account/Error.tsx index 6c3519b1..4afe30f0 100644 --- a/src/pages/Account/Error.tsx +++ b/src/pages/Account/Error.tsx @@ -32,14 +32,14 @@ export default function Error({error, address}: ErrorProps) { } else { return ( - To many requests. Please try again 5 minutes later. + Too many requests. Please try again 5 minutes later. ); } case ResponseErrorType.TOO_MANY_REQUESTS: return ( - To many requests. Please try again 5 minutes later. + Too many requests. Please try again 5 minutes later. ); } diff --git a/src/pages/DelegatoryValidator/Title.tsx b/src/pages/DelegatoryValidator/Title.tsx index 0c393e46..f8de9f9e 100644 --- a/src/pages/DelegatoryValidator/Title.tsx +++ b/src/pages/DelegatoryValidator/Title.tsx @@ -27,7 +27,9 @@ export default function ValidatorTitle({ diff --git a/src/pages/DelegatoryValidator/utils.tsx b/src/pages/DelegatoryValidator/utils.tsx index e5724602..c739b6f8 100644 --- a/src/pages/DelegatoryValidator/utils.tsx +++ b/src/pages/DelegatoryValidator/utils.tsx @@ -7,7 +7,6 @@ import { MINIMUM_APT_IN_POOL, } from "./constants"; import {ApolloError} from "@apollo/client"; -import {MoveValue} from "aptos/src/generated"; interface AccountResourceData { locked_until_secs: bigint; @@ -207,9 +206,9 @@ export type ValidatorStatus = | "Inactive"; export function getValidatorStatus( - validatorStatus: MoveValue[], + validatorStatus: number, ): ValidatorStatus | undefined { - switch (Number(validatorStatus[0])) { + switch (validatorStatus) { case 1: return "Pending Active"; case 2: diff --git a/src/pages/Validators/DelegationValidatorsTable.tsx b/src/pages/Validators/DelegationValidatorsTable.tsx index 446e4bc7..5ab30610 100644 --- a/src/pages/Validators/DelegationValidatorsTable.tsx +++ b/src/pages/Validators/DelegationValidatorsTable.tsx @@ -23,7 +23,6 @@ import CurrencyValue, { import {aptosColor, grey, primary} from "../../themes/colors/aptosColorPalette"; import {useGlobalState} from "../../global-config/GlobalConfig"; import {StyledLearnMoreTooltip} from "../../components/StyledTooltip"; -import {useGetDelegationNodeInfo} from "../../api/hooks/useGetDelegationNodeInfo"; import {OperatorAddrCell, ValidatorAddrCell} from "./ValidatorsTable"; import {useGetNumberOfDelegators} from "../../api/hooks/useGetNumberOfDelegators"; import VisibilityOutlinedIcon from "@mui/icons-material/VisibilityOutlined"; @@ -33,7 +32,6 @@ import CheckCircleIcon from "@mui/icons-material/CheckCircle"; import {Stack} from "@mui/material"; import {useGetDelegatedStakingPoolList} from "../../api/hooks/useGetDelegatedStakingPoolList"; import ValidatorStatusIcon from "../DelegatoryValidator/Components/ValidatorStatusIcon"; -import {ResponseError} from "../../api/client"; import Error from "../Account/Error"; import { ValidatorStatus, @@ -42,6 +40,10 @@ import { } from "../DelegatoryValidator/utils"; import {useLogEventWithBasic} from "../Account/hooks/useLogEventWithBasic"; import {useGetValidatorSet} from "../../api/hooks/useGetValidatorSet"; +import {useQuery} from "@tanstack/react-query"; +import {getValidatorCommisionAndState} from "../../api"; +import {MoveValue} from "aptos/src/generated"; +import {ResponseError} from "../../api/client"; function getSortedValidators( validators: ValidatorData[], @@ -228,10 +230,12 @@ const COLUMNS_WITHOUT_WALLET_CONNECTION: Column[] = [ ]; type ValidatorRowProps = { - validator: ValidatorData; + validator: ValidatorData & { + commission: number; + status: number; + }; columns: Column[]; connected: boolean; - setError: (error: ResponseError) => void; }; type ValidatorCellProps = { @@ -361,23 +365,16 @@ function MyDepositCell({validator}: ValidatorCellProps) { ); } -function ValidatorRow({ - validator, - columns, - connected, - setError, -}: ValidatorRowProps) { +function ValidatorRow({validator, columns, connected}: ValidatorRowProps) { const {account, wallet} = useWallet(); const logEvent = useLogEventWithBasic(); const {totalVotingPower} = useGetValidatorSet(); - const {commission, validatorStatus, error} = useGetDelegationNodeInfo({ - validatorAddress: validator.owner_address, - }); const validatorVotingPower = validator.voting_power; const networkPercentage = calculateNetworkPercentage( validatorVotingPower, totalVotingPower, ); + const {commission, status} = validator; const rowClick = (address: Types.Address) => { logEvent("delegation_validators_row_clicked", address, { @@ -386,20 +383,15 @@ function ValidatorRow({ network_percentage: networkPercentage ?? "", wallet_address: account?.address ?? "", wallet_name: wallet?.name ?? "", - validator_status: validatorStatus ? validatorStatus[0].toString() : "", + validator_status: status.toString(), }); }; - if (error) { - setError(error); - } - // Hide delegators that are inactive and have no delegated stake // TODO: Don't show inactive validators unless the users have a deposit // Would require some querying restructing to be efficient. if ( - validatorStatus && - getValidatorStatus(validatorStatus) === "Inactive" && + getValidatorStatus(status) === "Inactive" && validatorVotingPower === "0" ) { return null; @@ -420,9 +412,7 @@ function ValidatorRow({ delegatedStakeAmount={validatorVotingPower} networkPercentage={networkPercentage} connected={connected} - validatorStatus={ - validatorStatus ? getValidatorStatus(validatorStatus) : undefined - } + validatorStatus={getValidatorStatus(status)} /> ); })} @@ -444,12 +434,37 @@ export function DelegationValidatorsTable() { >([]); const {delegatedStakingPools, loading} = useGetDelegatedStakingPoolList() ?? []; - const [error, setError] = useState(); const sortedValidators = getSortedValidators( delegationValidators, sortColumn, sortDirection, ); + const sortedValidatorAddrs = sortedValidators.map((v) => v.owner_address); + const {data: sortedValidatorsWithCommissionAndState, error} = useQuery< + Types.MoveValue[], + ResponseError + >({ + queryKey: [ + "validatorCommisionAndState", + state.aptos_client, + ...sortedValidatorAddrs, + ], + queryFn: () => + getValidatorCommisionAndState(state.aptos_client, sortedValidatorAddrs), + select: (res: MoveValue[]) => { + /// First arg is always the return value + const ret = res[0] as [MoveValue, MoveValue][]; + return sortedValidators.map((v, i) => { + const commision = ret[i][0]; + const state = ret[i][1]; + return { + ...v, + commission: Number(commision) / 100, + status: Number(state), + }; + }); + }, // commission rate: 22.85% is represented as 2285 + }); useEffect(() => { if (!loading) { @@ -508,17 +523,18 @@ export function DelegationValidatorsTable() { - {sortedValidators.map((validator: any, i: number) => { - return ( - - ); - })} + {sortedValidatorsWithCommissionAndState?.map( + (validator: any, i: number) => { + return ( + + ); + }, + )} );