Add event status warnings (#6962)

* Add event status warnings

* xcmPallet
This commit is contained in:
Jaco 2022-02-10 08:17:05 +01:00 committed by GitHub
parent a1a9fa5c1d
commit cbcf7ba15c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 86 additions and 6 deletions

View File

@ -13,6 +13,7 @@ import { SubmittableResult } from '@polkadot/api';
import jsonrpc from '@polkadot/types/interfaces/jsonrpc';
import { getContractAbi } from '../util';
import { isIncompleteEvent } from './checks';
import { STATUS_COMPLETE } from './constants';
import { QueueProvider } from './Context';
@ -36,7 +37,10 @@ function mergeStatus (status: ActionStatusPartial[]): ActionStatus[] {
const initial = status
.reduce((result: StatusCount[], status): StatusCount[] => {
const prev = result.find(({ status: prev }) => prev.action === status.action && prev.status === status.status);
const prev = result.find(({ status: prev }) =>
prev.action === status.action &&
prev.status === status.status
);
if (prev) {
prev.count++;
@ -82,8 +86,13 @@ function extractEvents (result?: SubmittableResult): ActionStatus[] {
((result && result.events) || [])
// filter events handled globally, or those we are not interested in, these are
// handled by the global overview, so don't add them here
.filter((record): boolean => !!record.event && record.event.section !== 'democracy')
.map(({ event: { data, method, section } }): ActionStatusPartial => {
.filter((record) =>
!!record.event &&
record.event.section !== 'democracy'
)
.map((record): ActionStatusPartial => {
const { event: { data, method, section } } = record;
if (section === 'system' && method === 'ExtrinsicFailed') {
const [dispatchError] = data as unknown as ITuple<[DispatchError]>;
let message = dispatchError.type;
@ -133,6 +142,12 @@ function extractEvents (result?: SubmittableResult): ActionStatus[] {
message: 'contract evicted',
status: 'error'
};
} else if (isIncompleteEvent(record)) {
return {
action: `${section}.${method}`,
message: 'imcomplete execution',
status: 'eventWarn'
};
}
}
@ -198,7 +213,7 @@ function Queue ({ children }: Props): React.ReactElement<Props> {
...(status.map((item): QueueStatus => {
const id = ++nextId;
const removeItem = (): void =>
setStQueue([...stRef.current.filter((item): boolean => item.id !== id)]);
setStQueue([...stRef.current.filter((item) => item.id !== id)]);
setTimeout(removeItem, REMOVE_TIMEOUT);
@ -265,7 +280,7 @@ function Queue ({ children }: Props): React.ReactElement<Props> {
if (STATUS_COMPLETE.includes(status)) {
setTimeout((): void => {
const item = txRef.current.find((item): boolean => item.id === id);
const item = txRef.current.find((item) => item.id === id);
item && item.removeItem();
}, REMOVE_TIMEOUT);

View File

@ -0,0 +1,60 @@
// Copyright 2017-2022 @polkadot/react-components authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { Result } from '@polkadot/types';
import type { Event, EventRecord } from '@polkadot/types/interfaces';
import type { XcmV2TraitsOutcome } from '@polkadot/types/lookup';
import type { Codec } from '@polkadot/types/types';
type EventCheck = (event: Event) => boolean;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function acceptAll (_: Event): boolean {
return true;
}
function dispatchResult ({ data: [result] }: Event): boolean {
return !result || (result as Result<Codec, Codec>).isErr;
}
// [approving, timepoint, multisig, callHash, result]
function dispatchResultMulti ({ data: [,,,, result] }: Event): boolean {
return !result || (result as Result<Codec, Codec>).isErr;
}
function xcmAttempted ({ data: [outcome] }: Event): boolean {
return !outcome || (outcome as XcmV2TraitsOutcome).isIncomplete;
}
const xcmPallet: Record<string, EventCheck> = {
Attempted: xcmAttempted
};
const CHECKS: Record<string, Record<string, EventCheck>> = {
multisig: {
MultisigExecuted: dispatchResultMulti
},
polkadotXcm: xcmPallet,
proxy: {
ProxyExecuted: dispatchResult
},
sudo: {
Sudid: dispatchResult,
SudoAsDone: dispatchResult
},
utility: {
BatchInterrupted: acceptAll,
DispatchedAs: dispatchResult
},
xcmPallet
};
export function isIncompleteEvent ({ event }: EventRecord): boolean {
const { method, section } = event;
return (
!!CHECKS[section] &&
!!CHECKS[section][method] &&
CHECKS[section][method](event)
);
}

View File

@ -25,6 +25,7 @@ function iconName (status: string): IconName {
return 'ban';
case 'event':
case 'eventWarn':
return 'assistive-listening-systems';
case 'received':
@ -284,6 +285,10 @@ export default React.memo(styled(Status)`
background: teal;
}
&.eventWarn > .wraper > .container {
background: orange;
}
&.completed,
&.finalized,
&.inblock,

View File

@ -12,7 +12,7 @@ export type Actions = 'create' | 'edit' | 'restore' | 'forget' | 'backup' | 'cha
export interface ActionStatusBase {
account?: AccountId | Address | string;
message?: string;
status: 'error' | 'event' | 'queued' | 'received' | 'success';
status: 'error' | 'event' | 'eventWarn' | 'queued' | 'received' | 'success';
}
export interface ActionStatusPartial extends ActionStatusBase {