diff --git a/packages/brain/src/index.ts b/packages/brain/src/index.ts index f2f1a9b0..bc66f94d 100644 --- a/packages/brain/src/index.ts +++ b/packages/brain/src/index.ts @@ -23,7 +23,7 @@ const config = brainConfig(); logger.debug(`Chain config: ${JSON.stringify(config.chain)}`); // Create API instances. Must preceed db initialization -const { prometheusApi, signerApi, blockExplorerApi, validatorApi, beaconchainApi, dappmanagerApi, postgresClient } = +const { prometheusApi, signerApi, validatorApi, beaconchainApi, dappmanagerApi, postgresClient } = getApiClients(config); // Create DB instance @@ -69,7 +69,6 @@ const { uiServer, launchpadServer, brainApiServer } = getServers({ brainConfig: config, uiBuildPath: path.resolve(__dirname, params.uiBuildDirName), signerApi, - blockExplorerApi, postgresClient, validatorApi, beaconchainApi, diff --git a/packages/brain/src/modules/apiClients/blockExplorer/error.ts b/packages/brain/src/modules/apiClients/blockExplorer/error.ts deleted file mode 100644 index 5c5d2d2c..00000000 --- a/packages/brain/src/modules/apiClients/blockExplorer/error.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { ApiError } from "../error.js"; - -export class BlockExplorerApiError extends ApiError { - constructor(message: string) { - super(message); - this.name = "BlockExplorerApiError"; // Override the name if needed - } -} diff --git a/packages/brain/src/modules/apiClients/blockExplorer/index.ts b/packages/brain/src/modules/apiClients/blockExplorer/index.ts deleted file mode 100644 index 964ec2e4..00000000 --- a/packages/brain/src/modules/apiClients/blockExplorer/index.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { StandardApi } from "../standard.js"; -import { BeaconchaGetResponse } from "./types.js"; -import { BlockExplorerApiError } from "./error.js"; - -const maxValidatorsPerRequest = 100; //For beaconcha.in --> TODO: is it the same for Gnosis? - -export class BlockExplorerApi extends StandardApi { - /** - * Fetch info for every validator PK - */ - public async fetchAllValidatorsInfo({ pubkeys }: { pubkeys: string[] }): Promise { - const validatorsInfo = new Array(); - - const chunkSize = maxValidatorsPerRequest; - - for (let i = 0; i < pubkeys.length; i += chunkSize) { - const chunk = pubkeys.slice(i, i + chunkSize); - const chunkResponse = await this.fetchValidatorsInfo(chunk); - validatorsInfo.push(chunkResponse); - } - - //validatorInfo.data is an array only if there are multiple validators - // (Beaconcha.in response works like this) - validatorsInfo.forEach((validatorChunk) => { - //Check if validatorChunk.data is an array - if (!Array.isArray(validatorChunk.data)) { - validatorChunk.data = [validatorChunk.data]; - } - }); - - return validatorsInfo; - } - - /** - * Get validator indexes for a list of public keys - * https://beaconcha.in/api/v1/docs/index.html#/Validator/get_api_v1_validator__indexOrPubkey_ - */ - public async fetchValidatorsInfo(pubkeys: string[]): Promise { - const endpoint = `/api/v1/validator/${pubkeys.join(",")}`; - - try { - return (await this.request({ - method: "GET", - endpoint - })) as BeaconchaGetResponse; - } catch (e) { - throw new BlockExplorerApiError(`Error on getting indexes for validator public keys. ${e.message}`); - } - } -} diff --git a/packages/brain/src/modules/apiClients/blockExplorer/types.ts b/packages/brain/src/modules/apiClients/blockExplorer/types.ts deleted file mode 100644 index 19f8dd28..00000000 --- a/packages/brain/src/modules/apiClients/blockExplorer/types.ts +++ /dev/null @@ -1,19 +0,0 @@ -export interface BeaconchaGetResponse { - status: string; - data: { - activationeligibilityepoch?: number; - activationepoch?: number; - balance?: number; - effectivebalance?: number; - exitepoch?: number; - lastattestationslot?: number; - name?: string; - pubkey?: string; - slashed?: boolean; - status?: string; - validatorindex?: number; - withdrawableepoch?: number; - withdrawalcredentials?: string; - }[]; - error?: { message: string }; -} diff --git a/packages/brain/src/modules/apiClients/index.ts b/packages/brain/src/modules/apiClients/index.ts index c16314ba..d248c380 100644 --- a/packages/brain/src/modules/apiClients/index.ts +++ b/packages/brain/src/modules/apiClients/index.ts @@ -1,4 +1,3 @@ -import { BlockExplorerApi } from "./blockExplorer/index.js"; import { DappmanagerApi } from "./dappmanager/index.js"; import { PrometheusApi } from "./prometheus/index.js"; import { BeaconchainApi } from "./beaconchain/index.js"; @@ -9,7 +8,6 @@ import { BrainConfig } from "../config/types.js"; import { DappnodeSignatureVerifier } from "./signatureVerifier/index.js"; export { - BlockExplorerApi, DappmanagerApi, PrometheusApi, BeaconchainApi, @@ -20,18 +18,8 @@ export { }; export const getApiClients = (brainConfig: BrainConfig) => { - const { - prometheusUrl, - signerUrl, - blockExplorerUrl, - validatorUrl, - beaconchainUrl, - dappmanagerUrl, - postgresUrl, - token, - tlsCert, - host - } = brainConfig.apis; + const { prometheusUrl, signerUrl, validatorUrl, beaconchainUrl, dappmanagerUrl, postgresUrl, token, tlsCert, host } = + brainConfig.apis; const { minGenesisTime, secondsPerSlot, slotsPerEpoch, network } = brainConfig.chain; return { prometheusApi: new PrometheusApi({ @@ -49,7 +37,6 @@ export const getApiClients = (brainConfig: BrainConfig) => { }, network ), - blockExplorerApi: new BlockExplorerApi({ baseUrl: blockExplorerUrl }, network), validatorApi: new ValidatorApi( { baseUrl: validatorUrl, diff --git a/packages/brain/src/modules/apiClients/types.ts b/packages/brain/src/modules/apiClients/types.ts index 9a23da4d..9c1ff39c 100644 --- a/packages/brain/src/modules/apiClients/types.ts +++ b/packages/brain/src/modules/apiClients/types.ts @@ -1,5 +1,4 @@ export * from "./beaconchain/types.js"; -export * from "./blockExplorer/types.js"; export * from "./signer/types.js"; export * from "./validator/types.js"; export * from "./postgres/types.js"; diff --git a/packages/brain/src/modules/apiServers/index.ts b/packages/brain/src/modules/apiServers/index.ts index 00feb91f..dcdcf754 100644 --- a/packages/brain/src/modules/apiServers/index.ts +++ b/packages/brain/src/modules/apiServers/index.ts @@ -1,4 +1,3 @@ -import { BlockExplorerApi } from "../apiClients/blockExplorer/index.js"; import { PostgresClient } from "../apiClients/postgres/index.js"; import { Web3SignerApi } from "../apiClients/signer/index.js"; import { ValidatorApi } from "../apiClients/validator/index.js"; @@ -15,7 +14,6 @@ export const getServers = ({ brainConfig, uiBuildPath, signerApi, - blockExplorerApi, postgresClient, validatorApi, beaconchainApi, @@ -26,7 +24,6 @@ export const getServers = ({ brainConfig: BrainConfig; uiBuildPath: string; signerApi: Web3SignerApi; - blockExplorerApi: BlockExplorerApi; postgresClient: PostgresClient; validatorApi: ValidatorApi; beaconchainApi: BeaconchainApi; @@ -46,7 +43,6 @@ export const getServers = ({ reloadValidatorsCronTask, signerApi, validatorApi, - blockExplorerApi, beaconchainApi, postgresClient, allowedOriginsFromEnv diff --git a/packages/brain/src/modules/apiServers/ui/calls/beaconchaApi.ts b/packages/brain/src/modules/apiServers/ui/calls/beaconchaApi.ts deleted file mode 100644 index 129b488f..00000000 --- a/packages/brain/src/modules/apiServers/ui/calls/beaconchaApi.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { BlockExplorerApi } from "../../../apiClients/index.js"; -import { BeaconchaGetResponse } from "../../../apiClients/types.js"; - -export async function beaconchaFetchValidatorsInfo({ - blockExplorerApi, - pubkeys -}: { - blockExplorerApi: BlockExplorerApi; - pubkeys: string[]; -}): Promise { - return await blockExplorerApi.fetchValidatorsInfo(pubkeys); -} - -export async function beaconchaFetchAllValidatorsInfo({ - blockExplorerApi, - pubkeys -}: { - blockExplorerApi: BlockExplorerApi; - pubkeys: string[]; -}): Promise { - return await blockExplorerApi.fetchAllValidatorsInfo({ pubkeys }); -} diff --git a/packages/brain/src/modules/apiServers/ui/calls/index.ts b/packages/brain/src/modules/apiServers/ui/calls/index.ts index a2457f1a..fe59f2a1 100644 --- a/packages/brain/src/modules/apiServers/ui/calls/index.ts +++ b/packages/brain/src/modules/apiServers/ui/calls/index.ts @@ -1,4 +1,3 @@ -import { beaconchaFetchAllValidatorsInfo, beaconchaFetchValidatorsInfo } from "./beaconchaApi.js"; import { fetchValidatorsPerformanceData } from "./fetchValidatorsPerformanceData.js"; import { deleteValidators } from "./deleteValidators.js"; import { exitValidators, getExitValidators } from "./exitValidators.js"; @@ -13,19 +12,12 @@ import { CronJob } from "../../../cron/cron.js"; import { ActionRequestOrigin, CustomImportRequest, CustomValidatorUpdateRequest, RpcMethods } from "./types.js"; import { Web3signerDeleteRequest } from "../../../apiClients/types.js"; import { NumberOfDaysToQuery } from "../../../validatorsDataIngest/types.js"; -import { - BeaconchainApi, - BlockExplorerApi, - PostgresClient, - ValidatorApi, - Web3SignerApi -} from "../../../apiClients/index.js"; +import { BeaconchainApi, PostgresClient, ValidatorApi, Web3SignerApi } from "../../../apiClients/index.js"; import { BrainConfig } from "../../../config/types.js"; import { getBuilderRelayPresets } from "../../../config/builderRelayPresets.js"; export const createRpcMethods = ({ postgresClient, - blockExplorerApi, beaconchainApi, validatorApi, signerApi, @@ -34,7 +26,6 @@ export const createRpcMethods = ({ brainConfig }: { postgresClient: PostgresClient; - blockExplorerApi: BlockExplorerApi; beaconchainApi: BeaconchainApi; validatorApi: ValidatorApi; signerApi: Web3SignerApi; @@ -48,10 +39,6 @@ export const createRpcMethods = ({ return { getBuilderRelayPresets: async () => getBuilderRelayPresets(network), getBuilderConfigs: async (pubkeys: string[]) => await getBuilderConfigs({ pubkeys, brainDb, validatorApi }), - beaconchaFetchAllValidatorsInfo: async (pubkeys: string[]) => - await beaconchaFetchAllValidatorsInfo({ blockExplorerApi, pubkeys }), - beaconchaFetchValidatorsInfo: async (pubkeys: string[]) => - await beaconchaFetchValidatorsInfo({ blockExplorerApi, pubkeys }), deleteValidators: async (deleteRequest: Web3signerDeleteRequest) => await deleteValidators({ brainDb, reloadValidatorsCronTask, validatorApi, signerApi, deleteRequest }), exitValidators: async ({ pubkeys }: { pubkeys: string[] }) => diff --git a/packages/brain/src/modules/apiServers/ui/calls/types.ts b/packages/brain/src/modules/apiServers/ui/calls/types.ts index 0d8c3447..183c29cf 100644 --- a/packages/brain/src/modules/apiServers/ui/calls/types.ts +++ b/packages/brain/src/modules/apiServers/ui/calls/types.ts @@ -1,6 +1,5 @@ import { BuilderConfig, BuilderConfigStatus, BuilderRelayPresets, StakerConfig, Tag } from "@stakingbrain/common"; import type { - BeaconchaGetResponse, Web3signerDeleteRequest, Web3signerDeleteResponse, ValidatorExitExecute, @@ -14,8 +13,6 @@ import { NumberOfDaysToQuery } from "../../../validatorsDataIngest/types.js"; // Define the type for RPC methods export interface RpcMethods { getBuilderRelayPresets: () => Promise; - beaconchaFetchAllValidatorsInfo: (pubkeys: string[]) => Promise; - beaconchaFetchValidatorsInfo: (pubkeys: string[]) => Promise; deleteValidators: (deleteRequest: Web3signerDeleteRequest) => Promise; exitValidators: ({ pubkeys }: { pubkeys: string[] }) => Promise; getExitValidators: ({ pubkeys }: { pubkeys: string[] }) => Promise; diff --git a/packages/brain/src/modules/apiServers/ui/startUiServer.ts b/packages/brain/src/modules/apiServers/ui/startUiServer.ts index 74d53f2b..b17d2dfa 100644 --- a/packages/brain/src/modules/apiServers/ui/startUiServer.ts +++ b/packages/brain/src/modules/apiServers/ui/startUiServer.ts @@ -12,18 +12,11 @@ import { createRpcMethods } from "./calls/index.js"; import { CronJob } from "../../cron/cron.js"; import { BrainDataBase } from "../../db/index.js"; import { BrainConfig } from "../../config/types.js"; -import { - BeaconchainApi, - BlockExplorerApi, - PostgresClient, - ValidatorApi, - Web3SignerApi -} from "../../apiClients/index.js"; +import { BeaconchainApi, PostgresClient, ValidatorApi, Web3SignerApi } from "../../apiClients/index.js"; import { allowedOrigins, uiSocketOptions } from "./config.js"; export function startUiServer({ brainDb, - blockExplorerApi, beaconchainApi, validatorApi, signerApi, @@ -34,7 +27,6 @@ export function startUiServer({ allowedOriginsFromEnv }: { brainDb: BrainDataBase; - blockExplorerApi: BlockExplorerApi; beaconchainApi: BeaconchainApi; validatorApi: ValidatorApi; signerApi: Web3SignerApi; @@ -51,7 +43,6 @@ export function startUiServer({ // Initialize RPC methods const rpcMethods = createRpcMethods({ postgresClient, - blockExplorerApi, beaconchainApi, validatorApi, signerApi, diff --git a/packages/brain/src/modules/config/index.ts b/packages/brain/src/modules/config/index.ts index 14bb72c2..0e08d5d1 100644 --- a/packages/brain/src/modules/config/index.ts +++ b/packages/brain/src/modules/config/index.ts @@ -28,7 +28,7 @@ export const brainConfig = (): BrainConfig => { validatorUrl = `http://validator.${network}.dncore.dappnode:3500`; } - const { blockExplorerUrl, minGenesisTime, secondsPerSlot, slotsPerEpoch } = networkConfig(network); + const { minGenesisTime, secondsPerSlot, slotsPerEpoch } = networkConfig(network); // Default beaconchainUrl if not already set if (!beaconchainUrl) { @@ -48,7 +48,6 @@ export const brainConfig = (): BrainConfig => { apis: { prometheusUrl: "http://prometheus.dms.dappnode:9090", dappmanagerUrl: "http://my.dappnode:9000", - blockExplorerUrl, executionClientUrl: `http://execution.${network}.dncore.dappnode:8545`, validatorUrl, beaconchainUrl, diff --git a/packages/brain/src/modules/config/networks/gnosis.ts b/packages/brain/src/modules/config/networks/gnosis.ts index 3baca687..239e2ed4 100644 --- a/packages/brain/src/modules/config/networks/gnosis.ts +++ b/packages/brain/src/modules/config/networks/gnosis.ts @@ -1,6 +1,5 @@ export const gnosisBrainConfig = () => { return { - blockExplorerUrl: "https://gnosischa.in", minGenesisTime: 1638968400, // Dec 8, 2021, 13:00 UTC secondsPerSlot: 5, slotsPerEpoch: 16 diff --git a/packages/brain/src/modules/config/networks/hoodi.ts b/packages/brain/src/modules/config/networks/hoodi.ts index 353dfc2f..437a9aa1 100644 --- a/packages/brain/src/modules/config/networks/hoodi.ts +++ b/packages/brain/src/modules/config/networks/hoodi.ts @@ -1,6 +1,5 @@ export const hoodiBrainConfig = () => { return { - blockExplorerUrl: "https://hoodi.beaconcha.in", minGenesisTime: 1742212800, // Monday, 17 March 2025 12:00:00 secondsPerSlot: 12, slotsPerEpoch: 32 diff --git a/packages/brain/src/modules/config/networks/lukso.ts b/packages/brain/src/modules/config/networks/lukso.ts index 3d9cd314..6b1fd0e6 100644 --- a/packages/brain/src/modules/config/networks/lukso.ts +++ b/packages/brain/src/modules/config/networks/lukso.ts @@ -1,6 +1,5 @@ export const luksoBrainConfig = () => { return { - blockExplorerUrl: "https://explorer.consensus.mainnet.lukso.network/", minGenesisTime: 1684856400, // Tuesday, 23 May 2023 15:40:00 GMT secondsPerSlot: 12, slotsPerEpoch: 32 diff --git a/packages/brain/src/modules/config/networks/mainnet.ts b/packages/brain/src/modules/config/networks/mainnet.ts index 69d377bd..21f7aea4 100644 --- a/packages/brain/src/modules/config/networks/mainnet.ts +++ b/packages/brain/src/modules/config/networks/mainnet.ts @@ -1,6 +1,5 @@ export const mainnetBrainConfig = () => { return { - blockExplorerUrl: "https://beaconcha.in", minGenesisTime: 1606824000, secondsPerSlot: 12, slotsPerEpoch: 32 diff --git a/packages/brain/src/modules/config/types.ts b/packages/brain/src/modules/config/types.ts index c148e27d..2e14655d 100644 --- a/packages/brain/src/modules/config/types.ts +++ b/packages/brain/src/modules/config/types.ts @@ -8,7 +8,6 @@ export interface BrainConfig { export interface ApisConfig { prometheusUrl: string; signerUrl: string; - blockExplorerUrl: string; validatorUrl: string; beaconchainUrl: string; executionClientUrl: string; diff --git a/packages/brain/test/unit/modules/jsonBodyEncoding.unit.test.ts b/packages/brain/test/unit/modules/jsonBodyEncoding.unit.test.ts index c2e94600..906ff49e 100644 --- a/packages/brain/test/unit/modules/jsonBodyEncoding.unit.test.ts +++ b/packages/brain/test/unit/modules/jsonBodyEncoding.unit.test.ts @@ -11,13 +11,7 @@ import { ConsensusClient, ExecutionClient, Network } from "@stakingbrain/common" import { startBrainApi } from "../../../src/modules/apiServers/brain/startBrainApi.js"; import { startLaunchpadApi } from "../../../src/modules/apiServers/launchpad/startLaunchpadApi.js"; import { startUiServer } from "../../../src/modules/apiServers/ui/startUiServer.js"; -import { - BeaconchainApi, - BlockExplorerApi, - PostgresClient, - ValidatorApi, - Web3SignerApi -} from "../../../src/modules/apiClients/index.js"; +import { BeaconchainApi, PostgresClient, ValidatorApi, Web3SignerApi } from "../../../src/modules/apiClients/index.js"; import { BrainDataBase } from "../../../src/modules/db/index.js"; import { CronJob } from "../../../src/modules/cron/cron.js"; import { params } from "../../../src/params.js"; @@ -85,7 +79,6 @@ describe("JSON request content encoding", () => { signerApi, beaconchainApi, reloadValidatorsCronTask, - blockExplorerApi: sinon.createStubInstance(BlockExplorerApi), postgresClient: sinon.createStubInstance(PostgresClient), uiBuildPath: directory, allowedOriginsFromEnv, @@ -106,7 +99,6 @@ describe("JSON request content encoding", () => { executionClientUrl: signerUrl, prometheusUrl: signerUrl, dappmanagerUrl: signerUrl, - blockExplorerUrl: signerUrl, postgresUrl: signerUrl, token: "", tlsCert: null, diff --git a/packages/ui/src/components/ValidatorList/KeystoresDataGrid.tsx b/packages/ui/src/components/ValidatorList/KeystoresDataGrid.tsx index c9cc70f5..69916950 100644 --- a/packages/ui/src/components/ValidatorList/KeystoresDataGrid.tsx +++ b/packages/ui/src/components/ValidatorList/KeystoresDataGrid.tsx @@ -1,7 +1,7 @@ import type { JSX } from "react"; import { DataGrid, GridAlignment, GridRowId } from "@mui/x-data-grid"; import { useEffect, useState } from "react"; -import { beaconchaApiParamsMap } from "../../params"; +import { blockExplorerUrls } from "../../params"; import { MAINNET_ORACLE_URL, TESTNET_ORACLE_URL, @@ -16,7 +16,7 @@ import EditIcon from "@mui/icons-material/Edit"; import CheckCircleIcon from "@mui/icons-material/CheckCircle"; import CancelIcon from "@mui/icons-material/Cancel"; import HelpIcon from "@mui/icons-material/Help"; -import { capitalize, Chip, CircularProgress, IconButton, Paper, Stack, Tooltip } from "@mui/material"; +import { capitalize, Chip, IconButton, Paper, Stack, Tooltip } from "@mui/material"; import { PageHeader } from "../Layout/PageLayout"; import VpnKeyOutlinedIcon from "@mui/icons-material/VpnKeyOutlined"; import TuneIcon from "@mui/icons-material/Tune"; @@ -27,9 +27,8 @@ import { Link } from "react-router-dom"; import { BeaconchaUrlBuildingStatus, SmoothStatusByPubkey } from "../../types"; import buildValidatorSummaryURL from "../../utils/buildValidatorSummaryURL"; import LogoutIcon from "@mui/icons-material/Logout"; -import { rpcClient } from "../../socket"; import { selectedGridRowIds } from "../../utils/dataUtils"; -import type { BeaconchaGetResponse, CustomValidatorGetResponse } from "@stakingbrain/brain"; +import type { CustomValidatorGetResponse } from "@stakingbrain/brain"; import { SmoothValidatorByIndexApiResponse, SmoothValidator, MevSpSubscriptionStatus } from "../../types"; export default function KeystoresDataGrid({ @@ -43,7 +42,6 @@ export default function KeystoresDataGrid({ setEditFeesOpen, setBuilderConfigOpen, setExitOpen, - summaryUrlBuildingStatus, setSummaryUrlBuildingStatus, mevSpFeeRecipient }: { @@ -57,22 +55,15 @@ export default function KeystoresDataGrid({ setEditFeesOpen(open: boolean): void; setBuilderConfigOpen(open: boolean): void; setExitOpen(open: boolean): void; - summaryUrlBuildingStatus: BeaconchaUrlBuildingStatus; setSummaryUrlBuildingStatus: (status: BeaconchaUrlBuildingStatus) => void; mevSpFeeRecipient: string | null; }): JSX.Element { const [paginationModel, setPaginationModel] = useState({ page: 0, pageSize: 10 }); - const beaconchaBaseUrl = beaconchaApiParamsMap.get(network)?.baseUrl; - const [validatorSummaryURL, setValidatorSummaryURL] = useState(""); + const blockExplorerUrl = blockExplorerUrls.get(network); useEffect(() => { setSummaryUrlBuildingStatus(BeaconchaUrlBuildingStatus.NotStarted); - setValidatorSummaryURL(""); - }, [selectedRows]); - - useEffect(() => { - openDashboardTab(); - }, [validatorSummaryURL]); + }, [selectedRows, network, rows]); const [validatorsSubscriptionMap, setValidatorsSubscriptionMap] = useState(null); @@ -260,7 +251,7 @@ export default function KeystoresDataGrid({ const customRows = rows.map((row, index) => ({ pubkey: row.pubkey, - beaconcha_url: beaconchaBaseUrl ? beaconchaBaseUrl + "/validator/" + row.pubkey : "", + explorerUrl: blockExplorerUrl ? blockExplorerUrl + "/validator/" + row.pubkey : "", feeRecipient: row.feeRecipient, index: row.index, tag: row.tag, @@ -292,9 +283,9 @@ export default function KeystoresDataGrid({ ) }, { - field: "beaconchaUrl", + field: "explorerUrl", headerName: "URL", - description: "Beaconcha URL to track the status of this validator", + description: "Explorer URL to track the status of this validator", disableReorder: true, disableColumnMenu: true, disableExport: true, @@ -306,7 +297,7 @@ export default function KeystoresDataGrid({ component="a" size="small" aria-label="View validator in explorer" - href={rowData.row.beaconcha_url} + href={rowData.row.explorerUrl} target="_blank" rel="noopener noreferrer" > @@ -414,44 +405,26 @@ export default function KeystoresDataGrid({ } ); - async function getValidatorSummaryURL() { - if (!beaconchaApiParamsMap?.get(network)) { - setValidatorSummaryURL(""); + function openDashboardTab() { + if (!blockExplorerUrl) { setSummaryUrlBuildingStatus(BeaconchaUrlBuildingStatus.Error); return; } - let allValidatorsInfo: BeaconchaGetResponse[]; - - setSummaryUrlBuildingStatus(BeaconchaUrlBuildingStatus.InProgress); + const summaryUrl = buildValidatorSummaryURL({ + validatorIndexes: selectedRows.map((row) => rows[row as number]?.index ?? ""), + network + }); - try { - allValidatorsInfo = await rpcClient.call( - "beaconchaFetchAllValidatorsInfo", - selectedRows.map((row) => rows[row as number].pubkey) - ); - } catch (e) { - console.error(`Error fetching all validators info: ${e}`); + if (!summaryUrl) { setSummaryUrlBuildingStatus(BeaconchaUrlBuildingStatus.NoIndexes); - setValidatorSummaryURL(""); return; } - const summaryUrlBuilt = buildValidatorSummaryURL({ - allValidatorsInfo, - network - }); - - setValidatorSummaryURL(summaryUrlBuilt); + window.open(summaryUrl, "_blank", "noopener,noreferrer"); setSummaryUrlBuildingStatus(BeaconchaUrlBuildingStatus.Success); } - async function openDashboardTab() { - if (validatorSummaryURL) { - window.open(validatorSummaryURL, "_blank", "noopener, noreferrer"); - } - } - function areAllSelectedRowsExitable() { return selectedRows.every((row) => rows[row as number].tag !== "rocketpool"); } @@ -493,24 +466,11 @@ export default function KeystoresDataGrid({ label={selectedRows.length ? `${selectedRows.length} selected` : `${rows.length} validators`} /> - {summaryUrlBuildingStatus === BeaconchaUrlBuildingStatus.InProgress ? ( - - - - ) : ( - - { - await getValidatorSummaryURL(); - await openDashboardTab(); - }} - > - - - - )} + + + + +