Browse Source
Merge pull request #1307 from gre/debug-app-version-on-error
Add a way to get app version and log it if there is an error
master
Gaëtan Renaudeau
7 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with
150 additions and
2 deletions
-
src/commands/debugAppInfosForCurrency.js
-
src/commands/index.js
-
src/components/DebugAppInfosForCurrency.js
-
src/components/modals/AddAccounts/steps/03-step-import.js
-
src/components/modals/Receive/steps/03-step-confirm-address.js
-
src/components/modals/Send/steps/04-step-confirmation.js
-
src/helpers/debugAppInfosForCurrency/btc.js
-
src/helpers/debugAppInfosForCurrency/ethereum.js
-
src/helpers/debugAppInfosForCurrency/index.js
-
src/helpers/debugAppInfosForCurrency/ripple.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<Input, Result> = createCommand( |
|
|
|
'debugAppInfosForCurrency', |
|
|
|
({ currencyId, devicePath }) => |
|
|
|
fromPromise( |
|
|
|
withDevice(devicePath)(transport => |
|
|
|
debugAppInfosForCurrency(transport, getCryptoCurrencyById(currencyId)), |
|
|
|
), |
|
|
|
), |
|
|
|
) |
|
|
|
|
|
|
|
export default cmd |
|
|
@ -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<Command<any, any>> = [ |
|
|
|
debugAppInfosForCurrency, |
|
|
|
getAddress, |
|
|
|
getDeviceInfo, |
|
|
|
getCurrentFirmware, |
|
|
|
|
|
@ -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) |
|
|
@ -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<StepProps> { |
|
|
|
} |
|
|
|
|
|
|
|
renderError() { |
|
|
|
const { err } = this.props |
|
|
|
const { err, currency } = this.props |
|
|
|
invariant(err, 'Trying to render inexisting error') |
|
|
|
return ( |
|
|
|
<Box style={{ height: 200 }} px={5} justify="center"> |
|
|
|
<Box color="alertRed" align="center"> |
|
|
|
<IconExclamationCircleThin size={43} /> |
|
|
|
</Box> |
|
|
|
{currency ? <DebugAppInfosForCurrency currencyId={currency.id} /> : null} |
|
|
|
<Title> |
|
|
|
<TranslatedError error={err} field="title" /> |
|
|
|
</Title> |
|
|
|
|
|
@ -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<StepProps> { |
|
|
|
render() { |
|
|
@ -21,6 +22,7 @@ export default class StepConfirmAddress extends PureComponent<StepProps> { |
|
|
|
<TrackPage category="Receive Flow" name="Step 3" /> |
|
|
|
{isAddressVerified === false ? ( |
|
|
|
<Fragment> |
|
|
|
{account ? <DebugAppInfosForCurrency currencyId={account.currency.id} /> : null} |
|
|
|
<TrackPage category="Receive Flow" name="Step 3 Address Not Verified Error" /> |
|
|
|
<Title> |
|
|
|
<TranslatedError error={verifyAddressError} /> |
|
|
|
|
|
@ -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} /> |
|
|
|
|
|
@ -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 } |
|
|
|
} |
|
|
@ -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 } |
|
|
|
} |
|
|
@ -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 |
|
|
@ -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 } |
|
|
|
} |