Files
api/packages/api-derive/src/democracy/dispatchQueue.ts
T
Jeremías Díaz 66b1108c5c feat(types): add correct tuple type to storage key (#3054)
* feat(types): add correct tuple type to storage key

* refactor(types): remove unneeded type assertions
2021-01-15 16:06:23 +01:00

106 lines
3.6 KiB
TypeScript

// Copyright 2017-2021 @polkadot/api-derive authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { ApiInterfaceRx } from '@polkadot/api/types';
import type { Option, u64, Vec } from '@polkadot/types';
import type { BlockNumber, Hash, ReferendumIndex, Scheduled } from '@polkadot/types/interfaces';
import type { ITuple } from '@polkadot/types/types';
import type { Observable } from '@polkadot/x-rxjs';
import type { DeriveDispatch, DeriveProposalImage } from '../types';
import { isFunction, stringToHex } from '@polkadot/util';
import { combineLatest, of } from '@polkadot/x-rxjs';
import { map, switchMap } from '@polkadot/x-rxjs/operators';
import { memo } from '../util';
const DEMOCRACY_ID = stringToHex('democrac');
interface SchedulerInfo {
at: BlockNumber;
imageHash: Hash;
index: ReferendumIndex;
}
function queryQueue (api: ApiInterfaceRx): Observable<DeriveDispatch[]> {
return api.query.democracy.dispatchQueue<Vec<ITuple<[BlockNumber, Hash, ReferendumIndex]>>>().pipe(
switchMap((dispatches) =>
combineLatest([
of(dispatches),
api.derive.democracy.preimages(
dispatches.map(([, hash]) => hash))
])
),
map(([dispatches, images]) =>
dispatches.map(([at, imageHash, index], dispatchIndex): DeriveDispatch => ({
at,
image: images[dispatchIndex],
imageHash,
index
}))
)
);
}
function schedulerEntries (api: ApiInterfaceRx): Observable<[BlockNumber[], Option<Scheduled>[][]]> {
// We don't get entries, but rather we get the keys (triggered via finished referendums) and
// the subscribe to those keys - this means we pickup when the schedulers actually executes
// at a block, the entry for that block will become empty
return api.derive.democracy.referendumsFinished().pipe(
switchMap(() =>
api.query.scheduler.agenda.keys()
),
switchMap((keys) => {
const blockNumbers = keys.map((key) => key.args[0]);
return combineLatest([
of(blockNumbers),
api.query.scheduler.agenda.multi<Vec<Option<Scheduled>>>(blockNumbers)
]);
})
);
}
function queryScheduler (api: ApiInterfaceRx): Observable<DeriveDispatch[]> {
return schedulerEntries(api).pipe(
switchMap(([blockNumbers, agendas]): Observable<[SchedulerInfo[], (DeriveProposalImage | undefined)[]]> => {
const result: SchedulerInfo[] = [];
blockNumbers.forEach((at, index): void => {
agendas[index].filter((optScheduled) => optScheduled.isSome).forEach((optScheduled): void => {
const scheduled = optScheduled.unwrap();
if (scheduled.maybeId.isSome) {
const id = scheduled.maybeId.unwrap().toHex();
if (id.startsWith(DEMOCRACY_ID)) {
const [, index] = api.registry.createType('(u64, ReferendumIndex)' as any, id) as ITuple<[u64, ReferendumIndex]>;
const imageHash = scheduled.call.args[0] as Hash;
result.push({ at, imageHash, index });
}
}
});
});
return combineLatest([
of(result),
api.derive.democracy.preimages(result.map(({ imageHash }) => imageHash))
]);
}),
map(([infos, images]): DeriveDispatch[] =>
infos.map((info, index) => ({ ...info, image: images[index] }))
)
);
}
export function dispatchQueue (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveDispatch[]> {
return memo(instanceId, (): Observable<DeriveDispatch[]> =>
isFunction(api.query.scheduler?.agenda)
? queryScheduler(api)
: api.query.democracy.dispatchQueue
? queryQueue(api)
: of([])
);
}