parent
6e85de4730
commit
120fb7799e
@ -2,12 +2,12 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { Option, Vec } from '@polkadot/types';
|
||||
import type { AccountId, BlockNumber, HeadData, Header, ParaId, ParaLifecycle } from '@polkadot/types/interfaces';
|
||||
import type { AccountId, BlockNumber, CandidatePendingAvailability, HeadData, Header, ParaId, ParaLifecycle } from '@polkadot/types/interfaces';
|
||||
import type { Codec } from '@polkadot/types/types';
|
||||
import type { QueuedAction } from './types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { AddressMini, Badge, Expander, ParaLink } from '@polkadot/react-components';
|
||||
import { useApi, useCall, useCallMulti, useParaApi } from '@polkadot/react-hooks';
|
||||
@ -26,14 +26,16 @@ interface Props {
|
||||
lastBacked?: [string, string, BN];
|
||||
lastInclusion?: [string, string, BN];
|
||||
nextAction?: QueuedAction;
|
||||
sessionValidators?: AccountId[] | null;
|
||||
validators?: AccountId[];
|
||||
}
|
||||
|
||||
type QueryResult = [Option<HeadData>, Option<BlockNumber>, Option<ParaLifecycle>, Vec<Codec>, Vec<Codec>, Vec<Codec>, Vec<Codec>, Option<BlockNumber>];
|
||||
type QueryResult = [Option<HeadData>, Option<BlockNumber>, Option<ParaLifecycle>, Vec<Codec>, Vec<Codec>, Vec<Codec>, Vec<Codec>, Option<BlockNumber>, Option<CandidatePendingAvailability>];
|
||||
|
||||
interface QueryState {
|
||||
headHex: string | null;
|
||||
lifecycle: ParaLifecycle | null;
|
||||
pendingAvail: CandidatePendingAvailability | null;
|
||||
updateAt: BlockNumber | null;
|
||||
qDmp: number;
|
||||
qUmp: number;
|
||||
@ -50,6 +52,7 @@ const optionsMulti = {
|
||||
defaultValue: {
|
||||
headHex: null,
|
||||
lifecycle: null,
|
||||
pendingAvail: null,
|
||||
qDmp: 0,
|
||||
qHrmpE: 0,
|
||||
qHrmpI: 0,
|
||||
@ -57,11 +60,12 @@ const optionsMulti = {
|
||||
updateAt: null,
|
||||
watermark: null
|
||||
},
|
||||
transform: ([headData, optUp, optLifecycle, dmp, ump, hrmpE, hrmpI, optWm]: QueryResult): QueryState => ({
|
||||
transform: ([headData, optUp, optLifecycle, dmp, ump, hrmpE, hrmpI, optWm, optPending]: QueryResult): QueryState => ({
|
||||
headHex: headData.isSome
|
||||
? sliceHex(headData.unwrap())
|
||||
: null,
|
||||
lifecycle: optLifecycle.unwrapOr(null),
|
||||
pendingAvail: optPending.unwrapOr(null),
|
||||
qDmp: dmp.length,
|
||||
qHrmpE: hrmpE.length,
|
||||
qHrmpI: hrmpI.length,
|
||||
@ -71,7 +75,7 @@ const optionsMulti = {
|
||||
})
|
||||
};
|
||||
|
||||
function Parachain ({ bestNumber, className = '', id, isScheduled, lastBacked, lastInclusion, nextAction, validators }: Props): React.ReactElement<Props> {
|
||||
function Parachain ({ bestNumber, className = '', id, isScheduled, lastBacked, lastInclusion, nextAction, sessionValidators, validators }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const { api: paraApi } = useParaApi(id);
|
||||
@ -84,8 +88,10 @@ function Parachain ({ bestNumber, className = '', id, isScheduled, lastBacked, l
|
||||
[api.query.ump.relayDispatchQueues, id],
|
||||
[api.query.hrmp.hrmpEgressChannelsIndex, id],
|
||||
[api.query.hrmp.hrmpIngressChannelsIndex, id],
|
||||
[api.query.hrmp.hrmpWatermarks, id]
|
||||
[api.query.hrmp.hrmpWatermarks, id],
|
||||
[api.query.inclusion.pendingAvailability, id]
|
||||
], optionsMulti);
|
||||
const [nonBacked, setNonBacked] = useState<AccountId[]>([]);
|
||||
|
||||
const blockDelay = useMemo(
|
||||
() => bestNumber && (
|
||||
@ -108,6 +114,33 @@ function Parachain ({ bestNumber, className = '', id, isScheduled, lastBacked, l
|
||||
[validators]
|
||||
);
|
||||
|
||||
const bckRender = useCallback(
|
||||
() => nonBacked.map((id) => (
|
||||
<AddressMini
|
||||
key={id.toString()}
|
||||
value={id}
|
||||
/>
|
||||
)),
|
||||
[nonBacked]
|
||||
);
|
||||
|
||||
useEffect((): void => {
|
||||
if (sessionValidators) {
|
||||
if (paraInfo.pendingAvail) {
|
||||
const list = paraInfo.pendingAvail.availabilityVotes.toHuman()
|
||||
.slice(2)
|
||||
.replace(/_/g, '')
|
||||
.split('')
|
||||
.map((c, index) => c === '0' ? sessionValidators[index] : null)
|
||||
.filter((v, index): v is AccountId => !!v && index < sessionValidators.length);
|
||||
|
||||
list.length !== sessionValidators.length && setNonBacked(list);
|
||||
} else {
|
||||
setNonBacked([]);
|
||||
}
|
||||
}
|
||||
}, [paraInfo, sessionValidators]);
|
||||
|
||||
return (
|
||||
<tr className={className}>
|
||||
<td className='number'><h1>{formatNumber(id)}</h1></td>
|
||||
@ -125,6 +158,12 @@ function Parachain ({ bestNumber, className = '', id, isScheduled, lastBacked, l
|
||||
summary={t<string>('Validators ({{count}})', { replace: { count: formatNumber(validators.length) } })}
|
||||
/>
|
||||
)}
|
||||
{nonBacked && (
|
||||
<Expander
|
||||
renderChildren={bckRender}
|
||||
summary={t<string>('Non-voters ({{count}})', { replace: { count: formatNumber(nonBacked.length) } })}
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td className='start together hash'>{paraInfo.headHex}</td>
|
||||
<td className='start media--1100'>
|
||||
|
||||
@ -136,6 +136,7 @@ function Parachains ({ actionsQueue, ids, scheduled }: Props): React.ReactElemen
|
||||
nextAction={actionsQueue.find(({ paraIds }) =>
|
||||
paraIds.some((p) => p.eq(id))
|
||||
)}
|
||||
sessionValidators={validators}
|
||||
validators={validatorMap[index]}
|
||||
/>
|
||||
))}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user