import React, { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import PropTypes from 'prop-types'; import { LEDGER_TRANSPORT_TYPES, LEDGER_USB_VENDOR_ID, WEBHID_CONNECTED_STATUSES, TRANSPORT_STATES, } from '../../../../shared/constants/hardware-wallets'; import { PLATFORM_FIREFOX, ENVIRONMENT_TYPE_FULLSCREEN, } from '../../../../shared/constants/app'; import { setLedgerWebHidConnectedStatus, getLedgerWebHidConnectedStatus, setLedgerTransportStatus, getLedgerTransportStatus, } from '../../../ducks/app/app'; import Typography from '../../ui/typography/typography'; import Button from '../../ui/button'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { COLORS, FONT_WEIGHT, TYPOGRAPHY, } from '../../../helpers/constants/design-system'; import Dialog from '../../ui/dialog'; import { getPlatform, getEnvironmentType, } from '../../../../app/scripts/lib/util'; import { getLedgerTransportType } from '../../../ducks/metamask/metamask'; import { attemptLedgerTransportCreation } from '../../../store/actions'; const renderInstructionStep = (text, show = true, color = COLORS.PRIMARY3) => { return ( show && ( {text} ) ); }; export default function LedgerInstructionField({ showDataInstruction }) { const t = useI18nContext(); const dispatch = useDispatch(); const webHidConnectedStatus = useSelector(getLedgerWebHidConnectedStatus); const ledgerTransportType = useSelector(getLedgerTransportType); const transportStatus = useSelector(getLedgerTransportStatus); const environmentType = getEnvironmentType(); const environmentTypeIsFullScreen = environmentType === ENVIRONMENT_TYPE_FULLSCREEN; useEffect(() => { const initialConnectedDeviceCheck = async () => { if ( ledgerTransportType === LEDGER_TRANSPORT_TYPES.WEBHID && webHidConnectedStatus !== WEBHID_CONNECTED_STATUSES.CONNECTED ) { const devices = await window.navigator.hid.getDevices(); const webHidIsConnected = devices.some( (device) => device.vendorId === Number(LEDGER_USB_VENDOR_ID), ); dispatch( setLedgerWebHidConnectedStatus( webHidIsConnected ? WEBHID_CONNECTED_STATUSES.CONNECTED : WEBHID_CONNECTED_STATUSES.NOT_CONNECTED, ), ); } }; const determineTransportStatus = async () => { if ( ledgerTransportType === LEDGER_TRANSPORT_TYPES.WEBHID && webHidConnectedStatus === WEBHID_CONNECTED_STATUSES.CONNECTED && transportStatus === TRANSPORT_STATES.NONE ) { try { const transportedCreated = await attemptLedgerTransportCreation(); dispatch( setLedgerTransportStatus( transportedCreated ? TRANSPORT_STATES.VERIFIED : TRANSPORT_STATES.UNKNOWN_FAILURE, ), ); } catch (e) { if (e.message.match('Failed to open the device')) { dispatch( setLedgerTransportStatus(TRANSPORT_STATES.DEVICE_OPEN_FAILURE), ); } else if (e.message.match('the device is already open')) { dispatch(setLedgerTransportStatus(TRANSPORT_STATES.VERIFIED)); } else { dispatch( setLedgerTransportStatus(TRANSPORT_STATES.UNKNOWN_FAILURE), ); } } } }; determineTransportStatus(); initialConnectedDeviceCheck(); }, [dispatch, ledgerTransportType, webHidConnectedStatus, transportStatus]); useEffect(() => { return () => { dispatch(setLedgerTransportStatus(TRANSPORT_STATES.NONE)); }; }, [dispatch]); const usingLedgerLive = ledgerTransportType === LEDGER_TRANSPORT_TYPES.LIVE; const usingWebHID = ledgerTransportType === LEDGER_TRANSPORT_TYPES.WEBHID; const isFirefox = getPlatform() === PLATFORM_FIREFOX; return (
{renderInstructionStep(t('ledgerConnectionInstructionHeader'))} {renderInstructionStep( `- ${t('ledgerConnectionInstructionStepOne')}`, !isFirefox && usingLedgerLive, )} {renderInstructionStep( `- ${t('ledgerConnectionInstructionStepTwo')}`, !isFirefox && usingLedgerLive, )} {renderInstructionStep( `- ${t('ledgerConnectionInstructionStepThree')}`, )} {renderInstructionStep( `- ${t('ledgerConnectionInstructionStepFour')}`, showDataInstruction, )} {renderInstructionStep( , transportStatus === TRANSPORT_STATES.DEVICE_OPEN_FAILURE, )} {renderInstructionStep( , usingWebHID && webHidConnectedStatus === WEBHID_CONNECTED_STATUSES.NOT_CONNECTED, COLORS.SECONDARY1, )}
); } LedgerInstructionField.propTypes = { showDataInstruction: PropTypes.bool, };