diff --git a/packages/api-derive/src/staking/erasExposure.ts b/packages/api-derive/src/staking/erasExposure.ts index e066699f001a..bbc2768a53ba 100644 --- a/packages/api-derive/src/staking/erasExposure.ts +++ b/packages/api-derive/src/staking/erasExposure.ts @@ -2,10 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 import type { Observable } from 'rxjs'; -import type { StorageKey } from '@polkadot/types'; -import type { AccountId, EraIndex } from '@polkadot/types/interfaces'; -import type { PalletStakingExposure } from '@polkadot/types/lookup'; -import type { DeriveApi, DeriveEraExposure, DeriveEraNominatorExposure, DeriveEraValidatorExposure } from '../types.js'; +import type { Option, StorageKey, u32 } from '@polkadot/types'; +import type { AccountId, AccountId32, EraIndex } from '@polkadot/types/interfaces'; +import type { PalletStakingExposure, SpStakingExposurePage } from '@polkadot/types/lookup'; +import type { DeriveApi, DeriveEraExposurePaged, DeriveEraNominatorExposure, DeriveEraValidatorExposure, DeriveEraValidatorExposurePaged } from '../types.js'; import { map, of } from 'rxjs'; @@ -14,10 +14,11 @@ import { getEraCache, setEraCache } from './cache.js'; import { combineEras, erasHistoricApply, singleEra } from './util.js'; type KeysAndExposures = [StorageKey<[EraIndex, AccountId]>, PalletStakingExposure][]; +type KeysAndExposuresPaged = [StorageKey<[u32, AccountId32, u32]>, Option][]; const CACHE_KEY = 'eraExposure'; -function mapStakers (era: EraIndex, stakers: KeysAndExposures): DeriveEraExposure { +function mapStakersClipped (era: EraIndex, stakers: KeysAndExposures): DeriveEraExposurePaged { const nominators: DeriveEraNominatorExposure = {}; const validators: DeriveEraValidatorExposure = {}; @@ -37,15 +38,46 @@ function mapStakers (era: EraIndex, stakers: KeysAndExposures): DeriveEraExposur return { era, nominators, validators }; } -export function _eraExposure (instanceId: string, api: DeriveApi): (era: EraIndex, withActive?: boolean) => Observable { - return memo(instanceId, (era: EraIndex, withActive = false): Observable => { - const [cacheKey, cached] = getEraCache(CACHE_KEY, era, withActive); +function mapStakersPaged (era: EraIndex, stakers: KeysAndExposuresPaged): DeriveEraExposurePaged { + const nominators: DeriveEraNominatorExposure = {}; + const validators: DeriveEraValidatorExposurePaged = {}; + + stakers.forEach(([key, exposureOpt]): void => { + if (exposureOpt.isSome) { + const validatorId = key.args[1].toString(); + const exposure = exposureOpt.unwrap(); + + validators[validatorId] = exposure; + + exposure.others.forEach(({ who }, validatorIndex): void => { + const nominatorId = who.toString(); + + nominators[nominatorId] = nominators[nominatorId] || []; + nominators[nominatorId].push({ validatorId, validatorIndex }); + }); + } + }); + + return { era, nominators, validators }; +} + +/** + * erasStakersClipped will be deprecated and replaced with erasStakersPaged. Therefore support is given for both + * storage queries until erasStakersClipped has been completely out of use. + */ +export function _eraExposure (instanceId: string, api: DeriveApi): (era: EraIndex, withActive?: boolean) => Observable { + return memo(instanceId, (era: EraIndex, withActive = false): Observable => { + const [cacheKey, cached] = getEraCache(CACHE_KEY, era, withActive); return cached ? of(cached) - : api.query.staking.erasStakersClipped.entries(era).pipe( - map((r) => setEraCache(cacheKey, withActive, mapStakers(era, r))) - ); + : api.query.staking.erasStakersPaged + ? api.query.staking.erasStakersPaged.entries>(era).pipe( + map((r) => setEraCache(cacheKey, withActive, mapStakersPaged(era, r))) + ) + : api.query.staking.erasStakersClipped.entries(era).pipe( + map((r) => setEraCache(cacheKey, withActive, mapStakersClipped(era, r))) + ); }); } diff --git a/packages/api-derive/src/staking/stakerExposure.ts b/packages/api-derive/src/staking/stakerExposure.ts index 2cf0c932b26b..df3eb06d733b 100644 --- a/packages/api-derive/src/staking/stakerExposure.ts +++ b/packages/api-derive/src/staking/stakerExposure.ts @@ -4,7 +4,7 @@ import type { Observable } from 'rxjs'; import type { EraIndex } from '@polkadot/types/interfaces'; import type { DeriveApi } from '../types.js'; -import type { DeriveEraValidatorExposure, DeriveStakerExposure } from './types.js'; +import type { DeriveEraValidatorExposurePaged, DeriveStakerExposure } from './types.js'; import { map, switchMap } from 'rxjs'; @@ -19,7 +19,7 @@ export function _stakerExposures (instanceId: string, api: DeriveApi): (accountI stakerIds.map((stakerId) => exposures.map(({ era, nominators: allNominators, validators: allValidators }): DeriveStakerExposure => { const isValidator = !!allValidators[stakerId]; - const validators: DeriveEraValidatorExposure = {}; + const validators: DeriveEraValidatorExposurePaged = {}; const nominating = allNominators[stakerId] || []; if (isValidator) { diff --git a/packages/api-derive/src/staking/stakerRewards.ts b/packages/api-derive/src/staking/stakerRewards.ts index c439843a4eea..29ccdd1570fe 100644 --- a/packages/api-derive/src/staking/stakerRewards.ts +++ b/packages/api-derive/src/staking/stakerRewards.ts @@ -4,7 +4,7 @@ import type { Observable } from 'rxjs'; import type { u32, Vec } from '@polkadot/types'; import type { AccountId, EraIndex } from '@polkadot/types/interfaces'; -import type { PalletStakingStakingLedger } from '@polkadot/types/lookup'; +import type { PalletStakingExposure, PalletStakingStakingLedger, SpStakingExposurePage } from '@polkadot/types/lookup'; import type { BN } from '@polkadot/util'; import type { DeriveApi, DeriveEraPoints, DeriveEraPrefs, DeriveEraRewards, DeriveEraValPoints, DeriveEraValPrefs, DeriveStakerExposure, DeriveStakerReward, DeriveStakerRewardValidator } from '../types.js'; import type { DeriveStakingQuery } from './types.js'; @@ -38,7 +38,11 @@ function parseRewards (api: DeriveApi, stashId: AccountId, [erasPoints, erasPref Object.entries(eraValidators).forEach(([validatorId, exposure]): void => { const valPoints = allValPoints[validatorId] || BN_ZERO; const valComm = allValPrefs[validatorId]?.commission.unwrap() || BN_ZERO; - const expTotal = exposure.total?.unwrap() || BN_ZERO; + const expTotal = (exposure as PalletStakingExposure).total + ? (exposure as PalletStakingExposure).total?.unwrap() + : (exposure as SpStakingExposurePage).pageTotal + ? (exposure as SpStakingExposurePage).pageTotal?.unwrap() + : BN_ZERO; let avail = BN_ZERO; let value: BN | undefined; @@ -49,7 +53,13 @@ function parseRewards (api: DeriveApi, stashId: AccountId, [erasPoints, erasPref let staked: BN; if (validatorId === stakerId) { - staked = exposure.own.unwrap(); + if ((exposure as PalletStakingExposure).own) { + staked = (exposure as PalletStakingExposure).own.unwrap(); + } else { + const expAccount = exposure.others.find(({ who }) => who.toString() === validatorId); + + staked = expAccount ? expAccount.value.unwrap() : BN_ZERO; + } } else { const stakerExp = exposure.others.find(({ who }) => who.eq(stakerId)); diff --git a/packages/api-derive/src/staking/types.ts b/packages/api-derive/src/staking/types.ts index f486e4249505..b84cd9fecfcb 100644 --- a/packages/api-derive/src/staking/types.ts +++ b/packages/api-derive/src/staking/types.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import type { AccountId, Balance, EraIndex, RewardPoint } from '@polkadot/types/interfaces'; -import type { PalletStakingExposure, PalletStakingRewardDestination, PalletStakingStakingLedger, PalletStakingValidatorPrefs } from '@polkadot/types/lookup'; +import type { PalletStakingExposure, PalletStakingRewardDestination, PalletStakingStakingLedger, PalletStakingValidatorPrefs, SpStakingExposurePage } from '@polkadot/types/lookup'; import type { BN } from '@polkadot/util'; import type { DeriveSessionIndexes } from '../session/types.js'; @@ -55,18 +55,26 @@ export type DeriveEraNominatorExposure = Record; +export type DeriveEraValidatorExposurePaged = Record; + export interface DeriveEraExposure { era: EraIndex; nominators: DeriveEraNominatorExposure; validators: DeriveEraValidatorExposure; } +export interface DeriveEraExposurePaged { + era: EraIndex; + nominators: DeriveEraNominatorExposure; + validators: DeriveEraValidatorExposurePaged; +} + export interface DeriveStakerExposure { era: EraIndex; isEmpty: boolean; isValidator: boolean; nominating: DeriveEraExposureNominating[]; - validators: DeriveEraValidatorExposure; + validators: DeriveEraValidatorExposurePaged; } export interface DeriveStakerPrefs {