Add referensumsActive (#2091)

This commit is contained in:
Jaco Greeff
2020-03-25 09:43:05 +01:00
committed by GitHub
parent 15c3085511
commit 64f64c1001
3 changed files with 120 additions and 91 deletions
@@ -4,3 +4,4 @@
export * from './proposals';
export * from './referendums';
export * from './referendumsActive';
@@ -3,18 +3,17 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { AccountId, Balance, ReferendumIndex, ReferendumInfo, ReferendumInfoTo239, ReferendumStatus, Vote, Voting, VotingDirectVote } from '@polkadot/types/interfaces';
import { AccountId, Vote, Voting, VotingDirectVote } from '@polkadot/types/interfaces';
import { DerivedBalancesAccount, DerivedReferendum, DerivedReferendumExt, DerivedReferendumVote } from '../types';
import BN from 'bn.js';
import { Observable, of, combineLatest } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Option, Vec } from '@polkadot/types';
import { Vec } from '@polkadot/types';
import { bnSqrt } from '@polkadot/util';
import { memo } from '../util';
import { PreImage } from './proposals';
import { calcVotes, getStatus } from './util';
import { calcVotes } from './util';
function votesPrev (api: ApiInterfaceRx, referendumId: BN): Observable<DerivedReferendumVote[]> {
return api.query.democracy.votersFor<Vec<AccountId>>(referendumId).pipe(
@@ -70,101 +69,42 @@ function votesCurr (api: ApiInterfaceRx, referendumId: BN): Observable<DerivedRe
);
}
function constructInfo (api: ApiInterfaceRx, index: BN | number, status: ReferendumStatus | ReferendumInfoTo239, _preimage?: PreImage): DerivedReferendum | null {
const preImage = _preimage?.isSome
? _preimage.unwrap()
: null;
return {
index: api.registry.createType('PropIndex', index),
hash: status.proposalHash,
proposal: preImage
? api.registry.createType('Proposal', preImage[0].toU8a(true))
: undefined,
preimage: preImage
? {
at: preImage[3],
balance: preImage[2],
proposer: preImage[1]
}
: undefined,
status
};
}
function retrieveInfo (api: ApiInterfaceRx, index: BN | number, info: Option<ReferendumInfo | ReferendumInfoTo239>): Observable<DerivedReferendum | null> {
const status = getStatus(info);
return status
? api.query.democracy.preimages(status.proposalHash).pipe(
map((preimage?: PreImage): DerivedReferendum | null =>
constructInfo(api, index, status, preimage)
)
function retrieveVotes (api: ApiInterfaceRx, sqrtElectorate: BN, referendums: DerivedReferendum[]): Observable<DerivedReferendumExt[]> {
return combineLatest(
referendums.map((referendum): Observable<DerivedReferendumVote[]> =>
api.query.democracy.votingOf
? votesCurr(api, referendum.index)
: votesPrev(api, referendum.index)
)
).pipe(
map((votes) =>
referendums.map((referendum, index): DerivedReferendumExt => ({
...referendum,
...calcVotes(sqrtElectorate, referendum, votes[index])
}))
)
: of(null);
}
function referendumInfos (api: ApiInterfaceRx, ids: BN[]): Observable<DerivedReferendum[]> {
return api.query.democracy.referendumInfoOf.multi<Option<ReferendumInfo>>(ids).pipe(
switchMap((infos): Observable<(DerivedReferendum | null)[]> =>
combineLatest(
ids.map((id, index): Observable<DerivedReferendum | null> =>
retrieveInfo(api, id, infos[index])
)
)
),
map((infos) => infos.filter((referendum): referendum is DerivedReferendum => !!referendum))
);
}
function retrieveDerived (api: ApiInterfaceRx, totalIssuance: Balance, earliest: ReferendumIndex, referendumCount: ReferendumIndex): Observable<[BN, DerivedReferendum[]]> {
return combineLatest([
of(bnSqrt(totalIssuance)),
referendumCount.gt(earliest)
? referendumInfos(api, [
...Array(referendumCount.sub(earliest).toNumber())
].map((_, i): BN => earliest.addn(i)))
: of([])
]);
}
function retrieveVotes (api: ApiInterfaceRx, sqrtElectorate: BN, referendums: DerivedReferendum[]): Observable<[BN, DerivedReferendum[], DerivedReferendumVote[][]]> {
return combineLatest([
of(sqrtElectorate),
of(referendums),
referendums.length
? combineLatest(
referendums.map((referendum): Observable<DerivedReferendumVote[]> =>
api.query.democracy.votingOf
? votesCurr(api, referendum.index)
: votesPrev(api, referendum.index)
)
)
: of([])
]);
function sqrtElectorate (api: ApiInterfaceRx): Observable<BN> {
return api.query.balances.totalIssuance().pipe(
map((totalIssuance) =>
bnSqrt(totalIssuance)
)
);
}
export function referendums (api: ApiInterfaceRx): () => Observable<DerivedReferendumExt[]> {
return memo((): Observable<DerivedReferendumExt[]> =>
api.query.democracy?.lowestUnbaked
? api.queryMulti<[Balance, ReferendumIndex, ReferendumIndex]>([
api.query.balances.totalIssuance,
api.query.democracy.lowestUnbaked,
api.query.democracy.referendumCount
]).pipe(
switchMap(([totalIssuance, earliest, referendumCount]) =>
retrieveDerived(api, totalIssuance, earliest, referendumCount)
),
switchMap(([sqrtElectorate, referendums]) =>
retrieveVotes(api, sqrtElectorate, referendums)
),
map(([sqrtElectorate, referendums, votes]) =>
referendums.map((referendum, index): DerivedReferendumExt => ({
...referendum,
...calcVotes(sqrtElectorate, referendum, votes[index])
}))
)
combineLatest([
sqrtElectorate(api),
api.derive.democracy.referendumsActive()
]).pipe(
switchMap(([sqrtElectorate, referendums]) =>
referendums.length
? retrieveVotes(api, sqrtElectorate, referendums)
: of([])
)
: of([])
)
);
}
@@ -0,0 +1,88 @@
// 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 { ReferendumIndex, ReferendumInfo, ReferendumInfoTo239, ReferendumStatus } from '@polkadot/types/interfaces';
import { DerivedReferendum } 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 { memo } from '../util';
import { PreImage } from './proposals';
import { getStatus } from './util';
function constructInfo (api: ApiInterfaceRx, index: BN | number, status: ReferendumStatus | ReferendumInfoTo239, _preimage?: PreImage): DerivedReferendum | null {
const preImage = _preimage?.isSome
? _preimage.unwrap()
: null;
return {
index: api.registry.createType('PropIndex', index),
hash: status.proposalHash,
proposal: preImage
? api.registry.createType('Proposal', preImage[0].toU8a(true))
: undefined,
preimage: preImage
? {
at: preImage[3],
balance: preImage[2],
proposer: preImage[1]
}
: undefined,
status
};
}
function retrieveInfo (api: ApiInterfaceRx, index: BN | number, info: Option<ReferendumInfo | ReferendumInfoTo239>): Observable<DerivedReferendum | null> {
const status = getStatus(info);
return status
? api.query.democracy.preimages(status.proposalHash).pipe(
map((preimage?: PreImage): DerivedReferendum | null =>
constructInfo(api, index, status, preimage)
)
)
: of(null);
}
function referendumInfos (api: ApiInterfaceRx, ids: BN[]): Observable<DerivedReferendum[]> {
return api.query.democracy.referendumInfoOf.multi<Option<ReferendumInfo>>(ids).pipe(
switchMap((infos): Observable<(DerivedReferendum | null)[]> =>
combineLatest(
ids.map((id, index): Observable<DerivedReferendum | null> =>
retrieveInfo(api, id, infos[index])
)
)
),
map((infos) =>
infos.filter((referendum): referendum is DerivedReferendum => !!referendum)
)
);
}
function retrieveDerived (api: ApiInterfaceRx, earliest: ReferendumIndex, referendumCount: ReferendumIndex): Observable<DerivedReferendum[]> {
const indexes = [...Array(referendumCount.sub(earliest).toNumber())].map((_, i): BN => earliest.addn(i));
return referendumInfos(api, indexes);
}
export function referendumsActive (api: ApiInterfaceRx): () => Observable<DerivedReferendum[]> {
return memo((): Observable<DerivedReferendum[]> =>
api.query.democracy?.lowestUnbaked
? api.queryMulti<[ReferendumIndex, ReferendumIndex]>([
api.query.democracy.lowestUnbaked,
api.query.democracy.referendumCount
]).pipe(
switchMap(([earliest, referendumCount]) =>
referendumCount.gt(earliest)
? retrieveDerived(api, earliest, referendumCount)
: of([])
)
)
: of([])
);
}