Introduce signer busy (QR dupes) (#2994)

This commit is contained in:
Jaco Greeff 2020-06-20 08:23:42 +02:00 committed by GitHub
parent 5ab06dbead
commit 0f18e88022
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 57 additions and 33 deletions

View File

@ -27,7 +27,7 @@ function Spinner ({ className = '', label, variant = 'app' }: Props): React.Reac
size='medium'
>
{variant === 'app' && (
label || t<string>('Retrieving data')
<div className='text'>{label || t<string>('Retrieving data')}</div>
)}
</Loader>
</div>
@ -36,8 +36,7 @@ function Spinner ({ className = '', label, variant = 'app' }: Props): React.Reac
export default React.memo(styled(Spinner)`
.text {
margin: 0 auto 1.5rem auto;
color: inherit !important;
opacity: 0.6;
text-align: center;
}
`);

View File

@ -29,13 +29,16 @@ function PaymentInfo ({ accountId, className = '', extrinsic }: Props): React.Re
useEffect((): void => {
// eslint-disable-next-line @typescript-eslint/unbound-method
accountId && extrinsic && isFunction(extrinsic.paymentInfo) && isFunction(api.rpc.payment?.queryInfo) &&
Promise.resolve(
extrinsic
.paymentInfo(accountId)
.then((info): void => {
mountedRef.current && setDispatchInfo(info);
})
).catch((error: Error) => console.error(error.message));
setImmediate((): void => {
try {
extrinsic
.paymentInfo(accountId)
.then((info) => mountedRef.current && setDispatchInfo(info))
.catch(console.error);
} catch (error) {
console.error((error as Error).message);
}
});
}, [api, accountId, extrinsic, mountedRef]);
if (!dispatchInfo) {

View File

@ -6,9 +6,11 @@ import { BareProps } from '@polkadot/react-components/types';
import React from 'react';
import styled from 'styled-components';
import { Columar } from '@polkadot/react-components';
import { Columar, Spinner } from '@polkadot/react-components';
import { QrDisplayPayload, QrScanSignature } from '@polkadot/react-qr';
import { useTranslation } from './translate';
interface Props extends BareProps {
address: string;
className?: string;
@ -23,6 +25,14 @@ const CMD_HASH = 1;
const CMD_MORTAL = 2;
function Qr ({ address, className, genesisHash, isHashed, onSignature, payload }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
if (!address) {
return (
<Spinner label={<div>{t('Preparing QR for signing')}</div>} />
);
}
return (
<Columar className={className}>
<Columar.Column>

View File

@ -157,7 +157,8 @@ function TxSigned ({ className, currentItem, requestAddress }: Props): React.Rea
const { t } = useTranslation();
const { queueSetTxStatus } = useContext(StatusContext);
const [flags, setFlags] = useState(extractExternal(requestAddress));
const [{ isQrHashed, isQrVisible, qrAddress, qrPayload, qrResolve }, setQrState] = useState<QrState>({ isQrHashed: false, isQrVisible: false, qrAddress: '', qrPayload: new Uint8Array() });
const [{ isQrHashed, qrAddress, qrPayload, qrResolve }, setQrState] = useState<QrState>({ isQrHashed: false, qrAddress: '', qrPayload: new Uint8Array() });
const [isBusy, setBusy] = useState(false);
const [isRenderError, toggleRenderError] = useToggle();
const [isSubmit, setIsSubmit] = useState(true);
const [passwordError, setPasswordError] = useState<string | null>(null);
@ -216,8 +217,8 @@ function TxSigned ({ className, currentItem, requestAddress }: Props): React.Rea
);
const _onSendPayload = useCallback(
(): void => {
if (_unlock() && senderInfo.signAddress && currentItem.payload) {
(queueSetTxStatus: QueueTxMessageSetStatus, currentItem: QueueTx, senderInfo: AddressProxy): void => {
if (senderInfo.signAddress && currentItem.payload) {
const { id, payload, signerCb = NOOP } = currentItem;
const pair = keyring.getPair(senderInfo.signAddress);
const result = registry.createType('ExtrinsicPayload', payload, { version: payload.version }).sign(pair);
@ -226,12 +227,12 @@ function TxSigned ({ className, currentItem, requestAddress }: Props): React.Rea
queueSetTxStatus(id, 'completed');
}
},
[_unlock, currentItem, queueSetTxStatus, senderInfo]
[]
);
const _onSend = useCallback(
async (): Promise<void> => {
if (_unlock() && senderInfo.signAddress) {
async (queueSetTxStatus: QueueTxMessageSetStatus, currentItem: QueueTx, senderInfo: AddressProxy): Promise<void> => {
if (senderInfo.signAddress) {
const [tx, [status, pairOrAddress, options]] = await Promise.all([
wrapTx(api, currentItem, senderInfo),
extractParams(senderInfo.signAddress, { tip }, setQrState)
@ -242,12 +243,12 @@ function TxSigned ({ className, currentItem, requestAddress }: Props): React.Rea
await signAndSend(queueSetTxStatus, currentItem, tx, pairOrAddress, options);
}
},
[_unlock, api, currentItem, queueSetTxStatus, senderInfo, tip]
[api, tip]
);
const _onSign = useCallback(
async (): Promise<void> => {
if (_unlock() && senderInfo.signAddress) {
async (queueSetTxStatus: QueueTxMessageSetStatus, currentItem: QueueTx, senderInfo: AddressProxy): Promise<void> => {
if (senderInfo.signAddress) {
const [tx, [, pairOrAddress, options]] = await Promise.all([
wrapTx(api, currentItem, senderInfo),
extractParams(senderInfo.signAddress, { ...signedOptions, tip }, setQrState)
@ -256,14 +257,33 @@ function TxSigned ({ className, currentItem, requestAddress }: Props): React.Rea
setSignedTx(await signAsync(queueSetTxStatus, currentItem, tx, pairOrAddress, options));
}
},
[_unlock, api, currentItem, queueSetTxStatus, senderInfo, signedOptions, tip]
[api, signedOptions, tip]
);
const _doStart = useCallback(
(): void => {
setBusy(true);
setImmediate((): void => {
if (_unlock()) {
isSubmit
? currentItem.payload
? _onSendPayload(queueSetTxStatus, currentItem, senderInfo)
: _onSend(queueSetTxStatus, currentItem, senderInfo).catch(console.error)
: _onSign(queueSetTxStatus, currentItem, senderInfo).catch(console.error);
} else {
setBusy(false);
}
});
},
[_onSend, _onSendPayload, _onSign, _unlock, currentItem, isSubmit, queueSetTxStatus, senderInfo]
);
return (
<>
<Modal.Content className={className}>
<ErrorBoundary onError={toggleRenderError}>
{isQrVisible
{(isBusy && flags.isQr)
? (
<Qr
address={qrAddress}
@ -317,7 +337,7 @@ function TxSigned ({ className, currentItem, requestAddress }: Props): React.Rea
</ErrorBoundary>
</Modal.Content>
<Modal.Actions onCancel={_onCancel}>
{!isQrVisible && (
{!isBusy && (
<>
<Button
icon={
@ -334,18 +354,12 @@ function TxSigned ({ className, currentItem, requestAddress }: Props): React.Rea
? t<string>('Sign and Submit')
: t<string>('Sign (no submission)')
}
onClick={
isSubmit
? currentItem.payload
? _onSendPayload
: _onSend
: _onSign
}
onClick={_doStart}
tabIndex={2}
/>
<Toggle
className='signToggle'
isDisabled={isQrVisible || !!currentItem.payload}
isDisabled={!!currentItem.payload}
label={
isSubmit
? t<string>('Sign and Submit')

View File

@ -27,7 +27,6 @@ export default class QrSigner implements Signer {
this.#setState({
isQrHashed,
isQrVisible: true,
qrAddress: payload.address,
qrPayload,
qrReject: reject,

View File

@ -25,7 +25,6 @@ export interface AddressProxy {
export interface QrState {
isQrHashed: boolean;
isQrVisible: boolean;
qrAddress: string;
qrPayload: Uint8Array;
qrResolve?: (result: SignerResult) => void;