Optimize crowdloan refresh (delta only on events) (#5549)
* Optimize crowdloan refresh (delata only on events) * Adjust own contributions
This commit is contained in:
parent
ac622aa3d2
commit
c21dadcd9e
@ -16,5 +16,5 @@ export default function useAssetIds (): AssetId[] | undefined {
|
||||
const { api } = useApi();
|
||||
const trigger = useEventTrigger([api.events.assets.Created, api.events.assets.Destroyed]);
|
||||
|
||||
return useMapKeys(api.query.assets.asset, { at: trigger, transform: extractAssetIds });
|
||||
return useMapKeys(api.query.assets.asset, { at: trigger.blockHash, transform: extractAssetIds });
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
// Copyright 2017-2021 @polkadot/app-parachains authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { ApiPromise } from '@polkadot/api';
|
||||
import type { StorageKey } from '@polkadot/types';
|
||||
import type { Balance, EventRecord, ParaId } from '@polkadot/types/interfaces';
|
||||
|
||||
@ -23,7 +24,7 @@ const NO_CONTRIB: Contributions = {
|
||||
myContributions: {}
|
||||
};
|
||||
|
||||
function extractContributors (allAccountsHex: string[], keys: StorageKey[], ss58Format?: number): Contributions {
|
||||
function extractContributors (keys: StorageKey[], allAccountsHex: string[], ss58Format?: number): Contributions {
|
||||
const contributorsHex = keys.map((k) => k.toHex());
|
||||
const myAccountsHex = contributorsHex.filter((c) => allAccountsHex.includes(c));
|
||||
|
||||
@ -35,13 +36,36 @@ function extractContributors (allAccountsHex: string[], keys: StorageKey[], ss58
|
||||
};
|
||||
}
|
||||
|
||||
function extractDelta (api: ApiPromise, events: EventRecord[], prev: Contributions, allAccountsHex: string[], ss58Format?: number): Contributions {
|
||||
const removed = events
|
||||
.filter(({ event }) => api.events.crowdloan.Withdrew.is(event))
|
||||
.map(({ event: { data: [accountId] } }) => accountId.toHex());
|
||||
const contributorsHex = prev.contributorsHex.filter((h) => !removed.includes(h));
|
||||
|
||||
events
|
||||
.filter(({ event }) => api.events.crowdloan.Contributed.is(event))
|
||||
.forEach(({ event: { data: [accountId] } }): void => {
|
||||
contributorsHex.push(accountId.toHex());
|
||||
});
|
||||
|
||||
const myAccountsHex = contributorsHex.filter((c) => allAccountsHex.includes(c));
|
||||
|
||||
return {
|
||||
contributorsHex,
|
||||
myAccounts: myAccountsHex.map((a) => encodeAddress(a, ss58Format)),
|
||||
myAccountsHex,
|
||||
myContributions: {}
|
||||
};
|
||||
}
|
||||
|
||||
function useMyContributions (paraId: ParaId, childKey: string, keys: string[]): Record<string, Balance> {
|
||||
const { api } = useApi();
|
||||
const { allAccountsHex } = useAccounts();
|
||||
const [state, setState] = useState<Record<string, Balance>>({});
|
||||
|
||||
const trigger = useEventTrigger([
|
||||
api.events.crowdloan.Contributed
|
||||
api.events.crowdloan.Contributed,
|
||||
api.events.crowdloan.Withdrew
|
||||
], useCallback(
|
||||
({ event: { data: [accountId, eventParaId] } }: EventRecord) =>
|
||||
eventParaId.eq(paraId) &&
|
||||
@ -75,44 +99,69 @@ function useMyContributions (paraId: ParaId, childKey: string, keys: string[]):
|
||||
export default function useContributions (paraId: ParaId, childKey: string): Contributions {
|
||||
const { api } = useApi();
|
||||
const { allAccountsHex } = useAccounts();
|
||||
const [state, setState] = useState<Contributions>(() => NO_CONTRIB);
|
||||
const [state, _setState] = useState<Contributions>(() => NO_CONTRIB);
|
||||
const myContributions = useMyContributions(paraId, childKey, state.myAccountsHex);
|
||||
|
||||
const trigger = useEventTrigger([
|
||||
api.events.crowdloan.Contributed,
|
||||
api.events.crowdloan.Withdrew,
|
||||
// these trigger a full refresh of the keys
|
||||
const triggerAll = useEventTrigger([
|
||||
api.events.crowdloan.Dissolved,
|
||||
api.events.crowdloan.AllRefunded,
|
||||
api.events.crowdloan.PartiallyRefunded
|
||||
], useCallback(
|
||||
({ event: { data } }: EventRecord) =>
|
||||
((data.length === 1
|
||||
? data[0] // AllRefunded, PartiallyRefunded [ParaId]
|
||||
: data[1] // Contributed, Withdrew [AccountId, ParaId, Balance]
|
||||
) as ParaId).eq(paraId),
|
||||
({ event: { data: [eventParaId] } }: EventRecord) =>
|
||||
eventParaId.eq(paraId),
|
||||
[paraId]
|
||||
));
|
||||
|
||||
// these trigger a delta adjustment
|
||||
const triggerDelta = useEventTrigger([
|
||||
api.events.crowdloan.Contributed,
|
||||
api.events.crowdloan.Withdrew
|
||||
], useCallback(
|
||||
({ event: { data: [, eventParaId] } }: EventRecord) =>
|
||||
eventParaId.eq(paraId),
|
||||
[paraId]
|
||||
));
|
||||
|
||||
const setState = useCallback(
|
||||
(fn: (prev: Contributions) => Contributions) =>
|
||||
_setState((prev) => {
|
||||
const { contributorsHex, myAccounts, myAccountsHex } = fn(prev);
|
||||
|
||||
return {
|
||||
...prev,
|
||||
contributorsHex,
|
||||
...(prev.myAccounts.length === myAccounts.length
|
||||
? {}
|
||||
: { myAccounts, myAccountsHex }
|
||||
)
|
||||
};
|
||||
}),
|
||||
[]
|
||||
);
|
||||
|
||||
useEffect((): void => {
|
||||
trigger &&
|
||||
triggerAll &&
|
||||
api.rpc.childstate
|
||||
.getKeys(childKey, '0x')
|
||||
.then((keys) => setState((prev) => {
|
||||
const { contributorsHex, myAccounts, myAccountsHex } = extractContributors(allAccountsHex, keys, api.registry.chainSS58);
|
||||
|
||||
return {
|
||||
...prev,
|
||||
contributorsHex,
|
||||
...(prev.myAccounts.length === myAccounts.length
|
||||
? {}
|
||||
: { myAccounts, myAccountsHex }
|
||||
)
|
||||
};
|
||||
}))
|
||||
.then((keys) =>
|
||||
setState(() =>
|
||||
extractContributors(keys, allAccountsHex, api.registry.chainSS58)
|
||||
)
|
||||
)
|
||||
.catch(console.error);
|
||||
}, [allAccountsHex, api, childKey, trigger]);
|
||||
}, [allAccountsHex, api, childKey, setState, triggerAll]);
|
||||
|
||||
useEffect((): void => {
|
||||
setState((prev) => ({
|
||||
triggerDelta && triggerDelta.events.length &&
|
||||
setState((prev) =>
|
||||
extractDelta(api, triggerDelta.events, prev, allAccountsHex, api.registry.chainSS58)
|
||||
);
|
||||
}, [api, allAccountsHex, setState, triggerDelta]);
|
||||
|
||||
useEffect((): void => {
|
||||
// no deltas, set directly here
|
||||
_setState((prev) => ({
|
||||
...prev,
|
||||
myContributions
|
||||
}));
|
||||
|
||||
@ -167,7 +167,7 @@ export default function useFunds (): Campaigns {
|
||||
const { api } = useApi();
|
||||
const bestNumber = useBestNumber();
|
||||
const trigger = useEventTrigger([api.events.crowdloan?.Created]);
|
||||
const paraIds = useMapKeys(api.query.crowdloan?.funds, { at: trigger, transform: extractFundIds });
|
||||
const paraIds = useMapKeys(api.query.crowdloan?.funds, { at: trigger.blockHash, transform: extractFundIds });
|
||||
const campaigns = useCall<Campaign[]>(api.query.crowdloan?.funds.multi, [paraIds], optFundMulti);
|
||||
const leases = useCall<ParaId[]>(api.query.slots.leases.multi, [paraIds], optLeaseMulti);
|
||||
const [result, setResult] = useState<Campaigns>(EMPTY);
|
||||
|
||||
@ -35,7 +35,7 @@ export default function useHrmp (): AllChannels | undefined {
|
||||
(api.events.parasHrmp || api.events.hrmp)?.OpenChannelAccepted,
|
||||
(api.events.parasHrmp || api.events.hrmp)?.ChannelClosed
|
||||
]);
|
||||
const channelIds = useMapKeys((api.query.parasHrmp || api.query.hrmp)?.hrmpChannels, { at: trigger, transform: extractChannelIds });
|
||||
const channelIds = useMapKeys((api.query.parasHrmp || api.query.hrmp)?.hrmpChannels, { at: trigger.blockHash, transform: extractChannelIds });
|
||||
|
||||
return useCall<AllChannels>(channelIds && (api.query.parasHrmp || api.query.hrmp)?.hrmpChannels.multi, [channelIds], optChannels);
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ export default function useOwnedIds (): OwnedId[] {
|
||||
const { api } = useApi();
|
||||
const { allAccounts } = useAccounts();
|
||||
const trigger = useEventTrigger([api.events.registrar.Registered, api.events.registrar.Reserved]);
|
||||
const unfiltered = useMapEntries<Owned>(api.query.registrar.paras, { at: trigger, transform: extractIds });
|
||||
const unfiltered = useMapEntries<Owned>(api.query.registrar.paras, { at: trigger.blockHash, transform: extractIds });
|
||||
const hashes = useCall(api.query.paras.currentCodeHash.multi, [unfiltered ? unfiltered.ids : []], hashesOption);
|
||||
|
||||
return useMemo(
|
||||
|
||||
@ -35,8 +35,8 @@ export default function useProposals (): Proposals | undefined {
|
||||
const { api } = useApi();
|
||||
const mountedRef = useIsMountedRef();
|
||||
const trigger = useEventTrigger([api.events.proposeParachain?.ProposeParachain]);
|
||||
const proposalIds = useMapKeys(api.query.proposeParachain?.proposals, { at: trigger, transform: extractProposalIds });
|
||||
const scheduled = useMapEntries(api.query.proposeParachain?.scheduledProposals, { at: trigger, transform: extractScheduled });
|
||||
const proposalIds = useMapKeys(api.query.proposeParachain?.proposals, { at: trigger.blockHash, transform: extractProposalIds });
|
||||
const scheduled = useMapEntries(api.query.proposeParachain?.scheduledProposals, { at: trigger.blockHash, transform: extractScheduled });
|
||||
const [sessionIndex, approvedIds] = useCallMulti<MultiQuery>([
|
||||
api.query.session.currentIndex,
|
||||
api.query.proposeParachain?.approvedProposals
|
||||
|
||||
@ -28,5 +28,5 @@ export default function useUpomingIds (): ParaId[] | undefined {
|
||||
const { api } = useApi();
|
||||
const trigger = useEventTrigger([api.events.session.NewSession, api.events.registrar.Registered]);
|
||||
|
||||
return useMapEntries(api.query.paras.paraLifecycles, { at: trigger, transform: extractIds });
|
||||
return useMapEntries(api.query.paras.paraLifecycles, { at: trigger.blockHash, transform: extractIds });
|
||||
}
|
||||
|
||||
@ -14,5 +14,5 @@ export default function useTipHashes (): string[] | undefined {
|
||||
const { api } = useApi();
|
||||
const trigger = useEventTrigger([api.events.tips?.NewTip, api.events.tips?.TipClosed, api.events.tips?.TipRetracted]);
|
||||
|
||||
return useMapKeys((api.query.tips || api.query.treasury)?.tips, { at: trigger, transform: extractHashes });
|
||||
return useMapKeys((api.query.tips || api.query.treasury)?.tips, { at: trigger.blockHash, transform: extractHashes });
|
||||
}
|
||||
|
||||
@ -13,21 +13,41 @@ import { useIsMountedRef } from './useIsMountedRef';
|
||||
|
||||
type EventCheck = AugmentedEvent<'promise'> | false | undefined | null;
|
||||
|
||||
interface Result {
|
||||
blockHash: string;
|
||||
events: EventRecord[];
|
||||
}
|
||||
|
||||
const EMPTY_RESULT: Result = {
|
||||
blockHash: '',
|
||||
events: []
|
||||
};
|
||||
|
||||
const IDENTITY_FILTER = () => true;
|
||||
|
||||
export function useEventTrigger (checks: EventCheck[], filter: (record: EventRecord) => boolean = IDENTITY_FILTER): string {
|
||||
export function useEventTrigger (_checks: EventCheck[], filter: (record: EventRecord) => boolean = IDENTITY_FILTER): Result {
|
||||
const { api } = useApi();
|
||||
const [trigger, setTrigger] = useState('0');
|
||||
const [state, setState] = useState(() => EMPTY_RESULT);
|
||||
const [checks] = useState(() => _checks);
|
||||
const mountedRef = useIsMountedRef();
|
||||
const eventRecords = useCall<Vec<EventRecord>>(api.query.system.events);
|
||||
|
||||
useEffect((): void => {
|
||||
mountedRef.current && eventRecords && eventRecords.filter((r) =>
|
||||
r.event &&
|
||||
checks.some((c) => c && c.is(r.event)) &&
|
||||
filter(r)
|
||||
).length && setTrigger(eventRecords.createdAtHash?.toHex() || '');
|
||||
if (mountedRef.current && eventRecords) {
|
||||
const events = eventRecords.filter((r) =>
|
||||
r.event &&
|
||||
checks.some((c) => c && c.is(r.event)) &&
|
||||
filter(r)
|
||||
);
|
||||
|
||||
if (events.length) {
|
||||
setState({
|
||||
blockHash: eventRecords.createdAtHash?.toHex() || '',
|
||||
events
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [eventRecords, checks, filter, mountedRef]);
|
||||
|
||||
return trigger;
|
||||
return state;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user