Optimize use of derive staking.query (with full results) (#2897)

This commit is contained in:
Jaco Greeff
2020-12-02 14:49:14 +01:00
committed by GitHub
parent eccc6cc2c9
commit 895d44fe9f
10 changed files with 99 additions and 62 deletions
+1 -1
View File
@@ -63,7 +63,7 @@ export function accounts (instanceId: string, api: ApiInterfaceRx): (accountIds:
switchMap((sessionInfo) =>
combineLatest([
api.derive.staking.keysMulti(accountIds),
api.derive.staking.queryMulti(accountIds)
api.derive.staking.queryMulti(accountIds, true)
]).pipe(
map(([keys, queries]) => queries.map((query, index) => parseResult(api, sessionInfo, keys[index], query)))
)
@@ -18,7 +18,7 @@ export function electedInfo (instanceId: string, api: ApiInterfaceRx): () => Obs
return memo(instanceId, (): Observable<DeriveStakingElected> =>
api.derive.staking.validators().pipe(
switchMap(({ nextElected, validators }): Observable<DeriveStakingElected> =>
api.derive.staking.queryMulti(combineAccounts(nextElected, validators)).pipe(
api.derive.staking.queryMulti(combineAccounts(nextElected, validators), false).pipe(
map((info): DeriveStakingElected => ({
info,
nextElected,
+42 -26
View File
@@ -14,14 +14,16 @@ import { isFunction } from '@polkadot/util';
import { memo } from '../util';
type MultiResult = [Option<AccountId>, Option<ITuple<[Nominations]> | Nominations>, RewardDestination, ITuple<[ValidatorPrefs]> | ValidatorPrefs, Exposure];
type MultiResultPrev = [Option<AccountId>, Option<ITuple<[Nominations]>>, RewardDestination, ITuple<[ValidatorPrefs]> | ValidatorPrefs, Exposure];
function parseController (stashId: AccountId, [controllerIdOpt, nominatorsOpt, rewardDestination, validatorPrefs, exposure]: MultiResult, stakingLedgerOpt: Option<StakingLedger>): DeriveStakingQuery {
const nominators = nominatorsOpt.unwrapOr(null);
type MultiResultCombo = [Option<AccountId>, Option<ITuple<[Nominations]> | Nominations>, RewardDestination, ITuple<[ValidatorPrefs]> | ValidatorPrefs, Exposure];
function parseDetails (stashId: AccountId, [controllerIdOpt, nominatorsOpt, rewardDestination, validatorPrefs, exposure]: MultiResultCombo, stakingLedgerOpt: Option<StakingLedger>): DeriveStakingQuery {
const nominators = nominatorsOpt && nominatorsOpt.unwrapOr(null);
return {
accountId: stashId,
controllerId: controllerIdOpt.unwrapOr(null),
controllerId: controllerIdOpt && controllerIdOpt.unwrapOr(null),
exposure,
nominators: nominators
? Array.isArray(nominators)
@@ -37,8 +39,8 @@ function parseController (stashId: AccountId, [controllerIdOpt, nominatorsOpt, r
};
}
function retrievePrev (api: ApiInterfaceRx, stashId: AccountId): Observable<MultiResult> {
return api.queryMulti<MultiResult>([
function retrievePrev (api: ApiInterfaceRx, stashId: AccountId): Observable<MultiResultPrev> {
return api.queryMulti<MultiResultPrev>([
[api.query.staking.bonded, stashId],
[api.query.staking.nominators, stashId],
[api.query.staking.payee, stashId],
@@ -47,18 +49,26 @@ function retrievePrev (api: ApiInterfaceRx, stashId: AccountId): Observable<Mult
]);
}
function retrieveCurr (api: ApiInterfaceRx, stashIds: AccountId[], activeEra: EraIndex): Observable<MultiResult[]> {
function retrieveCurr (api: ApiInterfaceRx, stashIds: AccountId[], activeEra: EraIndex, withFull: boolean): Observable<MultiResultCombo[]> {
const emptyCont = api.registry.createType('Option<AccountId>');
const emptyNoms = api.registry.createType('Option<Nominations>');
const emptyRewa = api.registry.createType('RewardDestination');
return combineLatest([
api.query.staking.bonded.multi<Option<AccountId>>(stashIds),
api.query.staking.nominators
withFull
? api.query.staking.bonded.multi<Option<AccountId>>(stashIds)
: of(stashIds.map(() => emptyCont)),
withFull && api.query.staking.nominators
? api.query.staking.nominators.multi<Option<Nominations>>(stashIds)
: of(stashIds.map(() => api.registry.createType('Option<Nominations>'))),
api.query.staking.payee.multi<RewardDestination>(stashIds),
: of(stashIds.map(() => emptyNoms)),
withFull
? api.query.staking.payee.multi<RewardDestination>(stashIds)
: of(stashIds.map(() => emptyRewa)),
api.query.staking.validators.multi<ValidatorPrefs>(stashIds),
api.query.staking.erasStakers.multi<Exposure>(stashIds.map((stashId) => [activeEra, stashId]))
]).pipe(
map(([controllerIdOpt, nominatorsOpt, rewardDestination, validatorPrefs, exposure]): MultiResult[] =>
controllerIdOpt.map((controllerIdOpt, index): MultiResult =>
map(([controllerIdOpt, nominatorsOpt, rewardDestination, validatorPrefs, exposure]): MultiResultCombo[] =>
controllerIdOpt.map((controllerIdOpt, index): MultiResultCombo =>
[controllerIdOpt, nominatorsOpt[index], rewardDestination[index], validatorPrefs[index], exposure[index]]
)
)
@@ -67,9 +77,10 @@ function retrieveCurr (api: ApiInterfaceRx, stashIds: AccountId[], activeEra: Er
function retrieveControllers (api: ApiInterfaceRx, optControllerIds: Option<AccountId>[]): Observable<Option<StakingLedger>[]> {
const ids = optControllerIds.filter((opt) => opt.isSome).map((opt) => opt.unwrap());
const emptyLed = api.registry.createType('Option<StakingLedger>');
if (!ids.length) {
return of(optControllerIds.map(() => api.registry.createType('Option<StakingLedger>')));
return of(optControllerIds.map(() => emptyLed));
}
return api.query.staking.ledger.multi<Option<StakingLedger>>(ids).pipe(
@@ -79,7 +90,7 @@ function retrieveControllers (api: ApiInterfaceRx, optControllerIds: Option<Acco
return optControllerIds.map((opt): Option<StakingLedger> =>
opt.isSome
? optLedgers[++offset]
: api.registry.createType('Option<StakingLedger>')
: emptyLed
);
})
);
@@ -88,33 +99,38 @@ function retrieveControllers (api: ApiInterfaceRx, optControllerIds: Option<Acco
/**
* @description From a stash, retrieve the controllerId and all relevant details
*/
export function query (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DeriveStakingQuery> {
return memo(instanceId, (accountId: Uint8Array | string): Observable<DeriveStakingQuery> =>
api.derive.staking.queryMulti([accountId]).pipe(
export function query (instanceId: string, api: ApiInterfaceRx): (accountId: Uint8Array | string, withFull?: boolean) => Observable<DeriveStakingQuery> {
return memo(instanceId, (accountId: Uint8Array | string, withFull?: boolean): Observable<DeriveStakingQuery> =>
api.derive.staking.queryMulti([accountId], withFull).pipe(
map(([first]) => first)
)
);
}
export function queryMulti (instanceId: string, api: ApiInterfaceRx): (accountIds: (Uint8Array | string)[]) => Observable<DeriveStakingQuery[]> {
return memo(instanceId, (accountIds: (Uint8Array | string)[]): Observable<DeriveStakingQuery[]> =>
export function queryMulti (instanceId: string, api: ApiInterfaceRx): (accountIds: (Uint8Array | string)[], withFull?: boolean) => Observable<DeriveStakingQuery[]> {
return memo(instanceId, (accountIds: (Uint8Array | string)[], withFull = true): Observable<DeriveStakingQuery[]> =>
accountIds.length
? api.derive.session.indexes().pipe(
switchMap(({ activeEra }): Observable<DeriveStakingQuery[]> => {
const stashIds = accountIds.map((accountId) => api.registry.createType('AccountId', accountId));
const emptyLed = api.registry.createType('Option<StakingLedger>');
return (
isFunction(api.query.staking.erasStakers)
? retrieveCurr(api, stashIds, activeEra)
? retrieveCurr(api, stashIds, activeEra, withFull)
: combineLatest(stashIds.map((stashId) => retrievePrev(api, stashId)))
).pipe(
switchMap((results): Observable<DeriveStakingQuery[]> =>
retrieveControllers(api, results.map(([optController]) => optController)).pipe(
map((stakingLedgerOpts) =>
stashIds.map((stashId, index) => parseController(stashId, results[index], stakingLedgerOpts[index]))
withFull
? switchMap((results): Observable<DeriveStakingQuery[]> =>
retrieveControllers(api, results.map(([optController]) => optController)).pipe(
map((stakingLedgerOpts) =>
stashIds.map((stashId, index) => parseDetails(stashId, results[index], stakingLedgerOpts[index]))
)
)
)
)
: map((results): DeriveStakingQuery[] =>
stashIds.map((stashId, index) => parseDetails(stashId, results[index], emptyLed))
)
);
})
)
@@ -127,7 +127,7 @@ function filterRewards (api: ApiInterfaceRx, eras: EraIndex[], { migrateEra, rew
return (
isFunction(api.tx.staking.payoutStakers)
? api.derive.staking.queryMulti(validators)
? api.derive.staking.queryMulti(validators, false)
: of([])
).pipe(
map((queryValidators): DeriveStakerReward[] =>
@@ -150,7 +150,7 @@ function filterRewards (api: ApiInterfaceRx, eras: EraIndex[], { migrateEra, rew
.filter(({ validators }) => Object.keys(validators).length !== 0)
.map((reward) => ({
...reward,
nominators: reward.nominating.filter((n) => !!reward.validators[n.validatorId])
nominators: reward.nominating.filter((n) => reward.validators[n.validatorId])
}))
)
);
@@ -27,7 +27,8 @@ export function validatorsFrom (instanceId: string, api: ApiInterfaceRx): (stash
return validatorIds;
}, validatorIds);
}, [])
}, []),
false
)
)
)
@@ -20,7 +20,7 @@ export function waitingInfo (instanceId: string, api: ApiInterfaceRx): () => Obs
const elected = nextElected.map((a) => a.toString());
const waiting = stashes.filter((v) => !elected.includes(v.toString()));
return api.derive.staking.queryMulti(waiting).pipe(
return api.derive.staking.queryMulti(waiting, false).pipe(
map((info): DeriveStakingWaiting => ({
info,
waiting