Show expanded callData for multisig approvals (#5432)

* Show expanded callData for multisig approvals

* Update on hash swap

* No initial error

* api registry create
This commit is contained in:
Jaco 2021-06-03 14:02:01 +03:00 committed by GitHub
parent c6980ec629
commit 214eb57a4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -3,11 +3,12 @@
import type { SubmittableExtrinsic } from '@polkadot/api/types';
import type { AccountId, Call, H256, Multisig } from '@polkadot/types/interfaces';
import type { CallFunction } from '@polkadot/types/types';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import styled from 'styled-components';
import { AddressMini, Dropdown, Expander, Input, InputAddress, MarkError, Modal, Toggle, TxButton } from '@polkadot/react-components';
import { AddressMini, Call as CallDisplay, Dropdown, Expander, Input, InputAddress, MarkError, Modal, Toggle, TxButton } from '@polkadot/react-components';
import { useAccounts, useApi, useWeight } from '@polkadot/react-hooks';
import { assert, isHex } from '@polkadot/util';
@ -35,15 +36,21 @@ interface Option {
interface CallData {
callData: Call | null;
callError: string | null;
callInfo: CallFunction | null;
}
const EMPTY_CALL: CallData = { callData: null, callError: null };
const EMPTY_CALL: CallData = {
callData: null,
callError: null,
callInfo: null
};
function MultisigApprove ({ className = '', onClose, ongoing, threshold, who }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const { api } = useApi();
const { allAccounts } = useAccounts();
const [{ callData, callError }, setCallData] = useState<CallData>(EMPTY_CALL);
const [callHex, setCallHex] = useState<string>('');
const [{ callData, callError, callInfo }, setCallData] = useState<CallData>(EMPTY_CALL);
const [callWeight] = useWeight(callData);
const [hash, setHash] = useState<string | null>(ongoing[0][0].toHex());
const [{ isMultiCall, multisig }, setMultisig] = useState<MultiInfo>({ isMultiCall: false, multisig: null });
@ -101,6 +108,27 @@ function MultisigApprove ({ className = '', onClose, ongoing, threshold, who }:
);
}, [api, allAccounts, multisig, threshold, type, who]);
// when the hex changes, re-evaluate
useEffect((): void => {
if (callHex) {
try {
assert(isHex(callHex), 'Hex call data required');
const callData = api.createType('Call', callHex);
assert(callData.hash.eq(hash), 'Call data does not match the existing call hash');
const callInfo = api.registry.findMetaCall(callData.callIndex);
setCallData({ callData, callError: null, callInfo });
} catch (error) {
setCallData({ callData: null, callError: (error as Error).message, callInfo: null });
}
} else {
setCallData(EMPTY_CALL);
}
}, [api, callHex, hash]);
// based on the type, multisig, others create the tx. This can be either an approval or final call
useEffect((): void => {
const multiMod = api.tx.multisig || api.tx.utility;
@ -126,24 +154,6 @@ function MultisigApprove ({ className = '', onClose, ongoing, threshold, who }:
);
}, [api, callData, callWeight, hash, isCallOverride, isMultiCall, others, multisig, threshold, type]);
// when the actual call input changes, create a call and set it
const _setCallData = useCallback(
(callHex: string): void => {
try {
assert(isHex(callHex), 'Hex call data required');
const callData = api.createType('Call', callHex);
assert(callData.hash.eq(hash), 'Call data does not match the existing call hash');
setCallData({ callData, callError: null });
} catch (error) {
setCallData({ callData: null, callError: (error as Error).message });
}
},
[api, hash]
);
const isAye = type === 'aye';
return (
@ -217,13 +227,28 @@ function MultisigApprove ({ className = '', onClose, ongoing, threshold, who }:
<>
{isCallOverride && (
<Modal.Columns hint={t('The call data for this transaction matching the hash. Once sent, the multisig will be executed against this.')}>
<Input
autoFocus
help={t('For final approvals, the actual full call data is required to execute the transaction')}
isError={!callData}
label={t('call data for final approval')}
onChange={_setCallData}
/>
{callData && callInfo
? (
<Expander
isPadded
summary={`${callInfo.section}.${callInfo.method}`}
summaryMeta={callInfo.meta}
>
<CallDisplay
className='details'
value={callData}
/>
</Expander>
)
: (
<Input
autoFocus
help={t('For final approvals, the actual full call data is required to execute the transaction')}
isError={!callHex || !!callError}
label={t('call data for final approval')}
onChange={setCallHex}
/>
)}
{callError && (
<MarkError content={callError} />
)}