All files / app/components/tx-signing sign-transaction-software.tsx

0% Statements 0/41
0% Branches 0/11
0% Functions 0/5
0% Lines 0/39

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82                                                                                                                                                                   
import {
  StackingModalButton as Button,
  StackingModalFooter as Footer,
} from '../../modals/components/stacking-modal-layout';
import { SignTransactionProps } from './sign-transaction';
import routes from '@constants/routes.json';
import { isDecryptionError } from '@crypto/key-encryption';
import { useCreateSoftwareContractCallTx } from '@hooks/use-create-software-contract-call-tx';
import { createSoftwareWalletTokenTransferTx } from '@hooks/use-create-token-transfer-tx';
import { useDecryptWallet } from '@hooks/use-decrypt-wallet';
import { DecryptWalletForm } from '@modals/components/decrypt-wallet-form';
import { blastUndoStackToRemovePasswordFromMemory } from '@utils/blast-undo-stack';
import { capitalize } from '@utils/capitalize';
import { safeAwait } from '@utils/safe-await';
import { HomeSelectors } from 'app/tests/features/home.selectors';
import React, { useCallback, useRef, useState } from 'react';
import { useHistory } from 'react-router';
 
type SignTransactionSoftwareProps = SignTransactionProps;
 
export const SignTransactionSoftware: React.FC<SignTransactionSoftwareProps> = props => {
  const { action, txOptions, isBroadcasting, onTransactionSigned, onClose } = props;
 
  const [decryptionError, setDecryptionError] = useState<string | null>(null);
  const [hasSubmitted, setHasSubmitted] = useState(false);
  const [isBusy, setIsBusy] = useState(false);
 
  const inputRef = useRef<HTMLInputElement>(null);
 
  const [password, setPassword] = useState('');
  const history = useHistory();
 
  const { decryptWallet, isDecrypting } = useDecryptWallet();
  const { createSoftwareContractCallTx } = useCreateSoftwareContractCallTx();
 
  const createSoftwareWalletTx = useCallback(async () => {
    const { stxPrivateKey } = await decryptWallet(password);
    blastUndoStackToRemovePasswordFromMemory(inputRef.current);
    Iif ('recipient' in txOptions) {
      return createSoftwareWalletTokenTransferTx({ privateKey: stxPrivateKey, txOptions });
    }
    return createSoftwareContractCallTx({ privateKey: stxPrivateKey, txOptions });
  }, [decryptWallet, password, createSoftwareContractCallTx, txOptions]);
 
  return (
    <>
      <DecryptWalletForm
        description={`Enter your password to ${action}`}
        onSetPassword={password => setPassword(password)}
        onForgottenPassword={() => history.push(routes.SETTINGS)}
        hasSubmitted={hasSubmitted}
        decryptionError={decryptionError}
        ref={inputRef}
      />
      <Footer>
        <Button mode="tertiary" onClick={onClose}>
          Close
        </Button>
        <Button
          isLoading={isDecrypting || isBroadcasting || isBusy}
          isDisabled={isDecrypting || isBroadcasting || isBusy}
          data-test={HomeSelectors.BtnSendStxFormBroadcastTx}
          onClick={async () => {
            setHasSubmitted(true);
            setIsBusy(true);
            const [error, tx] = await safeAwait(createSoftwareWalletTx());
            Iif (error) {
              setDecryptionError(
                isDecryptionError(error) ? 'Unable to decrypt wallet' : 'Something went wrong'
              );
              setIsBusy(false);
            }
            Iif (tx) onTransactionSigned(tx);
          }}
        >
          {capitalize(action)}
        </Button>
      </Footer>
    </>
  );
};