Introduce signer busy (QR dupes) (#2994)
This commit is contained in:
parent
5ab06dbead
commit
0f18e88022
@ -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;
|
||||
}
|
||||
`);
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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')
|
||||
|
||||
@ -27,7 +27,6 @@ export default class QrSigner implements Signer {
|
||||
|
||||
this.#setState({
|
||||
isQrHashed,
|
||||
isQrVisible: true,
|
||||
qrAddress: payload.address,
|
||||
qrPayload,
|
||||
qrReject: reject,
|
||||
|
||||
@ -25,7 +25,6 @@ export interface AddressProxy {
|
||||
|
||||
export interface QrState {
|
||||
isQrHashed: boolean;
|
||||
isQrVisible: boolean;
|
||||
qrAddress: string;
|
||||
qrPayload: Uint8Array;
|
||||
qrResolve?: (result: SignerResult) => void;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user