diff --git a/packages/page-staking/src/Legend.tsx b/packages/page-staking/src/Legend.tsx index fbe856dcc0..caa4395865 100644 --- a/packages/page-staking/src/Legend.tsx +++ b/packages/page-staking/src/Legend.tsx @@ -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 { +function Legend ({ className, isRelay, minCommission }: Props): React.ReactElement { const { t } = useTranslation(); return ( @@ -25,6 +28,15 @@ function Legend ({ className, isRelay }: Props): React.ReactElement { /> {t('Next session')} + {minCommission && ( + + + {t('Chilled')} + + )} {isRelay && ( { +function Status ({ isChilled, isElected, isMain, isPara, isRelay, nominators = NO_NOMS, onlineCount, onlineMessage }: Props): React.ReactElement { const { allAccounts } = useAccounts(); const blockCount = onlineCount && onlineCount.toNumber(); @@ -52,14 +53,21 @@ function Status ({ isElected, isMain, isPara, isRelay, nominators = NO_NOMS, onl ) : )} - {isElected + {isChilled ? ( ) - : + : isElected + ? ( + + ) + : } {isMain && ( blockCount || onlineMessage diff --git a/packages/page-staking/src/Overview/Address/index.tsx b/packages/page-staking/src/Overview/Address/index.tsx index 89972d13a6..4d6aa8b1d8 100644 --- a/packages/page-staking/src/Overview/Address/index.tsx +++ b/packages/page-staking/src/Overview/Address/index.tsx @@ -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 | null { +function Address ({ address, className = '', filterName, hasQueries, isElected, isFavorite, isMain, isPara, lastBlock, minCommission, nominatedBy, points, recentlyOnline, toggleFavorite, validatorInfo, withIdentity }: Props): React.ReactElement | 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} /> ; 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 | null { +function CurrentList ({ favorites, hasQueries, isIntentions, minCommission, paraValidators = DEFAULT_PARAS, stakingOverview, targets, toggleFavorite }: Props): React.ReactElement | 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={ - + } > {!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]} diff --git a/packages/page-staking/src/Overview/index.tsx b/packages/page-staking/src/Overview/index.tsx index dd90fe204b..63741b2975 100644 --- a/packages/page-staking/src/Overview/index.tsx +++ b/packages/page-staking/src/Overview/index.tsx @@ -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; 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 { +function Overview ({ className = '', favorites, hasQueries, isIntentions, minCommission, paraValidators, stakingOverview, targets, toggleFavorite, toggleLedger }: Props): React.ReactElement { 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} diff --git a/packages/page-staking/src/index.tsx b/packages/page-staking/src/index.tsx index d340b91332..6079ef462c 100644 --- a/packages/page-staking/src/index.tsx +++ b/packages/page-staking/src/index.tsx @@ -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], - transform: ([eraElectionStatus, validators, activeValidatorIndices]: [ElectionStatus | null, ValidatorId[] | null, ParaValidatorIndex[] | null]): [boolean, Record] => [ + defaultValue: [false, undefined, {}] as [boolean, BN | undefined, Record], + transform: ([eraElectionStatus, minValidatorBond, validators, activeValidatorIndices]: [ElectionStatus | null, BN | undefined, ValidatorId[] | null, ParaValidatorIndex[] | null]): [boolean, BN | undefined, Record] => [ !!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(api.derive.staking.overview); - const [isInElection, paraValidators] = useCallMulti<[boolean, Record]>([ + const [isInElection, minCommission, paraValidators] = useCallMulti<[boolean, BN | undefined, Record]>([ 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