diff --git a/packages/page-staking/src/Actions/Account/ListNominees.tsx b/packages/page-staking/src/Actions/Account/ListNominees.tsx index 91c22e88e6..70f3cdc01f 100644 --- a/packages/page-staking/src/Actions/Account/ListNominees.tsx +++ b/packages/page-staking/src/Actions/Account/ListNominees.tsx @@ -15,10 +15,24 @@ interface Props { function ListNominees ({ nominating, stashId }: Props): React.ReactElement { const { t } = useTranslation(); - const { nomsActive, nomsChilled, nomsInactive, nomsWaiting } = useInactives(stashId, nominating); + const { nomsActive, nomsChilled, nomsInactive, nomsOver, nomsWaiting } = useInactives(stashId, nominating); return ( <> + {nomsOver && nomsOver.length !== 0 && ( + ('The validators that are over-subscribed, only the top 64 backing stake will be rewarded.')} + summary={t('Oversubscribed nominations ({{count}})', { replace: { count: nomsOver.length } })} + > + {nomsOver.map((nomineeId, index): React.ReactNode => ( + + ))} + + )} {nomsActive && nomsActive.length !== 0 && ( ('The validators selected by the Phragmen algorithm to nominate for this era.')} diff --git a/packages/page-staking/src/Actions/useInactives.ts b/packages/page-staking/src/Actions/useInactives.ts index df54efde2a..9c8f717faf 100644 --- a/packages/page-staking/src/Actions/useInactives.ts +++ b/packages/page-staking/src/Actions/useInactives.ts @@ -13,6 +13,7 @@ interface Inactives { nomsActive?: string[]; nomsChilled?: string[]; nomsInactive?: string[]; + nomsOver?: string[]; nomsWaiting?: string[]; } @@ -28,6 +29,15 @@ function extractState (stashId: string, slashes: Option[], nomine return !lastNonzeroSlash.isZero() && lastNonzeroSlash.gte(submittedIn); }); + // all nominations that are oversubscribed + const nomsOver = exposures + .map((exposure, index) => + exposure.others.length > 64 + ? nominees[index] + : null + ) + .filter((nominee): nominee is string => !!nominee && !nomsChilled.includes(nominee)); + // first a blanket find of nominations not in the active set let nomsInactive = exposures .map((exposure, index) => @@ -35,7 +45,7 @@ function extractState (stashId: string, slashes: Option[], nomine ? null : nominees[index] ) - .filter((inactiveId): inactiveId is string => !!inactiveId); + .filter((nominee): nominee is string => !!nominee); // waiting if validator is inactive or we have not submitted long enough ago const nomsWaiting = exposures @@ -44,19 +54,20 @@ function extractState (stashId: string, slashes: Option[], nomine ? nominees[index] : null ) - .filter((waitingId): waitingId is string => !!waitingId) - .filter((nominee) => !nomsChilled.includes(nominee)); + .filter((nominee): nominee is string => !!nominee) + .filter((nominee) => !nomsChilled.includes(nominee) && !nomsOver.includes(nominee)); // filter based on all inactives - const nomsActive = nominees.filter((nominee) => !nomsInactive.includes(nominee) && !nomsChilled.includes(nominee)); + const nomsActive = nominees.filter((nominee) => !nomsInactive.includes(nominee) && !nomsChilled.includes(nominee) && !nomsOver.includes(nominee)); // inactive also contains waiting, remove those - nomsInactive = nomsInactive.filter((nominee) => !nomsWaiting.includes(nominee) && !nomsChilled.includes(nominee)); + nomsInactive = nomsInactive.filter((nominee) => !nomsWaiting.includes(nominee) && !nomsChilled.includes(nominee) && !nomsOver.includes(nominee)); return { nomsActive, nomsChilled, nomsInactive, + nomsOver, nomsWaiting }; } diff --git a/packages/page-staking/src/MaxBadge.tsx b/packages/page-staking/src/MaxBadge.tsx index d616060ff7..dae093903b 100644 --- a/packages/page-staking/src/MaxBadge.tsx +++ b/packages/page-staking/src/MaxBadge.tsx @@ -19,7 +19,7 @@ function MaxBadge ({ numNominators }: Props): React.ReactElement | null { return ( ); } diff --git a/packages/page-staking/src/Overview/Address/Status.tsx b/packages/page-staking/src/Overview/Address/Status.tsx index 0a7179e6b9..04106df6aa 100644 --- a/packages/page-staking/src/Overview/Address/Status.tsx +++ b/packages/page-staking/src/Overview/Address/Status.tsx @@ -9,12 +9,13 @@ import MaxBadge from '../../MaxBadge'; interface Props { isElected: boolean; + isMain?: boolean; numNominators?: number; onlineCount?: false | number; onlineMessage?: boolean; } -function Status ({ isElected, numNominators, onlineCount, onlineMessage }: Props): React.ReactElement { +function Status ({ isElected, isMain, numNominators, onlineCount, onlineMessage }: Props): React.ReactElement { return ( <> {isElected @@ -26,11 +27,15 @@ function Status ({ isElected, numNominators, onlineCount, onlineMessage }: Props ) : } - {(!!onlineCount || onlineMessage) && ( - } - /> + {isMain && ( + !!onlineCount || onlineMessage + ? ( + } + /> + ) + : )} diff --git a/packages/page-staking/src/Overview/Address/index.tsx b/packages/page-staking/src/Overview/Address/index.tsx index be72e5f84d..8763e4c9db 100644 --- a/packages/page-staking/src/Overview/Address/index.tsx +++ b/packages/page-staking/src/Overview/Address/index.tsx @@ -120,7 +120,8 @@ function Address ({ address, className = '', filterName, hasQueries, isElected, /> diff --git a/packages/page-staking/src/Targets/index.tsx b/packages/page-staking/src/Targets/index.tsx index ff0e9120a8..9bd32e04be 100644 --- a/packages/page-staking/src/Targets/index.tsx +++ b/packages/page-staking/src/Targets/index.tsx @@ -109,8 +109,8 @@ function Targets ({ className = '', isInElection, ownStashes, targets: { avgStak const _selectProfitable = useCallback( () => setSelected( - (validators || []).reduce((result: string[], { hasIdentity, isElected, isFavorite, key, rewardPayout }): string[] => { - if ((result.length < MAX_NOMINATIONS) && (hasIdentity || !withIdentity) && (isElected || isFavorite) && !rewardPayout.isZero()) { + (validators || []).reduce((result: string[], { hasIdentity, isElected, isFavorite, key, numNominators, rewardPayout }): string[] => { + if ((numNominators < 64) && (result.length < MAX_NOMINATIONS) && (hasIdentity || !withIdentity) && (isElected || isFavorite) && !rewardPayout.isZero()) { result.push(key); }