Badge for selected para validators (#5341)

This commit is contained in:
Jaco 2021-05-21 23:10:05 +03:00 committed by GitHub
parent 7146900542
commit 430cfc54d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 48 additions and 10 deletions

View File

@ -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'

View File

@ -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

View File

@ -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}

View File

@ -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

View File

@ -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}

View File

@ -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}