From c301757dad51b9074af20d3fee4924424105a076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Fri, 27 Jul 2018 16:30:31 +0200 Subject: [PATCH] Add a way to get app version and log it if there is an error --- src/commands/debugAppInfosForCurrency.js | 28 ++++++++++ src/commands/index.js | 2 + src/components/DebugAppInfosForCurrency.js | 51 +++++++++++++++++++ .../AddAccounts/steps/03-step-import.js | 4 +- .../Receive/steps/03-step-confirm-address.js | 2 + .../modals/Send/steps/04-step-confirmation.js | 4 +- src/helpers/debugAppInfosForCurrency/btc.js | 12 +++++ .../debugAppInfosForCurrency/ethereum.js | 10 ++++ src/helpers/debugAppInfosForCurrency/index.js | 29 +++++++++++ .../debugAppInfosForCurrency/ripple.js | 10 ++++ 10 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 src/commands/debugAppInfosForCurrency.js create mode 100644 src/components/DebugAppInfosForCurrency.js create mode 100644 src/helpers/debugAppInfosForCurrency/btc.js create mode 100644 src/helpers/debugAppInfosForCurrency/ethereum.js create mode 100644 src/helpers/debugAppInfosForCurrency/index.js create mode 100644 src/helpers/debugAppInfosForCurrency/ripple.js diff --git a/src/commands/debugAppInfosForCurrency.js b/src/commands/debugAppInfosForCurrency.js new file mode 100644 index 00000000..25239a1b --- /dev/null +++ b/src/commands/debugAppInfosForCurrency.js @@ -0,0 +1,28 @@ +// @flow + +import { getCryptoCurrencyById } from '@ledgerhq/live-common/lib/helpers/currencies' +import { createCommand, Command } from 'helpers/ipc' +import { fromPromise } from 'rxjs/observable/fromPromise' +import { withDevice } from 'helpers/deviceAccess' +import debugAppInfosForCurrency from 'helpers/debugAppInfosForCurrency' + +type Input = { + currencyId: string, + devicePath: string, +} + +type Result = { + version?: string, +} + +const cmd: Command = createCommand( + 'debugAppInfosForCurrency', + ({ currencyId, devicePath }) => + fromPromise( + withDevice(devicePath)(transport => + debugAppInfosForCurrency(transport, getCryptoCurrencyById(currencyId)), + ), + ), +) + +export default cmd diff --git a/src/commands/index.js b/src/commands/index.js index a03ac6ab..758e1416 100644 --- a/src/commands/index.js +++ b/src/commands/index.js @@ -3,6 +3,7 @@ import invariant from 'invariant' import type { Command } from 'helpers/ipc' +import debugAppInfosForCurrency from 'commands/debugAppInfosForCurrency' import getAddress from 'commands/getAddress' import getDeviceInfo from 'commands/getDeviceInfo' import getCurrentFirmware from 'commands/getCurrentFirmware' @@ -34,6 +35,7 @@ import testInterval from 'commands/testInterval' import uninstallApp from 'commands/uninstallApp' const all: Array> = [ + debugAppInfosForCurrency, getAddress, getDeviceInfo, getCurrentFirmware, diff --git a/src/components/DebugAppInfosForCurrency.js b/src/components/DebugAppInfosForCurrency.js new file mode 100644 index 00000000..df42ea9a --- /dev/null +++ b/src/components/DebugAppInfosForCurrency.js @@ -0,0 +1,51 @@ +// @flow +import { Component } from 'react' +import { connect } from 'react-redux' +import { createStructuredSelector } from 'reselect' +import { getCurrentDevice } from 'reducers/devices' +import debugAppInfosForCurrency from 'commands/debugAppInfosForCurrency' + +class DebugAppInfosForCurrency extends Component< + { + children?: (?string) => React$Node, + currencyId: string, + device: *, + }, + { + version: ?string, + }, +> { + state = { + version: null, + } + componentDidMount() { + const { device, currencyId } = this.props + if (device) { + debugAppInfosForCurrency + .send({ currencyId, devicePath: device.path }) + .toPromise() + .then( + ({ version }) => { + if (this.unmounted) return + this.setState({ version }) + }, + () => {}, + ) + } + } + componentWillUnmount() { + this.unmounted = true + } + unmounted = false + render() { + const { children } = this.props + const { version } = this.state + return children ? children(version) : null + } +} + +export default connect( + createStructuredSelector({ + device: getCurrentDevice, + }), +)(DebugAppInfosForCurrency) diff --git a/src/components/modals/AddAccounts/steps/03-step-import.js b/src/components/modals/AddAccounts/steps/03-step-import.js index 9e673098..fc5e59cf 100644 --- a/src/components/modals/AddAccounts/steps/03-step-import.js +++ b/src/components/modals/AddAccounts/steps/03-step-import.js @@ -22,6 +22,7 @@ import IconExclamationCircleThin from 'icons/ExclamationCircleThin' import TranslatedError from 'components/TranslatedError' import Spinner from 'components/base/Spinner' import Text from 'components/base/Text' +import DebugAppInfosForCurrency from 'components/DebugAppInfosForCurrency' import type { StepProps } from '../index' @@ -184,13 +185,14 @@ class StepImport extends PureComponent { } renderError() { - const { err } = this.props + const { err, currency } = this.props invariant(err, 'Trying to render inexisting error') return ( + {currency ? : null} <TranslatedError error={err} field="title" /> diff --git a/src/components/modals/Receive/steps/03-step-confirm-address.js b/src/components/modals/Receive/steps/03-step-confirm-address.js index 2c8b516e..51687ae7 100644 --- a/src/components/modals/Receive/steps/03-step-confirm-address.js +++ b/src/components/modals/Receive/steps/03-step-confirm-address.js @@ -12,6 +12,7 @@ import ExternalLinkButton from 'components/base/ExternalLinkButton' import RetryButton from 'components/base/RetryButton' import type { StepProps } from '../index' import TranslatedError from '../../../TranslatedError' +import DebugAppInfosForCurrency from '../../../DebugAppInfosForCurrency' export default class StepConfirmAddress extends PureComponent { render() { @@ -21,6 +22,7 @@ export default class StepConfirmAddress extends PureComponent { {isAddressVerified === false ? ( + {account ? : null} <TranslatedError error={verifyAddressError} /> diff --git a/src/components/modals/Send/steps/04-step-confirmation.js b/src/components/modals/Send/steps/04-step-confirmation.js index 800fb9fb..7abbea0d 100644 --- a/src/components/modals/Send/steps/04-step-confirmation.js +++ b/src/components/modals/Send/steps/04-step-confirmation.js @@ -13,6 +13,7 @@ import Button from 'components/base/Button' import Spinner from 'components/base/Spinner' import RetryButton from 'components/base/RetryButton' import TranslatedError from 'components/TranslatedError' +import DebugAppInfosForCurrency from 'components/DebugAppInfosForCurrency' import IconCheckCircle from 'icons/CheckCircle' import IconExclamationCircleThin from 'icons/ExclamationCircleThin' @@ -43,7 +44,7 @@ const Text = styled(Box).attrs({ text-align: center; ` -export default function StepConfirmation({ t, optimisticOperation, error }: StepProps<*>) { +export default function StepConfirmation({ account, t, optimisticOperation, error }: StepProps<*>) { const Icon = optimisticOperation ? IconCheckCircle : error ? IconExclamationCircleThin : Spinner const iconColor = optimisticOperation ? colors.positiveGreen @@ -53,6 +54,7 @@ export default function StepConfirmation({ t, optimisticOperation, error }: Step return ( <Container> + {error && account ? <DebugAppInfosForCurrency currencyId={account.currency.id} /> : null} <TrackPage category="Send Flow" name="Step 4" /> <span style={{ color: iconColor }}> <Icon size={43} /> diff --git a/src/helpers/debugAppInfosForCurrency/btc.js b/src/helpers/debugAppInfosForCurrency/btc.js new file mode 100644 index 00000000..b7375e7c --- /dev/null +++ b/src/helpers/debugAppInfosForCurrency/btc.js @@ -0,0 +1,12 @@ +// @flow + +import type Transport from '@ledgerhq/hw-transport' +import { createCustomErrorClass } from '../errors' + +export const BtcUnmatchedApp = createCustomErrorClass('BtcUnmatchedApp') + +export default async (transport: Transport<*>) => { + const r = await transport.send(0xe0, 0xc4, 0, 0) + const version = `${r[2]}.${r[3]}.${r[4]}` + return { version } +} diff --git a/src/helpers/debugAppInfosForCurrency/ethereum.js b/src/helpers/debugAppInfosForCurrency/ethereum.js new file mode 100644 index 00000000..ce090c76 --- /dev/null +++ b/src/helpers/debugAppInfosForCurrency/ethereum.js @@ -0,0 +1,10 @@ +// @flow + +import Eth from '@ledgerhq/hw-app-eth' +import type Transport from '@ledgerhq/hw-transport' + +export default async (transport: Transport<*>) => { + const eth = new Eth(transport) + const { version } = await eth.getAppConfiguration() + return { version } +} diff --git a/src/helpers/debugAppInfosForCurrency/index.js b/src/helpers/debugAppInfosForCurrency/index.js new file mode 100644 index 00000000..95aeead3 --- /dev/null +++ b/src/helpers/debugAppInfosForCurrency/index.js @@ -0,0 +1,29 @@ +// @flow + +import type { CryptoCurrency } from '@ledgerhq/live-common/lib/types' +import invariant from 'invariant' +import type Transport from '@ledgerhq/hw-transport' +import bitcoin from './btc' +import ethereum from './ethereum' +import ripple from './ripple' + +type Resolver = ( + transport: Transport<*>, + currency: CryptoCurrency, +) => Promise<{ + version?: string, +}> + +const perFamily: { [_: string]: * } = { + bitcoin, + ethereum, + ripple, +} + +const proxy: Resolver = (transport, currency) => { + const getAddress = perFamily[currency.family] + invariant(getAddress, `getAddress not implemented for ${currency.id}`) + return getAddress(transport) +} + +export default proxy diff --git a/src/helpers/debugAppInfosForCurrency/ripple.js b/src/helpers/debugAppInfosForCurrency/ripple.js new file mode 100644 index 00000000..dcabc884 --- /dev/null +++ b/src/helpers/debugAppInfosForCurrency/ripple.js @@ -0,0 +1,10 @@ +// @flow + +import Xrp from '@ledgerhq/hw-app-xrp' +import type Transport from '@ledgerhq/hw-transport' + +export default async (transport: Transport<*>) => { + const xrp = new Xrp(transport) + const { version } = await xrp.getAppConfiguration() + return { version } +}