diff --git a/src/components/EnsureDeviceApp.js b/src/components/EnsureDeviceApp.js index 0c160e68..7685c77c 100644 --- a/src/components/EnsureDeviceApp.js +++ b/src/components/EnsureDeviceApp.js @@ -12,6 +12,7 @@ import getAddress from 'commands/getAddress' import { createCancelablePolling } from 'helpers/promise' import { standardDerivation } from 'helpers/derivations' import { isSegwitAccount } from 'helpers/bip32' +import { BtcUnmatchedApp } from 'helpers/getAddressForCurrency/btc' import DeviceInteraction from 'components/DeviceInteraction' import Text from 'components/base/Text' @@ -45,44 +46,31 @@ class EnsureDeviceApp extends Component<{ }) 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 }) + createCancelablePolling( + async () => { + const { account, currency: _currency } = this.props + const currency = account ? account.currency : _currency + invariant(currency, 'No currency given') + const address = await getAddressFromAccountOrCurrency(device, account, currency) + if (account) { + const { freshAddress } = account + if (account && freshAddress !== address) { + logger.warn({ freshAddress, address }) + throw new WrongDeviceForAccount(`WrongDeviceForAccount ${account.name}`, { + accountName: account.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 - }) + return address + }, + { + shouldThrow: (err: Error) => { + const isWrongApp = err instanceof BtcUnmatchedApp + const isWrongDevice = err instanceof WrongDeviceForAccount + return isWrongApp || isWrongDevice + }, + }, + ) renderOpenAppTitle = () => { const { account, currency } = this.props @@ -103,6 +91,7 @@ class EnsureDeviceApp extends Component<{ const Icon = cur ? getCryptoCurrencyIcon(cur) : null return ( , diff --git a/src/helpers/promise.js b/src/helpers/promise.js index 7142c7ff..2918c5f7 100644 --- a/src/helpers/promise.js +++ b/src/helpers/promise.js @@ -32,20 +32,29 @@ export function idleCallback() { return new Promise(resolve => window.requestIdleCallback(resolve)) } +type CancellablePollingOpts = { + pollingInterval?: number, + shouldThrow?: Error => boolean, +} + export function createCancelablePolling( job: any => Promise, - { pollingInterval = 500 }: { pollingInterval: number } = {}, + { pollingInterval = 500, shouldThrow }: CancellablePollingOpts = {}, ) { let isUnsub = false const unsubscribe = () => (isUnsub = true) const getUnsub = () => isUnsub - const promise = new Promise(resolve => { + const promise = new Promise((resolve, reject) => { async function poll() { try { const res = await job() if (getUnsub()) return resolve(res) } catch (err) { + if (shouldThrow && shouldThrow(err)) { + reject(err) + return + } await delay(pollingInterval) if (getUnsub()) return poll()