meriadec
7 years ago
1 changed files with 118 additions and 0 deletions
@ -0,0 +1,118 @@ |
|||
// @flow
|
|||
|
|||
import React, { Component } from 'react' |
|||
import invariant from 'invariant' |
|||
import { connect } from 'react-redux' |
|||
import type { Account, CryptoCurrency } from '@ledgerhq/live-common/lib/types' |
|||
import { getCryptoCurrencyIcon } from '@ledgerhq/live-common/lib/react' |
|||
|
|||
import logger from 'logger' |
|||
import { createCancelablePolling } from 'helpers/promise' |
|||
import { standardDerivation } from 'helpers/derivations' |
|||
import { isSegwitAccount } from 'helpers/bip32' |
|||
import DeviceInteraction from 'components/DeviceInteraction' |
|||
import getAddress from 'commands/getAddress' |
|||
import IconUsb from 'icons/Usb' |
|||
|
|||
import type { Device } from 'types/common' |
|||
|
|||
import { createCustomErrorClass } from 'helpers/errors' |
|||
import { getCurrentDevice } from 'reducers/devices' |
|||
|
|||
export const WrongAppOpened = createCustomErrorClass('WrongAppOpened') |
|||
export const WrongDeviceForAccount = createCustomErrorClass('WrongDeviceForAccount') |
|||
|
|||
const usbIcon = <IconUsb size={36} /> |
|||
|
|||
const mapStateToProps = state => ({ |
|||
device: getCurrentDevice(state), |
|||
}) |
|||
|
|||
class EnsureDeviceAppInteraction extends Component<{ |
|||
device: ?Device, |
|||
account?: ?Account, |
|||
currency?: ?CryptoCurrency, |
|||
}> { |
|||
connectInteractionHandler = () => |
|||
createCancelablePolling(() => { |
|||
if (!this.props.device) return Promise.reject() |
|||
return Promise.resolve(this.props.device) |
|||
}) |
|||
|
|||
openAppInteractionHandler = ({ device }) => |
|||
createCancelablePolling(async () => { |
|||
const { account, currency } = this.props |
|||
const cur = account ? account.currency : currency |
|||
invariant(cur, 'No currency given') |
|||
const { address } = await getAddress |
|||
.send({ |
|||
devicePath: device.path, |
|||
currencyId: cur.id, |
|||
path: account |
|||
? account.freshAddressPath |
|||
: standardDerivation({ currency: cur, segwit: false, x: 0 }), |
|||
segwit: account ? isSegwitAccount(account) : false, |
|||
}) |
|||
.toPromise() |
|||
.catch(e => { |
|||
if ( |
|||
e && |
|||
(e.name === 'TransportStatusError' || |
|||
// we don't want these error to appear (caused by usb disconnect..)
|
|||
e.message === 'could not read from HID device' || |
|||
e.message === 'Cannot write to HID device') |
|||
) { |
|||
throw new WrongAppOpened(`WrongAppOpened ${cur.id}`, { currencyName: cur.name }) |
|||
} |
|||
throw e |
|||
}) |
|||
|
|||
if (account) { |
|||
const { freshAddress } = account |
|||
if (account && freshAddress !== address) { |
|||
logger.warn({ freshAddress, address }) |
|||
throw new WrongDeviceForAccount(`WrongDeviceForAccount ${account.name}`, { |
|||
accountName: account.name, |
|||
}) |
|||
} |
|||
} |
|||
return address |
|||
}) |
|||
|
|||
renderOpenAppTitle = ({ device }) => { |
|||
const { account, currency } = this.props |
|||
const cur = account ? account.currency : currency |
|||
invariant(cur, 'No currency given') |
|||
return `Open the ${cur.name} app on your ${device ? `${device.product} ` : 'device'}` |
|||
} |
|||
|
|||
render() { |
|||
const { account, currency, ...props } = this.props |
|||
const cur = account ? account.currency : currency |
|||
const Icon = cur ? getCryptoCurrencyIcon(cur) : null |
|||
return ( |
|||
<DeviceInteraction |
|||
steps={[ |
|||
{ |
|||
id: 'device', |
|||
title: 'Connect your device', |
|||
icon: usbIcon, |
|||
desc: 'Because it is required', |
|||
minMs: 300, |
|||
run: this.connectInteractionHandler, |
|||
}, |
|||
{ |
|||
id: 'address', |
|||
title: this.renderOpenAppTitle, |
|||
desc: 'To be able to retriev your Bitcoins', |
|||
icon: Icon ? <Icon size={24} /> : null, |
|||
run: this.openAppInteractionHandler, |
|||
}, |
|||
]} |
|||
{...props} |
|||
/> |
|||
) |
|||
} |
|||
} |
|||
|
|||
export default connect(mapStateToProps)(EnsureDeviceAppInteraction) |
Loading…
Reference in new issue