Badge for selected para validators (#5341)
This commit is contained in:
parent
7146900542
commit
430cfc54d3
@ -24,6 +24,13 @@ function Legend ({ className }: Props): React.ReactElement<Props> {
|
||||
/>
|
||||
{t('Next session')}
|
||||
</span>
|
||||
<span>
|
||||
<Badge
|
||||
color='purple'
|
||||
icon='vector-square'
|
||||
/>
|
||||
{t('Para validator')}
|
||||
</span>
|
||||
<span>
|
||||
<Badge
|
||||
color='green'
|
||||
|
||||
@ -12,12 +12,15 @@ import MaxBadge from '../../MaxBadge';
|
||||
interface Props {
|
||||
isElected: boolean;
|
||||
isMain?: boolean;
|
||||
isPara?: boolean;
|
||||
nominators?: { nominatorId: string }[];
|
||||
onlineCount?: false | BN;
|
||||
onlineMessage?: boolean;
|
||||
}
|
||||
|
||||
function Status ({ isElected, isMain, nominators = [], onlineCount, onlineMessage }: Props): React.ReactElement<Props> {
|
||||
const NO_NOMS: { nominatorId: string }[] = [];
|
||||
|
||||
function Status ({ isElected, isMain, isPara, nominators = NO_NOMS, onlineCount, onlineMessage }: Props): React.ReactElement<Props> {
|
||||
const { allAccounts } = useAccounts();
|
||||
const blockCount = onlineCount && onlineCount.toNumber();
|
||||
|
||||
@ -37,6 +40,15 @@ function Status ({ isElected, isMain, nominators = [], onlineCount, onlineMessag
|
||||
)
|
||||
: <Badge color='transparent' />
|
||||
}
|
||||
{isPara
|
||||
? (
|
||||
<Badge
|
||||
color='purple'
|
||||
icon='vector-square'
|
||||
/>
|
||||
)
|
||||
: <Badge color='transparent' />
|
||||
}
|
||||
{isElected
|
||||
? (
|
||||
<Badge
|
||||
|
||||
@ -30,6 +30,7 @@ interface Props {
|
||||
isElected: boolean;
|
||||
isFavorite: boolean;
|
||||
isMain?: boolean;
|
||||
isPara?: boolean;
|
||||
lastBlock?: string;
|
||||
nominatedBy?: NominatedByType[];
|
||||
points?: string;
|
||||
@ -83,7 +84,7 @@ function useAddressCalls (api: ApiPromise, address: string, isMain?: boolean) {
|
||||
return { accountInfo, slashingSpans };
|
||||
}
|
||||
|
||||
function Address ({ address, className = '', filterName, hasQueries, isElected, isFavorite, isMain, lastBlock, nominatedBy, points, recentlyOnline, toggleFavorite, validatorInfo, withIdentity }: Props): React.ReactElement<Props> | null {
|
||||
function Address ({ address, className = '', filterName, hasQueries, isElected, isFavorite, isMain, isPara, lastBlock, nominatedBy, points, recentlyOnline, toggleFavorite, validatorInfo, withIdentity }: Props): React.ReactElement<Props> | null {
|
||||
const { api } = useApi();
|
||||
const { accountInfo, slashingSpans } = useAddressCalls(api, address, isMain);
|
||||
|
||||
@ -121,6 +122,7 @@ function Address ({ address, className = '', filterName, hasQueries, isElected,
|
||||
<Status
|
||||
isElected={isElected}
|
||||
isMain={isMain}
|
||||
isPara={isPara}
|
||||
nominators={isMain ? nominators : nominatedBy}
|
||||
onlineCount={recentlyOnline?.blockCount}
|
||||
onlineMessage={recentlyOnline?.hasMessage}
|
||||
|
||||
@ -22,6 +22,7 @@ interface Props {
|
||||
favorites: string[];
|
||||
hasQueries: boolean;
|
||||
isIntentions?: boolean;
|
||||
paraValidators?: Record<string, boolean>;
|
||||
setNominators?: (nominators: string[]) => void;
|
||||
stakingOverview?: DeriveStakingOverview;
|
||||
targets: SortedTargets;
|
||||
@ -71,7 +72,9 @@ function getFiltered (stakingOverview: DeriveStakingOverview, favorites: string[
|
||||
};
|
||||
}
|
||||
|
||||
function CurrentList ({ favorites, hasQueries, isIntentions, stakingOverview, targets, toggleFavorite }: Props): React.ReactElement<Props> | null {
|
||||
const DEFAULT_PARAS = {};
|
||||
|
||||
function CurrentList ({ favorites, hasQueries, isIntentions, paraValidators = DEFAULT_PARAS, stakingOverview, targets, toggleFavorite }: Props): React.ReactElement<Props> | null {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const { byAuthor, eraPoints } = useContext(isIntentions ? EmptyAuthorsContext : BlockAuthorsContext);
|
||||
@ -126,6 +129,7 @@ function CurrentList ({ favorites, hasQueries, isIntentions, stakingOverview, ta
|
||||
isElected={isElected}
|
||||
isFavorite={isFavorite}
|
||||
isMain={isMain}
|
||||
isPara={paraValidators[address]}
|
||||
key={address}
|
||||
lastBlock={byAuthor[address]}
|
||||
nominatedBy={nominatedBy ? (nominatedBy[address] || []) : undefined}
|
||||
@ -136,7 +140,7 @@ function CurrentList ({ favorites, hasQueries, isIntentions, stakingOverview, ta
|
||||
withIdentity={toggles.withIdentity}
|
||||
/>
|
||||
)),
|
||||
[byAuthor, eraPoints, hasQueries, infoMap, nameFilter, nominatedBy, recentlyOnline, toggleFavorite, toggles]
|
||||
[byAuthor, eraPoints, hasQueries, infoMap, nameFilter, nominatedBy, paraValidators, recentlyOnline, toggleFavorite, toggles]
|
||||
);
|
||||
|
||||
return isIntentions
|
||||
|
||||
@ -13,13 +13,14 @@ interface Props {
|
||||
favorites: string[];
|
||||
hasQueries: boolean;
|
||||
isIntentions?: boolean;
|
||||
paraValidators?: Record<string, boolean>;
|
||||
stakingOverview?: DeriveStakingOverview;
|
||||
targets: SortedTargets;
|
||||
toggleFavorite: (address: string) => void;
|
||||
toggleLedger?: () => void;
|
||||
}
|
||||
|
||||
function Overview ({ className = '', favorites, hasQueries, isIntentions, stakingOverview, targets, toggleFavorite, toggleLedger }: Props): React.ReactElement<Props> {
|
||||
function Overview ({ className = '', favorites, hasQueries, isIntentions, paraValidators, stakingOverview, targets, toggleFavorite, toggleLedger }: Props): React.ReactElement<Props> {
|
||||
useEffect((): void => {
|
||||
toggleLedger && toggleLedger();
|
||||
}, [toggleLedger]);
|
||||
@ -30,6 +31,7 @@ function Overview ({ className = '', favorites, hasQueries, isIntentions, stakin
|
||||
favorites={favorites}
|
||||
hasQueries={hasQueries}
|
||||
isIntentions={isIntentions}
|
||||
paraValidators={paraValidators}
|
||||
stakingOverview={stakingOverview}
|
||||
targets={targets}
|
||||
toggleFavorite={toggleFavorite}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
import type { DeriveStakingOverview } from '@polkadot/api-derive/types';
|
||||
import type { AppProps as Props, ThemeProps } from '@polkadot/react-components/types';
|
||||
import type { ElectionStatus } from '@polkadot/types/interfaces';
|
||||
import type { ElectionStatus, ParaValidatorIndex, ValidatorId } from '@polkadot/types/interfaces';
|
||||
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { Route, Switch } from 'react-router';
|
||||
@ -12,7 +12,7 @@ import styled from 'styled-components';
|
||||
|
||||
import { HelpOverlay } from '@polkadot/react-components';
|
||||
import Tabs from '@polkadot/react-components/Tabs';
|
||||
import { useAccounts, useApi, useAvailableSlashes, useCall, useFavorites, useOwnStashInfos } from '@polkadot/react-hooks';
|
||||
import { useAccounts, useApi, useAvailableSlashes, useCall, useCallMulti, useFavorites, useOwnStashInfos } from '@polkadot/react-hooks';
|
||||
import { isFunction } from '@polkadot/util';
|
||||
|
||||
import basicMd from './md/basic.md';
|
||||
@ -30,8 +30,14 @@ import useSortedTargets from './useSortedTargets';
|
||||
|
||||
const HIDDEN_ACC = ['actions', 'payout'];
|
||||
|
||||
const transformElection = {
|
||||
transform: (status: ElectionStatus) => status.isOpen
|
||||
const optionsParaValidators = {
|
||||
defaultValue: [false, {}] as [boolean, Record<string, boolean>],
|
||||
transform: ([eraElectionStatus, validators, activeValidatorIndices]: [ElectionStatus | null, ValidatorId[] | null, ParaValidatorIndex[] | null]): [boolean, Record<string, boolean>] => [
|
||||
!!eraElectionStatus && eraElectionStatus.isOpen,
|
||||
validators && activeValidatorIndices
|
||||
? activeValidatorIndices.reduce((all, index) => ({ ...all, [validators[index.toNumber()].toString()]: true }), {})
|
||||
: {}
|
||||
]
|
||||
};
|
||||
|
||||
function StakingApp ({ basePath, className = '' }: Props): React.ReactElement<Props> {
|
||||
@ -42,7 +48,11 @@ function StakingApp ({ basePath, className = '' }: Props): React.ReactElement<Pr
|
||||
const [withLedger, setWithLedger] = useState(false);
|
||||
const [favorites, toggleFavorite] = useFavorites(STORE_FAVS_BASE);
|
||||
const stakingOverview = useCall<DeriveStakingOverview>(api.derive.staking.overview);
|
||||
const isInElection = useCall<boolean>(api.query.staking?.eraElectionStatus, undefined, transformElection);
|
||||
const [isInElection, paraValidators] = useCallMulti<[boolean, Record<string, boolean>]>([
|
||||
api.query.staking.eraElectionStatus,
|
||||
api.query.session.validators,
|
||||
(api.query.parasShared || api.query.shared)?.activeValidatorIndices
|
||||
], optionsParaValidators);
|
||||
const ownStashes = useOwnStashInfos();
|
||||
const slashes = useAvailableSlashes();
|
||||
const targets = useSortedTargets(favorites, withLedger);
|
||||
@ -165,6 +175,7 @@ function StakingApp ({ basePath, className = '' }: Props): React.ReactElement<Pr
|
||||
className={basePath === pathname ? '' : 'staking--hidden'}
|
||||
favorites={favorites}
|
||||
hasQueries={hasQueries}
|
||||
paraValidators={paraValidators}
|
||||
stakingOverview={stakingOverview}
|
||||
targets={targets}
|
||||
toggleFavorite={toggleFavorite}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user