All files / app/pages/onboarding/05-connect-ledger connect-ledger.tsx

0% Statements 0/48
0% Branches 0/20
0% Functions 0/3
0% Lines 0/47

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 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128                                                                                                                                                                                                                                                               
import { ErrorLabel } from '@components/error-label';
import { ErrorText } from '@components/error-text';
import { LedgerConnectInstructions } from '@components/ledger/ledger-connect-instructions';
import {
  Onboarding,
  OnboardingTitle,
  OnboardingText,
  OnboardingButton,
} from '@components/onboarding';
import routes from '@constants/routes.json';
import { useBackButton } from '@hooks/use-back-url';
import { usePrepareLedger, LedgerConnectStep } from '@hooks/use-prepare-ledger';
import { Box, color, Text } from '@stacks/ui';
import { setLedgerWallet } from '@store/keys';
import { delay } from '@utils/delay';
import { isMainnet } from '@utils/network-utils';
import { LedgerError } from '@zondax/ledger-blockstack';
import React, { useState } from 'react';
import { useDispatch } from 'react-redux';
import { useHistory } from 'react-router-dom';
 
export const ConnectLedger: React.FC = () => {
  const [loading, setLoading] = useState(false);
  const [didRejectTx, setDidRejectTx] = useState(false);
  const [hasConfirmedAddress, setHasConfirmedAddress] = useState(false);
  const [deviceError, setDeviceError] = useState<string | null>(null);
 
  const [ledgerLaunchVersionError, setLedgerLaunchVersionError] = useState<string | null>(null);
  useBackButton(routes.CREATE);
 
  const { step, isLocked, appVersionErrorText, isSupportedAppVersion } = usePrepareLedger();
 
  const dispatch = useDispatch();
  const history = useHistory();
 
  async function handleLedger() {
    setDeviceError(null);
    setLoading(true);
 
    try {
      const deviceResponse = await main.ledger.requestAndConfirmStxAddress();
      Iif (deviceResponse.returnCode === LedgerError.TransactionRejected) {
        setDidRejectTx(true);
        setLoading(false);
        return;
      }
 
      Iif (deviceResponse.returnCode === 0xffff) {
        throw new Error(deviceResponse.errorMessage);
      }
 
      Iif ('publicKey' in deviceResponse) {
        setLoading(true);
        setHasConfirmedAddress(true);
        await delay(750);
        Iif (isMainnet() && !deviceResponse.address.startsWith('SP')) {
          setLedgerLaunchVersionError(
            'Make sure you have the most recent version of Ledger app. Address generated is for testnet'
          );
          return;
        }
        dispatch(
          setLedgerWallet({
            address: deviceResponse.address,
            publicKey: deviceResponse.publicKey,
            onSuccess: () => history.push(routes.HOME),
          })
        );
      }
    } catch (e) {
      setLoading(false);
      setDeviceError(String(e));
    }
  }
 
  return (
    <Onboarding>
      <OnboardingTitle>Connect your Ledger</OnboardingTitle>
      <OnboardingText>Follow these steps to connect your Ledger Nano S or X</OnboardingText>
      <Box>
        <Text
          textStyle="caption"
          color={color('text-caption')}
          mt="tight"
          display="block"
          textAlign="center"
          lineHeight="18px"
        >
          Press both buttons on your Ledger device simultaneously
        </Text>
      </Box>
      <LedgerConnectInstructions
        action="Confirm your address"
        step={hasConfirmedAddress ? LedgerConnectStep.ActionComplete : step}
        isLocked={isLocked}
      />
      {deviceError && (
        <ErrorLabel mt="base-loose">
          <ErrorText>{deviceError}</ErrorText>
        </ErrorLabel>
      )}
      {ledgerLaunchVersionError !== null && (
        <ErrorLabel mt="base-loose">
          <ErrorText>{ledgerLaunchVersionError}</ErrorText>
        </ErrorLabel>
      )}
      {didRejectTx && (
        <ErrorLabel mt="base-loose">
          <ErrorText>You must approve the action that appears on your Ledger device</ErrorText>
        </ErrorLabel>
      )}
      {!isSupportedAppVersion && (
        <ErrorLabel mt="base-loose">
          <ErrorText>{appVersionErrorText}</ErrorText>
        </ErrorLabel>
      )}
      <OnboardingButton
        mt="loose"
        onClick={handleLedger}
        isDisabled={step < 2 || loading || isLocked || !isSupportedAppVersion}
        isLoading={loading}
      >
        Continue
      </OnboardingButton>
    </Onboarding>
  );
};