Filter old rewards with stakingLedger (ledger can update) (#2155)

* Filter old rewards with stakingLedger (ledger can update)

* Cleanup internal functions
This commit is contained in:
Jaco Greeff
2020-04-10 18:06:14 +02:00
committed by GitHub
parent 3089529405
commit e5d9bbc264
17 changed files with 169 additions and 203 deletions
@@ -1,32 +0,0 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { ReferendumInfo, ReferendumInfoTo239 } from '@polkadot/types/interfaces';
import { DeriveReferendum } from '../types';
import BN from 'bn.js';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { Option } from '@polkadot/types';
import { memo } from '../util';
import { getStatus, parseImage } from './util';
export function _referendumInfo (api: ApiInterfaceRx): (index: BN, info: Option<ReferendumInfo | ReferendumInfoTo239>) => Observable<DeriveReferendum | null> {
return memo((index: BN, info: Option<ReferendumInfo | ReferendumInfoTo239>): Observable<DeriveReferendum | null> => {
const status = getStatus(info);
return status
? api.query.democracy.preimages(status.proposalHash).pipe(
map((preimage): DeriveReferendum => ({
image: parseImage(api, preimage),
imageHash: status.proposalHash,
index: api.registry.createType('ReferendumIndex', index),
status
}))
)
: of(null);
});
}
@@ -1,84 +0,0 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { AccountId, Vote, Voting, VotingDirectVote } from '@polkadot/types/interfaces';
import { DeriveBalancesAccount, DeriveReferendum, DeriveReferendumVote, DeriveReferendumVotes } from '../types';
import BN from 'bn.js';
import { Observable, of, combineLatest } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Vec } from '@polkadot/types';
import { memo } from '../util';
import { calcVotes } from './util';
function votesPrev (api: ApiInterfaceRx, referendumId: BN): Observable<DeriveReferendumVote[]> {
return api.query.democracy.votersFor<Vec<AccountId>>(referendumId).pipe(
switchMap((votersFor): Observable<[Vec<AccountId>, Vote[], DeriveBalancesAccount[]]> =>
combineLatest([
of(votersFor),
votersFor.length
? api.query.democracy.voteOf.multi<Vote>(
votersFor.map((accountId): [BN | number, AccountId] =>
[referendumId, accountId]
)
)
: of([]),
api.derive.balances.votingBalances(votersFor)
])
),
map(([votersFor, votes, balances]): DeriveReferendumVote[] =>
votersFor.map((accountId, index): DeriveReferendumVote => ({
accountId,
balance: balances[index].votingBalance || api.registry.createType('Balance'),
vote: votes[index] || api.registry.createType('Vote')
}))
)
);
}
function votesCurr (api: ApiInterfaceRx, referendumId: BN): Observable<DeriveReferendumVote[]> {
return api.query.democracy.votingOf.entries<Voting>().pipe(
map((allVoting): DeriveReferendumVote[] =>
allVoting
.map(([key, voting]): [AccountId, Voting] => [key.args[0] as AccountId, voting])
// FIXME We are ignoring delegated votes
.filter(([, voting]) => voting.isDirect)
.map(([accountId, voting]): [AccountId, VotingDirectVote[]] => [
accountId,
voting.asDirect.votes.filter(([idx]) => idx.eq(referendumId))
])
.filter(([, directVotes]) => !!directVotes.length)
.reduce((result: DeriveReferendumVote[], [accountId, votes]) =>
// FIXME We are ignoring split votes
votes.reduce((result: DeriveReferendumVote[], [, vote]): DeriveReferendumVote[] => {
if (vote.isStandard) {
result.push({
accountId,
...vote.asStandard
});
}
return result;
}, result), []
)
)
);
}
export function _referendumVotes (api: ApiInterfaceRx): (referendum: DeriveReferendum) => Observable<DeriveReferendumVotes> {
return memo((referendum: DeriveReferendum): Observable<DeriveReferendumVotes> =>
combineLatest([
api.derive.democracy.sqrtElectorate(),
api.query.democracy.votingOf
? votesCurr(api, referendum.index)
: votesPrev(api, referendum.index)
]).pipe(
map(([sqrtElectorate, votes]) =>
calcVotes(sqrtElectorate, referendum, votes)
)
)
);
}
@@ -1,22 +0,0 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DeriveReferendum, DeriveReferendumVotes } from '../types';
import { Observable, of, combineLatest } from 'rxjs';
import { memo } from '../util';
export function _referendumsVotes (api: ApiInterfaceRx): (referendums: DeriveReferendum[]) => Observable<DeriveReferendumVotes[]> {
return memo((referendums: DeriveReferendum[]): Observable<DeriveReferendumVotes[]> =>
referendums.length
? combineLatest(
referendums.map((referendum): Observable<DeriveReferendumVotes> =>
api.derive.democracy._referendumVotes(referendum)
)
)
: of([])
);
}
@@ -2,9 +2,6 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
export * from './_referendumsVotes';
export * from './_referendumVotes';
export * from './_referendumInfo';
export * from './dispatchQueue';
export * from './nextExternal';
export * from './preimage';
@@ -3,15 +3,114 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { ReferendumInfo } from '@polkadot/types/interfaces';
import { DeriveReferendum } from '../types';
import { AccountId, ReferendumInfo, ReferendumInfoTo239, Vote, Voting, VotingDirectVote } from '@polkadot/types/interfaces';
import { DeriveBalancesAccount, DeriveReferendum, DeriveReferendumVote, DeriveReferendumVotes } from '../types';
import BN from 'bn.js';
import { Observable, of, combineLatest } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Option } from '@polkadot/types';
import { Option, Vec } from '@polkadot/types';
import { memo } from '../util';
import { calcVotes, getStatus, parseImage } from './util';
function votesPrev (api: ApiInterfaceRx, referendumId: BN): Observable<DeriveReferendumVote[]> {
return api.query.democracy.votersFor<Vec<AccountId>>(referendumId).pipe(
switchMap((votersFor): Observable<[Vec<AccountId>, Vote[], DeriveBalancesAccount[]]> =>
combineLatest([
of(votersFor),
votersFor.length
? api.query.democracy.voteOf.multi<Vote>(
votersFor.map((accountId): [BN | number, AccountId] =>
[referendumId, accountId]
)
)
: of([]),
api.derive.balances.votingBalances(votersFor)
])
),
map(([votersFor, votes, balances]): DeriveReferendumVote[] =>
votersFor.map((accountId, index): DeriveReferendumVote => ({
accountId,
balance: balances[index].votingBalance || api.registry.createType('Balance'),
vote: votes[index] || api.registry.createType('Vote')
}))
)
);
}
function votesCurr (api: ApiInterfaceRx, referendumId: BN): Observable<DeriveReferendumVote[]> {
return api.query.democracy.votingOf.entries<Voting>().pipe(
map((allVoting): DeriveReferendumVote[] =>
allVoting
.map(([key, voting]): [AccountId, Voting] => [key.args[0] as AccountId, voting])
// FIXME We are ignoring delegated votes
.filter(([, voting]) => voting.isDirect)
.map(([accountId, voting]): [AccountId, VotingDirectVote[]] => [
accountId,
voting.asDirect.votes.filter(([idx]) => idx.eq(referendumId))
])
.filter(([, directVotes]) => !!directVotes.length)
.reduce((result: DeriveReferendumVote[], [accountId, votes]) =>
// FIXME We are ignoring split votes
votes.reduce((result: DeriveReferendumVote[], [, vote]): DeriveReferendumVote[] => {
if (vote.isStandard) {
result.push({
accountId,
...vote.asStandard
});
}
return result;
}, result), []
)
)
);
}
export function _referendumVotes (api: ApiInterfaceRx): (referendum: DeriveReferendum) => Observable<DeriveReferendumVotes> {
return memo((referendum: DeriveReferendum): Observable<DeriveReferendumVotes> =>
combineLatest([
api.derive.democracy.sqrtElectorate(),
api.query.democracy.votingOf
? votesCurr(api, referendum.index)
: votesPrev(api, referendum.index)
]).pipe(
map(([sqrtElectorate, votes]) =>
calcVotes(sqrtElectorate, referendum, votes)
)
)
);
}
export function _referendumsVotes (api: ApiInterfaceRx): (referendums: DeriveReferendum[]) => Observable<DeriveReferendumVotes[]> {
return memo((referendums: DeriveReferendum[]): Observable<DeriveReferendumVotes[]> =>
referendums.length
? combineLatest(
referendums.map((referendum): Observable<DeriveReferendumVotes> =>
api.derive.democracy._referendumVotes(referendum)
)
)
: of([])
);
}
export function _referendumInfo (api: ApiInterfaceRx): (index: BN, info: Option<ReferendumInfo | ReferendumInfoTo239>) => Observable<DeriveReferendum | null> {
return memo((index: BN, info: Option<ReferendumInfo | ReferendumInfoTo239>): Observable<DeriveReferendum | null> => {
const status = getStatus(info);
return status
? api.query.democracy.preimages(status.proposalHash).pipe(
map((preimage): DeriveReferendum => ({
image: parseImage(api, preimage),
imageHash: status.proposalHash,
index: api.registry.createType('ReferendumIndex', index),
status
}))
)
: of(null);
});
}
export function referendumsInfo (api: ApiInterfaceRx): (ids: BN[]) => Observable<DeriveReferendum[]> {
return memo((ids: BN[]): Observable<DeriveReferendum[]> =>
@@ -42,7 +42,7 @@ export function eraExposure (api: ApiInterfaceRx): (era: EraIndex) => Observable
);
}
export function erasExposureOver (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraExposure[]> {
export function _erasExposure (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraExposure[]> {
return memo((eras: EraIndex[]): Observable<DeriveEraExposure[]> =>
eras.length
? combineLatest(eras.map((era) => api.derive.staking.eraExposure(era)))
@@ -53,7 +53,7 @@ export function erasExposureOver (api: ApiInterfaceRx): (eras: EraIndex[]) => Ob
export function erasExposure (api: ApiInterfaceRx): (withActive?: boolean) => Observable<DeriveEraExposure[]> {
return memo((withActive?: boolean): Observable<DeriveEraExposure[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => api.derive.staking.erasExposureOver(eras))
switchMap((eras) => api.derive.staking._erasExposure(eras))
)
);
}
@@ -21,7 +21,7 @@ function mapValidators ({ individual }: EraRewardPoints): DeriveEraValPoints {
}, {});
}
export function erasPointsOver (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraPoints[]> {
export function _erasPoints (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraPoints[]> {
return memo((eras: EraIndex[]): Observable<DeriveEraPoints[]> =>
eras.length
? api.query.staking.erasRewardPoints.multi<EraRewardPoints>(eras).pipe(
@@ -40,7 +40,7 @@ export function erasPointsOver (api: ApiInterfaceRx): (eras: EraIndex[]) => Obse
export function erasPoints (api: ApiInterfaceRx): (withActive?: boolean) => Observable<DeriveEraPoints[]> {
return memo((withActive?: boolean): Observable<DeriveEraPoints[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => api.derive.staking.erasPointsOver(eras))
switchMap((eras) => api.derive.staking._erasPoints(eras))
)
);
}
+2 -2
View File
@@ -30,7 +30,7 @@ export function eraPrefs (api: ApiInterfaceRx): (era: EraIndex) => Observable<De
);
}
export function erasPrefsOver (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraPrefs[]> {
export function _erasPrefs (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraPrefs[]> {
return memo((eras: EraIndex[]): Observable<DeriveEraPrefs[]> =>
eras.length
? combineLatest(eras.map((era) => api.derive.staking.eraPrefs(era)))
@@ -41,7 +41,7 @@ export function erasPrefsOver (api: ApiInterfaceRx): (eras: EraIndex[]) => Obser
export function erasPrefs (api: ApiInterfaceRx): (withActive?: boolean) => Observable<DeriveEraPrefs[]> {
return memo((withActive?: boolean): Observable<DeriveEraPrefs[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => api.derive.staking.erasPrefsOver(eras))
switchMap((eras) => api.derive.staking._erasPrefs(eras))
)
);
}
@@ -12,7 +12,7 @@ import { Option } from '@polkadot/types';
import { memo } from '../util';
export function erasRewardsOver (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraRewards[]> {
export function _erasRewards (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraRewards[]> {
return memo((eras: EraIndex[]): Observable<DeriveEraRewards[]> =>
eras.length
? api.query.staking.erasValidatorReward.multi<Option<Balance>>(eras).pipe(
@@ -28,7 +28,7 @@ export function erasRewardsOver (api: ApiInterfaceRx): (eras: EraIndex[]) => Obs
export function erasRewards (api: ApiInterfaceRx): (withActive?: boolean) => Observable<DeriveEraRewards[]> {
return memo((withActive?: boolean): Observable<DeriveEraRewards[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => api.derive.staking.erasRewardsOver(eras))
switchMap((eras) => api.derive.staking._erasRewards(eras))
)
);
}
@@ -39,7 +39,7 @@ export function eraSlashes (api: ApiInterfaceRx): (era: EraIndex) => Observable<
);
}
export function erasSlashesOver (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraSlashes[]> {
export function _erasSlashes (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraSlashes[]> {
return memo((eras: EraIndex[]): Observable<DeriveEraSlashes[]> =>
eras.length
? combineLatest(
@@ -52,7 +52,7 @@ export function erasSlashesOver (api: ApiInterfaceRx): (eras: EraIndex[]) => Obs
export function erasSlashes (api: ApiInterfaceRx): (withActive?: boolean) => Observable<DeriveEraSlashes[]> {
return memo((withActive?: boolean): Observable<DeriveEraSlashes[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => api.derive.staking.erasSlashesOver(eras))
switchMap((eras) => api.derive.staking._erasSlashes(eras))
)
);
}
+22 -11
View File
@@ -55,7 +55,7 @@ function retrieveCurr (api: ApiInterfaceRx, stashId: AccountId): Observable<Mult
);
}
function retrieveController (api: ApiInterfaceRx, stashId: AccountId, [queuedKeys, [controllerIdOpt, nominatorsOpt, rewardDestination, validatorPrefs, nextKeys, exposure]]: [Vec<ITuple<[AccountId, Keys]>>, MultiResult]): Observable<DeriveStakingQuery> {
function retrieveController (api: ApiInterfaceRx, stashId: AccountId, queuedKeys: Vec<ITuple<[AccountId, Keys]>>, [controllerIdOpt, nominatorsOpt, rewardDestination, validatorPrefs, nextKeys, exposure]: MultiResult): Observable<DeriveStakingQuery> {
const controllerId = controllerIdOpt.unwrapOr(null);
const nominators = nominatorsOpt.unwrapOr(null);
@@ -82,30 +82,41 @@ function retrieveController (api: ApiInterfaceRx, stashId: AccountId, [queuedKey
: of({ accountId: stashId, nextSessionIds: [], sessionIds: [] });
}
/**
* @description From a stash, retrieve the controllerId and all relevant details
*/
export function query (api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DeriveStakingQuery> {
return memo((accountId: Uint8Array | string): Observable<DeriveStakingQuery> => {
export function queryWithQueued (api: ApiInterfaceRx): (accountId: Uint8Array | string, queuedKeys: Vec<ITuple<[AccountId, Keys]>>) => Observable<DeriveStakingQuery> {
return memo((accountId: Uint8Array | string, queuedKeys: Vec<ITuple<[AccountId, Keys]>>): Observable<DeriveStakingQuery> => {
const stashId = api.registry.createType('AccountId', accountId);
return combineLatest([
api.query.session.queuedKeys<Vec<ITuple<[AccountId, Keys]>>>(),
return (
api.query.staking.erasStakers
? retrieveCurr(api, stashId)
: retrievePrev(api, stashId)
]).pipe(
).pipe(
switchMap((result): Observable<DeriveStakingQuery> =>
retrieveController(api, stashId, result)
retrieveController(api, stashId, queuedKeys, result)
)
);
});
}
/**
* @description From a stash, retrieve the controllerId and all relevant details
*/
export function query (api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DeriveStakingQuery> {
return memo((accountId: Uint8Array | string): Observable<DeriveStakingQuery> =>
api.query.session.queuedKeys<Vec<ITuple<[AccountId, Keys]>>>().pipe(
switchMap((queuedKeys) => api.derive.staking.queryWithQueued(accountId, queuedKeys))
)
);
}
export function queryMulti (api: ApiInterfaceRx): (accountIds: (Uint8Array | string)[]) => Observable<DeriveStakingQuery[]> {
return memo((accountIds: (Uint8Array | string)[]): Observable<DeriveStakingQuery[]> =>
accountIds.length
? combineLatest(accountIds.map((acc) => api.derive.staking.query(acc)))
? api.query.session.queuedKeys<Vec<ITuple<[AccountId, Keys]>>>().pipe(
switchMap((queuedKeys) => combineLatest(
accountIds.map((acc) => api.derive.staking.queryWithQueued(acc, queuedKeys))
))
)
: of([])
);
}
@@ -11,11 +11,11 @@ import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util';
export function stakerExposureOver (api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[]) => Observable<DeriveStakerExposure[]> {
export function _stakerExposure (api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[]) => Observable<DeriveStakerExposure[]> {
return memo((accountId: Uint8Array | string, eras: EraIndex[]): Observable<DeriveStakerExposure[]> => {
const stakerId = api.registry.createType('AccountId', accountId).toString();
return api.derive.staking.erasExposureOver(eras).pipe(
return api.derive.staking._erasExposure(eras).pipe(
map((exposures): DeriveStakerExposure[] =>
exposures.map(({ era, nominators: allNominators, validators: allValidators }): DeriveStakerExposure => {
const isValidator = !!allValidators[stakerId];
@@ -40,7 +40,7 @@ export function stakerExposureOver (api: ApiInterfaceRx): (accountId: Uint8Array
export function stakerExposure (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable<DeriveStakerExposure[]> {
return memo((accountId: Uint8Array | string, withActive?: boolean): Observable<DeriveStakerExposure[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => api.derive.staking.stakerExposureOver(accountId, eras))
switchMap((eras) => api.derive.staking._stakerExposure(accountId, eras))
)
);
}
@@ -11,11 +11,11 @@ import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util';
export function stakerPointsOver (api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[]) => Observable<DeriveStakerPoints[]> {
export function _stakerPoints (api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[]) => Observable<DeriveStakerPoints[]> {
return memo((accountId: Uint8Array | string, eras: EraIndex[]): Observable<DeriveStakerPoints[]> => {
const stakerId = api.registry.createType('AccountId', accountId).toString();
return api.derive.staking.erasPointsOver(eras).pipe(
return api.derive.staking._erasPoints(eras).pipe(
map((points): DeriveStakerPoints[] =>
points.map(({ era, eraPoints, validators }): DeriveStakerPoints => ({
era,
@@ -30,7 +30,7 @@ export function stakerPointsOver (api: ApiInterfaceRx): (accountId: Uint8Array |
export function stakerPoints (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable<DeriveStakerPoints[]> {
return memo((accountId: Uint8Array | string, withActive?: boolean): Observable<DeriveStakerPoints[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => api.derive.staking.stakerPointsOver(accountId, eras))
switchMap((eras) => api.derive.staking._stakerPoints(accountId, eras))
)
);
}
@@ -16,7 +16,9 @@ import { memo } from '../util';
type Result = [DeriveEraPoints[], DeriveEraPrefs[], DeriveEraRewards[], DeriveStakerExposure[]];
const ZERO = new BN(0);
const MIN_ONE = new BN(-1);
const COMM_DIV = new BN(1_000_000_000);
const MAX_ERAS = new BN(1_000_000_000);
function parseRewards (api: ApiInterfaceRx, stashId: AccountId, [erasPoints, erasPrefs, erasRewards, exposures]: Result): DeriveStakerReward[] {
return exposures.map(({ era, isEmpty, isValidator, nominating, validators: eraValidators }): DeriveStakerReward => {
@@ -25,7 +27,6 @@ function parseRewards (api: ApiInterfaceRx, stashId: AccountId, [erasPoints, era
const { validators: allValPrefs } = erasPrefs.find((p) => p.era.eq(era)) || { validators: {} as DeriveEraValPrefs };
const validators: Record<string, DeriveStakerRewardValidator> = {};
const stakerId = stashId.toString();
let total = ZERO;
Object.entries(eraValidators).forEach(([validatorId, exposure]): void => {
const valPoints = allValPoints[validatorId] || ZERO;
@@ -49,7 +50,6 @@ function parseRewards (api: ApiInterfaceRx, stashId: AccountId, [erasPoints, era
}
value = avail.sub(valCut).mul(staked).div(expTotal).add(validatorId === stakerId ? valCut : ZERO);
total = total.add(value);
}
validators[validatorId] = {
@@ -64,7 +64,6 @@ function parseRewards (api: ApiInterfaceRx, stashId: AccountId, [erasPoints, era
isEmpty,
isValidator,
nominating,
total: api.registry.createType('Balance', total),
validators
};
});
@@ -88,7 +87,17 @@ function isOldLedger (ledger?: StakingLedger | StakingLedgerTo240): ledger is St
return !!(ledger as StakingLedgerTo240)?.lastReward;
}
function filterRewards (api: ApiInterfaceRx, rewards: DeriveStakerReward[], withActive?: boolean): Observable<DeriveStakerReward[]> {
function filterEra (era: EraIndex, stakingLedger: StakingLedger): boolean {
return isOldLedger(stakingLedger)
? era.gt(stakingLedger.lastReward.unwrapOr(MIN_ONE))
: !stakingLedger.claimedRewards.some((e) => e.eq(era));
}
function filterEras (eras: EraIndex[], stakingLedger: StakingLedger): EraIndex[] {
return eras.filter((era) => filterEra(era, stakingLedger));
}
function filterRewards (api: ApiInterfaceRx, rewards: DeriveStakerReward[], stakingLedger: StakingLedger, withActive?: boolean): Observable<DeriveStakerReward[]> {
if (withActive) {
return of(rewards);
}
@@ -98,20 +107,20 @@ function filterRewards (api: ApiInterfaceRx, rewards: DeriveStakerReward[], with
return combineLatest([
api.query.staking.migrateEra
? api.query.staking.migrateEra<Option<EraIndex>>()
: of(api.registry.createType('Option<EraIndex>', api.tx.staking.payoutStakers ? 0 : 1_000_000_000)),
: of({ unwrapOr: () => api.tx.staking.payoutStakers ? MIN_ONE : MAX_ERAS }),
api.tx.staking.payoutStakers
? api.derive.staking.queryMulti(validators)
: of([])
]).pipe(
map(([optMigrate, queryValidators]): DeriveStakerReward[] => {
const migrateEra = optMigrate.unwrapOr(new BN(-1));
const migrateEra: BN = optMigrate.unwrapOr(MIN_ONE);
return rewards
.filter(({ isEmpty }) => !isEmpty)
.filter((reward): boolean => {
if (reward.era.lte(migrateEra)) {
// we have already filtered these inside the stakerRewardsOver query, so all are valid
return true;
// we filter again here, the actual ledger may have changed, e.g. something has been claimed
return filterEra(reward.era, stakingLedger);
}
reward.isStakerPayout = true;
@@ -145,19 +154,7 @@ function filterRewards (api: ApiInterfaceRx, rewards: DeriveStakerReward[], with
);
}
function filterEras (eras: EraIndex[], stakingLedger: StakingLedger): EraIndex[] {
if (!stakingLedger) {
return eras;
} else if (isOldLedger(stakingLedger)) {
const lastReward = stakingLedger.lastReward.unwrapOr(new BN(-1));
return eras.filter((era) => era.gt(lastReward));
}
return eras.filter((era) => !stakingLedger.claimedRewards.some((e) => e.eq(era)));
}
export function stakerRewardsOver (api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[], withActive?: boolean) => Observable<DeriveStakerReward[]> {
export function _stakerRewards (api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[], withActive?: boolean) => Observable<DeriveStakerReward[]> {
return memo((accountId: Uint8Array | string, _eras: EraIndex[], withActive?: boolean): Observable<DeriveStakerReward[]> =>
api.derive.staking.query(accountId).pipe(
switchMap(({ stakingLedger, stashId }): Observable<DeriveStakerReward[]> => {
@@ -170,13 +167,13 @@ export function stakerRewardsOver (api: ApiInterfaceRx): (accountId: Uint8Array
: filterEras(_eras, stakingLedger);
return combineLatest([
api.derive.staking.erasPointsOver(eras),
api.derive.staking.erasPrefsOver(eras),
api.derive.staking.erasRewardsOver(eras),
api.derive.staking.stakerExposureOver(stashId, eras)
api.derive.staking._erasPoints(eras),
api.derive.staking._erasPrefs(eras),
api.derive.staking._erasRewards(eras),
api.derive.staking._stakerExposure(stashId, eras)
]).pipe(
switchMap((result): Observable<DeriveStakerReward[]> =>
filterRewards(api, parseRewards(api, stashId, result), withActive)
filterRewards(api, parseRewards(api, stashId, result), stakingLedger, withActive)
)
);
})
@@ -187,7 +184,7 @@ export function stakerRewardsOver (api: ApiInterfaceRx): (accountId: Uint8Array
export function stakerRewards (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable<DeriveStakerReward[]> {
return memo((accountId: Uint8Array | string, withActive?: boolean): Observable<DeriveStakerReward[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => api.derive.staking.stakerRewardsOver(accountId, eras, withActive))
switchMap((eras) => api.derive.staking._stakerRewards(accountId, eras, withActive))
)
);
}
@@ -197,7 +194,7 @@ export function stakerRewardsMulti (api: ApiInterfaceRx): (accountIds: (Uint8Arr
accountIds.length
? api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) =>
combineLatest(accountIds.map((acc) => api.derive.staking.stakerRewardsOver(acc, eras, withActive)))
combineLatest(accountIds.map((acc) => api.derive.staking._stakerRewards(acc, eras, withActive)))
)
)
: of([])
@@ -11,11 +11,11 @@ import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util';
export function stakerSlashesOver (api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[]) => Observable<DeriveStakerSlashes[]> {
export function _stakerSlashes (api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[]) => Observable<DeriveStakerSlashes[]> {
return memo((accountId: Uint8Array | string, eras: EraIndex[]): Observable<DeriveStakerSlashes[]> => {
const stakerId = api.registry.createType('AccountId', accountId).toString();
return api.derive.staking.erasSlashesOver(eras).pipe(
return api.derive.staking._erasSlashes(eras).pipe(
map((slashes): DeriveStakerSlashes[] =>
slashes.map(({ era, nominators, validators }): DeriveStakerSlashes => ({
era,
@@ -29,7 +29,7 @@ export function stakerSlashesOver (api: ApiInterfaceRx): (accountId: Uint8Array
export function stakerSlashes (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable<DeriveStakerSlashes[]> {
return memo((accountId: Uint8Array | string, withActive?: boolean): Observable<DeriveStakerSlashes[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => api.derive.staking.stakerSlashesOver(accountId, eras))
switchMap((eras) => api.derive.staking._stakerSlashes(accountId, eras))
)
);
}
-1
View File
@@ -84,7 +84,6 @@ export interface DeriveStakerReward {
isEmpty: boolean;
isValidator: boolean;
nominating: DeriveEraExposureNominating[];
total: Balance;
validators: Record<string, DeriveStakerRewardValidator>;
}