Display parachain validators (#4667)
This commit is contained in:
parent
cb3d879bcf
commit
a2fc3e53fd
@ -2,17 +2,18 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { Option, Vec } from '@polkadot/types';
|
||||
import type { BlockNumber, HeadData, Header, ParaId } from '@polkadot/types/interfaces';
|
||||
import type { AccountId, BlockNumber, HeadData, Header, ParaId } from '@polkadot/types/interfaces';
|
||||
import type { Codec } from '@polkadot/types/types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React, { useMemo } from 'react';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
|
||||
import { Badge, ParaLink } from '@polkadot/react-components';
|
||||
import { AddressMini, Badge, Expander, ParaLink } from '@polkadot/react-components';
|
||||
import { useApi, useCall, useCallMulti, useParaApi } from '@polkadot/react-hooks';
|
||||
import { BlockToTime } from '@polkadot/react-query';
|
||||
import { BN_ONE, formatNumber } from '@polkadot/util';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
import { sliceHex } from '../util';
|
||||
|
||||
interface Props {
|
||||
@ -22,6 +23,7 @@ interface Props {
|
||||
isScheduled?: boolean;
|
||||
lastBacked?: [string, string, BN];
|
||||
lastInclusion?: [string, string, BN];
|
||||
validators?: AccountId[];
|
||||
}
|
||||
|
||||
type QueryResult = [Option<HeadData>, Option<BlockNumber>, Vec<Codec>, Vec<Codec>, Vec<Codec>, Vec<Codec>, Option<BlockNumber>];
|
||||
@ -63,7 +65,8 @@ const optionsMulti = {
|
||||
})
|
||||
};
|
||||
|
||||
function Parachain ({ bestNumber, className = '', id, isScheduled, lastBacked, lastInclusion }: Props): React.ReactElement<Props> {
|
||||
function Parachain ({ bestNumber, className = '', id, isScheduled, lastBacked, lastInclusion, validators }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const { api: paraApi } = useParaApi(id);
|
||||
const paraBest = useCall<BlockNumber>(paraApi?.rpc.chain.subscribeNewHeads, undefined, transformHeader);
|
||||
@ -89,6 +92,16 @@ function Parachain ({ bestNumber, className = '', id, isScheduled, lastBacked, l
|
||||
[bestNumber, lastRelayNumber, paraInfo]
|
||||
);
|
||||
|
||||
const valRender = useCallback(
|
||||
() => validators?.map((id) => (
|
||||
<AddressMini
|
||||
key={id.toString()}
|
||||
value={id}
|
||||
/>
|
||||
)),
|
||||
[validators]
|
||||
);
|
||||
|
||||
return (
|
||||
<tr className={className}>
|
||||
<td className='number'><h1>{formatNumber(id)}</h1></td>
|
||||
@ -99,6 +112,14 @@ function Parachain ({ bestNumber, className = '', id, isScheduled, lastBacked, l
|
||||
/>
|
||||
)}</td>
|
||||
<td className='badge together'><ParaLink id={id} /></td>
|
||||
<td className='number media--1500'>
|
||||
{validators && validators.length !== 0 && (
|
||||
<Expander
|
||||
renderChildren={valRender}
|
||||
summary={t<string>('Validators ({{count}})', { replace: { count: formatNumber(validators.length) } })}
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td className='all start together hash'>{paraInfo.headHex}</td>
|
||||
<td className='number'>{blockDelay && <BlockToTime blocks={blockDelay} />}</td>
|
||||
<td className='number'>
|
||||
|
||||
@ -2,14 +2,14 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { SignedBlockExtended } from '@polkadot/api-derive/type';
|
||||
import type { CandidateReceipt, Event, ParaId } from '@polkadot/types/interfaces';
|
||||
import type { AccountId, CandidateReceipt, Event, ParaId, ParaValidatorIndex } from '@polkadot/types/interfaces';
|
||||
import type { ScheduledProposals } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import { Table } from '@polkadot/react-components';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall, useCallMulti } from '@polkadot/react-hooks';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
import Parachain from './Parachain';
|
||||
@ -26,6 +26,10 @@ interface LastEvents {
|
||||
lastIncluded: EventMap;
|
||||
}
|
||||
|
||||
const optionsMulti = {
|
||||
defaultValue: [null, null] as [AccountId[] | null, ParaValidatorIndex[][] | null]
|
||||
};
|
||||
|
||||
function includeEntry (map: EventMap, event: Event, blockHash: string, blockNumber: BN): void {
|
||||
const { descriptor } = event.data[0] as CandidateReceipt;
|
||||
|
||||
@ -44,6 +48,10 @@ function ParachainList ({ ids, scheduled }: Props): React.ReactElement<Props> {
|
||||
const bestNumber = useCall<BN>(api.derive.chain.bestNumber);
|
||||
const lastBlock = useCall<SignedBlockExtended>(api.derive.chain.subscribeNewBlocks);
|
||||
const [{ lastBacked, lastIncluded }, setLastEvents] = useState<LastEvents>({ lastBacked: {}, lastIncluded: {} });
|
||||
const [validators, validatorGroups] = useCallMulti<[AccountId[] | null, ParaValidatorIndex[][] | null]>([
|
||||
api.query.session.validators,
|
||||
api.query.paraScheduler?.validatorGroups || api.query.scheduler?.validatorGroups
|
||||
], optionsMulti);
|
||||
|
||||
const scheduledIds = useMemo(
|
||||
() => (scheduled || []).reduce((all: Record<string, boolean>, { scheduledIds }: ScheduledProposals): Record<string, boolean> => {
|
||||
@ -52,6 +60,17 @@ function ParachainList ({ ids, scheduled }: Props): React.ReactElement<Props> {
|
||||
[scheduled]
|
||||
);
|
||||
|
||||
const validatorMap = useMemo(
|
||||
() => validators && validatorGroups && ids && ids.length === validatorGroups.length
|
||||
? validatorGroups.map((ids) =>
|
||||
ids
|
||||
.map((id) => validators[id.toNumber()])
|
||||
.filter((a) => a)
|
||||
)
|
||||
: [],
|
||||
[ids, validators, validatorGroups]
|
||||
);
|
||||
|
||||
useEffect((): void => {
|
||||
lastBlock && setLastEvents((prev) => {
|
||||
const backed: Record<string, [string, string, BN]> = {};
|
||||
@ -88,6 +107,7 @@ function ParachainList ({ ids, scheduled }: Props): React.ReactElement<Props> {
|
||||
|
||||
const headerRef = useRef([
|
||||
[t('parachains'), 'start', 3],
|
||||
['', 'media--1500'],
|
||||
[t('heads'), 'start'],
|
||||
[t('included (parent)'), undefined, 2],
|
||||
[t('backed')],
|
||||
@ -101,7 +121,7 @@ function ParachainList ({ ids, scheduled }: Props): React.ReactElement<Props> {
|
||||
empty={ids && t<string>('There are no registered parachains')}
|
||||
header={headerRef.current}
|
||||
>
|
||||
{ids?.map((id): React.ReactNode => (
|
||||
{ids?.map((id, index): React.ReactNode => (
|
||||
<Parachain
|
||||
bestNumber={bestNumber}
|
||||
id={id}
|
||||
@ -109,6 +129,7 @@ function ParachainList ({ ids, scheduled }: Props): React.ReactElement<Props> {
|
||||
key={id.toString()}
|
||||
lastBacked={lastBacked[id.toString()]}
|
||||
lastInclusion={lastIncluded[id.toString()]}
|
||||
validators={validatorMap[index]}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user