ApiDerive.staking backwards compatibility. (#5868)
* Start of backwards compatibility for api.derive.staking * Update nextElected to be compatible * lint * Comments * remove clipped from query * Ensure backwards compat for ownExposure * Fix query
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
import type { Observable } from 'rxjs';
|
||||
import type { Option, u32 } from '@polkadot/types';
|
||||
import type { EraIndex } from '@polkadot/types/interfaces';
|
||||
import type { SpStakingExposurePage } from '@polkadot/types/lookup';
|
||||
import type { SpStakingExposure, SpStakingExposurePage, SpStakingPagedExposureMetadata } from '@polkadot/types/lookup';
|
||||
import type { AnyNumber } from '@polkadot/types-codec/types';
|
||||
import type { DeriveApi, DeriveOwnExposure } from '../types.js';
|
||||
|
||||
@@ -15,13 +15,27 @@ import { erasHistoricApplyAccount } from './util.js';
|
||||
|
||||
export function _ownExposures (instanceId: string, api: DeriveApi): (accountId: Uint8Array | string, eras: EraIndex[], withActive: boolean, page: u32 | AnyNumber) => Observable<DeriveOwnExposure[]> {
|
||||
return memo(instanceId, (accountId: Uint8Array | string, eras: EraIndex[], _withActive: boolean, page: u32 | AnyNumber): Observable<DeriveOwnExposure[]> => {
|
||||
const emptyStakingExposure = api.registry.createType<SpStakingExposure>('Exposure');
|
||||
// The reason we don't explicitly make the actual types is for compatibility. If the chain doesn't have the noted type it will fail
|
||||
// on construction. Therefore we just make an empty option.
|
||||
const emptyOptionPage = api.registry.createType<Option<SpStakingExposurePage>>('Option<Null>');
|
||||
const emptyOptionMeta = api.registry.createType<Option<SpStakingPagedExposureMetadata>>('Option<Null>');
|
||||
|
||||
return eras.length
|
||||
? combineLatest([
|
||||
// Backwards and forward compat for historical integrity when using `erasHistoricApplyAccount`
|
||||
combineLatest(eras.map((e) => api.query.staking.erasStakersClipped(e, accountId))),
|
||||
combineLatest(eras.map((e) => api.query.staking.erasStakers(e, accountId))),
|
||||
combineLatest(eras.map((e) => api.query.staking.erasStakersPaged<Option<SpStakingExposurePage>>(e, accountId, page))),
|
||||
combineLatest(eras.map((e) => api.query.staking.erasStakersOverview(e, accountId)))
|
||||
api.query.staking.erasStakersClipped
|
||||
? combineLatest(eras.map((e) => api.query.staking.erasStakersClipped(e, accountId)))
|
||||
: of(eras.map((_) => emptyStakingExposure)),
|
||||
api.query.staking.erasStakers
|
||||
? combineLatest(eras.map((e) => api.query.staking.erasStakers(e, accountId)))
|
||||
: of(eras.map((_) => emptyStakingExposure)),
|
||||
api.query.staking.erasStakersPaged
|
||||
? combineLatest(eras.map((e) => api.query.staking.erasStakersPaged<Option<SpStakingExposurePage>>(e, accountId, page)))
|
||||
: of(eras.map((_) => emptyOptionPage)),
|
||||
api.query.staking.erasStakersOverview
|
||||
? combineLatest(eras.map((e) => api.query.staking.erasStakersOverview(e, accountId)))
|
||||
: of(eras.map((_) => emptyOptionMeta))
|
||||
]).pipe(
|
||||
map(([clp, exp, paged, expMeta]): DeriveOwnExposure[] =>
|
||||
eras.map((era, index) => ({ clipped: clp[index], era, exposure: exp[index], exposureMeta: expMeta[index], exposurePaged: paged[index] }))
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import type { Observable } from 'rxjs';
|
||||
import type { Option, u32, Vec } from '@polkadot/types';
|
||||
import type { AccountId, EraIndex } from '@polkadot/types/interfaces';
|
||||
import type { PalletStakingNominations, PalletStakingRewardDestination, PalletStakingStakingLedger, PalletStakingValidatorPrefs, SpStakingExposurePage, SpStakingPagedExposureMetadata } from '@polkadot/types/lookup';
|
||||
import type { PalletStakingNominations, PalletStakingRewardDestination, PalletStakingStakingLedger, PalletStakingValidatorPrefs, SpStakingExposure, SpStakingExposurePage, SpStakingPagedExposureMetadata } from '@polkadot/types/lookup';
|
||||
import type { AnyNumber } from '@polkadot/types-codec/types';
|
||||
import type { DeriveApi, DeriveStakingQuery, StakingQueryFlags } from '../types.js';
|
||||
|
||||
@@ -24,11 +24,12 @@ function filterClaimedRewards (api: DeriveApi, cl: number[]): Vec<u32> {
|
||||
return api.registry.createType('Vec<u32>', cl.filter((c) => c !== -1));
|
||||
}
|
||||
|
||||
function parseDetails (api: DeriveApi, stashId: AccountId, controllerIdOpt: Option<AccountId> | null, nominatorsOpt: Option<PalletStakingNominations>, rewardDestinationOpts: Option<PalletStakingRewardDestination> | PalletStakingRewardDestination, validatorPrefs: PalletStakingValidatorPrefs, exposure: Option<SpStakingExposurePage>, stakingLedgerOpt: Option<PalletStakingStakingLedger>, exposureMeta: Option<SpStakingPagedExposureMetadata>, claimedRewards: number[]): DeriveStakingQuery {
|
||||
function parseDetails (api: DeriveApi, stashId: AccountId, controllerIdOpt: Option<AccountId> | null, nominatorsOpt: Option<PalletStakingNominations>, rewardDestinationOpts: Option<PalletStakingRewardDestination> | PalletStakingRewardDestination, validatorPrefs: PalletStakingValidatorPrefs, exposure: Option<SpStakingExposurePage>, stakingLedgerOpt: Option<PalletStakingStakingLedger>, exposureMeta: Option<SpStakingPagedExposureMetadata>, claimedRewards: number[], exposureEraStakers: SpStakingExposure): DeriveStakingQuery {
|
||||
return {
|
||||
accountId: stashId,
|
||||
claimedRewardsEras: filterClaimedRewards(api, claimedRewards),
|
||||
controllerId: controllerIdOpt?.unwrapOr(null) || null,
|
||||
exposureEraStakers,
|
||||
exposureMeta,
|
||||
exposurePaged: exposure,
|
||||
nominators: nominatorsOpt.isSome
|
||||
@@ -64,12 +65,15 @@ function getLedgers (api: DeriveApi, optIds: (Option<AccountId> | null)[], { wit
|
||||
);
|
||||
}
|
||||
|
||||
function getStashInfo (api: DeriveApi, stashIds: AccountId[], activeEra: EraIndex, { withClaimedRewardsEras, withController, withDestination, withExposure, withExposureMeta, withLedger, withNominations, withPrefs }: StakingQueryFlags, page: u32 | AnyNumber): Observable<[(Option<AccountId> | null)[], Option<PalletStakingNominations>[], Option<PalletStakingRewardDestination>[], PalletStakingValidatorPrefs[], Option<SpStakingExposurePage>[], Option<SpStakingPagedExposureMetadata>[], number[][]]> {
|
||||
function getStashInfo (api: DeriveApi, stashIds: AccountId[], activeEra: EraIndex, { withClaimedRewardsEras, withController, withDestination, withExposure, withExposureErasStakersLegacy, withExposureMeta, withLedger, withNominations, withPrefs }: StakingQueryFlags, page: u32 | AnyNumber): Observable<[(Option<AccountId> | null)[], Option<PalletStakingNominations>[], Option<PalletStakingRewardDestination>[], PalletStakingValidatorPrefs[], Option<SpStakingExposurePage>[], Option<SpStakingPagedExposureMetadata>[], number[][], SpStakingExposure[]]> {
|
||||
const emptyNoms = api.registry.createType<Option<PalletStakingNominations>>('Option<Nominations>');
|
||||
const emptyRewa = api.registry.createType<Option<PalletStakingRewardDestination>>('RewardDestination');
|
||||
const emptyExpo = api.registry.createType<Option<SpStakingExposurePage>>('Option<SpStakingExposurePage>');
|
||||
const emptyExpoEraStakers = api.registry.createType<SpStakingExposure>('Exposure');
|
||||
const emptyPrefs = api.registry.createType<PalletStakingValidatorPrefs>('ValidatorPrefs');
|
||||
const emptyExpoMeta = api.registry.createType<Option<SpStakingPagedExposureMetadata>>('Option<SpStakingPagedExposureMetadata>');
|
||||
// The reason we don't explicitly make the actual types is for compatibility. If the chain doesn't have the noted type it will fail
|
||||
// on construction. Therefore we just make an empty option.
|
||||
const emptyExpo = api.registry.createType<Option<SpStakingExposurePage>>('Option<Null>');
|
||||
const emptyExpoMeta = api.registry.createType<Option<SpStakingPagedExposureMetadata>>('Option<Null>');
|
||||
const emptyClaimedRewards = [-1];
|
||||
|
||||
const depth = Number(api.consts.staking.historyDepth.toNumber());
|
||||
@@ -94,13 +98,13 @@ function getStashInfo (api: DeriveApi, stashIds: AccountId[], activeEra: EraInde
|
||||
withPrefs
|
||||
? combineLatest(stashIds.map((s) => api.query.staking.validators(s)))
|
||||
: of(stashIds.map(() => emptyPrefs)),
|
||||
withExposure
|
||||
withExposure && api.query.staking.erasStakersPaged
|
||||
? combineLatest(stashIds.map((s) => api.query.staking.erasStakersPaged<Option<SpStakingExposurePage>>(activeEra, s, page)))
|
||||
: of(stashIds.map(() => emptyExpo)),
|
||||
withExposureMeta
|
||||
withExposureMeta && api.query.staking.erasStakersOverview
|
||||
? combineLatest(stashIds.map((s) => api.query.staking.erasStakersOverview(activeEra, s)))
|
||||
: of(stashIds.map(() => emptyExpoMeta)),
|
||||
withClaimedRewardsEras
|
||||
withClaimedRewardsEras && api.query.staking.claimedRewards
|
||||
? combineLatest(stashIds.map((s) =>
|
||||
combineLatest([
|
||||
combineLatest(eras.map((e) => api.query.staking.claimedRewards(e, s))),
|
||||
@@ -122,17 +126,20 @@ function getStashInfo (api: DeriveApi, stashIds: AccountId[], activeEra: EraInde
|
||||
});
|
||||
})
|
||||
)
|
||||
: of(stashIds.map(() => emptyClaimedRewards))
|
||||
: of(stashIds.map(() => emptyClaimedRewards)),
|
||||
withExposureErasStakersLegacy && api.query.staking.erasStakers
|
||||
? combineLatest(stashIds.map((s) => api.query.staking.erasStakers(activeEra, s)))
|
||||
: of(stashIds.map(() => emptyExpoEraStakers))
|
||||
]);
|
||||
}
|
||||
|
||||
function getBatch (api: DeriveApi, activeEra: EraIndex, stashIds: AccountId[], flags: StakingQueryFlags, page: u32 | AnyNumber): Observable<DeriveStakingQuery[]> {
|
||||
return getStashInfo(api, stashIds, activeEra, flags, page).pipe(
|
||||
switchMap(([controllerIdOpt, nominatorsOpt, rewardDestination, validatorPrefs, exposure, exposureMeta, claimedRewardsEras]): Observable<DeriveStakingQuery[]> =>
|
||||
switchMap(([controllerIdOpt, nominatorsOpt, rewardDestination, validatorPrefs, exposure, exposureMeta, claimedRewardsEras, exposureEraStakers]): Observable<DeriveStakingQuery[]> =>
|
||||
getLedgers(api, controllerIdOpt, flags).pipe(
|
||||
map((stakingLedgerOpts) =>
|
||||
stashIds.map((stashId, index) =>
|
||||
parseDetails(api, stashId, controllerIdOpt[index], nominatorsOpt[index], rewardDestination[index], validatorPrefs[index], exposure[index], stakingLedgerOpts[index], exposureMeta[index], claimedRewardsEras[index])
|
||||
parseDetails(api, stashId, controllerIdOpt[index], nominatorsOpt[index], rewardDestination[index], validatorPrefs[index], exposure[index], stakingLedgerOpts[index], exposureMeta[index], claimedRewardsEras[index], exposureEraStakers[index])
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -118,6 +118,8 @@ export interface DeriveStakingValidators {
|
||||
|
||||
export interface DeriveStakingStash {
|
||||
controllerId: AccountId | null;
|
||||
// Legacy Support for erasStakers
|
||||
exposureEraStakers: SpStakingExposure;
|
||||
exposurePaged: Option<SpStakingExposurePage>;
|
||||
exposureMeta: Option<SpStakingPagedExposureMetadata>;
|
||||
nominators: AccountId[];
|
||||
@@ -162,6 +164,7 @@ export interface StakingQueryFlags {
|
||||
withController?: boolean;
|
||||
withDestination?: boolean;
|
||||
withExposure?: boolean;
|
||||
withExposureErasStakersLegacy?: boolean,
|
||||
withLedger?: boolean;
|
||||
withNominations?: boolean;
|
||||
withPrefs?: boolean;
|
||||
|
||||
@@ -11,6 +11,7 @@ import { memo } from '../util/index.js';
|
||||
|
||||
export function nextElected (instanceId: string, api: DeriveApi): () => Observable<AccountId[]> {
|
||||
return memo(instanceId, (): Observable<AccountId[]> =>
|
||||
// Compatibility for future generation changes in staking.
|
||||
api.query.staking.erasStakersPaged
|
||||
? api.derive.session.indexes().pipe(
|
||||
// only populate for next era in the last session, so track both here - entries are not
|
||||
@@ -18,7 +19,14 @@ export function nextElected (instanceId: string, api: DeriveApi): () => Observab
|
||||
switchMap(({ currentEra }) => api.query.staking.erasStakersPaged.keys(currentEra)),
|
||||
map((keys) => keys.map(({ args: [, accountId] }) => accountId))
|
||||
)
|
||||
: api.query.staking['currentElected']<AccountId[]>()
|
||||
: api.query.staking.erasStakers
|
||||
? api.derive.session.indexes().pipe(
|
||||
// only populate for next era in the last session, so track both here - entries are not
|
||||
// subscriptions, so we need a trigger - currentIndex acts as that trigger to refresh
|
||||
switchMap(({ currentEra }) => api.query.staking.erasStakers.keys(currentEra)),
|
||||
map((keys) => keys.map(({ args: [, accountId] }) => accountId))
|
||||
)
|
||||
: api.query.staking['currentElected']<AccountId[]>()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user