From 0f05e086fe3bb6c3d6e40eae3983a7416c3e3505 Mon Sep 17 00:00:00 2001 From: Justin Starry Date: Thu, 29 Oct 2020 20:34:05 +0800 Subject: [PATCH] Explorer: fix slot links and block details page on devnet (#13274) --- .../components/account/BlockHistoryCard.tsx | 41 +++++++++---------- explorer/src/components/common/Slot.tsx | 3 +- explorer/src/providers/block.tsx | 39 ++++++++++-------- 3 files changed, 44 insertions(+), 39 deletions(-) diff --git a/explorer/src/components/account/BlockHistoryCard.tsx b/explorer/src/components/account/BlockHistoryCard.tsx index 606c0f8f71..d6371580db 100644 --- a/explorer/src/components/account/BlockHistoryCard.tsx +++ b/explorer/src/components/account/BlockHistoryCard.tsx @@ -6,32 +6,31 @@ import { Signature } from "components/common/Signature"; import { ErrorCard } from "components/common/ErrorCard"; import { LoadingCard } from "components/common/LoadingCard"; import { Slot } from "components/common/Slot"; +import { ClusterStatus, useCluster } from "providers/cluster"; export function BlockHistoryCard({ slot }: { slot: number }) { const confirmedBlock = useBlock(slot); const fetchBlock = useFetchBlock(); + const { status } = useCluster(); const refresh = () => fetchBlock(slot); + // Fetch block on load React.useEffect(() => { - if (!confirmedBlock) refresh(); - }, [confirmedBlock, slot]); // eslint-disable-line react-hooks/exhaustive-deps - - if (!confirmedBlock) { - return null; - } - - if (confirmedBlock.data === undefined) { - if (confirmedBlock.status === FetchStatus.Fetching) { - return ; - } + if (!confirmedBlock && status === ClusterStatus.Connected) refresh(); + }, [slot, status]); // eslint-disable-line react-hooks/exhaustive-deps + if (!confirmedBlock || confirmedBlock.status === FetchStatus.Fetching) { + return ; + } else if ( + confirmedBlock.data === undefined || + confirmedBlock.status === FetchStatus.FetchFailed + ) { return ; + } else if (confirmedBlock.data.block === undefined) { + return ; } - if (confirmedBlock.status === FetchStatus.FetchFailed) { - return ; - } - + const block = confirmedBlock.data.block; return ( <>
@@ -44,31 +43,31 @@ export function BlockHistoryCard({ slot }: { slot: number }) { Slot - + Parent Slot - + Blockhash - {confirmedBlock.data.blockhash} + {block.blockhash} Previous Blockhash - {confirmedBlock.data.previousBlockhash} + {block.previousBlockhash}
- {confirmedBlock.data.transactions.length === 0 ? ( + {block.transactions.length === 0 ? ( ) : (
@@ -85,7 +84,7 @@ export function BlockHistoryCard({ slot }: { slot: number }) { - {confirmedBlock.data.transactions.map((tx, i) => { + {block.transactions.map((tx, i) => { let statusText; let statusClass; let signature: React.ReactNode; diff --git a/explorer/src/components/common/Slot.tsx b/explorer/src/components/common/Slot.tsx index 1e1d680ad1..88da2025b3 100644 --- a/explorer/src/components/common/Slot.tsx +++ b/explorer/src/components/common/Slot.tsx @@ -1,5 +1,6 @@ import React, { useState } from "react"; import { Link } from "react-router-dom"; +import { clusterPath } from "utils/url"; type CopyState = "copy" | "copied"; type Props = { @@ -30,7 +31,7 @@ export function Slot({ slot, link }: Props) { return link ? ( {copyButton} - + {slot.toLocaleString("en-US")} diff --git a/explorer/src/providers/block.tsx b/explorer/src/providers/block.tsx index c1bf178dc3..3890786dcd 100644 --- a/explorer/src/providers/block.tsx +++ b/explorer/src/providers/block.tsx @@ -15,8 +15,12 @@ export enum ActionType { Clear, } -type State = Cache.State; -type Dispatch = Cache.Dispatch; +type Block = { + block?: ConfirmedBlock; +}; + +type State = Cache.State; +type Dispatch = Cache.Dispatch; const StateContext = React.createContext(undefined); const DispatchContext = React.createContext(undefined); @@ -25,7 +29,7 @@ type BlockProviderProps = { children: React.ReactNode }; export function BlockProvider({ children }: BlockProviderProps) { const { url } = useCluster(); - const [state, dispatch] = Cache.useReducer(url); + const [state, dispatch] = Cache.useReducer(url); React.useEffect(() => { dispatch({ type: ActionType.Clear, url }); @@ -40,9 +44,7 @@ export function BlockProvider({ children }: BlockProviderProps) { ); } -export function useBlock( - key: number -): Cache.CacheEntry | undefined { +export function useBlock(key: number): Cache.CacheEntry | undefined { const context = React.useContext(StateContext); if (!context) { @@ -66,18 +68,23 @@ export async function fetchBlock( }); let status: FetchStatus; - let data: ConfirmedBlock | undefined; + let data: Block | undefined = undefined; try { const connection = new Connection(url, "max"); - data = await connection.getConfirmedBlock(Number(key)); + data = { block: await connection.getConfirmedBlock(Number(key)) }; status = FetchStatus.Fetched; - } catch (error) { - console.log(error); - if (cluster !== Cluster.Custom) { - Sentry.captureException(error, { tags: { url } }); + } catch (err) { + const error = err as Error; + if (error.message.includes("not found")) { + data = {} as Block; + status = FetchStatus.Fetched; + } else { + status = FetchStatus.FetchFailed; + if (cluster !== Cluster.Custom) { + Sentry.captureException(error, { tags: { url } }); + } } - status = FetchStatus.FetchFailed; } dispatch({ @@ -90,14 +97,12 @@ export async function fetchBlock( } export function useFetchBlock() { - const { cluster, url } = useCluster(); - const state = React.useContext(StateContext); const dispatch = React.useContext(DispatchContext); - - if (!state || !dispatch) { + if (!dispatch) { throw new Error(`useFetchBlock must be used within a BlockProvider`); } + const { cluster, url } = useCluster(); return React.useCallback( (key: number) => fetchBlock(dispatch, url, cluster, key), [dispatch, cluster, url]