Display chilled (only with minCommission) (#7141)
This commit is contained in:
parent
9e019b481c
commit
178afa65d9
@ -1,6 +1,8 @@
|
||||
// Copyright 2017-2022 @polkadot/app-staking authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { BN } from '@polkadot/util';
|
||||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
@ -11,9 +13,10 @@ import { useTranslation } from './translate';
|
||||
interface Props {
|
||||
className?: string;
|
||||
isRelay?: boolean;
|
||||
minCommission?: BN;
|
||||
}
|
||||
|
||||
function Legend ({ className, isRelay }: Props): React.ReactElement<Props> {
|
||||
function Legend ({ className, isRelay, minCommission }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
@ -25,6 +28,15 @@ function Legend ({ className, isRelay }: Props): React.ReactElement<Props> {
|
||||
/>
|
||||
{t('Next session')}
|
||||
</span>
|
||||
{minCommission && (
|
||||
<span>
|
||||
<Badge
|
||||
color='red'
|
||||
icon='cancel'
|
||||
/>
|
||||
{t('Chilled')}
|
||||
</span>
|
||||
)}
|
||||
{isRelay && (
|
||||
<span>
|
||||
<Badge
|
||||
|
||||
@ -11,6 +11,7 @@ import { useAccounts } from '@polkadot/react-hooks';
|
||||
import MaxBadge from '../../MaxBadge';
|
||||
|
||||
interface Props {
|
||||
isChilled?: boolean;
|
||||
isElected: boolean;
|
||||
isMain?: boolean;
|
||||
isPara?: boolean;
|
||||
@ -22,7 +23,7 @@ interface Props {
|
||||
|
||||
const NO_NOMS: { nominatorId: string }[] = [];
|
||||
|
||||
function Status ({ isElected, isMain, isPara, isRelay, nominators = NO_NOMS, onlineCount, onlineMessage }: Props): React.ReactElement<Props> {
|
||||
function Status ({ isChilled, isElected, isMain, isPara, isRelay, nominators = NO_NOMS, onlineCount, onlineMessage }: Props): React.ReactElement<Props> {
|
||||
const { allAccounts } = useAccounts();
|
||||
const blockCount = onlineCount && onlineCount.toNumber();
|
||||
|
||||
@ -52,14 +53,21 @@ function Status ({ isElected, isMain, isPara, isRelay, nominators = NO_NOMS, onl
|
||||
)
|
||||
: <Badge color='transparent' />
|
||||
)}
|
||||
{isElected
|
||||
{isChilled
|
||||
? (
|
||||
<Badge
|
||||
color='blue'
|
||||
icon='chevron-right'
|
||||
color='red'
|
||||
icon='cancel'
|
||||
/>
|
||||
)
|
||||
: <Badge color='transparent' />
|
||||
: isElected
|
||||
? (
|
||||
<Badge
|
||||
color='blue'
|
||||
icon='chevron-right'
|
||||
/>
|
||||
)
|
||||
: <Badge color='transparent' />
|
||||
}
|
||||
{isMain && (
|
||||
blockCount || onlineMessage
|
||||
|
||||
@ -32,6 +32,7 @@ interface Props {
|
||||
isMain?: boolean;
|
||||
isPara?: boolean;
|
||||
lastBlock?: string;
|
||||
minCommission?: BN;
|
||||
nominatedBy?: NominatedByType[];
|
||||
points?: string;
|
||||
recentlyOnline?: DeriveHeartbeatAuthor;
|
||||
@ -41,6 +42,7 @@ interface Props {
|
||||
}
|
||||
|
||||
interface StakingState {
|
||||
isChilled?: boolean;
|
||||
commission?: string;
|
||||
nominators: NominatorValue[];
|
||||
stakeTotal?: BN;
|
||||
@ -48,7 +50,7 @@ interface StakingState {
|
||||
stakeOwn?: BN;
|
||||
}
|
||||
|
||||
function expandInfo ({ exposure, validatorPrefs }: ValidatorInfo): StakingState {
|
||||
function expandInfo ({ exposure, validatorPrefs }: ValidatorInfo, minCommission?: BN): StakingState {
|
||||
let nominators: NominatorValue[] = [];
|
||||
let stakeTotal: BN | undefined;
|
||||
let stakeOther: BN | undefined;
|
||||
@ -65,6 +67,7 @@ function expandInfo ({ exposure, validatorPrefs }: ValidatorInfo): StakingState
|
||||
|
||||
return {
|
||||
commission: commission?.toHuman(),
|
||||
isChilled: commission && minCommission && commission.lt(minCommission),
|
||||
nominators,
|
||||
stakeOther,
|
||||
stakeOwn,
|
||||
@ -84,15 +87,15 @@ function useAddressCalls (api: ApiPromise, address: string, isMain?: boolean) {
|
||||
return { accountInfo, slashingSpans };
|
||||
}
|
||||
|
||||
function Address ({ address, className = '', filterName, hasQueries, isElected, isFavorite, isMain, isPara, lastBlock, nominatedBy, points, recentlyOnline, toggleFavorite, validatorInfo, withIdentity }: Props): React.ReactElement<Props> | null {
|
||||
function Address ({ address, className = '', filterName, hasQueries, isElected, isFavorite, isMain, isPara, lastBlock, minCommission, nominatedBy, points, recentlyOnline, toggleFavorite, validatorInfo, withIdentity }: Props): React.ReactElement<Props> | null {
|
||||
const { api } = useApi();
|
||||
const { accountInfo, slashingSpans } = useAddressCalls(api, address, isMain);
|
||||
|
||||
const { commission, nominators, stakeOther, stakeOwn } = useMemo(
|
||||
const { commission, isChilled, nominators, stakeOther, stakeOwn } = useMemo(
|
||||
() => validatorInfo
|
||||
? expandInfo(validatorInfo)
|
||||
? expandInfo(validatorInfo, minCommission)
|
||||
: { nominators: [] },
|
||||
[validatorInfo]
|
||||
[minCommission, validatorInfo]
|
||||
);
|
||||
|
||||
const isVisible = useMemo(
|
||||
@ -118,6 +121,7 @@ function Address ({ address, className = '', filterName, hasQueries, isElected,
|
||||
toggleFavorite={toggleFavorite}
|
||||
/>
|
||||
<Status
|
||||
isChilled={isChilled}
|
||||
isElected={isElected}
|
||||
isMain={isMain}
|
||||
isPara={isPara}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
import type { DeriveHeartbeats, DeriveStakingOverview } from '@polkadot/api-derive/types';
|
||||
import type { Authors } from '@polkadot/react-query/BlockAuthors';
|
||||
import type { AccountId } from '@polkadot/types/interfaces';
|
||||
import type { BN } from '@polkadot/util';
|
||||
import type { SortedTargets, ValidatorInfo } from '../types';
|
||||
|
||||
import React, { useContext, useMemo, useRef, useState } from 'react';
|
||||
@ -22,6 +23,7 @@ interface Props {
|
||||
favorites: string[];
|
||||
hasQueries: boolean;
|
||||
isIntentions?: boolean;
|
||||
minCommission?: BN;
|
||||
paraValidators?: Record<string, boolean>;
|
||||
setNominators?: (nominators: string[]) => void;
|
||||
stakingOverview?: DeriveStakingOverview;
|
||||
@ -71,7 +73,7 @@ function getFiltered (stakingOverview: DeriveStakingOverview, favorites: string[
|
||||
|
||||
const DEFAULT_PARAS = {};
|
||||
|
||||
function CurrentList ({ favorites, hasQueries, isIntentions, paraValidators = DEFAULT_PARAS, stakingOverview, targets, toggleFavorite }: Props): React.ReactElement<Props> | null {
|
||||
function CurrentList ({ favorites, hasQueries, isIntentions, minCommission, paraValidators = DEFAULT_PARAS, stakingOverview, targets, toggleFavorite }: Props): React.ReactElement<Props> | null {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const { byAuthor, eraPoints } = useContext(isIntentions ? EmptyAuthorsContext : BlockAuthorsContext);
|
||||
@ -147,7 +149,10 @@ function CurrentList ({ favorites, hasQueries, isIntentions, paraValidators = DE
|
||||
}
|
||||
header={headerRef.current}
|
||||
legend={
|
||||
<Legend isRelay={!isIntentions && !!(api.query.parasShared || api.query.shared)?.activeValidatorIndices} />
|
||||
<Legend
|
||||
isRelay={!isIntentions && !!(api.query.parasShared || api.query.shared)?.activeValidatorIndices}
|
||||
minCommission={minCommission}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{!isLoading && (
|
||||
@ -166,6 +171,7 @@ function CurrentList ({ favorites, hasQueries, isIntentions, paraValidators = DE
|
||||
isPara={isIntentions ? false : paraValidators[address]}
|
||||
key={address}
|
||||
lastBlock={byAuthor[address]}
|
||||
minCommission={minCommission}
|
||||
nominatedBy={nominatedBy?.[address]}
|
||||
points={eraPoints[address]}
|
||||
recentlyOnline={recentlyOnline?.[address]}
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { DeriveStakingOverview } from '@polkadot/api-derive/types';
|
||||
import type { BN } from '@polkadot/util';
|
||||
import type { SortedTargets } from '../types';
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
@ -13,6 +14,7 @@ interface Props {
|
||||
favorites: string[];
|
||||
hasQueries: boolean;
|
||||
isIntentions?: boolean;
|
||||
minCommission?: BN;
|
||||
paraValidators?: Record<string, boolean>;
|
||||
stakingOverview?: DeriveStakingOverview;
|
||||
targets: SortedTargets;
|
||||
@ -20,7 +22,7 @@ interface Props {
|
||||
toggleLedger?: () => void;
|
||||
}
|
||||
|
||||
function Overview ({ className = '', favorites, hasQueries, isIntentions, paraValidators, stakingOverview, targets, toggleFavorite, toggleLedger }: Props): React.ReactElement<Props> {
|
||||
function Overview ({ className = '', favorites, hasQueries, isIntentions, minCommission, paraValidators, stakingOverview, targets, toggleFavorite, toggleLedger }: Props): React.ReactElement<Props> {
|
||||
useEffect((): void => {
|
||||
toggleLedger && toggleLedger();
|
||||
}, [toggleLedger]);
|
||||
@ -31,6 +33,7 @@ function Overview ({ className = '', favorites, hasQueries, isIntentions, paraVa
|
||||
favorites={favorites}
|
||||
hasQueries={hasQueries}
|
||||
isIntentions={isIntentions}
|
||||
minCommission={minCommission}
|
||||
paraValidators={paraValidators}
|
||||
stakingOverview={stakingOverview}
|
||||
targets={targets}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
import type { DeriveStakingOverview } from '@polkadot/api-derive/types';
|
||||
import type { AppProps as Props, ThemeProps } from '@polkadot/react-components/types';
|
||||
import type { ElectionStatus, ParaValidatorIndex, ValidatorId } from '@polkadot/types/interfaces';
|
||||
import type { BN } from '@polkadot/util';
|
||||
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { Route, Switch } from 'react-router';
|
||||
@ -30,9 +31,12 @@ import useSortedTargets from './useSortedTargets';
|
||||
const HIDDEN_ACC = ['actions', 'payout'];
|
||||
|
||||
const optionsParaValidators = {
|
||||
defaultValue: [false, {}] as [boolean, Record<string, boolean>],
|
||||
transform: ([eraElectionStatus, validators, activeValidatorIndices]: [ElectionStatus | null, ValidatorId[] | null, ParaValidatorIndex[] | null]): [boolean, Record<string, boolean>] => [
|
||||
defaultValue: [false, undefined, {}] as [boolean, BN | undefined, Record<string, boolean>],
|
||||
transform: ([eraElectionStatus, minValidatorBond, validators, activeValidatorIndices]: [ElectionStatus | null, BN | undefined, ValidatorId[] | null, ParaValidatorIndex[] | null]): [boolean, BN | undefined, Record<string, boolean>] => [
|
||||
!!eraElectionStatus && eraElectionStatus.isOpen,
|
||||
minValidatorBond && !minValidatorBond.isZero()
|
||||
? minValidatorBond
|
||||
: undefined,
|
||||
validators && activeValidatorIndices
|
||||
? activeValidatorIndices.reduce((all, index) => ({ ...all, [validators[index.toNumber()].toString()]: true }), {})
|
||||
: {}
|
||||
@ -47,8 +51,9 @@ 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, paraValidators] = useCallMulti<[boolean, Record<string, boolean>]>([
|
||||
const [isInElection, minCommission, paraValidators] = useCallMulti<[boolean, BN | undefined, Record<string, boolean>]>([
|
||||
api.query.staking.eraElectionStatus,
|
||||
api.query.staking.minCommission,
|
||||
api.query.session.validators,
|
||||
(api.query.parasShared || api.query.shared)?.activeValidatorIndices
|
||||
], optionsParaValidators);
|
||||
@ -174,6 +179,7 @@ function StakingApp ({ basePath, className = '' }: Props): React.ReactElement<Pr
|
||||
className={basePath === pathname ? '' : 'staking--hidden'}
|
||||
favorites={favorites}
|
||||
hasQueries={hasQueries}
|
||||
minCommission={minCommission}
|
||||
paraValidators={paraValidators}
|
||||
stakingOverview={stakingOverview}
|
||||
targets={targets}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user