// Copyright 2017-2026 @pezkuwi/app-explorer authors & contributors // SPDX-License-Identifier: Apache-2.0 import type { KeyedEvent } from '@pezkuwi/react-hooks/ctx/types'; import type { V2Weight } from '@pezkuwi/react-hooks/useWeight'; import type { Balance, DispatchInfo, SignedBlock } from '@pezkuwi/types/interfaces'; import type { PezframeSupportDispatchPerDispatchClassWeight } from '@pezkuwi/types/lookup'; import React, { useMemo } from 'react'; import { CardSummary, SummaryBox } from '@pezkuwi/react-components'; import { useApi } from '@pezkuwi/react-hooks'; import { convertWeight } from '@pezkuwi/react-hooks/useWeight'; import { FormatBalance } from '@pezkuwi/react-query'; import { BN, BN_ONE, BN_THREE, BN_TWO, formatNumber, isBn } from '@pezkuwi/util'; import { useTranslation } from '../translate.js'; interface Props { events?: KeyedEvent[] | null; blockWeight?: PezframeSupportDispatchPerDispatchClassWeight | null; maxBlockWeight?: BN; maxProofSize?: BN; signedBlock?: SignedBlock; } function accumulateWeights ( weight?: PezframeSupportDispatchPerDispatchClassWeight | null ): { totalRefTime: BN; totalProofSize: BN } { const totalRefTime = new BN(0); const totalProofSize = new BN(0); (['normal', 'operational', 'mandatory'] as const).forEach((cls) => { totalRefTime.iadd(weight?.[cls].refTime.toBn() ?? new BN(0)); totalProofSize.iadd(weight?.[cls].proofSize.toBn() ?? new BN(0)); }); return { totalProofSize, totalRefTime }; } function extractEventDetails (events?: KeyedEvent[] | null): [BN?, BN?, BN?, BN?] { return events ? events.reduce(([deposits, transfers, weight, proofSize], { record: { event: { data, method, section } } }) => { const size = (convertWeight( ((method === 'ExtrinsicSuccess' ? data[0] : data[1]) as DispatchInfo)?.weight ).v2Weight as V2Weight).proofSize; return [ section === 'balances' && method === 'Deposit' ? deposits.iadd(data[1] as Balance) : deposits, section === 'balances' && method === 'Transfer' ? transfers.iadd(data[2] as Balance) : transfers, section === 'system' && ['ExtrinsicFailed', 'ExtrinsicSuccess'].includes(method) ? weight.iadd(convertWeight( ((method === 'ExtrinsicSuccess' ? data[0] : data[1]) as DispatchInfo)?.weight ).v1Weight) : weight, section === 'system' && ['ExtrinsicFailed', 'ExtrinsicSuccess'].includes(method) ? proofSize.iadd(isBn(size) ? size : size.toBn()) : proofSize ]; }, [new BN(0), new BN(0), new BN(0), new BN(0)]) : []; } function Summary ({ blockWeight, events, maxBlockWeight, maxProofSize, signedBlock }: Props): React.ReactElement | null { const { t } = useTranslation(); const { api } = useApi(); const [deposits, transfers, weight, size] = useMemo( () => { const eventDetails = extractEventDetails(events); const { totalProofSize, totalRefTime } = accumulateWeights(blockWeight); // Block weight is the source of truth; using events data as fallback only if (blockWeight) { eventDetails[2] = totalRefTime; eventDetails[3] = totalProofSize; } return eventDetails; }, [blockWeight, events] ); return (
{api.query.balances && ( <> )}
{weight ? formatNumber(weight) : 999,999,999} {maxProofSize && size && {formatNumber(size)} }
{events ? formatNumber(events.length) : 99} {signedBlock ? formatNumber(signedBlock.block.extrinsics.length) : 99}
); } export default React.memo(Summary);