diff --git a/packages/page-explorer/src/BlockInfo/ByHash.tsx b/packages/page-explorer/src/BlockInfo/ByHash.tsx index 2243a92a5f5e..e0081b5f206c 100644 --- a/packages/page-explorer/src/BlockInfo/ByHash.tsx +++ b/packages/page-explorer/src/BlockInfo/ByHash.tsx @@ -4,12 +4,12 @@ import type { HeaderExtended } from '@polkadot/api-derive/types'; import type { KeyedEvent } from '@polkadot/react-hooks/ctx/types'; import type { V2Weight } from '@polkadot/react-hooks/useWeight'; -import type { EventRecord, RuntimeVersionPartial, SignedBlock } from '@polkadot/types/interfaces'; +import type { EventRecord, Hash, RuntimeVersionPartial, SignedBlock } from '@polkadot/types/interfaces'; import React, { useEffect, useMemo, useState } from 'react'; import { Link } from 'react-router-dom'; -import { AddressSmall, Columar, LinkExternal, MarkError, Table } from '@polkadot/react-components'; +import { AddressSmall, Columar, CopyButton, LinkExternal, MarkError, styled, Table } from '@polkadot/react-components'; import { useApi, useIsMountedRef } from '@polkadot/react-hooks'; import { convertWeight } from '@polkadot/react-hooks/useWeight'; import { formatNumber, isBn } from '@polkadot/util'; @@ -31,6 +31,7 @@ interface State { events?: KeyedEvent[] | null; getBlock?: SignedBlock; getHeader?: HeaderExtended; + nextBlockHash?: Hash | null; runtimeVersion?: RuntimeVersionPartial; } @@ -53,7 +54,7 @@ function BlockByHash ({ className = '', error, value }: Props): React.ReactEleme const { t } = useTranslation(); const { api } = useApi(); const mountedRef = useIsMountedRef(); - const [{ events, getBlock, getHeader, runtimeVersion }, setState] = useState({}); + const [{ events, getBlock, getHeader, nextBlockHash, runtimeVersion }, setState] = useState({}); const [blkError, setBlkError] = useState(error); const [evtError, setEvtError] = useState(); @@ -102,12 +103,53 @@ function BlockByHash ({ className = '', error, value }: Props): React.ReactEleme }); }, [api, mountedRef, value]); + useEffect((): (() => void) | undefined => { + if (!mountedRef.current || !getHeader?.number) { + return; + } + + const nextBlockNumber = getHeader.number.unwrap().addn(1); + let unsub: (() => void) | undefined; + + api.rpc.chain.getBlockHash(nextBlockNumber) + .then((hash) => { + if (!hash.isEmpty) { + setState((prev) => ({ + ...prev, + nextBlockHash: hash + })); + } else { + api.derive.chain.subscribeNewHeads((header: HeaderExtended): void => { + if (mountedRef.current && header.number.unwrap().eq(nextBlockNumber)) { + setState((prev) => ({ + ...prev, + nextBlockHash: header.hash + })); + unsub && unsub(); + } + }).then((_unsub) => { + unsub = _unsub; + }).catch((error: Error) => { + mountedRef.current && setBlkError(error); + }); + } + }) + .catch((error: Error) => { + mountedRef.current && setBlkError(error); + }); + + return (): void => { + unsub && unsub(); + }; + }, [api, getHeader?.number, mountedRef]); + const header = useMemo<[React.ReactNode?, string?, number?][]>( () => getHeader ? [ [formatNumber(getHeader.number.unwrap()), 'start --digits', 1], [t('hash'), 'start'], [t('parent'), 'start'], + [t('next'), 'start'], [t('extrinsics'), 'start media--1300'], [t('state'), 'start media--1200'], [runtimeVersion ? `${runtimeVersion.specName.toString()}/${runtimeVersion.specVersion.toString()}` : undefined, 'media--1000'] @@ -128,7 +170,7 @@ function BlockByHash ({ className = '', error, value }: Props): React.ReactEleme maxProofSize={isBn(maxBlockWeight.proofSize) ? maxBlockWeight.proofSize : (maxBlockWeight as V2Weight).proofSize.toBn()} signedBlock={getBlock} /> - + {blkError ? ( @@ -147,9 +189,24 @@ function BlockByHash ({ className = '', error, value }: Props): React.ReactEleme + ) } -
{getHeader.hash.toHex()} { hasParent - ? {parentHash} + ? ( + + {parentHash} + + + ) : parentHash }{ + nextBlockHash + ? ( + + {nextBlockHash.toHex()} + + + ) + : t('Waiting for next block...') + } {getHeader.extrinsicsRoot.toHex()} {getHeader.stateRoot.toHex()} @@ -163,7 +220,7 @@ function BlockByHash ({ className = '', error, value }: Props): React.ReactEleme
+ {getBlock && getHeader && ( <>