diff --git a/CHANGELOG.md b/CHANGELOG.md
index ef044158cf..28dbc66ca0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@ Changes:
- Add individual era-slash cancels on staking slashes page
- Adjust staking slashes with per-era selector
+- Staking list details now fully shared with targets (query optimizations)
- Adjust max payout batch size (40 txs for 64 payees) based on staking payout constant
- Add "copy seed" button to align with the extension UX on new accounts
- Combine confirmation/backup of imports/new account into the modals (no double-modal)
diff --git a/packages/page-staking/src/Overview/Address/Status.tsx b/packages/page-staking/src/Overview/Address/Status.tsx
index 04106df6aa..41040f4a01 100644
--- a/packages/page-staking/src/Overview/Address/Status.tsx
+++ b/packages/page-staking/src/Overview/Address/Status.tsx
@@ -2,6 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
+import BN from 'bn.js';
import React from 'react';
import { Badge, Icon } from '@polkadot/react-components';
@@ -11,7 +12,7 @@ interface Props {
isElected: boolean;
isMain?: boolean;
numNominators?: number;
- onlineCount?: false | number;
+ onlineCount?: false | BN;
onlineMessage?: boolean;
}
@@ -32,7 +33,7 @@ function Status ({ isElected, isMain, numNominators, onlineCount, onlineMessage
? (
}
+ info={onlineCount ? onlineCount.toNumber() : }
/>
)
:
diff --git a/packages/page-staking/src/Overview/Address/index.tsx b/packages/page-staking/src/Overview/Address/index.tsx
index 8763e4c9db..62b169137c 100644
--- a/packages/page-staking/src/Overview/Address/index.tsx
+++ b/packages/page-staking/src/Overview/Address/index.tsx
@@ -2,8 +2,9 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
-import { Balance, EraIndex, SlashingSpans } from '@polkadot/types/interfaces';
-import { DeriveAccountInfo, DeriveStakingQuery } from '@polkadot/api-derive/types';
+import { Balance, EraIndex, SlashingSpans, ValidatorPrefs } from '@polkadot/types/interfaces';
+import { DeriveAccountInfo } from '@polkadot/api-derive/types';
+import { ValidatorInfo } from '../../types';
import BN from 'bn.js';
import React, { useCallback, useMemo } from 'react';
@@ -29,10 +30,11 @@ interface Props {
isMain?: boolean;
lastBlock?: string;
nominatedBy?: [string, EraIndex, number][];
- onlineCount?: false | number;
+ onlineCount?: false | BN;
onlineMessage?: boolean;
points?: string;
toggleFavorite: (accountId: string) => void;
+ validatorInfo?: ValidatorInfo;
withIdentity: boolean;
}
@@ -44,9 +46,7 @@ interface StakingState {
stakeOwn?: BN;
}
-const PERBILL_PERCENT = 10_000_000;
-
-function expandInfo ({ exposure, validatorPrefs }: DeriveStakingQuery): StakingState {
+function expandInfo ({ exposure, validatorPrefs }: ValidatorInfo): StakingState {
let nominators: [string, Balance][] = [];
let stakeTotal: BN | undefined;
let stakeOther: BN | undefined;
@@ -59,12 +59,10 @@ function expandInfo ({ exposure, validatorPrefs }: DeriveStakingQuery): StakingS
stakeOther = stakeTotal.sub(stakeOwn);
}
- const commission = validatorPrefs?.commission?.unwrap();
+ const commission = (validatorPrefs as ValidatorPrefs)?.commission?.unwrap();
return {
- commission: commission
- ? `${(commission.toNumber() / PERBILL_PERCENT).toFixed(2)}%`
- : undefined,
+ commission: commission?.toHuman(),
nominators,
stakeOther,
stakeOwn,
@@ -80,18 +78,17 @@ function useAddressCalls (api: ApiPromise, address: string, isMain?: boolean) {
const params = useMemo(() => [address], [address]);
const accountInfo = useCall(api.derive.accounts.info, params);
const slashingSpans = useCall(!isMain && api.query.staking.slashingSpans, params, transformSlashes);
- const stakingInfo = useCall(api.derive.staking.query, params);
- return { accountInfo, slashingSpans, stakingInfo };
+ return { accountInfo, slashingSpans };
}
-function Address ({ address, className = '', filterName, hasQueries, isElected, isFavorite, isMain, lastBlock, nominatedBy, onlineCount, onlineMessage, points, toggleFavorite, withIdentity }: Props): React.ReactElement | null {
+function Address ({ address, className = '', filterName, hasQueries, isElected, isFavorite, isMain, lastBlock, nominatedBy, onlineCount, onlineMessage, points, toggleFavorite, validatorInfo, withIdentity }: Props): React.ReactElement | null {
const { api } = useApi();
- const { accountInfo, slashingSpans, stakingInfo } = useAddressCalls(api, address, isMain);
+ const { accountInfo, slashingSpans } = useAddressCalls(api, address, isMain);
const { commission, nominators, stakeOther, stakeOwn } = useMemo(
- () => stakingInfo ? expandInfo(stakingInfo) : { nominators: [] },
- [stakingInfo]
+ () => validatorInfo ? expandInfo(validatorInfo) : { nominators: [] },
+ [validatorInfo]
);
const isVisible = useMemo(
@@ -121,7 +118,7 @@ function Address ({ address, className = '', filterName, hasQueries, isElected,
diff --git a/packages/page-staking/src/Overview/CurrentList.tsx b/packages/page-staking/src/Overview/CurrentList.tsx
index f7620af607..bd4a1b7c5a 100644
--- a/packages/page-staking/src/Overview/CurrentList.tsx
+++ b/packages/page-staking/src/Overview/CurrentList.tsx
@@ -5,6 +5,7 @@
import { DeriveHeartbeats, DeriveStakingOverview } from '@polkadot/api-derive/types';
import { AccountId, EraIndex, Nominations } from '@polkadot/types/interfaces';
import { Authors } from '@polkadot/react-query/BlockAuthors';
+import { SortedTargets, ValidatorInfo } from '../types';
import React, { useCallback, useContext, useMemo, useRef, useState } from 'react';
import { Table } from '@polkadot/react-components';
@@ -23,6 +24,7 @@ interface Props {
next?: string[];
setNominators?: (nominators: string[]) => void;
stakingOverview?: DeriveStakingOverview;
+ targets: SortedTargets;
toggleFavorite: (address: string) => void;
}
@@ -91,7 +93,7 @@ function extractNominators (nominations: [StorageKey, Option][]): R
}, {});
}
-function CurrentList ({ favorites, hasQueries, isIntentions, next, stakingOverview, toggleFavorite }: Props): React.ReactElement | null {
+function CurrentList ({ favorites, hasQueries, isIntentions, next, stakingOverview, targets, toggleFavorite }: Props): React.ReactElement | null {
const { t } = useTranslation();
const { api } = useApi();
const { byAuthor, eraPoints } = useContext(isIntentions ? EmptyAuthorsContext : BlockAuthorsContext);
@@ -108,6 +110,15 @@ function CurrentList ({ favorites, hasQueries, isIntentions, next, stakingOvervi
[favorites, next, stakingOverview]
);
+ const infoMap = useMemo(
+ () => (targets?.validators || []).reduce((result: Record, info): Record => {
+ result[info.accountId.toString()] = info;
+
+ return result;
+ }, {}),
+ [targets]
+ );
+
const nominatedBy = useMemo(
() => nominators ? extractNominators(nominators) : null,
[nominators]
@@ -145,14 +156,15 @@ function CurrentList ({ favorites, hasQueries, isIntentions, next, stakingOvervi
key={address}
lastBlock={byAuthor[address]}
nominatedBy={nominatedBy ? (nominatedBy[address] || []) : undefined}
- onlineCount={recentlyOnline?.[address]?.blockCount.toNumber()}
+ onlineCount={recentlyOnline?.[address]?.blockCount}
onlineMessage={recentlyOnline?.[address]?.hasMessage}
points={eraPoints[address]}
toggleFavorite={toggleFavorite}
+ validatorInfo={infoMap[address]}
withIdentity={withIdentity}
/>
)),
- [byAuthor, eraPoints, hasQueries, nameFilter, nominatedBy, recentlyOnline, toggleFavorite, withIdentity]
+ [byAuthor, eraPoints, hasQueries, infoMap, nameFilter, nominatedBy, recentlyOnline, toggleFavorite, withIdentity]
);
return isIntentions
diff --git a/packages/page-staking/src/Overview/index.tsx b/packages/page-staking/src/Overview/index.tsx
index 624b925558..28e7161ee9 100644
--- a/packages/page-staking/src/Overview/index.tsx
+++ b/packages/page-staking/src/Overview/index.tsx
@@ -3,6 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { DeriveStakingOverview } from '@polkadot/api-derive/types';
+import { SortedTargets } from '../types';
import React from 'react';
@@ -15,10 +16,11 @@ interface Props {
isIntentions?: boolean;
next?: string[];
stakingOverview?: DeriveStakingOverview;
+ targets: SortedTargets;
toggleFavorite: (address: string) => void;
}
-function Overview ({ className = '', favorites, hasQueries, isIntentions, next, stakingOverview, toggleFavorite }: Props): React.ReactElement {
+function Overview ({ className = '', favorites, hasQueries, isIntentions, next, stakingOverview, targets, toggleFavorite }: Props): React.ReactElement {
return (
diff --git a/packages/page-staking/src/index.tsx b/packages/page-staking/src/index.tsx
index 3e112cf52f..428d6c2e98 100644
--- a/packages/page-staking/src/index.tsx
+++ b/packages/page-staking/src/index.tsx
@@ -155,6 +155,7 @@ function StakingApp ({ basePath, className = '' }: Props): React.ReactElement
@@ -171,6 +172,7 @@ function StakingApp ({ basePath, className = '' }: Props): React.ReactElement
diff --git a/packages/page-staking/src/types.ts b/packages/page-staking/src/types.ts
index 71e9631671..9faa26b277 100644
--- a/packages/page-staking/src/types.ts
+++ b/packages/page-staking/src/types.ts
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
-import { AccountId, Balance, BlockNumber, Hash, SessionIndex } from '@polkadot/types/interfaces';
+import { AccountId, Balance, BlockNumber, Exposure, Hash, SessionIndex, ValidatorPrefs, ValidatorPrefsTo196 } from '@polkadot/types/interfaces';
import BN from 'bn.js';
@@ -46,6 +46,7 @@ export interface ValidatorInfo extends ValidatorInfoRank {
bondShare: number;
bondTotal: Balance;
commissionPer: number;
+ exposure: Exposure;
hasIdentity: boolean;
isActive: boolean;
isCommission: boolean;
@@ -57,6 +58,7 @@ export interface ValidatorInfo extends ValidatorInfoRank {
rewardPayout: BN;
rewardSplit: BN;
validatorPayment: BN;
+ validatorPrefs?: ValidatorPrefs | ValidatorPrefsTo196;
}
export type TargetSortBy = keyof ValidatorInfoRank;
diff --git a/packages/page-staking/src/useSortedTargets.ts b/packages/page-staking/src/useSortedTargets.ts
index 2cab234521..7037e00fc0 100644
--- a/packages/page-staking/src/useSortedTargets.ts
+++ b/packages/page-staking/src/useSortedTargets.ts
@@ -65,14 +65,8 @@ function sortValidators (list: ValidatorInfo[]): ValidatorInfo[] {
}
function extractSingle (allAccounts: string[], amount: BN = baseBalance(), { info }: DeriveStakingElected | DeriveStakingWaiting, favorites: string[], perValidatorReward: BN, isElected: boolean): [ValidatorInfo[], string[]] {
- const defaultExposure = {
- others: registry.createType('Vec'),
- own: registry.createType('Compact'),
- total: registry.createType('Compact')
- };
- const defaultPrefs = {
- commission: registry.createType('Compact')
- };
+ const defaultExposure = registry.createType('Exposure');
+ const defaultPrefs = registry.createType('ValidatorPrefs');
const nominators: Record = {};
const list = info.map(({ accountId, exposure: _exposure, stakingLedger, validatorPrefs }): ValidatorInfo => {
const exposure = _exposure || defaultExposure;
@@ -108,6 +102,7 @@ function extractSingle (allAccounts: string[], amount: BN = baseBalance(), { inf
bondShare: 0,
bondTotal,
commissionPer: (((prefs as ValidatorPrefs).commission?.unwrap() || BN_ZERO).toNumber() / 10_000_000),
+ exposure,
hasIdentity: false,
isActive: !skipRewards,
isCommission: !!(prefs as ValidatorPrefs).commission,
@@ -126,7 +121,8 @@ function extractSingle (allAccounts: string[], amount: BN = baseBalance(), { inf
rankReward: 0,
rewardPayout: skipRewards ? BN_ZERO : rewardPayout,
rewardSplit,
- validatorPayment
+ validatorPayment,
+ validatorPrefs: prefs
};
});
@@ -146,14 +142,6 @@ function extractInfo (allAccounts: string[], amount: BN = baseBalance(), elected
const totalStaked = activeTotals.reduce((total: BN, value) => total.iadd(value), new BN(0));
const avgStaked = totalStaked.divn(activeTotals.length);
- // median
- // const midIndex = Math.floor(activeTotals.length / 2);
- // const avgStaked = activeTotals.length
- // ? activeTotals.length % 2
- // ? activeTotals[midIndex]
- // : activeTotals[midIndex - 1].add(activeTotals[midIndex]).divn(2)
- // : BN_ZERO;
-
return { avgStaked, lowStaked: activeTotals[0] || BN_ZERO, nominators, totalStaked, validatorIds, validators };
}