diff --git a/src/Block.tsx b/src/Block.tsx index 473ef75..0b96cda 100644 --- a/src/Block.tsx +++ b/src/Block.tsx @@ -25,6 +25,7 @@ import { useLatestBlockNumber } from "./useLatestBlock"; import { blockTxsURL } from "./url"; import { useBlockData } from "./useErigonHooks"; import { useETHUSDOracle } from "./usePriceOracle"; +import BlockNotFound from "./components/BlockNotFound"; const Block: React.FC = () => { const { provider } = useContext(RuntimeContext); @@ -35,10 +36,10 @@ const Block: React.FC = () => { const block = useBlockData(provider, blockNumberOrHash); useEffect(() => { - if (block) { - document.title = `Block #${block.number} | Otterscan`; + if (block !== undefined) { + document.title = `Block #${blockNumberOrHash} | Otterscan`; } - }, [block]); + }, [blockNumberOrHash, block]); const extraStr = useMemo(() => { try { @@ -71,6 +72,9 @@ const Block: React.FC = () => { )} + {block === null && ( + + )} {block && ( diff --git a/src/components/BlockNotFound.tsx b/src/components/BlockNotFound.tsx new file mode 100644 index 0000000..b1ddee8 --- /dev/null +++ b/src/components/BlockNotFound.tsx @@ -0,0 +1,14 @@ +import React from "react"; +import ContentFrame from "../ContentFrame"; + +type BlockNotFoundProps = { + blockNumberOrHash: string; +}; + +const BlockNotFound: React.FC = ({ blockNumberOrHash }) => ( + +
Block "{blockNumberOrHash}" not found.
+
+); + +export default React.memo(BlockNotFound); diff --git a/src/special/london/Blocks.tsx b/src/special/london/Blocks.tsx index 095bbc2..8a00597 100644 --- a/src/special/london/Blocks.tsx +++ b/src/special/london/Blocks.tsx @@ -75,6 +75,9 @@ const Blocks: React.FC = ({ latestBlock, targetBlockNumber }) => { if (_blocks.length > 0 && blockNumber === _blocks[0].number) { return _blocks; } + if (extBlock === null) { + return _blocks; + } // Leave the last block because of transition animation const newBlocks = [extBlock, ..._blocks].slice( diff --git a/src/useErigonHooks.ts b/src/useErigonHooks.ts index 54e1800..ad9b0b8 100644 --- a/src/useErigonHooks.ts +++ b/src/useErigonHooks.ts @@ -36,17 +36,24 @@ export interface ExtendedBlock extends Block { export const readBlock = async ( provider: JsonRpcProvider, blockNumberOrHash: string -) => { +): Promise => { let blockPromise: Promise; if (isHexString(blockNumberOrHash, 32)) { blockPromise = provider.send("ots_getBlockDetailsByHash", [ blockNumberOrHash, ]); } else { - blockPromise = provider.send("ots_getBlockDetails", [blockNumberOrHash]); + const blockNumber = parseInt(blockNumberOrHash); + if (isNaN(blockNumber) || blockNumber < 0) { + return null; + } + blockPromise = provider.send("ots_getBlockDetails", [blockNumber]); } const _rawBlock = await blockPromise; + if (_rawBlock === null) { + return null; + } const _block = provider.formatter.block(_rawBlock.block); const _rawIssuance = _rawBlock.issuance; @@ -160,11 +167,11 @@ export const useBlockTransactions = ( export const useBlockData = ( provider: JsonRpcProvider | undefined, blockNumberOrHash: string -) => { - const [block, setBlock] = useState(); +): ExtendedBlock | null | undefined => { + const [block, setBlock] = useState(); useEffect(() => { if (!provider) { - return; + return undefined; } const _readBlock = async () => { @@ -199,7 +206,7 @@ export const useTxData = ( return; } - let _block: ExtendedBlock | undefined; + let _block: ExtendedBlock | null | undefined; if (_response.blockNumber) { _block = await readBlock(provider, _response.blockNumber.toString()); }