useCallMulti on parachain proposals (#4436)

This commit is contained in:
Jaco Greeff 2021-01-18 12:48:37 +01:00 committed by GitHub
parent d3c15f9fc7
commit 00563a240b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 13 deletions

View File

@ -39,7 +39,7 @@ const transformLast = {
transform: (header: Header) => header.number.unwrap()
};
const transformMulti = {
const optionsMulti = {
defaultValue: {
headHex: null,
qDmp: 0,
@ -76,7 +76,7 @@ function Parachain ({ bestNumber, className = '', id, isScheduled, lastInclusion
[api.query.hrmp.hrmpEgressChannelsIndex, id],
[api.query.hrmp.hrmpIngressChannelsIndex, id],
[api.query.hrmp.hrmpWatermarks, id]
], transformMulti) as QueryState; // we have a default value, cast is safe
], optionsMulti);
const blockDelay = useMemo(
() => bestNumber && (

View File

@ -7,7 +7,9 @@ import type { ProposalExt, Proposals, ScheduledProposals } from '../types';
import { useEffect, useMemo, useState } from 'react';
import { useApi, useCall, useIsMountedRef } from '@polkadot/react-hooks';
import { useApi, useCall, useCallMulti, useIsMountedRef } from '@polkadot/react-hooks';
type MultiQuery = [EventRecord[], SessionIndex | undefined, ParaId[] | undefined];
function createResult (sessionIndex: SessionIndex, approvedIds: ParaId[], proposalKeys: { args: [ParaId] }[], scheduledProposals: [{ args: [SessionIndex] }, ParaId[]][]): Proposals {
return {
@ -22,19 +24,30 @@ function createResult (sessionIndex: SessionIndex, approvedIds: ParaId[], propos
};
}
const optionsMulti = {
defaultValue: [[], undefined, undefined] as MultiQuery,
transform: ([records, sessionIndex, approvedIds]: [EventRecord[], SessionIndex, ParaId[] | undefined]): MultiQuery => [
records.filter(({ event, phase }) => phase?.isApplyExtrinsic && event?.section === 'proposeParachain'),
sessionIndex,
approvedIds
]
};
export default function useProposals (): Proposals | undefined {
const { api } = useApi();
const mountedRef = useIsMountedRef();
const [state, setState] = useState<Proposals | undefined>();
const [trigger, setTrigger] = useState(Date.now());
const sessionIndex = useCall<SessionIndex>(api.query.session.currentIndex);
const approvedIds = useCall<ParaId[]>(api.query.proposeParachain?.approvedProposals);
const events = useCall<EventRecord[]>(api.query.system.events);
const [events, sessionIndex, approvedIds] = useCallMulti<MultiQuery>([
api.query.system.events,
api.query.session.currentIndex,
api.query.proposeParachain?.approvedProposals
], optionsMulti);
// trigger on any proposeParachain events
useEffect((): void => {
mountedRef.current && events && setTrigger((trigger) =>
events.filter((r) => r && r.phase?.isApplyExtrinsic && r.event?.section === 'proposeParachain').length
events.length
? Date.now()
: trigger
);

View File

@ -27,15 +27,22 @@ function subscribe <T> (api: ApiPromise, mountedRef: MountedRef, tracker: Tracke
setTimeout((): void => {
if (mountedRef.current) {
if (calls.length) {
// swap to acive mode
const included = calls.map((c) => !!c);
const filtered = calls.filter((_, index) => included[index]);
if (filtered.length) {
// swap to active mode
tracker.current.isActive = true;
tracker.current.subscriber = api.queryMulti(calls, (value): void => {
tracker.current.subscriber = api.queryMulti(filtered, (value): void => {
// we use the isActive flag here since .subscriber may not be set on immediate callback)
if (mountedRef.current && tracker.current.isActive) {
let valueIndex = -1;
mountedRef.current && tracker.current.isActive && setValue(
transform(value)
transform(
calls.map((_, index) => included[index] ? value[++valueIndex] : undefined)
)
);
}
});
@ -47,11 +54,11 @@ function subscribe <T> (api: ApiPromise, mountedRef: MountedRef, tracker: Tracke
}
// very much copied from useCall
export function useCallMulti <T> (calls?: QueryableStorageMultiArg<'promise'>[] | null | false, options?: CallOptions<T>): T | undefined {
export function useCallMulti <T> (calls?: QueryableStorageMultiArg<'promise'>[] | null | false, options?: CallOptions<T>): T {
const { api } = useApi();
const mountedRef = useIsMountedRef();
const tracker = useRef<Tracker>({ isActive: false, serialized: null, subscriber: null });
const [value, setValue] = useState<T | undefined>((options || {}).defaultValue);
const [value, setValue] = useState<T>((options || {}).defaultValue || [] as unknown as T);
// initial effect, we need an un-subscription
useEffect((): () => void => {