From 217b94a5e43c18dce77e0610ad3fd143e35ca571 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Sat, 16 May 2020 09:12:06 +0200 Subject: [PATCH] Add blockHash & blockNumber to keyed event context (#2756) --- packages/react-query/src/BlockAuthors.tsx | 9 +++--- packages/react-query/src/Events.tsx | 39 +++++++++++++++++------ 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/packages/react-query/src/BlockAuthors.tsx b/packages/react-query/src/BlockAuthors.tsx index ec66fb8c75..1c1a660a1d 100644 --- a/packages/react-query/src/BlockAuthors.tsx +++ b/packages/react-query/src/BlockAuthors.tsx @@ -22,7 +22,7 @@ interface Props { children: React.ReactNode; } -const MAX_HEADERS = 25; +const MAX_HEADERS = 50; const byAuthor: Record = {}; const eraPoints: Record = {}; @@ -36,8 +36,7 @@ function BlockAuthorsBase ({ children }: Props): React.ReactElement { const [validators, setValidators] = useState([]); useEffect((): void => { - // TODO We should really unsub - but since this should just be used once, - // atm I'm rather typing this than doing it the way it is supposed to be + // No unsub, global context - destroyed on app close api.isReady.then((): void => { let lastHeaders: HeaderExtended[] = []; let lastBlockAuthors: string[] = []; @@ -45,7 +44,7 @@ function BlockAuthorsBase ({ children }: Props): React.ReactElement { // subscribe to all validators api.query.session && api.query.session.validators((validatorIds): void => { - setValidators(validatorIds.map((validatorId): string => validatorId.toString())); + setValidators(validatorIds.map((validatorId) => validatorId.toString())); }); // subscribe to new headers @@ -73,7 +72,7 @@ function BlockAuthorsBase ({ children }: Props): React.ReactElement { return next; }, [lastHeader]) - .sort((a, b): number => b.number.unwrap().cmp(a.number.unwrap())); + .sort((a, b) => b.number.unwrap().cmp(a.number.unwrap())); setState({ byAuthor, eraPoints, lastBlockAuthors: lastBlockAuthors.slice(), lastBlockNumber, lastHeader, lastHeaders }); } diff --git a/packages/react-query/src/Events.tsx b/packages/react-query/src/Events.tsx index ec6041f881..86e453edfe 100644 --- a/packages/react-query/src/Events.tsx +++ b/packages/react-query/src/Events.tsx @@ -2,13 +2,16 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. +import { BlockNumber, EventRecord } from '@polkadot/types/interfaces'; + import React, { useEffect, useState } from 'react'; import { useApi } from '@polkadot/react-hooks'; -import { EventRecord } from '@polkadot/types/interfaces'; import { stringToU8a } from '@polkadot/util'; import { xxhashAsHex } from '@polkadot/util-crypto'; interface KeyedEvent { + blockHash: string; + blockNumber: BlockNumber; key: string; record: EventRecord; } @@ -19,7 +22,7 @@ interface Props { children: React.ReactNode; } -const MAX_EVENTS = 25; +const MAX_EVENTS = 50; const EventsContext: React.Context = React.createContext([]); @@ -28,21 +31,37 @@ function EventsBase ({ children }: Props): React.ReactElement { const [state, setState] = useState([]); useEffect((): void => { - // TODO We should really unsub - but since this should just be used once, - // atm I'm rather typing this than doing it the way it is supposed to be + // No unsub, global context - destroyed on app close api.isReady.then((): void => { - let prevEventHash = ''; + let prevBlockHash: string | null = null; + let prevEventHash: string | null = null; api.query.system.events((records): void => { - const newEvents = records - .filter(({ event }): boolean => event.section !== 'system') - .map((record, index): KeyedEvent => ({ key: `${Date.now()}-${index}`, record })); + const newEvents = records.filter(({ event }) => event.section !== 'system'); const newEventHash = xxhashAsHex(stringToU8a(JSON.stringify(newEvents))); - if (newEventHash !== prevEventHash) { + if (newEventHash !== prevEventHash && newEvents.length) { prevEventHash = newEventHash; - setState((events) => [...newEvents, ...events].slice(0, MAX_EVENTS)); + // retrieve the last header, this will map to the current state + api.rpc.chain.getHeader().then((header): void => { + const blockNumber = header.number.unwrap(); + const blockHash = header.hash.toHex(); + + if (blockHash !== prevBlockHash) { + prevBlockHash = blockHash; + + setState((events) => [ + ...newEvents.map((record, index): KeyedEvent => ({ + blockHash, + blockNumber, + key: `${blockNumber}-${blockHash}-${index}`, + record + })), + ...events + ].slice(0, MAX_EVENTS)); + } + }); } }); });