Skip to content

Commit

Permalink
add serial for newly created wallets and more error handling improvem…
Browse files Browse the repository at this point in the history
…ents
  • Loading branch information
v-almonacid committed Sep 16, 2020
1 parent 0ed84f8 commit 20359b9
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 23 deletions.
23 changes: 9 additions & 14 deletions src/components/Ledger/LedgerConnect.js
Expand Up @@ -14,18 +14,16 @@ import {
import {injectIntl, defineMessages, intlShape} from 'react-intl'
import TransportBLE from '@ledgerhq/react-native-hw-transport-ble'
import TransportHID from '@v-almonacid/react-native-hid'
import {BleError} from 'react-native-ble-plx'
import {ErrorCodes} from '@cardano-foundation/ledgerjs-hw-app-cardano'

import {
BluetoothDisabledError,
GeneralConnectionError,
LedgerUserError,
RejectedByUserError,
} from '../../crypto/shelley/ledgerUtils'
import {Text, BulletPointItem, Button} from '../UiKit'
import DeviceItem from './DeviceItem'
import {ledgerMessages, confirmationMessages} from '../../i18n/global-messages'
import {Logger} from '../../utils/logging'
import LocalizableError from '../../i18n/LocalizableError'

import styles from './styles/LedgerConnect.style'
import bleImage from '../../assets/img/bluetooth.png'
Expand Down Expand Up @@ -216,7 +214,7 @@ class LedgerConnect extends React.Component<Props, State> {
await onConnectBLE(device.id.toString())
} catch (e) {
Logger.debug(e)
if (e.statusCode === ErrorCodes.ERR_REJECTED_BY_USER) {
if (e instanceof RejectedByUserError) {
this.reload()
return
}
Expand All @@ -236,7 +234,7 @@ class LedgerConnect extends React.Component<Props, State> {
await this.props.onConnectUSB(deviceObj)
} catch (e) {
Logger.debug(e)
if (e.statusCode === ErrorCodes.ERR_REJECTED_BY_USER) {
if (e instanceof RejectedByUserError) {
this.reload()
return
}
Expand Down Expand Up @@ -265,14 +263,11 @@ class LedgerConnect extends React.Component<Props, State> {
let msg, errMsg
if (error != null) {
msg = intl.formatMessage(messages.error)
if (error instanceof BluetoothDisabledError) {
errMsg = intl.formatMessage(ledgerMessages.bluetoothDisabledError)
} else if (
error instanceof BleError ||
error instanceof GeneralConnectionError ||
error instanceof LedgerUserError
) {
errMsg = intl.formatMessage(ledgerMessages.connectionError)
if (error instanceof LocalizableError) {
errMsg = intl.formatMessage({
id: error.id,
defaultMessage: error.defaultMessage,
})
} else {
errMsg = String(error.message)
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/WalletInit/ConnectNanoX/ConnectNanoXScreen.js
Expand Up @@ -62,14 +62,14 @@ const _navigateToSave = async (
})
} catch (e) {
if (e instanceof LocalizableError) {
await showErrorDialog(errorMessages.hwConnectionError, intl, {
await showErrorDialog(errorMessages.generalLocalizableError, intl, {
message: intl.formatMessage({
id: e.id,
defaultMessage: e.defaultMessage,
}),
})
} else {
Logger.error(e)
Logger.info(e)
await showErrorDialog(errorMessages.hwConnectionError, intl, {
message: String(e.message),
})
Expand Down
40 changes: 33 additions & 7 deletions src/crypto/shelley/ledgerUtils.js
Expand Up @@ -59,6 +59,7 @@ import type {
BIP32Path,
GetVersionResponse,
GetExtendedPublicKeyResponse,
GetSerialResponse,
InputTypeUTxO,
OutputTypeAddress,
OutputTypeAddressParams,
Expand Down Expand Up @@ -136,7 +137,7 @@ const _isConnectionError = (e: Error | TransportStatusError): boolean => {

// note: e.statusCode === ErrorCodes.ERR_CLA_NOT_SUPPORTED is more probably due
// to user not having ADA app opened instead of having the wrong app opened
const _isUserError = (e: any): boolean => {
const _isUserError = (e: Error | TransportStatusError): boolean => {
if (
e &&
e.statusCode != null &&
Expand All @@ -147,20 +148,34 @@ const _isUserError = (e: any): boolean => {
return false
}

const _isRejectedError = (e: Error | TransportStatusError): boolean => {
if (
e &&
e.statusCode != null &&
e.statusCode === ErrorCodes.ERR_REJECTED_BY_USER
) {
return true
}
return false
}

export const mapLedgerError = (
e: Error | TransportStatusError,
): Error | LocalizableError => {
if (_isUserError(e)) {
Logger.info('ledgerUtils::handleLedgerError: User-side error', e)
Logger.info('ledgerUtils::mapLedgerError: User-side error', e)
return new LedgerUserError()
} else if (_isRejectedError(e)) {
Logger.info('ledgerUtils::mapLedgerError: Rejected by user error', e)
return new RejectedByUserError()
} else if (_isConnectionError(e)) {
Logger.info('ledgerUtils::handleLedgerError: General/BleError', e)
Logger.info('ledgerUtils::mapLedgerError: General/BleError', e)
return new GeneralConnectionError()
} else if (e instanceof DeprecatedFirmwareError) {
Logger.info('ledgerUtils::handleLedgerError: deprecated firmware', e)
Logger.info('ledgerUtils::mapLedgerError: Deprecated firmware', e)
return e
} else {
Logger.error('ledgerUtils::handleLedgerError: Unexpected error', e)
Logger.error('ledgerUtils::mapLedgerError: Unexpected error', e)
return e
}
}
Expand All @@ -186,6 +201,7 @@ type LedgerConnectionResponse = {|
extendedPublicKeyResp: GetExtendedPublicKeyResponse,
deviceId: ?DeviceId,
deviceObj: ?DeviceObj,
serial: string,
|}

// Hardware wallet device Features object
Expand All @@ -195,6 +211,7 @@ export type HWFeatures = {|
model: string,
deviceId: ?DeviceId, // for establishing a connection through BLE
deviceObj: ?DeviceObj, // for establishing a connection through USB
serial?: string,
|}

export type HWDeviceInfo = {|
Expand Down Expand Up @@ -244,7 +261,7 @@ const makeCardanoAccountBIP44Path = (
) => [WALLET_TYPE_PURPOSE[walletType], COIN_TYPE, HARDENED + account]

const validateHWResponse = (resp: LedgerConnectionResponse): boolean => {
const {extendedPublicKeyResp, deviceId, deviceObj} = resp
const {extendedPublicKeyResp, deviceId, deviceObj, serial} = resp
if (deviceId == null && deviceObj == null) {
throw new Error(
'LedgerUtils::validateHWResponse: a non-null descriptor is required',
Expand All @@ -255,12 +272,17 @@ const validateHWResponse = (resp: LedgerConnectionResponse): boolean => {
'LedgerUtils::validateHWResponse: extended public key is undefined',
)
}
if (serial == null) {
throw new Error(
'LedgerUtils::validateHWResponse: device serial number is undefined',
)
}
return true
}

const normalizeHWResponse = (resp: LedgerConnectionResponse): HWDeviceInfo => {
validateHWResponse(resp)
const {extendedPublicKeyResp, deviceId, deviceObj} = resp
const {extendedPublicKeyResp, deviceId, deviceObj, serial} = resp
return {
bip44AccountPublic:
extendedPublicKeyResp.publicKeyHex + extendedPublicKeyResp.chainCodeHex,
Expand All @@ -269,6 +291,7 @@ const normalizeHWResponse = (resp: LedgerConnectionResponse): HWDeviceInfo => {
model: MODEL,
deviceId,
deviceObj,
serial,
},
}
}
Expand Down Expand Up @@ -357,10 +380,13 @@ export const getHWDeviceInfo = async (
Logger.debug('extended public key', extendedPublicKeyResp)
Logger.debug('transport.id', transport.id)

const serial: GetSerialResponse = await appAda.getSerial()

const hwDeviceInfo = normalizeHWResponse({
extendedPublicKeyResp,
deviceId,
deviceObj,
...serial,
})
Logger.info('ledgerUtils::getHWDeviceInfo: Ledger device OK')
Logger.info('hwDeviceInfo', hwDeviceInfo)
Expand Down
10 changes: 10 additions & 0 deletions src/i18n/global-messages.js
Expand Up @@ -370,6 +370,16 @@ export const errorMessages = {
'!!!Requested operation failed. This is all we know: {message}',
},
}),
generalLocalizableError: defineMessages({
title: {
id: 'global.actions.dialogs.generalLocalizableError.title',
defaultMessage: '!!!Operation failed',
},
message: {
id: 'global.actions.dialogs.generalLocalizableError.message',
defaultMessage: '!!!Requested operation failed: {message}',
},
}),
generalTxError: defineMessages({
title: {
id: 'global.actions.dialogs.generalTxError.title',
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/locales/en-US.json
Expand Up @@ -334,6 +334,8 @@
"global.actions.dialogs.enableSystemAuthFirst.title": "Lock screen disabled",
"global.actions.dialogs.generalError.message": "Requested operation failed. This is all we know: {message}",
"global.actions.dialogs.generalError.title": "Unexpected error",
"global.actions.dialogs.generalLocalizableError.message": "Requested operation failed: {message}",
"global.actions.dialogs.generalLocalizableError.title": "Operation failed",
"global.actions.dialogs.generalTxError.title": "Error sending transaction",
"global.actions.dialogs.generalTxError.message": "An error occurred while trying to send the transaction: {message}",
"global.actions.dialogs.hwConnectionError.message": "An error occurred while trying to connect with your hardware wallet. Please, make sure you are following the steps correctly. Restarting your hardware wallet may also fix the problem. Error: {message}",
Expand Down

0 comments on commit 20359b9

Please sign in to comment.