From d2b76a4acbaffbb855f9fa6d3cc15e01d01eb9e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Fri, 14 Dec 2018 18:18:04 +0100 Subject: [PATCH 01/26] Use deviceAccess from incoming live-common --- package.json | 12 +-- src/commands/debugAppInfosForCurrency.js | 10 +-- src/commands/getAddress.js | 34 +++---- src/commands/getDeviceInfo.js | 6 +- src/commands/getIsGenuine.js | 6 +- src/commands/getMemInfo.js | 6 +- src/commands/installApp.js | 6 +- src/commands/installFinalFirmware.js | 6 +- src/commands/installMcu.js | 6 +- src/commands/installOsuFirmware.js | 8 +- src/commands/isDashboardOpen.js | 6 +- src/commands/libcoreSignAndBroadcast.js | 40 +++++---- src/commands/signTransaction.js | 10 +-- src/commands/testApdu.js | 15 ++-- src/commands/uninstallApp.js | 6 +- src/helpers/deviceAccess.js | 64 ------------- src/helpers/libcore.js | 15 ++-- src/helpers/live-common-setup-internal-hw.js | 50 +++++++++++ src/helpers/live-common-setup.js | 8 ++ src/internals/index.js | 7 +- src/main/app.js | 2 + src/renderer/init.js | 2 + yarn.lock | 95 ++++++++++---------- 23 files changed, 214 insertions(+), 206 deletions(-) delete mode 100644 src/helpers/deviceAccess.js create mode 100644 src/helpers/live-common-setup-internal-hw.js create mode 100644 src/helpers/live-common-setup.js diff --git a/package.json b/package.json index 07c4767d..6600f5b0 100644 --- a/package.json +++ b/package.json @@ -35,13 +35,13 @@ } }, "dependencies": { - "@ledgerhq/hw-app-btc": "^v4.30.0", - "@ledgerhq/hw-app-eth": "^4.24.0", - "@ledgerhq/hw-app-xrp": "^4.25.0", - "@ledgerhq/hw-transport": "^4.24.0", - "@ledgerhq/hw-transport-node-hid": "4.24.0", + "@ledgerhq/hw-app-btc": "^4.32.0", + "@ledgerhq/hw-app-eth": "^4.32.0", + "@ledgerhq/hw-app-xrp": "^4.32.0", + "@ledgerhq/hw-transport": "^4.32.0", + "@ledgerhq/hw-transport-node-hid": "^4.32.0", "@ledgerhq/ledger-core": "2.0.0-rc.12", - "@ledgerhq/live-common": "4.6.0", + "@ledgerhq/live-common": "4.8.0-beta.3", "animated": "^0.2.2", "async": "^2.6.1", "axios": "^0.18.0", diff --git a/src/commands/debugAppInfosForCurrency.js b/src/commands/debugAppInfosForCurrency.js index 1e13096a..8ba70516 100644 --- a/src/commands/debugAppInfosForCurrency.js +++ b/src/commands/debugAppInfosForCurrency.js @@ -2,8 +2,8 @@ import { getCryptoCurrencyById } from '@ledgerhq/live-common/lib/currencies' import { createCommand, Command } from 'helpers/ipc' -import { fromPromise } from 'rxjs/observable/fromPromise' -import { withDevice } from 'helpers/deviceAccess' +import { from } from 'rxjs' +import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' import debugAppInfosForCurrency from 'helpers/debugAppInfosForCurrency' type Input = { @@ -18,10 +18,8 @@ type Result = { const cmd: Command = createCommand( 'debugAppInfosForCurrency', ({ currencyId, devicePath }) => - fromPromise( - withDevice(devicePath)(transport => - debugAppInfosForCurrency(transport, getCryptoCurrencyById(currencyId)), - ), + withDevice(devicePath)(transport => + from(debugAppInfosForCurrency(transport, getCryptoCurrencyById(currencyId))), ), ) diff --git a/src/commands/getAddress.js b/src/commands/getAddress.js index 801f33e7..1c7109ee 100644 --- a/src/commands/getAddress.js +++ b/src/commands/getAddress.js @@ -2,8 +2,8 @@ import { getCryptoCurrencyById } from '@ledgerhq/live-common/lib/currencies' import { createCommand, Command } from 'helpers/ipc' -import { fromPromise } from 'rxjs/observable/fromPromise' -import { withDevice } from 'helpers/deviceAccess' +import { from } from 'rxjs' +import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' import getAddressForCurrency from 'helpers/getAddressForCurrency' import { DeviceAppVerifyNotSupported, UserRefusedAddress } from 'config/errors' @@ -25,20 +25,22 @@ type Result = { const cmd: Command = createCommand( 'getAddress', ({ currencyId, devicePath, path, ...options }) => - fromPromise( - withDevice(devicePath)(transport => - getAddressForCurrency(transport, getCryptoCurrencyById(currencyId), path, options), - ).catch(e => { - if (e && e.name === 'TransportStatusError') { - if (e.statusCode === 0x6b00 && options.verify) { - throw new DeviceAppVerifyNotSupported() - } - if (e.statusCode === 0x6985) { - throw new UserRefusedAddress() - } - } - throw e - }), + withDevice(devicePath)(transport => + from( + getAddressForCurrency(transport, getCryptoCurrencyById(currencyId), path, options).catch( + e => { + if (e && e.name === 'TransportStatusError') { + if (e.statusCode === 0x6b00 && options.verify) { + throw new DeviceAppVerifyNotSupported() + } + if (e.statusCode === 0x6985) { + throw new UserRefusedAddress() + } + } + throw e + }, + ), + ), ), ) diff --git a/src/commands/getDeviceInfo.js b/src/commands/getDeviceInfo.js index 9cbbfae1..22135389 100644 --- a/src/commands/getDeviceInfo.js +++ b/src/commands/getDeviceInfo.js @@ -1,8 +1,8 @@ // @flow import { createCommand, Command } from 'helpers/ipc' -import { fromPromise } from 'rxjs/observable/fromPromise' -import { withDevice } from 'helpers/deviceAccess' +import { from } from 'rxjs' +import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' import getDeviceInfo from 'helpers/devices/getDeviceInfo' import type { DeviceInfo } from 'helpers/types' @@ -14,7 +14,7 @@ type Input = { type Result = DeviceInfo const cmd: Command = createCommand('getDeviceInfo', ({ devicePath }) => - fromPromise(withDevice(devicePath)(transport => getDeviceInfo(transport))), + withDevice(devicePath)(transport => from(getDeviceInfo(transport))), ) export default cmd diff --git a/src/commands/getIsGenuine.js b/src/commands/getIsGenuine.js index e3e163b8..406d7cac 100644 --- a/src/commands/getIsGenuine.js +++ b/src/commands/getIsGenuine.js @@ -1,11 +1,11 @@ // @flow import { createCommand, Command } from 'helpers/ipc' -import { fromPromise } from 'rxjs/observable/fromPromise' +import { from } from 'rxjs' import type { DeviceInfo } from 'helpers/types' import getIsGenuine from 'helpers/devices/getIsGenuine' -import { withDevice } from 'helpers/deviceAccess' +import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' type Input = { devicePath: string, @@ -14,7 +14,7 @@ type Input = { type Result = string const cmd: Command = createCommand('getIsGenuine', ({ devicePath, deviceInfo }) => - fromPromise(withDevice(devicePath)(transport => getIsGenuine(transport, deviceInfo))), + withDevice(devicePath)(transport => from(getIsGenuine(transport, deviceInfo))), ) export default cmd diff --git a/src/commands/getMemInfo.js b/src/commands/getMemInfo.js index 848fa032..acaf532f 100644 --- a/src/commands/getMemInfo.js +++ b/src/commands/getMemInfo.js @@ -1,9 +1,9 @@ // @flow import { createCommand, Command } from 'helpers/ipc' -import { fromPromise } from 'rxjs/observable/fromPromise' +import { from } from 'rxjs' -import { withDevice } from 'helpers/deviceAccess' +import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' import getMemInfo from 'helpers/devices/getMemInfo' type Input = { @@ -13,7 +13,7 @@ type Input = { type Result = * const cmd: Command = createCommand('getMemInfo', ({ devicePath }) => - fromPromise(withDevice(devicePath)(transport => getMemInfo(transport))), + withDevice(devicePath)(transport => from(getMemInfo(transport))), ) export default cmd diff --git a/src/commands/installApp.js b/src/commands/installApp.js index cd1a2e81..2fd3c1c4 100644 --- a/src/commands/installApp.js +++ b/src/commands/installApp.js @@ -1,9 +1,9 @@ // @flow import { createCommand, Command } from 'helpers/ipc' -import { fromPromise } from 'rxjs/observable/fromPromise' +import { from } from 'rxjs' -import { withDevice } from 'helpers/deviceAccess' +import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' import installApp from 'helpers/apps/installApp' import type { ApplicationVersion } from 'helpers/types' @@ -19,7 +19,7 @@ type Result = void const cmd: Command = createCommand( 'installApp', ({ devicePath, targetId, ...app }) => - fromPromise(withDevice(devicePath)(transport => installApp(transport, targetId, app))), + withDevice(devicePath)(transport => from(installApp(transport, targetId, app))), ) export default cmd diff --git a/src/commands/installFinalFirmware.js b/src/commands/installFinalFirmware.js index 42671301..bf56eeb3 100644 --- a/src/commands/installFinalFirmware.js +++ b/src/commands/installFinalFirmware.js @@ -1,8 +1,8 @@ // @flow import { createCommand, Command } from 'helpers/ipc' -import { fromPromise } from 'rxjs/observable/fromPromise' -import { withDevice } from 'helpers/deviceAccess' +import { from } from 'rxjs' +import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' import installFinalFirmware from 'helpers/firmware/installFinalFirmware' @@ -15,7 +15,7 @@ type Result = { } const cmd: Command = createCommand('installFinalFirmware', ({ devicePath }) => - fromPromise(withDevice(devicePath)(transport => installFinalFirmware(transport))), + withDevice(devicePath)(transport => from(installFinalFirmware(transport))), ) export default cmd diff --git a/src/commands/installMcu.js b/src/commands/installMcu.js index 660bd546..1301a68b 100644 --- a/src/commands/installMcu.js +++ b/src/commands/installMcu.js @@ -1,9 +1,9 @@ // @flow import { createCommand, Command } from 'helpers/ipc' -import { fromPromise } from 'rxjs/observable/fromPromise' +import { from } from 'rxjs' -import { withDevice } from 'helpers/deviceAccess' +import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' import installMcu from 'helpers/firmware/installMcu' type Input = { @@ -13,7 +13,7 @@ type Input = { type Result = void const cmd: Command = createCommand('installMcu', ({ devicePath }) => - fromPromise(withDevice(devicePath)(transport => installMcu(transport))), + withDevice(devicePath)(transport => from(installMcu(transport))), ) export default cmd diff --git a/src/commands/installOsuFirmware.js b/src/commands/installOsuFirmware.js index 83b29a39..e306eaa4 100644 --- a/src/commands/installOsuFirmware.js +++ b/src/commands/installOsuFirmware.js @@ -1,9 +1,9 @@ // @flow import { createCommand, Command } from 'helpers/ipc' -import { fromPromise } from 'rxjs/observable/fromPromise' +import { from } from 'rxjs' -import { withDevice } from 'helpers/deviceAccess' +import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' import installOsuFirmware from 'helpers/firmware/installOsuFirmware' import type { Firmware } from 'components/modals/UpdateFirmware' @@ -19,9 +19,7 @@ type Result = { success: boolean } const cmd: Command = createCommand( 'installOsuFirmware', ({ devicePath, firmware, targetId }) => - fromPromise( - withDevice(devicePath)(transport => installOsuFirmware(transport, targetId, firmware)), - ), + withDevice(devicePath)(transport => from(installOsuFirmware(transport, targetId, firmware))), ) export default cmd diff --git a/src/commands/isDashboardOpen.js b/src/commands/isDashboardOpen.js index 2a33ff22..ce9c48db 100644 --- a/src/commands/isDashboardOpen.js +++ b/src/commands/isDashboardOpen.js @@ -1,8 +1,8 @@ // @flow import { createCommand, Command } from 'helpers/ipc' -import { fromPromise } from 'rxjs/observable/fromPromise' -import { withDevice } from 'helpers/deviceAccess' +import { from } from 'rxjs' +import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' import isDashboardOpen from '../helpers/devices/isDashboardOpen' @@ -13,7 +13,7 @@ type Input = { type Result = boolean const cmd: Command = createCommand('isDashboardOpen', ({ devicePath }) => - fromPromise(withDevice(devicePath)(transport => isDashboardOpen(transport))), + withDevice(devicePath)(transport => from(isDashboardOpen(transport))), ) export default cmd diff --git a/src/commands/libcoreSignAndBroadcast.js b/src/commands/libcoreSignAndBroadcast.js index c9413694..f2990c34 100644 --- a/src/commands/libcoreSignAndBroadcast.js +++ b/src/commands/libcoreSignAndBroadcast.js @@ -4,7 +4,7 @@ import logger from 'logger' import { BigNumber } from 'bignumber.js' import { StatusCodes } from '@ledgerhq/hw-transport' import Btc from '@ledgerhq/hw-app-btc' -import { Observable } from 'rxjs' +import { Observable, from } from 'rxjs' import { isSegwitDerivationMode } from '@ledgerhq/live-common/lib/derivation' import { getCryptoCurrencyById } from '@ledgerhq/live-common/lib/currencies' import type { OperationRaw, DerivationMode, CryptoCurrency } from '@ledgerhq/live-common/lib/types' @@ -18,7 +18,7 @@ import { UpdateYourApp } from 'config/errors' import withLibcore from 'helpers/withLibcore' import { createCommand, Command } from 'helpers/ipc' -import { withDevice } from 'helpers/deviceAccess' +import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' type BitcoinLikeTransaction = { amount: string, @@ -245,22 +245,26 @@ export async function doSignAndBroadcast({ const hasTimestamp = !!njsWalletCurrency.bitcoinLikeNetworkParameters.UsesTimestampedTransaction // TODO: const timestampDelay = njsWalletCurrency.bitcoinLikeNetworkParameters.TimestampDelay - const signedTransaction = await withDevice(deviceId)(async transport => - signTransaction({ - hwApp: new Btc(transport), - currency, - blockHeight, - transaction: builded, - sigHashType: parseInt(sigHashType, 16), - hasTimestamp, - derivationMode, - }), - ).catch(e => { - if (e && e.statusCode === StatusCodes.INCORRECT_P1_P2) { - throw new UpdateYourApp(`UpdateYourApp ${currency.id}`, currency) - } - throw e - }) + const signedTransaction = await withDevice(deviceId)(transport => + from( + signTransaction({ + hwApp: new Btc(transport), + currency, + blockHeight, + transaction: builded, + sigHashType: parseInt(sigHashType, 16), + hasTimestamp, + derivationMode, + }), + ), + ) + .toPromise() + .catch(e => { + if (e && e.statusCode === StatusCodes.INCORRECT_P1_P2) { + throw new UpdateYourApp(`UpdateYourApp ${currency.id}`, currency) + } + throw e + }) if (!signedTransaction || isCancelled() || !njsAccount) return onSigned() diff --git a/src/commands/signTransaction.js b/src/commands/signTransaction.js index 7ffea26b..56ffebdc 100644 --- a/src/commands/signTransaction.js +++ b/src/commands/signTransaction.js @@ -1,8 +1,8 @@ // @flow import { createCommand, Command } from 'helpers/ipc' -import { fromPromise } from 'rxjs/observable/fromPromise' -import { withDevice } from 'helpers/deviceAccess' +import { from } from 'rxjs' +import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' import signTransactionForCurrency from 'helpers/signTransactionForCurrency' type Input = { @@ -17,10 +17,8 @@ type Result = string const cmd: Command = createCommand( 'signTransaction', ({ currencyId, devicePath, path, transaction }) => - fromPromise( - withDevice(devicePath)(transport => - signTransactionForCurrency(currencyId)(transport, currencyId, path, transaction), - ), + withDevice(devicePath)(transport => + from(signTransactionForCurrency(currencyId)(transport, currencyId, path, transaction)), ), ) diff --git a/src/commands/testApdu.js b/src/commands/testApdu.js index 079cbcc1..652aaba1 100644 --- a/src/commands/testApdu.js +++ b/src/commands/testApdu.js @@ -3,8 +3,8 @@ // This is a test example for dev testing purpose. import { createCommand, Command } from 'helpers/ipc' -import { fromPromise } from 'rxjs/observable/fromPromise' -import { withDevice } from 'helpers/deviceAccess' +import { from } from 'rxjs' +import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' type Input = { devicePath: string, @@ -15,11 +15,12 @@ type Result = { } const cmd: Command = createCommand('testApdu', ({ apduHex, devicePath }) => - fromPromise( - withDevice(devicePath)(async transport => { - const res = await transport.exchange(Buffer.from(apduHex, 'hex')) - return { responseHex: res.toString('hex') } - }), + withDevice(devicePath)(transport => + from( + transport + .exchange(Buffer.from(apduHex, 'hex')) + .then(res => ({ responseHex: res.toString('hex') })), + ), ), ) diff --git a/src/commands/uninstallApp.js b/src/commands/uninstallApp.js index 9b6df8a2..b0b581b8 100644 --- a/src/commands/uninstallApp.js +++ b/src/commands/uninstallApp.js @@ -1,8 +1,8 @@ // @flow import { createCommand, Command } from 'helpers/ipc' -import { fromPromise } from 'rxjs/observable/fromPromise' -import { withDevice } from 'helpers/deviceAccess' +import { from } from 'rxjs' +import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' import uninstallApp from 'helpers/apps/uninstallApp' @@ -19,7 +19,7 @@ type Result = void const cmd: Command = createCommand( 'uninstallApp', ({ devicePath, targetId, ...app }) => - fromPromise(withDevice(devicePath)(transport => uninstallApp(transport, targetId, app))), + withDevice(devicePath)(transport => from(uninstallApp(transport, targetId, app))), ) export default cmd diff --git a/src/helpers/deviceAccess.js b/src/helpers/deviceAccess.js deleted file mode 100644 index 86b3e738..00000000 --- a/src/helpers/deviceAccess.js +++ /dev/null @@ -1,64 +0,0 @@ -// @flow -import logger from 'logger' -import throttle from 'lodash/throttle' -import type Transport from '@ledgerhq/hw-transport' -import TransportNodeHid from '@ledgerhq/hw-transport-node-hid' -import { DisconnectedDevice, CantOpenDevice } from 'config/errors' -import { retry } from './promise' - -// all open to device must use openDevice so we can prevent race conditions -// and guarantee we do one device access at a time. It also will handle the .close() -// NOTE optim: in the future we can debounce the close & reuse the same transport instance. - -type WithDevice = (devicePath: string) => (job: (Transport<*>) => Promise<*>) => Promise - -const mapError = e => { - if (e && e.message && e.message.indexOf('cannot open device with path') >= 0) { - throw new CantOpenDevice(e.message) - } - if (e && e.message && e.message.indexOf('HID') >= 0) { - throw new DisconnectedDevice(e.message) - } - throw e -} - -let queue = Promise.resolve() - -let busy = false - -TransportNodeHid.setListenDevicesPollingSkip(() => busy) - -const refreshBusyUIState = throttle(() => { - if (process.env.CLI) return - process.send({ - type: 'setDeviceBusy', - busy, - }) -}, 100) - -export const withDevice: WithDevice = devicePath => job => { - const p = queue.then(async () => { - busy = true - refreshBusyUIState() - try { - // $FlowFixMe not sure what's wrong - const t = await retry(() => TransportNodeHid.open(devicePath), { maxRetry: 2 }).catch( - mapError, - ) - t.setDebugMode(logger.apdu) - try { - const res = await job(t).catch(mapError) - return res - } finally { - await t.close() - } - } finally { - busy = false - refreshBusyUIState() - } - }) - - queue = p.catch(() => null) - - return p -} diff --git a/src/helpers/libcore.js b/src/helpers/libcore.js index b12709bd..0c486d1b 100644 --- a/src/helpers/libcore.js +++ b/src/helpers/libcore.js @@ -5,7 +5,8 @@ import logger from 'logger' import { BigNumber } from 'bignumber.js' import Btc from '@ledgerhq/hw-app-btc' -import { withDevice } from 'helpers/deviceAccess' +import { from } from 'rxjs' +import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' import { getDerivationModesForCurrency, getDerivationScheme, @@ -99,9 +100,9 @@ async function scanAccountsOnDeviceBySegwit({ const { coinType } = unsplitFork ? getCryptoCurrencyById(unsplitFork) : currency const path = `${isSegwit ? '49' : '44'}'/${coinType}'` - const { publicKey: seedIdentifier } = await withDevice(devicePath)(async transport => - new Btc(transport).getWalletPublicKey(path, false, isSegwit), - ) + const { publicKey: seedIdentifier } = await withDevice(devicePath)(transport => + from(new Btc(transport).getWalletPublicKey(path, false, isSegwit)), + ).toPromise() if (isUnsubscribed()) return [] @@ -141,9 +142,9 @@ const createAccount = async (wallet, devicePath) => { await accountCreationInfos.derivations.reduce( (promise, derivation) => promise.then(async () => { - const { publicKey, chainCode } = await withDevice(devicePath)(async transport => - new Btc(transport).getWalletPublicKey(derivation), - ) + const { publicKey, chainCode } = await withDevice(devicePath)(transport => + from(new Btc(transport).getWalletPublicKey(derivation)), + ).toPromise() accountCreationInfos.publicKeys.push(hexToBytes(publicKey)) accountCreationInfos.chainCodes.push(hexToBytes(chainCode)) }), diff --git a/src/helpers/live-common-setup-internal-hw.js b/src/helpers/live-common-setup-internal-hw.js new file mode 100644 index 00000000..7c04155e --- /dev/null +++ b/src/helpers/live-common-setup-internal-hw.js @@ -0,0 +1,50 @@ +// @flow +import logger from 'logger' +import { throwError } from 'rxjs' +import { registerTransportModule } from '@ledgerhq/live-common/lib/hw' +import { addAccessHook, setErrorRemapping } from '@ledgerhq/live-common/lib/hw/deviceAccess' +import throttle from 'lodash/throttle' +import type Transport from '@ledgerhq/hw-transport' +import TransportNodeHid from '@ledgerhq/hw-transport-node-hid' +import { DisconnectedDevice, CantOpenDevice } from 'config/errors' +import { retry } from './promise' + +let busy = false + +TransportNodeHid.setListenDevicesPollingSkip(() => busy) + +const refreshBusyUIState = throttle(() => { + if (process.env.CLI) return + process.send({ + type: 'setDeviceBusy', + busy, + }) +}, 100) + +addAccessHook(() => { + busy = true + refreshBusyUIState() + return () => { + busy = false + refreshBusyUIState() + } +}) + +setErrorRemapping(e => { + // NB ideally we should solve it in ledgerjs + if (e && e.message && e.message.indexOf('HID') >= 0) { + return throwError(new DisconnectedDevice(e.message)) + } + return throwError(e) +}) + +registerTransportModule({ + id: 'hid', + open: async devicePath => { + // $FlowFixMe + const t = await retry(() => TransportNodeHid.open(devicePath), { maxRetry: 2 }) + t.setDebugMode(logger.apdu) + return t + }, + disconnect: () => Promise.resolve(), +}) diff --git a/src/helpers/live-common-setup.js b/src/helpers/live-common-setup.js new file mode 100644 index 00000000..b740c0a0 --- /dev/null +++ b/src/helpers/live-common-setup.js @@ -0,0 +1,8 @@ +// @flow +import { setNetwork } from '@ledgerhq/live-common/lib/network' +import { setEnv } from '@ledgerhq/live-common/lib/env' +import network from 'api/network' +import * as constants from 'config/constants' + +setNetwork(network) +setEnv('FORCE_PROVIDER', constants.FORCE_PROVIDER) diff --git a/src/internals/index.js b/src/internals/index.js index cb86c75c..7f5d4b2b 100644 --- a/src/internals/index.js +++ b/src/internals/index.js @@ -1,5 +1,8 @@ // @flow import '@babel/polyfill' +import 'helpers/live-common-setup' +import 'helpers/live-common-setup-internal-hw' + import commands from 'commands' import logger from 'logger' import LoggerTransport from 'logger/logger-transport-internal' @@ -9,10 +12,10 @@ import sentry from 'sentry/node' import { EXPERIMENTAL_HTTP_ON_RENDERER } from 'config/constants' import { serializeError } from 'helpers/errors' -logger.add(new LoggerTransport()) - require('../env') +logger.add(new LoggerTransport()) + process.title = 'Ledger Live Internal' process.on('uncaughtException', err => { diff --git a/src/main/app.js b/src/main/app.js index 6d354e68..53d3ad9a 100644 --- a/src/main/app.js +++ b/src/main/app.js @@ -1,5 +1,7 @@ // @flow +import 'helpers/live-common-setup' + import { app, BrowserWindow, Menu, screen } from 'electron' import debounce from 'lodash/debounce' import { diff --git a/src/renderer/init.js b/src/renderer/init.js index d5df5010..c0b030f4 100644 --- a/src/renderer/init.js +++ b/src/renderer/init.js @@ -1,5 +1,7 @@ // @flow +import 'helpers/live-common-setup' + import logger from 'logger' import LoggerTransport from 'logger/logger-transport-renderer' import React from 'react' diff --git a/yarn.lock b/yarn.lock index 97920ad2..8c57dda9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1677,12 +1677,12 @@ camelcase "^5.0.0" prettier "^1.13.7" -"@ledgerhq/hw-app-btc@^4.24.0": - version "4.27.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-btc/-/hw-app-btc-4.27.0.tgz#11fc822bd34a47a39b1a7ae03ced69cf1d432796" - integrity sha512-7Ck48wCBb6nd9UXarNeGOsOqbOTi2cs4AxFhbDNrVLvPiBSH0yEiNQEF95J6u5BxKkAdM1GV9LoRumR4KhZGqQ== +"@ledgerhq/hw-app-btc@^4.32.0": + version "4.32.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-btc/-/hw-app-btc-4.32.0.tgz#e883dcaa3ebb4aca1e2cb27acfc47b8db4e85f3f" + integrity sha512-N/RxtkPVjTDwU+lDPQQE7+4YQMXaXStDrpufQbDn0NXoaJ8KgY+QGkOH6bkuwV+LQvc7rEaM7E3p7/t58KJpMg== dependencies: - "@ledgerhq/hw-transport" "^4.24.0" + "@ledgerhq/hw-transport" "^4.32.0" create-hash "^1.1.3" "@ledgerhq/hw-app-btc@^4.7.3": @@ -1693,43 +1693,27 @@ "@ledgerhq/hw-transport" "^4.15.0" create-hash "^1.1.3" -"@ledgerhq/hw-app-btc@^v4.30.0": - version "4.30.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-btc/-/hw-app-btc-4.30.0.tgz#50cef544c361072ce12b12b1e8166d7a8b0d9dbd" - integrity sha512-xVXcI4cvBZiqx2o6fB+3tt0HhzJwGH17EoGP3PRJoFvIRi3Mnf3R0CU5k8Y7xFzISvmBEO2GKcetjg4dfgqDKw== +"@ledgerhq/hw-app-eth@^4.32.0": + version "4.32.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-eth/-/hw-app-eth-4.32.0.tgz#7d43ca2c7952f1fb726e02c3b4485be10af481a2" + integrity sha512-d22WinjcsqJNoZSI+6UpTWZ7hl+UhL2dFeVeliCwtBWSj40z6F25MpoviGxPsv0WC7IUjayw+a9jIRcOJ5kkIw== dependencies: - "@ledgerhq/hw-transport" "^4.24.0" - create-hash "^1.1.3" + "@ledgerhq/hw-transport" "^4.32.0" -"@ledgerhq/hw-app-eth@^4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-eth/-/hw-app-eth-4.24.0.tgz#b62514e0d18672d6d35d76dfbeaf93b67d2e5324" - integrity sha512-x8qFHN+JUsLgtm4GI3E1OxwL/7LVIaUfGkKs53a2Zr89h5YFp2GZvFcHdwbEypQAWS8cs+4vEqaEYFwQ9bSwlQ== - dependencies: - "@ledgerhq/hw-transport" "^4.24.0" - -"@ledgerhq/hw-app-xrp@^4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-xrp/-/hw-app-xrp-4.24.0.tgz#cb41975597ac43d6f95dfb6ef52ff3ce5376ab80" - integrity sha512-KWxqnf4Ci3pF/2RsavDLNXHwh7iG2xBkUBD5iYgui9WaWCJfTv+F5zBYeeDeULfTSj9+WAtNcPXFHyiKLYPTfw== +"@ledgerhq/hw-app-xrp@^4.32.0": + version "4.32.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-xrp/-/hw-app-xrp-4.32.0.tgz#260daafa9de1073598ea91ddfeb168dc437edd50" + integrity sha512-MNmLAGUp7Bnj/mjg1Lo5bK1v+q/QPYw7RJAbI4Vl1A4Fsqj6oiZspnSK+BTHGp+CRJavCwumjKuf5y3X5Dp8cA== dependencies: - "@ledgerhq/hw-transport" "^4.24.0" + "@ledgerhq/hw-transport" "^4.32.0" bip32-path "0.4.2" -"@ledgerhq/hw-app-xrp@^4.25.0": - version "4.25.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-xrp/-/hw-app-xrp-4.25.0.tgz#d97d7e85290dd2d1ec99f85747a26145e7a7383e" - integrity sha512-kG9S8CxUFMG1hbLBiKtoPMquzlTigndDsxhoXB8oywAdbGsoCi2cufMHV2p5Bek6YlGfn5J5p49Hx5iNIf2y5Q== - dependencies: - "@ledgerhq/hw-transport" "^4.24.0" - bip32-path "0.4.2" - -"@ledgerhq/hw-transport-node-hid@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-4.24.0.tgz#8457969d66819e8f7f50d5dd96527ab26cd3787d" - integrity sha512-RA3ZlRM+6y/XL/sAFKUpuLIU5tsmEpDBwJEBKC+qdzG508Vl/kBJDMuQyo6pmx/YcKZrtjfKiXXQEXP9Fgk75w== +"@ledgerhq/hw-transport-node-hid@^4.32.0": + version "4.32.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-4.32.0.tgz#75fec81c44e9f8fbe0f918080e2b70e99de2a346" + integrity sha512-uZO+52TBxaYVhGIULHbhvyZWx+uLjvflDwfLicQR1eYxbYACB6xLXwq4sz9gL5He966t637Zx9iPsLi87rtqvQ== dependencies: - "@ledgerhq/hw-transport" "^4.24.0" + "@ledgerhq/hw-transport" "^4.32.0" lodash "^4.17.11" node-hid "^0.7.2" usb "^1.3.3" @@ -1749,13 +1733,20 @@ dependencies: events "^2.0.0" -"@ledgerhq/hw-transport@^4.21.0", "@ledgerhq/hw-transport@^4.24.0": +"@ledgerhq/hw-transport@^4.21.0": version "4.24.0" resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-4.24.0.tgz#8def925d8c2e1f73d15128d9e27ead729870be58" integrity sha512-L34TG1Ss7goRB+5BxtvBwUuu0CmDSIxS33oUqkpEy6rCs31k7XicV48iUGAnRnt8hNY2DvJ9WFyaOroUE9h6wQ== dependencies: events "^3.0.0" +"@ledgerhq/hw-transport@^4.32.0": + version "4.32.0" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-4.32.0.tgz#592b9dc51459cb1cd31ce9444cf943f627bc4beb" + integrity sha512-Wgsk9UHC4RShqYoDeIEeKgHZOvNCtB0WWIG0xqlVPzS+IcKDkIxtXQw7hTA7GQSuDuGeauVtlbTQ5yat6+2/BA== + dependencies: + events "^3.0.0" + "@ledgerhq/ledger-core@2.0.0-rc.12": version "2.0.0-rc.12" resolved "https://registry.yarnpkg.com/@ledgerhq/ledger-core/-/ledger-core-2.0.0-rc.12.tgz#bdd3e4b601acb0c74c640f40bea2609bb5e4b0f4" @@ -1768,16 +1759,16 @@ bindings "^1.3.0" nan "^2.6.2" -"@ledgerhq/live-common@4.6.0": - version "4.6.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-4.6.0.tgz#d99b82123e5275affebded1001ace6e1e98d117e" - integrity sha512-kyKa4o7fR0DrGmu2GxlgMEkVE4aA9BJujr+q5bTpRhO5xDv2jSHT52NOPdhB6H7EfbHChaBaKv/C6wW7Q37Xyw== +"@ledgerhq/live-common@4.8.0-beta.3": + version "4.8.0-beta.3" + resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-4.8.0-beta.3.tgz#eca9a9cb55f28523696fb76c7682a8705c1fb123" + integrity sha512-GBi4V0eeu9WQA2eFK0RwTrSI9r6ZWPjkU2d9pTptVCNlHUAOl/9aFZdc2nDVWobfbNFCchWwA636XJj80bF6ZA== dependencies: "@aeternity/ledger-app-api" "0.0.4" - "@ledgerhq/hw-app-btc" "^4.24.0" - "@ledgerhq/hw-app-eth" "^4.24.0" - "@ledgerhq/hw-app-xrp" "^4.24.0" - "@ledgerhq/hw-transport" "^4.24.0" + "@ledgerhq/hw-app-btc" "^4.32.0" + "@ledgerhq/hw-app-eth" "^4.32.0" + "@ledgerhq/hw-app-xrp" "^4.32.0" + "@ledgerhq/hw-transport" "^4.32.0" bignumber.js "^7.2.1" compressjs gre/compressjs#hermit eip55 "^1.0.3" @@ -1790,6 +1781,8 @@ react-redux "^5.0.7" redux "^4.0.0" reselect "^3.0.1" + rxjs "^6.3.3" + rxjs-compat "^6.3.3" "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" @@ -14214,6 +14207,11 @@ rxjs-compat@^6.2.1: resolved "https://registry.yarnpkg.com/rxjs-compat/-/rxjs-compat-6.2.1.tgz#f5a5e4bd700db414e82aa7cb34e5c9222c6d3756" integrity sha512-Pst0lkAwVodBbBOIZic9aM1vY9asJ2u8GfKN115+goIH83PAlizJDyvixuxPAuQ1UtkmBuro7+0PqKQ3PSkhEg== +rxjs-compat@^6.3.3: + version "6.3.3" + resolved "https://registry.yarnpkg.com/rxjs-compat/-/rxjs-compat-6.3.3.tgz#2ab3b9ac0dac0c073749d55fef9c03ea1df2045c" + integrity sha512-caGN7ixiabHpOofginKEquuHk7GgaCrC7UpUQ9ZqGp80tMc68msadOeP/2AKy2R4YJsT1+TX5GZCtxO82qWkyA== + rxjs@^5.1.1, rxjs@^5.5.2: version "5.5.11" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.11.tgz#f733027ca43e3bec6b994473be4ab98ad43ced87" @@ -14228,6 +14226,13 @@ rxjs@^6.1.0, rxjs@^6.2.1: dependencies: tslib "^1.9.0" +rxjs@^6.3.3: + version "6.3.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz#3c6a7fa420e844a81390fb1158a9ec614f4bad55" + integrity sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw== + dependencies: + tslib "^1.9.0" + safe-buffer@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" From 71f0098572848b945255305cf38d479822d57109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Fri, 14 Dec 2018 19:07:38 +0100 Subject: [PATCH 02/26] use errors from live-common --- .flowconfig | 1 + package.json | 2 +- src/api/Ethereum.js | 2 +- src/api/Fees.js | 2 +- src/api/network.js | 6 +- src/bridge/EthereumJSBridge.js | 2 +- src/bridge/LibcoreBridge.js | 2 +- src/bridge/RippleJSBridge.js | 2 +- src/commands/getAddress.js | 21 +--- src/commands/libcoreGetFees.js | 2 +- src/commands/libcoreSignAndBroadcast.js | 2 +- src/components/EnsureDeviceApp.js | 6 +- src/components/FeesField/BitcoinKind.js | 2 +- src/components/FeesField/EthereumKind.js | 2 +- src/components/FeesField/RippleKind.js | 2 +- src/components/GenuineCheck.js | 6 +- src/components/IsUnlocked.js | 2 +- .../SettingsPage/DisablePasswordModal.js | 2 +- src/components/SettingsPage/PasswordForm.js | 2 +- src/components/SettingsPage/PasswordModal.js | 2 +- .../modals/AccountSettingRenderBody.js | 2 +- .../Receive/steps/04-step-receive-funds.js | 19 ++-- .../modals/Send/fields/RecipientField.js | 4 +- src/components/modals/Send/index.js | 2 +- src/config/errors.js | 53 ---------- src/helpers/apps/installApp.js | 2 +- src/helpers/apps/uninstallApp.js | 2 +- src/helpers/db/index.js | 2 +- src/helpers/errors.js | 96 ------------------- src/helpers/firmware/getNextMCU.js | 2 +- src/helpers/firmware/installFinalFirmware.js | 2 +- src/helpers/firmware/installMcu.js | 2 +- src/helpers/firmware/installOsuFirmware.js | 2 +- src/helpers/getAddressForCurrency/btc.js | 44 --------- src/helpers/getAddressForCurrency/ethereum.js | 18 ---- src/helpers/getAddressForCurrency/index.js | 32 ------- src/helpers/getAddressForCurrency/ripple.js | 16 ---- src/helpers/init-libcore.js | 2 +- src/helpers/ipc.js | 2 +- src/helpers/libcore.js | 4 +- src/helpers/live-common-setup-internal-hw.js | 3 +- src/helpers/promise.js | 2 +- src/helpers/reset.js | 2 +- src/helpers/socket.js | 2 +- src/internals/index.js | 2 +- src/main/bridge.js | 2 +- yarn.lock | 8 +- 47 files changed, 67 insertions(+), 332 deletions(-) delete mode 100644 src/config/errors.js delete mode 100644 src/helpers/errors.js delete mode 100644 src/helpers/getAddressForCurrency/btc.js delete mode 100644 src/helpers/getAddressForCurrency/ethereum.js delete mode 100644 src/helpers/getAddressForCurrency/index.js delete mode 100644 src/helpers/getAddressForCurrency/ripple.js diff --git a/.flowconfig b/.flowconfig index ce56a529..b7155c37 100644 --- a/.flowconfig +++ b/.flowconfig @@ -5,6 +5,7 @@ [untyped] .*/node_modules/react-select +/node_modules/qrloop/lib/Buffer.js* [include] diff --git a/package.json b/package.json index 6600f5b0..42001c02 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "@ledgerhq/hw-transport": "^4.32.0", "@ledgerhq/hw-transport-node-hid": "^4.32.0", "@ledgerhq/ledger-core": "2.0.0-rc.12", - "@ledgerhq/live-common": "4.8.0-beta.3", + "@ledgerhq/live-common": "4.8.0-beta.4", "animated": "^0.2.2", "async": "^2.6.1", "axios": "^0.18.0", diff --git a/src/api/Ethereum.js b/src/api/Ethereum.js index 12a01c6b..4542ddb6 100644 --- a/src/api/Ethereum.js +++ b/src/api/Ethereum.js @@ -1,7 +1,7 @@ // @flow import type { CryptoCurrency } from '@ledgerhq/live-common/lib/types' import { BigNumber } from 'bignumber.js' -import { LedgerAPINotAvailable } from 'config/errors' +import { LedgerAPINotAvailable } from '@ledgerhq/live-common/lib/errors' import network from './network' import { blockchainBaseURL } from './Ledger' diff --git a/src/api/Fees.js b/src/api/Fees.js index fb380905..476ea5d0 100644 --- a/src/api/Fees.js +++ b/src/api/Fees.js @@ -2,7 +2,7 @@ import invariant from 'invariant' import LRU from 'lru-cache' import type { Currency } from '@ledgerhq/live-common/lib/types' -import { FeeEstimationFailed } from 'config/errors' +import { FeeEstimationFailed } from '@ledgerhq/live-common/lib/errors' import { blockchainBaseURL } from './Ledger' import network from './network' diff --git a/src/api/network.js b/src/api/network.js index 0da18166..db0a3e5d 100644 --- a/src/api/network.js +++ b/src/api/network.js @@ -3,7 +3,11 @@ import axios from 'axios' import { GET_CALLS_RETRY, GET_CALLS_TIMEOUT } from 'config/constants' import { retry } from 'helpers/promise' import logger from 'logger' -import { LedgerAPIErrorWithMessage, LedgerAPIError, NetworkDown } from 'config/errors' +import { + LedgerAPIErrorWithMessage, + LedgerAPIError, + NetworkDown, +} from '@ledgerhq/live-common/lib/errors' import anonymizer from 'helpers/anonymizer' const userFriendlyError = (p: Promise, { url, method, startTime, ...rest }): Promise => diff --git a/src/bridge/EthereumJSBridge.js b/src/bridge/EthereumJSBridge.js index 0fd3f2a9..a337dd85 100644 --- a/src/bridge/EthereumJSBridge.js +++ b/src/bridge/EthereumJSBridge.js @@ -25,7 +25,7 @@ import { apiForCurrency } from 'api/Ethereum' import type { Tx } from 'api/Ethereum' import getAddressCommand from 'commands/getAddress' import signTransactionCommand from 'commands/signTransaction' -import { NotEnoughBalance, FeeNotLoaded, ETHAddressNonEIP } from 'config/errors' +import { NotEnoughBalance, FeeNotLoaded, ETHAddressNonEIP } from '@ledgerhq/live-common/lib/errors' import type { EditProps, WalletBridge } from './types' type Transaction = { diff --git a/src/bridge/LibcoreBridge.js b/src/bridge/LibcoreBridge.js index 8ed8de3d..16d52909 100644 --- a/src/bridge/LibcoreBridge.js +++ b/src/bridge/LibcoreBridge.js @@ -11,7 +11,7 @@ import libcoreSyncAccount from 'commands/libcoreSyncAccount' import libcoreSignAndBroadcast from 'commands/libcoreSignAndBroadcast' import libcoreGetFees, { extractGetFeesInputFromAccount } from 'commands/libcoreGetFees' import libcoreValidAddress from 'commands/libcoreValidAddress' -import { NotEnoughBalance, FeeNotLoaded } from 'config/errors' +import { NotEnoughBalance, FeeNotLoaded } from '@ledgerhq/live-common/lib/errors' import type { WalletBridge, EditProps } from './types' const NOT_ENOUGH_FUNDS = 52 diff --git a/src/bridge/RippleJSBridge.js b/src/bridge/RippleJSBridge.js index 31c9c356..c67a5a94 100644 --- a/src/bridge/RippleJSBridge.js +++ b/src/bridge/RippleJSBridge.js @@ -32,7 +32,7 @@ import { NotEnoughBalance, FeeNotLoaded, NotEnoughBalanceBecauseDestinationNotCreated, -} from 'config/errors' +} from '@ledgerhq/live-common/lib/errors' import type { WalletBridge, EditProps } from './types' type Transaction = { diff --git a/src/commands/getAddress.js b/src/commands/getAddress.js index 1c7109ee..24fe89bc 100644 --- a/src/commands/getAddress.js +++ b/src/commands/getAddress.js @@ -4,16 +4,13 @@ import { getCryptoCurrencyById } from '@ledgerhq/live-common/lib/currencies' import { createCommand, Command } from 'helpers/ipc' import { from } from 'rxjs' import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' -import getAddressForCurrency from 'helpers/getAddressForCurrency' - -import { DeviceAppVerifyNotSupported, UserRefusedAddress } from 'config/errors' +import getAddress from '@ledgerhq/live-common/lib/hw/getAddress' type Input = { currencyId: string, devicePath: string, path: string, verify?: boolean, - segwit?: boolean, } type Result = { @@ -26,21 +23,7 @@ const cmd: Command = createCommand( 'getAddress', ({ currencyId, devicePath, path, ...options }) => withDevice(devicePath)(transport => - from( - getAddressForCurrency(transport, getCryptoCurrencyById(currencyId), path, options).catch( - e => { - if (e && e.name === 'TransportStatusError') { - if (e.statusCode === 0x6b00 && options.verify) { - throw new DeviceAppVerifyNotSupported() - } - if (e.statusCode === 0x6985) { - throw new UserRefusedAddress() - } - } - throw e - }, - ), - ), + from(getAddress(transport, getCryptoCurrencyById(currencyId), path, options.verify)), ), ) diff --git a/src/commands/libcoreGetFees.js b/src/commands/libcoreGetFees.js index c3eb9f7d..3b813421 100644 --- a/src/commands/libcoreGetFees.js +++ b/src/commands/libcoreGetFees.js @@ -13,7 +13,7 @@ import { bigNumberToLibcoreAmount, getOrCreateWallet, } from 'helpers/libcore' -import { InvalidAddress } from 'config/errors' +import { InvalidAddress } from '@ledgerhq/live-common/lib/errors' type BitcoinLikeTransaction = { // TODO we rename this Transaction concept into transactionInput diff --git a/src/commands/libcoreSignAndBroadcast.js b/src/commands/libcoreSignAndBroadcast.js index f2990c34..86cca208 100644 --- a/src/commands/libcoreSignAndBroadcast.js +++ b/src/commands/libcoreSignAndBroadcast.js @@ -14,7 +14,7 @@ import { bigNumberToLibcoreAmount, getOrCreateWallet, } from 'helpers/libcore' -import { UpdateYourApp } from 'config/errors' +import { UpdateYourApp } from '@ledgerhq/live-common/lib/errors' import withLibcore from 'helpers/withLibcore' import { createCommand, Command } from 'helpers/ipc' diff --git a/src/components/EnsureDeviceApp.js b/src/components/EnsureDeviceApp.js index e742a663..47f90e79 100644 --- a/src/components/EnsureDeviceApp.js +++ b/src/components/EnsureDeviceApp.js @@ -23,7 +23,11 @@ import IconUsb from 'icons/Usb' import type { Device } from 'types/common' -import { WrongDeviceForAccount, CantOpenDevice, UpdateYourApp } from 'config/errors' +import { + WrongDeviceForAccount, + CantOpenDevice, + UpdateYourApp, +} from '@ledgerhq/live-common/lib/errors' import { getCurrentDevice } from 'reducers/devices' const usbIcon = diff --git a/src/components/FeesField/BitcoinKind.js b/src/components/FeesField/BitcoinKind.js index 8eb47667..2b102792 100644 --- a/src/components/FeesField/BitcoinKind.js +++ b/src/components/FeesField/BitcoinKind.js @@ -8,7 +8,7 @@ import { translate } from 'react-i18next' import type { T } from 'types/common' -import { FeeNotLoaded } from 'config/errors' +import { FeeNotLoaded } from '@ledgerhq/live-common/lib/errors' import InputCurrency from 'components/base/InputCurrency' import Select from 'components/base/Select' import type { Fees } from 'api/Fees' diff --git a/src/components/FeesField/EthereumKind.js b/src/components/FeesField/EthereumKind.js index 0c51a07e..aa02c86a 100644 --- a/src/components/FeesField/EthereumKind.js +++ b/src/components/FeesField/EthereumKind.js @@ -4,7 +4,7 @@ import React, { Component } from 'react' import { BigNumber } from 'bignumber.js' import type { Account } from '@ledgerhq/live-common/lib/types' -import { FeeNotLoaded } from 'config/errors' +import { FeeNotLoaded } from '@ledgerhq/live-common/lib/errors' import InputCurrency from 'components/base/InputCurrency' import type { Fees } from 'api/Fees' import WithFeesAPI from '../WithFeesAPI' diff --git a/src/components/FeesField/RippleKind.js b/src/components/FeesField/RippleKind.js index 4a8ba3e9..8692cb12 100644 --- a/src/components/FeesField/RippleKind.js +++ b/src/components/FeesField/RippleKind.js @@ -4,7 +4,7 @@ import React, { Component } from 'react' import type { BigNumber } from 'bignumber.js' import type { Account } from '@ledgerhq/live-common/lib/types' import { apiForEndpointConfig, parseAPIValue } from 'api/Ripple' -import { FeeNotLoaded } from 'config/errors' +import { FeeNotLoaded } from '@ledgerhq/live-common/lib/errors' import InputCurrency from 'components/base/InputCurrency' import GenericContainer from './GenericContainer' diff --git a/src/components/GenuineCheck.js b/src/components/GenuineCheck.js index aef771e9..ff02986c 100644 --- a/src/components/GenuineCheck.js +++ b/src/components/GenuineCheck.js @@ -14,7 +14,11 @@ import type { DeviceInfo } from 'helpers/types' import { GENUINE_TIMEOUT, DEVICE_INFOS_TIMEOUT, GENUINE_CACHE_DELAY } from 'config/constants' import { getCurrentDevice } from 'reducers/devices' -import { CantOpenDevice, DeviceNotGenuineError, DeviceGenuineSocketEarlyClose } from 'config/errors' +import { + CantOpenDevice, + DeviceNotGenuineError, + DeviceGenuineSocketEarlyClose, +} from '@ledgerhq/live-common/lib/errors' import getDeviceInfo from 'commands/getDeviceInfo' import getIsGenuine from 'commands/getIsGenuine' diff --git a/src/components/IsUnlocked.js b/src/components/IsUnlocked.js index d2b22ada..391599db 100644 --- a/src/components/IsUnlocked.js +++ b/src/components/IsUnlocked.js @@ -17,7 +17,7 @@ import { hardReset } from 'helpers/reset' import { fetchAccounts } from 'actions/accounts' import { isLocked, unlock } from 'reducers/application' -import { PasswordIncorrectError } from 'config/errors' +import { PasswordIncorrectError } from '@ledgerhq/live-common/lib/errors' import Box from 'components/base/Box' import InputPassword from 'components/base/InputPassword' diff --git a/src/components/SettingsPage/DisablePasswordModal.js b/src/components/SettingsPage/DisablePasswordModal.js index bf08c536..bf5ebe61 100644 --- a/src/components/SettingsPage/DisablePasswordModal.js +++ b/src/components/SettingsPage/DisablePasswordModal.js @@ -1,7 +1,7 @@ // @flow import React, { PureComponent } from 'react' -import { PasswordIncorrectError } from 'config/errors' +import { PasswordIncorrectError } from '@ledgerhq/live-common/lib/errors' import db from 'helpers/db' import Box from 'components/base/Box' diff --git a/src/components/SettingsPage/PasswordForm.js b/src/components/SettingsPage/PasswordForm.js index 99766e6f..396a1355 100644 --- a/src/components/SettingsPage/PasswordForm.js +++ b/src/components/SettingsPage/PasswordForm.js @@ -6,7 +6,7 @@ import Box from 'components/base/Box' import InputPassword from 'components/base/InputPassword' import Label from 'components/base/Label' -import { PasswordsDontMatchError } from 'config/errors' +import { PasswordsDontMatchError } from '@ledgerhq/live-common/lib/errors' import type { T } from 'types/common' diff --git a/src/components/SettingsPage/PasswordModal.js b/src/components/SettingsPage/PasswordModal.js index be3755cc..00abe296 100644 --- a/src/components/SettingsPage/PasswordModal.js +++ b/src/components/SettingsPage/PasswordModal.js @@ -5,7 +5,7 @@ import React, { PureComponent } from 'react' import type { T } from 'types/common' import db from 'helpers/db' -import { PasswordIncorrectError } from 'config/errors' +import { PasswordIncorrectError } from '@ledgerhq/live-common/lib/errors' import Box from 'components/base/Box' import Button from 'components/base/Button' import { Modal, ModalContent, ModalBody, ModalTitle, ModalFooter } from 'components/base/Modal' diff --git a/src/components/modals/AccountSettingRenderBody.js b/src/components/modals/AccountSettingRenderBody.js index ae029eb2..0575d4c1 100644 --- a/src/components/modals/AccountSettingRenderBody.js +++ b/src/components/modals/AccountSettingRenderBody.js @@ -17,7 +17,7 @@ import { setDataModal } from 'reducers/modals' import { getBridgeForCurrency } from 'bridge' -import { AccountNameRequiredError, EnpointConfigError } from 'config/errors' +import { AccountNameRequiredError, EnpointConfigError } from '@ledgerhq/live-common/lib/errors' import TrackPage from 'analytics/TrackPage' import Spoiler from 'components/base/Spoiler' diff --git a/src/components/modals/Receive/steps/04-step-receive-funds.js b/src/components/modals/Receive/steps/04-step-receive-funds.js index 59e1cf37..45cd33e1 100644 --- a/src/components/modals/Receive/steps/04-step-receive-funds.js +++ b/src/components/modals/Receive/steps/04-step-receive-funds.js @@ -5,10 +5,9 @@ import React, { PureComponent } from 'react' import TrackPage from 'analytics/TrackPage' import getAddress from 'commands/getAddress' -import { isSegwitDerivationMode } from '@ledgerhq/live-common/lib/derivation' import Box from 'components/base/Box' import CurrentAddressForAccount from 'components/CurrentAddressForAccount' -import { DisconnectedDevice, WrongDeviceForAccount } from 'config/errors' +import { DisconnectedDevice, WrongDeviceForAccount } from '@ledgerhq/live-common/lib/errors' import type { StepProps } from '..' @@ -25,14 +24,14 @@ export default class StepReceiveFunds extends PureComponent { if (!device || !account) { throw new DisconnectedDevice() } - const params = { - currencyId: account.currency.id, - devicePath: device.path, - path: account.freshAddressPath, - segwit: isSegwitDerivationMode(account.derivationMode), - verify: true, - } - const { address } = await getAddress.send(params).toPromise() + const { address } = await getAddress + .send({ + currencyId: account.currency.id, + devicePath: device.path, + path: account.freshAddressPath, + verify: true, + }) + .toPromise() if (address !== account.freshAddress) { throw new WrongDeviceForAccount(`WrongDeviceForAccount ${account.name}`, { diff --git a/src/components/modals/Send/fields/RecipientField.js b/src/components/modals/Send/fields/RecipientField.js index ab23cb3c..c4e9f92e 100644 --- a/src/components/modals/Send/fields/RecipientField.js +++ b/src/components/modals/Send/fields/RecipientField.js @@ -9,8 +9,8 @@ import Box from 'components/base/Box' import LabelWithExternalIcon from 'components/base/LabelWithExternalIcon' import RecipientAddress from 'components/RecipientAddress' import { track } from 'analytics/segment' -import { createCustomErrorClass } from 'helpers/errors' -import { CantScanQRCode } from 'config/errors' +import { createCustomErrorClass } from '@ledgerhq/live-common/lib/errors/helpers' +import { CantScanQRCode } from '@ledgerhq/live-common/lib/errors' type Props = { t: T, diff --git a/src/components/modals/Send/index.js b/src/components/modals/Send/index.js index 6ed05d4c..17801759 100644 --- a/src/components/modals/Send/index.js +++ b/src/components/modals/Send/index.js @@ -20,7 +20,7 @@ import type { StepProps as DefaultStepProps } from 'components/base/Stepper' import { getCurrentDevice } from 'reducers/devices' import { accountsSelector } from 'reducers/accounts' import { closeModal, openModal } from 'reducers/modals' -import { DisconnectedDevice, UserRefusedOnDevice } from 'config/errors' +import { DisconnectedDevice, UserRefusedOnDevice } from '@ledgerhq/live-common/lib/errors' import Modal from 'components/base/Modal' import Stepper from 'components/base/Stepper' diff --git a/src/config/errors.js b/src/config/errors.js deleted file mode 100644 index c9ea06a3..00000000 --- a/src/config/errors.js +++ /dev/null @@ -1,53 +0,0 @@ -// @flow - -// TODO we need to start porting all custom errors here. - -import { createCustomErrorClass } from 'helpers/errors' - -export const AccountNameRequiredError = createCustomErrorClass('AccountNameRequired') -export const BtcUnmatchedApp = createCustomErrorClass('BtcUnmatchedApp') -export const CantOpenDevice = createCustomErrorClass('CantOpenDevice') -export const DeviceAppVerifyNotSupported = createCustomErrorClass('DeviceAppVerifyNotSupported') -export const DeviceGenuineSocketEarlyClose = createCustomErrorClass('DeviceGenuineSocketEarlyClose') -export const DeviceNotGenuineError = createCustomErrorClass('DeviceNotGenuine') -export const DeviceSocketFail = createCustomErrorClass('DeviceSocketFail') -export const DeviceSocketNoBulkStatus = createCustomErrorClass('DeviceSocketNoBulkStatus') -export const DeviceSocketNoHandler = createCustomErrorClass('DeviceSocketNoHandler') -export const DisconnectedDevice = createCustomErrorClass('DisconnectedDevice') -export const EnpointConfigError = createCustomErrorClass('EnpointConfig') -export const FeeEstimationFailed = createCustomErrorClass('FeeEstimationFailed') -export const HardResetFail = createCustomErrorClass('HardResetFail') -export const InvalidAddress = createCustomErrorClass('InvalidAddress') -export const LatestMCUInstalledError = createCustomErrorClass('LatestMCUInstalledError') -export const LedgerAPIError = createCustomErrorClass('LedgerAPIError') -export const LedgerAPIErrorWithMessage = createCustomErrorClass('LedgerAPIErrorWithMessage') -export const LedgerAPINotAvailable = createCustomErrorClass('LedgerAPINotAvailable') -export const ManagerAppAlreadyInstalledError = createCustomErrorClass('ManagerAppAlreadyInstalled') -export const ManagerAppRelyOnBTCError = createCustomErrorClass('ManagerAppRelyOnBTC') -export const ManagerDeviceLockedError = createCustomErrorClass('ManagerDeviceLocked') -export const ManagerNotEnoughSpaceError = createCustomErrorClass('ManagerNotEnoughSpace') -export const ManagerUninstallBTCDep = createCustomErrorClass('ManagerUninstallBTCDep') -export const NetworkDown = createCustomErrorClass('NetworkDown') -export const NoAddressesFound = createCustomErrorClass('NoAddressesFound') -export const NotEnoughBalance = createCustomErrorClass('NotEnoughBalance') -export const NotEnoughBalanceBecauseDestinationNotCreated = createCustomErrorClass( - 'NotEnoughBalanceBecauseDestinationNotCreated', -) -export const PasswordsDontMatchError = createCustomErrorClass('PasswordsDontMatch') -export const PasswordIncorrectError = createCustomErrorClass('PasswordIncorrect') -export const TimeoutTagged = createCustomErrorClass('TimeoutTagged') -export const UpdateYourApp = createCustomErrorClass('UpdateYourApp') -export const UserRefusedAddress = createCustomErrorClass('UserRefusedAddress') -export const UserRefusedFirmwareUpdate = createCustomErrorClass('UserRefusedFirmwareUpdate') -export const UserRefusedOnDevice = createCustomErrorClass('UserRefusedOnDevice') // TODO rename because it's just for transaction refusal -export const WebsocketConnectionError = createCustomErrorClass('WebsocketConnectionError') -export const WebsocketConnectionFailed = createCustomErrorClass('WebsocketConnectionFailed') -export const WrongDeviceForAccount = createCustomErrorClass('WrongDeviceForAccount') -export const ETHAddressNonEIP = createCustomErrorClass('ETHAddressNonEIP') -export const CantScanQRCode = createCustomErrorClass('CantScanQRCode') -export const FeeNotLoaded = createCustomErrorClass('FeeNotLoaded') - -// db stuff, no need to translate -export const NoDBPathGiven = createCustomErrorClass('NoDBPathGiven') -export const DBWrongPassword = createCustomErrorClass('DBWrongPassword') -export const DBNotReset = createCustomErrorClass('DBNotReset') diff --git a/src/helpers/apps/installApp.js b/src/helpers/apps/installApp.js index 875890bc..1c854062 100644 --- a/src/helpers/apps/installApp.js +++ b/src/helpers/apps/installApp.js @@ -11,7 +11,7 @@ import { ManagerDeviceLockedError, ManagerAppAlreadyInstalledError, ManagerAppRelyOnBTCError, -} from 'config/errors' +} from '@ledgerhq/live-common/lib/errors' function remapError(promise) { return promise.catch((e: Error) => { diff --git a/src/helpers/apps/uninstallApp.js b/src/helpers/apps/uninstallApp.js index b3c2b98b..161c0ae8 100644 --- a/src/helpers/apps/uninstallApp.js +++ b/src/helpers/apps/uninstallApp.js @@ -4,7 +4,7 @@ import type Transport from '@ledgerhq/hw-transport' import { createDeviceSocket } from 'helpers/socket' import type { ApplicationVersion } from 'helpers/types' -import { ManagerDeviceLockedError, ManagerUninstallBTCDep } from 'config/errors' +import { ManagerDeviceLockedError, ManagerUninstallBTCDep } from '@ledgerhq/live-common/lib/errors' import { WS_INSTALL } from 'helpers/urls' function remapError(promise) { diff --git a/src/helpers/db/index.js b/src/helpers/db/index.js index 6b072415..f1e2d533 100644 --- a/src/helpers/db/index.js +++ b/src/helpers/db/index.js @@ -11,7 +11,7 @@ import logger from 'logger' import { fsReadFile, fsUnlink } from 'helpers/fs' import { promisify, debounce } from 'helpers/promise' -import { NoDBPathGiven, DBWrongPassword } from 'config/errors' +import { NoDBPathGiven, DBWrongPassword } from '@ledgerhq/live-common/lib/errors' type Transform = { get: any => any, diff --git a/src/helpers/errors.js b/src/helpers/errors.js deleted file mode 100644 index 22436e4b..00000000 --- a/src/helpers/errors.js +++ /dev/null @@ -1,96 +0,0 @@ -// @flow -/* eslint-disable no-continue */ - -// TODO we need to centralize the error in one place. so all are recorded -const errorClasses = {} - -export const createCustomErrorClass = (name: string): Class => { - const C = function CustomError(message?: string, fields?: Object) { - Object.assign(this, fields) - this.name = name - this.message = message || name - this.stack = new Error().stack - } - // $FlowFixMe - C.prototype = new Error() - - errorClasses[name] = C - // $FlowFixMe we can't easily type a subset of Error for now... - return C -} - -// inspired from https://github.com/programble/errio/blob/master/index.js -export const deserializeError = (object: mixed): Error => { - if (typeof object === 'object' && object) { - try { - // $FlowFixMe FIXME HACK - const msg = JSON.parse(object.message) - if (msg.message && msg.name) { - object = msg - } - } catch (e) { - // nothing - } - const constructor = - object.name === 'Error' - ? Error - : typeof object.name === 'string' - ? errorClasses[object.name] || createCustomErrorClass(object.name) - : Error - - const error = Object.create(constructor.prototype) - for (const prop in object) { - if (object.hasOwnProperty(prop)) { - error[prop] = object[prop] - } - } - if (!error.stack && Error.captureStackTrace) { - Error.captureStackTrace(error, deserializeError) - } - return error - } - return new Error(String(object)) -} - -// inspired from https://github.com/sindresorhus/serialize-error/blob/master/index.js -export const serializeError = (value: mixed) => { - if (!value) return value - if (typeof value === 'object') { - return destroyCircular(value, []) - } - if (typeof value === 'function') { - return `[Function: ${value.name || 'anonymous'}]` - } - return value -} - -// https://www.npmjs.com/package/destroy-circular -function destroyCircular(from: Object, seen) { - const to = {} - seen.push(from) - for (const key of Object.keys(from)) { - const value = from[key] - if (typeof value === 'function') { - continue - } - if (!value || typeof value !== 'object') { - to[key] = value - continue - } - if (seen.indexOf(from[key]) === -1) { - to[key] = destroyCircular(from[key], seen.slice(0)) - continue - } - to[key] = '[Circular]' - } - if (typeof from.name === 'string') { - to.name = from.name - } - if (typeof from.message === 'string') { - to.message = from.message - } - if (typeof from.stack === 'string') { - to.stack = from.stack - } - return to -} diff --git a/src/helpers/firmware/getNextMCU.js b/src/helpers/firmware/getNextMCU.js index fcb82cd7..92f877a3 100644 --- a/src/helpers/firmware/getNextMCU.js +++ b/src/helpers/firmware/getNextMCU.js @@ -3,7 +3,7 @@ import network from 'api/network' import { GET_NEXT_MCU } from 'helpers/urls' import type { OsuFirmware } from 'helpers/types' -import { LatestMCUInstalledError } from 'config/errors' +import { LatestMCUInstalledError } from '@ledgerhq/live-common/lib/errors' type NetworkResponse = { data: OsuFirmware | 'default' } diff --git a/src/helpers/firmware/installFinalFirmware.js b/src/helpers/firmware/installFinalFirmware.js index 7857ffb8..8d643e31 100644 --- a/src/helpers/firmware/installFinalFirmware.js +++ b/src/helpers/firmware/installFinalFirmware.js @@ -7,7 +7,7 @@ import { createDeviceSocket } from 'helpers/socket' import getDeviceVersion from 'helpers/devices/getDeviceVersion' import getOsuFirmware from 'helpers/devices/getOsuFirmware' import getDeviceInfo from 'helpers/devices/getDeviceInfo' -import { ManagerDeviceLockedError } from 'config/errors' +import { ManagerDeviceLockedError } from '@ledgerhq/live-common/lib/errors' import getFinalFirmwareById from './getFinalFirmwareById' diff --git a/src/helpers/firmware/installMcu.js b/src/helpers/firmware/installMcu.js index 18cd4872..b8ece4a4 100644 --- a/src/helpers/firmware/installMcu.js +++ b/src/helpers/firmware/installMcu.js @@ -5,7 +5,7 @@ import { WS_MCU } from 'helpers/urls' import { createDeviceSocket } from 'helpers/socket' import getNextMCU from 'helpers/firmware/getNextMCU' import getDeviceInfo from 'helpers/devices/getDeviceInfo' -import { ManagerDeviceLockedError } from 'config/errors' +import { ManagerDeviceLockedError } from '@ledgerhq/live-common/lib/errors' import type { DeviceInfo } from 'helpers/types' diff --git a/src/helpers/firmware/installOsuFirmware.js b/src/helpers/firmware/installOsuFirmware.js index 04a9ba33..a1194d3c 100644 --- a/src/helpers/firmware/installOsuFirmware.js +++ b/src/helpers/firmware/installOsuFirmware.js @@ -10,7 +10,7 @@ import { ManagerNotEnoughSpaceError, ManagerDeviceLockedError, UserRefusedFirmwareUpdate, -} from 'config/errors' +} from '@ledgerhq/live-common/lib/errors' function remapError(promise) { return promise.catch((e: Error) => { diff --git a/src/helpers/getAddressForCurrency/btc.js b/src/helpers/getAddressForCurrency/btc.js deleted file mode 100644 index 69524069..00000000 --- a/src/helpers/getAddressForCurrency/btc.js +++ /dev/null @@ -1,44 +0,0 @@ -// @flow - -import type { CryptoCurrency } from '@ledgerhq/live-common/lib/types' -import Btc from '@ledgerhq/hw-app-btc' -import type Transport from '@ledgerhq/hw-transport' -import { BtcUnmatchedApp, UpdateYourApp } from 'config/errors' -import getBitcoinLikeInfo from '../devices/getBitcoinLikeInfo' - -const oldP2SH = { - digibyte: 5, -} - -export default async ( - transport: Transport<*>, - currency: CryptoCurrency, - path: string, - { - segwit = true, - verify = false, - }: { - segwit?: boolean, - verify?: boolean, - }, -) => { - const btc = new Btc(transport) - const { bitcoinAddress, publicKey } = await btc.getWalletPublicKey(path, verify, segwit) - - const { bitcoinLikeInfo } = currency - if (bitcoinLikeInfo) { - const { P2SH, P2PKH } = await getBitcoinLikeInfo(transport) - if (P2SH !== bitcoinLikeInfo.P2SH || P2PKH !== bitcoinLikeInfo.P2PKH) { - if ( - currency.id in oldP2SH && - P2SH === oldP2SH[currency.id] && - P2PKH === bitcoinLikeInfo.P2PKH - ) { - throw new UpdateYourApp(`UpdateYourApp ${currency.id}`, currency) - } - throw new BtcUnmatchedApp(`BtcUnmatchedApp ${currency.id}`, currency) - } - } - - return { address: bitcoinAddress, path, publicKey } -} diff --git a/src/helpers/getAddressForCurrency/ethereum.js b/src/helpers/getAddressForCurrency/ethereum.js deleted file mode 100644 index 4835c26d..00000000 --- a/src/helpers/getAddressForCurrency/ethereum.js +++ /dev/null @@ -1,18 +0,0 @@ -// @flow - -import type { CryptoCurrency } from '@ledgerhq/live-common/lib/types' -import Eth from '@ledgerhq/hw-app-eth' -import type Transport from '@ledgerhq/hw-transport' -import eip55 from 'eip55' - -export default async ( - transport: Transport<*>, - currency: CryptoCurrency, - path: string, - { verify = false }: *, -) => { - const eth = new Eth(transport) - const r = await eth.getAddress(path, verify) - const address = eip55.encode(r.address) - return { path, address, publicKey: r.publicKey } -} diff --git a/src/helpers/getAddressForCurrency/index.js b/src/helpers/getAddressForCurrency/index.js deleted file mode 100644 index b3d843d6..00000000 --- a/src/helpers/getAddressForCurrency/index.js +++ /dev/null @@ -1,32 +0,0 @@ -// @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, - path: string, - options: { - segwit?: boolean, - verify?: boolean, - }, -) => Promise<{ address: string, path: string, publicKey: string }> - -const perFamily: { [_: string]: Resolver } = { - bitcoin, - ethereum, - ripple, -} - -const proxy: Resolver = (transport, currency, path, options) => { - const getAddress = perFamily[currency.family] - invariant(getAddress, `getAddress not implemented for ${currency.id}`) - return getAddress(transport, currency, path, options) -} - -export default proxy diff --git a/src/helpers/getAddressForCurrency/ripple.js b/src/helpers/getAddressForCurrency/ripple.js deleted file mode 100644 index 8e98b42f..00000000 --- a/src/helpers/getAddressForCurrency/ripple.js +++ /dev/null @@ -1,16 +0,0 @@ -// @flow - -import Xrp from '@ledgerhq/hw-app-xrp' -import type Transport from '@ledgerhq/hw-transport' -import type { CryptoCurrency } from '@ledgerhq/live-common/lib/types' - -export default async ( - transport: Transport<*>, - currency: CryptoCurrency, - path: string, - { verify = false }: *, -) => { - const xrp = new Xrp(transport) - const { address, publicKey } = await xrp.getAddress(path, verify) - return { path, address, publicKey } -} diff --git a/src/helpers/init-libcore.js b/src/helpers/init-libcore.js index 5f9ee7cb..b9877a78 100644 --- a/src/helpers/init-libcore.js +++ b/src/helpers/init-libcore.js @@ -3,7 +3,7 @@ import logger from 'logger' import invariant from 'invariant' import network from 'api/network' -import { serializeError } from './errors' +import { serializeError } from '@ledgerhq/live-common/lib/errors/helpers' const lib = require('@ledgerhq/ledger-core') diff --git a/src/helpers/ipc.js b/src/helpers/ipc.js index d506ca0f..6a1166c9 100644 --- a/src/helpers/ipc.js +++ b/src/helpers/ipc.js @@ -2,7 +2,7 @@ import logger from 'logger' import { Observable } from 'rxjs' import uuidv4 from 'uuid/v4' -import { deserializeError } from './errors' +import { deserializeError } from '@ledgerhq/live-common/lib/errors/helpers' export function createCommand(id: string, impl: In => Observable): Command { return new Command(id, impl) diff --git a/src/helpers/libcore.js b/src/helpers/libcore.js index 0c486d1b..4f3447df 100644 --- a/src/helpers/libcore.js +++ b/src/helpers/libcore.js @@ -32,8 +32,8 @@ import type { } from '@ledgerhq/live-common/lib/types' import type { NJSAccount, NJSOperation } from '@ledgerhq/ledger-core/src/ledgercore_doc' -import { NoAddressesFound } from 'config/errors' -import { deserializeError } from './errors' +import { NoAddressesFound } from '@ledgerhq/live-common/lib/errors' +import { deserializeError } from '@ledgerhq/live-common/lib/errors/helpers' import { timeoutTagged } from './promise' export function isValidAddress(core: *, currency: *, address: string): boolean { diff --git a/src/helpers/live-common-setup-internal-hw.js b/src/helpers/live-common-setup-internal-hw.js index 7c04155e..02250401 100644 --- a/src/helpers/live-common-setup-internal-hw.js +++ b/src/helpers/live-common-setup-internal-hw.js @@ -4,9 +4,8 @@ import { throwError } from 'rxjs' import { registerTransportModule } from '@ledgerhq/live-common/lib/hw' import { addAccessHook, setErrorRemapping } from '@ledgerhq/live-common/lib/hw/deviceAccess' import throttle from 'lodash/throttle' -import type Transport from '@ledgerhq/hw-transport' import TransportNodeHid from '@ledgerhq/hw-transport-node-hid' -import { DisconnectedDevice, CantOpenDevice } from 'config/errors' +import { DisconnectedDevice } from '@ledgerhq/live-common/lib/errors' import { retry } from './promise' let busy = false diff --git a/src/helpers/promise.js b/src/helpers/promise.js index 7a0d7676..d3cbc908 100644 --- a/src/helpers/promise.js +++ b/src/helpers/promise.js @@ -2,7 +2,7 @@ // small utilities for Promises import logger from 'logger' -import { TimeoutTagged } from 'config/errors' +import { TimeoutTagged } from '@ledgerhq/live-common/lib/errors' export const delay = (ms: number): Promise => new Promise(f => setTimeout(f, ms)) diff --git a/src/helpers/reset.js b/src/helpers/reset.js index cc1b7eec..1a64a15d 100644 --- a/src/helpers/reset.js +++ b/src/helpers/reset.js @@ -9,7 +9,7 @@ import { disable as disableDBMiddleware } from 'middlewares/db' import db from 'helpers/db' import { delay } from 'helpers/promise' import killInternalProcess from 'commands/killInternalProcess' -import { DBNotReset } from 'config/errors' +import { DBNotReset } from '@ledgerhq/live-common/lib/errors' async function resetLibcoreDatabase() { await killInternalProcess.send().toPromise() diff --git a/src/helpers/socket.js b/src/helpers/socket.js index cf9d29a8..452df930 100644 --- a/src/helpers/socket.js +++ b/src/helpers/socket.js @@ -11,7 +11,7 @@ import { DeviceSocketFail, DeviceSocketNoBulkStatus, DeviceSocketNoHandler, -} from 'config/errors' +} from '@ledgerhq/live-common/lib/errors' /** * use Ledger WebSocket API to exchange data with the device diff --git a/src/internals/index.js b/src/internals/index.js index 7f5d4b2b..e40fbdb7 100644 --- a/src/internals/index.js +++ b/src/internals/index.js @@ -10,7 +10,7 @@ import uuid from 'uuid/v4' import { setImplementation } from 'api/network' import sentry from 'sentry/node' import { EXPERIMENTAL_HTTP_ON_RENDERER } from 'config/constants' -import { serializeError } from 'helpers/errors' +import { serializeError } from '@ledgerhq/live-common/lib/errors/helpers' require('../env') diff --git a/src/main/bridge.js b/src/main/bridge.js index 8e5bd8be..50d16f6a 100644 --- a/src/main/bridge.js +++ b/src/main/bridge.js @@ -11,7 +11,7 @@ import LoggerTransport from 'logger/logger-transport-main' import sentry, { captureException } from 'sentry/node' import user from 'helpers/user' import { cleanUpBeforeClosingSync } from 'helpers/log' -import { deserializeError } from 'helpers/errors' +import { deserializeError } from '@ledgerhq/live-common/lib/errors/helpers' import setupAutoUpdater, { quitAndInstall } from './autoUpdate' import { setInternalProcessPID } from './terminator' diff --git a/yarn.lock b/yarn.lock index 8c57dda9..9d71064e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1759,10 +1759,10 @@ bindings "^1.3.0" nan "^2.6.2" -"@ledgerhq/live-common@4.8.0-beta.3": - version "4.8.0-beta.3" - resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-4.8.0-beta.3.tgz#eca9a9cb55f28523696fb76c7682a8705c1fb123" - integrity sha512-GBi4V0eeu9WQA2eFK0RwTrSI9r6ZWPjkU2d9pTptVCNlHUAOl/9aFZdc2nDVWobfbNFCchWwA636XJj80bF6ZA== +"@ledgerhq/live-common@4.8.0-beta.4": + version "4.8.0-beta.4" + resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-4.8.0-beta.4.tgz#291641f42a5cac8c26cf3baf0c303542509df86c" + integrity sha512-xmNLrljtCPSDJDiJndIlSX+wsgVQBNEZH25c+Dz3/uaZVtOVldE4iav7r7qKkGVNoUwvEhoqSAcjSuqKEFiBhg== dependencies: "@aeternity/ledger-app-api" "0.0.4" "@ledgerhq/hw-app-btc" "^4.32.0" From 75a7dc831d4bdfe74b2a2065046a57d458fe9698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Mon, 17 Dec 2018 19:16:57 +0100 Subject: [PATCH 03/26] Implement Repair & Fix firmware update --- package.json | 2 +- src/commands/.DS_Store | Bin 0 -> 6148 bytes src/commands/firmwareCheckId.js | 19 ++ src/commands/firmwareMain.js | 19 ++ src/commands/firmwareRepair.js | 14 ++ src/commands/getLatestFirmwareForDevice.js | 17 +- src/commands/index.js | 14 +- src/commands/installApp.js | 16 +- src/commands/installFinalFirmware.js | 21 -- src/commands/installMcu.js | 19 -- src/commands/installOsuFirmware.js | 25 --- src/commands/shouldFlashMcu.js | 15 -- src/commands/uninstallApp.js | 12 +- src/components/GenuineCheck.js | 8 +- src/components/ManagerPage/AppsList.js | 67 +++--- src/components/ManagerPage/FirmwareUpdate.js | 67 ++---- .../ManagerPage/UpdateFirmwareButton.js | 13 +- src/components/ProgressBar/index.js | 2 +- src/components/ProgressCircle/index.js | 4 +- .../SettingsPage/RepairDeviceButton.js | 90 ++++++++ src/components/SettingsPage/sections/Help.js | 7 + src/components/base/Modal/ConfirmModal.js | 4 +- .../modals/UpdateFirmware/Disclaimer.js | 16 +- .../modals/UpdateFirmware/Installing.js | 7 +- src/components/modals/UpdateFirmware/index.js | 36 +-- .../steps/01-step-install-full-firmware.js | 112 +++------- .../UpdateFirmware/steps/02-step-flash-mcu.js | 127 +++-------- src/helpers/devices/getDeviceInfo.js | 41 +--- .../devices/getLatestFirmwareForDevice.js | 76 ------- src/helpers/devices/shouldFlashMcu.js | 49 ---- src/helpers/firmware/installFinalFirmware.js | 51 ----- src/helpers/firmware/installMcu.js | 34 --- src/helpers/firmware/installOsuFirmware.js | 50 ----- src/helpers/live-common-setup-internal-hw.js | 1 - src/helpers/live-common-setup.js | 4 +- static/i18n/en/app.json | 9 + yarn.lock | 211 ++++++++++++------ 37 files changed, 488 insertions(+), 791 deletions(-) create mode 100644 src/commands/.DS_Store create mode 100644 src/commands/firmwareCheckId.js create mode 100644 src/commands/firmwareMain.js create mode 100644 src/commands/firmwareRepair.js delete mode 100644 src/commands/installFinalFirmware.js delete mode 100644 src/commands/installMcu.js delete mode 100644 src/commands/installOsuFirmware.js delete mode 100644 src/commands/shouldFlashMcu.js create mode 100644 src/components/SettingsPage/RepairDeviceButton.js delete mode 100644 src/helpers/devices/getLatestFirmwareForDevice.js delete mode 100644 src/helpers/devices/shouldFlashMcu.js delete mode 100644 src/helpers/firmware/installFinalFirmware.js delete mode 100644 src/helpers/firmware/installMcu.js delete mode 100644 src/helpers/firmware/installOsuFirmware.js diff --git a/package.json b/package.json index 9ee3d020..9c98dca4 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "@ledgerhq/hw-transport": "^4.32.0", "@ledgerhq/hw-transport-node-hid": "^4.32.0", "@ledgerhq/ledger-core": "2.0.0-rc.14", - "@ledgerhq/live-common": "4.8.0-beta.4", + "@ledgerhq/live-common": "4.8.0-beta.12", "animated": "^0.2.2", "async": "^2.6.1", "axios": "^0.18.0", diff --git a/src/commands/.DS_Store b/src/commands/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 = createCommand( + 'firmwareCheckId', + ({ devicePath, osuFirmware }) => checkId(devicePath, osuFirmware), +) + +export default cmd diff --git a/src/commands/firmwareMain.js b/src/commands/firmwareMain.js new file mode 100644 index 00000000..4397a590 --- /dev/null +++ b/src/commands/firmwareMain.js @@ -0,0 +1,19 @@ +// @flow + +import main from '@ledgerhq/live-common/lib/hw/firmwareUpdate-main' +import type { FinalFirmware } from '@ledgerhq/live-common/lib/types/manager' +import { createCommand, Command } from 'helpers/ipc' + +type Input = { + finalFirmware: FinalFirmware, +} + +type Result = * + +const cmd: Command = createCommand( + 'firmwareMain', + ({ finalFirmware }) => main('', finalFirmware), + // devicePath='' HACK to not depend on a devicePath because it's dynamic +) + +export default cmd diff --git a/src/commands/firmwareRepair.js b/src/commands/firmwareRepair.js new file mode 100644 index 00000000..41e34401 --- /dev/null +++ b/src/commands/firmwareRepair.js @@ -0,0 +1,14 @@ +// @flow + +import repair from '@ledgerhq/live-common/lib/hw/firmwareUpdate-repair' +import { createCommand, Command } from 'helpers/ipc' + +type Input = void +type Result = * + +const cmd: Command = createCommand( + 'firmwareRepair', + () => repair(''), // devicePath='' HACK to not depend on a devicePath because it's dynamic +) + +export default cmd diff --git a/src/commands/getLatestFirmwareForDevice.js b/src/commands/getLatestFirmwareForDevice.js index e88f6a50..5dfe8a72 100644 --- a/src/commands/getLatestFirmwareForDevice.js +++ b/src/commands/getLatestFirmwareForDevice.js @@ -1,15 +1,18 @@ // @flow import { createCommand, Command } from 'helpers/ipc' -import { fromPromise } from 'rxjs/observable/fromPromise' -import type { DeviceInfo, OsuFirmware } from 'helpers/types' +import { from } from 'rxjs' +import type { + DeviceInfo, + OsuFirmware, + FinalFirmware, +} from '@ledgerhq/live-common/lib/types/manager' +import manager from '@ledgerhq/live-common/lib/manager' -import getLatestFirmwareForDevice from '../helpers/devices/getLatestFirmwareForDevice' +type Result = ?{ osu: OsuFirmware, final: FinalFirmware } -type Result = ?(OsuFirmware & { shouldFlashMcu: boolean }) - -const cmd: Command = createCommand('getLatestFirmwareForDevice', data => - fromPromise(getLatestFirmwareForDevice(data)), +const cmd: Command = createCommand('getLatestFirmwareForDevice', deviceInfo => + from(manager.getLatestFirmwareForDevice(deviceInfo)), ) export default cmd diff --git a/src/commands/index.js b/src/commands/index.js index 1022021c..a55d2bb4 100644 --- a/src/commands/index.js +++ b/src/commands/index.js @@ -4,6 +4,9 @@ import invariant from 'invariant' import type { Command } from 'helpers/ipc' import debugAppInfosForCurrency from 'commands/debugAppInfosForCurrency' +import firmwareCheckId from 'commands/firmwareCheckId' +import firmwareMain from 'commands/firmwareMain' +import firmwareRepair from 'commands/firmwareRepair' import getAddress from 'commands/getAddress' import getDeviceInfo from 'commands/getDeviceInfo' import getCurrentFirmware from 'commands/getCurrentFirmware' @@ -11,9 +14,6 @@ import getIsGenuine from 'commands/getIsGenuine' import getLatestFirmwareForDevice from 'commands/getLatestFirmwareForDevice' import getMemInfo from 'commands/getMemInfo' import installApp from 'commands/installApp' -import installFinalFirmware from 'commands/installFinalFirmware' -import installMcu from 'commands/installMcu' -import installOsuFirmware from 'commands/installOsuFirmware' import isDashboardOpen from 'commands/isDashboardOpen' import killInternalProcess from 'commands/killInternalProcess' import libcoreGetFees from 'commands/libcoreGetFees' @@ -28,7 +28,6 @@ import listAppVersions from 'commands/listAppVersions' import listCategories from 'commands/listCategories' import listenDevices from 'commands/listenDevices' import ping from 'commands/ping' -import shouldFlashMcu from 'commands/shouldFlashMcu' import signTransaction from 'commands/signTransaction' import testApdu from 'commands/testApdu' import testCrash from 'commands/testCrash' @@ -37,6 +36,9 @@ import uninstallApp from 'commands/uninstallApp' const all: Array> = [ debugAppInfosForCurrency, + firmwareCheckId, + firmwareMain, + firmwareRepair, getAddress, getDeviceInfo, getCurrentFirmware, @@ -44,9 +46,6 @@ const all: Array> = [ getLatestFirmwareForDevice, getMemInfo, installApp, - installFinalFirmware, - installMcu, - installOsuFirmware, isDashboardOpen, killInternalProcess, libcoreGetFees, @@ -61,7 +60,6 @@ const all: Array> = [ listCategories, listenDevices, ping, - shouldFlashMcu, signTransaction, testApdu, testCrash, diff --git a/src/commands/installApp.js b/src/commands/installApp.js index 2fd3c1c4..71e04ecb 100644 --- a/src/commands/installApp.js +++ b/src/commands/installApp.js @@ -1,25 +1,21 @@ // @flow import { createCommand, Command } from 'helpers/ipc' -import { from } from 'rxjs' +import installApp from '@ledgerhq/live-common/lib/hw/installApp' import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' -import installApp from 'helpers/apps/installApp' - -import type { ApplicationVersion } from 'helpers/types' +import type { ApplicationVersion } from '@ledgerhq/live-common/lib/types/manager' type Input = { - app: ApplicationVersion, devicePath: string, targetId: string | number, + app: ApplicationVersion, } -type Result = void +type Result = * -const cmd: Command = createCommand( - 'installApp', - ({ devicePath, targetId, ...app }) => - withDevice(devicePath)(transport => from(installApp(transport, targetId, app))), +const cmd: Command = createCommand('installApp', ({ devicePath, targetId, app }) => + withDevice(devicePath)(transport => installApp(transport, targetId, app)), ) export default cmd diff --git a/src/commands/installFinalFirmware.js b/src/commands/installFinalFirmware.js deleted file mode 100644 index bf56eeb3..00000000 --- a/src/commands/installFinalFirmware.js +++ /dev/null @@ -1,21 +0,0 @@ -// @flow - -import { createCommand, Command } from 'helpers/ipc' -import { from } from 'rxjs' -import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' - -import installFinalFirmware from 'helpers/firmware/installFinalFirmware' - -type Input = { - devicePath: string, -} - -type Result = { - success: boolean, -} - -const cmd: Command = createCommand('installFinalFirmware', ({ devicePath }) => - withDevice(devicePath)(transport => from(installFinalFirmware(transport))), -) - -export default cmd diff --git a/src/commands/installMcu.js b/src/commands/installMcu.js deleted file mode 100644 index 1301a68b..00000000 --- a/src/commands/installMcu.js +++ /dev/null @@ -1,19 +0,0 @@ -// @flow - -import { createCommand, Command } from 'helpers/ipc' -import { from } from 'rxjs' - -import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' -import installMcu from 'helpers/firmware/installMcu' - -type Input = { - devicePath: string, -} - -type Result = void - -const cmd: Command = createCommand('installMcu', ({ devicePath }) => - withDevice(devicePath)(transport => from(installMcu(transport))), -) - -export default cmd diff --git a/src/commands/installOsuFirmware.js b/src/commands/installOsuFirmware.js deleted file mode 100644 index e306eaa4..00000000 --- a/src/commands/installOsuFirmware.js +++ /dev/null @@ -1,25 +0,0 @@ -// @flow - -import { createCommand, Command } from 'helpers/ipc' -import { from } from 'rxjs' - -import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' -import installOsuFirmware from 'helpers/firmware/installOsuFirmware' - -import type { Firmware } from 'components/modals/UpdateFirmware' - -type Input = { - devicePath: string, - targetId: string | number, - firmware: Firmware, -} - -type Result = { success: boolean } - -const cmd: Command = createCommand( - 'installOsuFirmware', - ({ devicePath, firmware, targetId }) => - withDevice(devicePath)(transport => from(installOsuFirmware(transport, targetId, firmware))), -) - -export default cmd diff --git a/src/commands/shouldFlashMcu.js b/src/commands/shouldFlashMcu.js deleted file mode 100644 index f58c629c..00000000 --- a/src/commands/shouldFlashMcu.js +++ /dev/null @@ -1,15 +0,0 @@ -// @flow - -import { createCommand, Command } from 'helpers/ipc' -import { fromPromise } from 'rxjs/observable/fromPromise' -import shouldFlashMcu from 'helpers/devices/shouldFlashMcu' - -import type { DeviceInfo } from 'helpers/types' - -type Result = boolean - -const cmd: Command = createCommand('shouldFlashMcu', data => - fromPromise(shouldFlashMcu(data)), -) - -export default cmd diff --git a/src/commands/uninstallApp.js b/src/commands/uninstallApp.js index b0b581b8..684712c3 100644 --- a/src/commands/uninstallApp.js +++ b/src/commands/uninstallApp.js @@ -1,10 +1,8 @@ // @flow import { createCommand, Command } from 'helpers/ipc' -import { from } from 'rxjs' import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' - -import uninstallApp from 'helpers/apps/uninstallApp' +import uninstallApp from '@ledgerhq/live-common/lib/hw/uninstallApp' import type { ApplicationVersion } from 'helpers/types' @@ -14,12 +12,10 @@ type Input = { targetId: string | number, } -type Result = void +type Result = * -const cmd: Command = createCommand( - 'uninstallApp', - ({ devicePath, targetId, ...app }) => - withDevice(devicePath)(transport => from(uninstallApp(transport, targetId, app))), +const cmd: Command = createCommand('uninstallApp', ({ devicePath, targetId, app }) => + withDevice(devicePath)(transport => uninstallApp(transport, targetId, app)), ) export default cmd diff --git a/src/components/GenuineCheck.js b/src/components/GenuineCheck.js index ff02986c..76a53ba7 100644 --- a/src/components/GenuineCheck.js +++ b/src/components/GenuineCheck.js @@ -18,6 +18,7 @@ import { CantOpenDevice, DeviceNotGenuineError, DeviceGenuineSocketEarlyClose, + UnexpectedBootloader, } from '@ledgerhq/live-common/lib/errors' import getDeviceInfo from 'commands/getDeviceInfo' @@ -81,7 +82,12 @@ class GenuineCheck extends PureComponent { device: Device, deviceInfo: DeviceInfo, }) => { - if (deviceInfo.isOSU || deviceInfo.isBootloader) { + if (deviceInfo.isBootloader) { + logger.log('device is in bootloader mode') + throw new UnexpectedBootloader() + } + + if (deviceInfo.isOSU) { logger.log('device is in update mode. skipping genuine') return true } diff --git a/src/components/ManagerPage/AppsList.js b/src/components/ManagerPage/AppsList.js index 91443678..a155af7c 100644 --- a/src/components/ManagerPage/AppsList.js +++ b/src/components/ManagerPage/AppsList.js @@ -6,6 +6,8 @@ import styled from 'styled-components' import { translate } from 'react-i18next' import { connect } from 'react-redux' import { compose } from 'redux' +import { throttleTime, filter, map } from 'rxjs/operators' + import type { Device, T } from 'types/common' import type { ApplicationVersion, DeviceInfo } from 'helpers/types' import { getFullListSortedCryptoCurrencies } from 'helpers/countervalues' @@ -19,7 +21,7 @@ import Space from 'components/base/Space' import Modal, { ModalBody, ModalFooter, ModalTitle, ModalContent } from 'components/base/Modal' import Tooltip from 'components/base/Tooltip' import Text from 'components/base/Text' -import Progress from 'components/base/Progress' +import ProgressBar from 'components/ProgressBar' import Spinner from 'components/base/Spinner' import Button from 'components/base/Button' import TranslatedError from 'components/TranslatedError' @@ -65,6 +67,7 @@ type State = { appsLoaded: boolean, app: string, mode: Mode, + progress: number, } const oldAppsInstallDisabled = ['ZenCash', 'Ripple'] @@ -86,6 +89,7 @@ class AppsList extends PureComponent { appsLoaded: false, app: '', mode: 'home', + progress: 0, } componentDidMount() { @@ -158,41 +162,44 @@ class AppsList extends PureComponent { } } - handleInstallApp = (app: ApplicationVersion) => async () => { - this.setState({ status: 'busy', app: app.name, mode: 'installing' }) - try { - const { - device: { path: devicePath }, - deviceInfo, - } = this.props - const data = { app, devicePath, targetId: deviceInfo.targetId } - await installApp.send(data).toPromise() - this.setState({ status: 'success' }) - } catch (err) { - this.setState({ status: 'error', error: err, mode: 'home' }) - } + sub: * + runAppScript = (app: ApplicationVersion, mode: *, cmd: *) => { + this.setState({ status: 'busy', app: app.name, mode, progress: 0 }) + const { + device: { path: devicePath }, + deviceInfo: { targetId }, + } = this.props + this.sub = cmd + .send({ app, devicePath, targetId }) + .pipe( + filter(e => e.type === 'bulk-progress'), // only bulk progress interests the UI + throttleTime(100), // throttle to only emit 10 event/s max, to not spam the UI + map(e => e.progress), // extract a stream of progress percentage + ) + .subscribe({ + next: progress => { + this.setState({ progress }) + }, + complete: () => { + this.setState({ status: 'success' }) + }, + error: error => { + this.setState({ status: 'error', error, app: '', mode: 'home' }) + }, + }) } - handleUninstallApp = (app: ApplicationVersion) => async () => { - this.setState({ status: 'busy', app: app.name, mode: 'uninstalling' }) - try { - const { - device: { path: devicePath }, - deviceInfo, - } = this.props - const data = { app, devicePath, targetId: deviceInfo.targetId } - await uninstallApp.send(data).toPromise() - this.setState({ status: 'success' }) - } catch (err) { - this.setState({ status: 'error', error: err, app: '', mode: 'home' }) - } - } + handleInstallApp = (app: ApplicationVersion) => () => + this.runAppScript(app, 'installing', installApp) + + handleUninstallApp = (app: ApplicationVersion) => () => + this.runAppScript(app, 'uninstalling', uninstallApp) handleCloseModal = () => this.setState({ status: 'idle', mode: 'home' }) renderModal = () => { const { t } = this.props - const { app, status, error, mode } = this.state + const { app, status, error, mode, progress } = this.state return ( { {t(`manager.apps.${mode}`, { app })} - + diff --git a/src/components/ManagerPage/FirmwareUpdate.js b/src/components/ManagerPage/FirmwareUpdate.js index 90e997b1..e9c7fe72 100644 --- a/src/components/ManagerPage/FirmwareUpdate.js +++ b/src/components/ManagerPage/FirmwareUpdate.js @@ -5,18 +5,17 @@ import React, { PureComponent, Fragment } from 'react' import { translate } from 'react-i18next' import isEqual from 'lodash/isEqual' import isEmpty from 'lodash/isEmpty' -import invariant from 'invariant' import type { Device, T } from 'types/common' -import type { DeviceInfo, OsuFirmware } from 'helpers/types' +import type { + DeviceInfo, + OsuFirmware, + FinalFirmware, +} from '@ledgerhq/live-common/lib/types/manager' import type { StepId } from 'components/modals/UpdateFirmware' import getLatestFirmwareForDevice from 'commands/getLatestFirmwareForDevice' -import shouldFlashMcu from 'commands/shouldFlashMcu' -import installOsuFirmware from 'commands/installOsuFirmware' -import installFinalFirmware from 'commands/installFinalFirmware' -import installMcu from 'commands/installMcu' import DisclaimerModal from 'components/modals/UpdateFirmware/Disclaimer' import UpdateModal from 'components/modals/UpdateFirmware' @@ -42,7 +41,7 @@ type Props = { } type State = { - latestFirmware: ?OsuFirmware & ?{ shouldFlashMcu: boolean }, + firmware: ?{ osu: OsuFirmware, final: FinalFirmware }, modal: ModalStatus, stepId: ?StepId, shouldFlash: boolean, @@ -50,7 +49,7 @@ type State = { } const intializeState = ({ deviceInfo }): State => ({ - latestFirmware: null, + firmware: null, modal: 'closed', stepId: deviceInfo.isBootloader ? 'updateMCU' : 'idCheck', shouldFlash: false, @@ -64,9 +63,7 @@ class FirmwareUpdate extends PureComponent { const { deviceInfo } = this.props if (!deviceInfo.isOSU && !deviceInfo.isBootloader) { this.fetchLatestFirmware() - } else if (deviceInfo.isOSU) { - this.shouldFlashMcu() - } else if (deviceInfo.isBootloader) { + } else { this.handleInstallModal('updateMCU', true) } } @@ -79,45 +76,16 @@ class FirmwareUpdate extends PureComponent { fetchLatestFirmware = async () => { const { deviceInfo } = this.props - const latestFirmware = await getLatestFirmwareForDevice.send(deviceInfo).toPromise() - if ( - !isEmpty(latestFirmware) && - !isEqual(this.state.latestFirmware, latestFirmware) && - !this._unmounting - ) { - this.setState({ latestFirmware, ready: true }) + const firmware = await getLatestFirmwareForDevice.send(deviceInfo).toPromise() + if (!isEmpty(firmware) && !isEqual(this.state.firmware, firmware) && !this._unmounting) { + this.setState({ firmware, ready: true }) } } - shouldFlashMcu = async () => { - const { deviceInfo } = this.props - const shouldFlash = await shouldFlashMcu.send(deviceInfo).toPromise() - if (!this._unmounting) { - this.setState({ shouldFlash, modal: 'install', stepId: 'idCheck', ready: true }) - } - } - - installOsuFirmware = async (device: Device) => { - const { latestFirmware } = this.state - const { deviceInfo } = this.props - invariant(latestFirmware, 'did not find a new firmware or firmware is not set') - - this.setState({ modal: 'install' }) - const result = await installOsuFirmware - .send({ devicePath: device.path, firmware: latestFirmware, targetId: deviceInfo.targetId }) - .toPromise() - - return result - } - - installFinalFirmware = (device: Device) => - installFinalFirmware.send({ devicePath: device.path }).toPromise() - - flashMCU = async (device: Device) => installMcu.send({ devicePath: device.path }).toPromise() - handleCloseModal = () => this.setState({ modal: 'closed' }) handleDisclaimerModal = () => this.setState({ modal: 'disclaimer' }) + handleInstallModal = (stepId: StepId = 'idCheck', shouldFlash?: boolean) => this.setState({ modal: 'install', stepId, shouldFlash, ready: true }) @@ -125,7 +93,7 @@ class FirmwareUpdate extends PureComponent { render() { const { deviceInfo, t, device } = this.props - const { latestFirmware, modal, stepId, shouldFlash, ready } = this.state + const { firmware, modal, stepId, shouldFlash, ready } = this.state return ( @@ -151,12 +119,12 @@ class FirmwareUpdate extends PureComponent { })} - + {ready ? ( { status={modal} stepId={stepId} onClose={this.handleCloseModal} - firmware={latestFirmware} + firmware={firmware} shouldFlashMcu={shouldFlash} - installOsuFirmware={this.installOsuFirmware} - installFinalFirmware={this.installFinalFirmware} - flashMCU={this.flashMCU} /> ) : null} diff --git a/src/components/ManagerPage/UpdateFirmwareButton.js b/src/components/ManagerPage/UpdateFirmwareButton.js index fcfc529e..66d6e314 100644 --- a/src/components/ManagerPage/UpdateFirmwareButton.js +++ b/src/components/ManagerPage/UpdateFirmwareButton.js @@ -3,19 +3,14 @@ import React, { Fragment } from 'react' import { translate } from 'react-i18next' import type { T } from 'types/common' - +import type { OsuFirmware, FinalFirmware } from '@ledgerhq/live-common/lib/types/manager' import Button from 'components/base/Button' import Text from 'components/base/Text' import { getCleanVersion } from 'components/ManagerPage/FirmwareUpdate' -type FirmwareInfos = { - name: string, - notes: string, -} - type Props = { t: T, - firmware: ?FirmwareInfos, + firmware: ?{ osu: OsuFirmware, finalFirmware: FinalFirmware }, onClick: () => void, } @@ -23,14 +18,14 @@ const UpdateFirmwareButton = ({ t, firmware, onClick }: Props) => firmware ? ( - {t('manager.firmware.latest', { version: getCleanVersion(firmware.name) })} + {t('manager.firmware.latest', { version: getCleanVersion(firmware.osu.name) })} + + + + ) + } +} + +export default translate()(CleanButton) diff --git a/src/components/SettingsPage/sections/Help.js b/src/components/SettingsPage/sections/Help.js index c4577020..15eba3c4 100644 --- a/src/components/SettingsPage/sections/Help.js +++ b/src/components/SettingsPage/sections/Help.js @@ -11,6 +11,7 @@ import ExportLogsBtn from 'components/ExportLogsBtn' import OpenUserDataDirectoryBtn from 'components/OpenUserDataDirectoryBtn' import CleanButton from '../CleanButton' import ResetButton from '../ResetButton' +import RepairDeviceButton from '../RepairDeviceButton' import AboutRowItem from '../AboutRowItem' import LaunchOnboardingBtn from '../LaunchOnboardingBtn' @@ -72,6 +73,12 @@ class SectionHelp extends PureComponent { > + + + ) diff --git a/src/components/base/Modal/ConfirmModal.js b/src/components/base/Modal/ConfirmModal.js index 9ed7cbe6..0512a981 100644 --- a/src/components/base/Modal/ConfirmModal.js +++ b/src/components/base/Modal/ConfirmModal.js @@ -25,11 +25,13 @@ type Props = { t: T, isLoading?: boolean, analyticsName: string, + cancellable?: boolean, } class ConfirmModal extends PureComponent { render() { const { + cancellable, isOpened, title, subTitle, @@ -54,7 +56,7 @@ class ConfirmModal extends PureComponent { preventBackdropClick={isLoading} {...props} render={({ onClose }) => ( - + {title} diff --git a/src/components/modals/UpdateFirmware/Disclaimer.js b/src/components/modals/UpdateFirmware/Disclaimer.js index f4fce175..bdc9d22f 100644 --- a/src/components/modals/UpdateFirmware/Disclaimer.js +++ b/src/components/modals/UpdateFirmware/Disclaimer.js @@ -3,7 +3,7 @@ import React, { PureComponent, Fragment } from 'react' import { translate, Trans } from 'react-i18next' - +import type { OsuFirmware, FinalFirmware } from '@ledgerhq/live-common/lib/types/manager' import type { T } from 'types/common' import Modal, { ModalBody, ModalFooter, ModalTitle, ModalContent } from 'components/base/Modal' @@ -18,15 +18,13 @@ import type { ModalStatus } from 'components/ManagerPage/FirmwareUpdate' import { getCleanVersion } from 'components/ManagerPage/FirmwareUpdate' -type FirmwareInfos = { - name: string, - notes: string, -} - type Props = { t: T, status: ModalStatus, - firmware: FirmwareInfos, + firmware: { + osu: OsuFirmware, + final: FinalFirmware, + }, goToNextStep: () => void, onClose: () => void, } @@ -50,7 +48,7 @@ class DisclaimerModal extends PureComponent { You are about to install - {`firmware version ${firmware ? getCleanVersion(firmware.name) : ''}`} + {`firmware version ${firmware ? getCleanVersion(firmware.osu.name) : ''}`} @@ -62,7 +60,7 @@ class DisclaimerModal extends PureComponent { - {firmware.notes} + {firmware.osu.notes} diff --git a/src/components/modals/UpdateFirmware/Installing.js b/src/components/modals/UpdateFirmware/Installing.js index 2333399e..5a06c152 100644 --- a/src/components/modals/UpdateFirmware/Installing.js +++ b/src/components/modals/UpdateFirmware/Installing.js @@ -4,19 +4,20 @@ import { translate } from 'react-i18next' import Box from 'components/base/Box' import Text from 'components/base/Text' -import Spinner from 'components/base/Spinner' +import ProgressCircle from 'components/ProgressCircle' import type { T } from 'types/common' type Props = { t: T, + progress: number, } -function Installing({ t }: Props) { +function Installing({ t, progress }: Props) { return ( - + diff --git a/src/components/modals/UpdateFirmware/index.js b/src/components/modals/UpdateFirmware/index.js index d2888743..a18a8023 100644 --- a/src/components/modals/UpdateFirmware/index.js +++ b/src/components/modals/UpdateFirmware/index.js @@ -2,22 +2,22 @@ import React, { PureComponent } from 'react' import { translate } from 'react-i18next' -import type { T, Device } from 'types/common' +import type { T } from 'types/common' import Modal from 'components/base/Modal' import Stepper from 'components/base/Stepper' import SyncSkipUnderPriority from 'components/SyncSkipUnderPriority' +import type { OsuFirmware, FinalFirmware } from '@ledgerhq/live-common/lib/types/manager' import type { StepProps as DefaultStepProps, Step } from 'components/base/Stepper' import type { ModalStatus } from 'components/ManagerPage/FirmwareUpdate' -import type { OsuFirmware } from 'helpers/types' import { FreezeDeviceChangeEvents } from '../../ManagerPage/HookDeviceChange' import StepFullFirmwareInstall from './steps/01-step-install-full-firmware' import StepFlashMcu from './steps/02-step-flash-mcu' import StepConfirmation, { StepConfirmFooter } from './steps/03-step-confirmation' -const createSteps = ({ t, shouldFlashMcu }: { t: T, shouldFlashMcu: boolean }): Array<*> => { +const createSteps = ({ t }: { t: T }): Array<*> => { const updateStep = { id: 'idCheck', label: t('manager.modal.identifier'), @@ -45,26 +45,13 @@ const createSteps = ({ t, shouldFlashMcu }: { t: T, shouldFlashMcu: boolean }): hideFooter: true, } - const steps = [updateStep] - - if (shouldFlashMcu) { - steps.push(mcuStep) - } - - steps.push(finalStep) - - return steps + return [updateStep, mcuStep, finalStep] } -export type Firmware = OsuFirmware & { shouldFlashMcu: boolean } - export type StepProps = DefaultStepProps & { - firmware: Firmware, + osu: OsuFirmware, + final: FinalFirmware, onCloseModal: () => void, - installOsuFirmware: (device: Device) => void, - installFinalFirmware: (device: Device) => void, - flashMCU: (device: Device) => void, - shouldFlashMcu: boolean, error: ?Error, setError: Error => void, } @@ -75,11 +62,7 @@ type Props = { t: T, status: ModalStatus, onClose: () => void, - firmware: Firmware, - shouldFlashMcu: boolean, - installOsuFirmware: (device: Device) => void, - installFinalFirmware: (device: Device) => void, - flashMCU: (device: Device) => void, + firmware: { osu: OsuFirmware, final: FinalFirmware }, stepId: StepId | string, } @@ -98,9 +81,6 @@ class UpdateModal extends PureComponent { STEPS = createSteps({ t: this.props.t, - shouldFlashMcu: this.props.firmware - ? this.props.firmware.shouldFlashMcu - : this.props.shouldFlashMcu, }) setError = (e: Error) => this.setState({ error: e }) @@ -114,10 +94,10 @@ class UpdateModal extends PureComponent { const { stepId, error, nonce } = this.state const additionalProps = { - firmware, error, onCloseModal: onClose, setError: this.setError, + ...firmware, ...props, } diff --git a/src/components/modals/UpdateFirmware/steps/01-step-install-full-firmware.js b/src/components/modals/UpdateFirmware/steps/01-step-install-full-firmware.js index 154eafb0..4121ff06 100644 --- a/src/components/modals/UpdateFirmware/steps/01-step-install-full-firmware.js +++ b/src/components/modals/UpdateFirmware/steps/01-step-install-full-firmware.js @@ -3,24 +3,16 @@ import React, { PureComponent, Fragment } from 'react' import styled from 'styled-components' import { connect } from 'react-redux' -import { timeout } from 'rxjs/operators/timeout' - -import { DEVICE_INFOS_TIMEOUT } from 'config/constants' -import getDeviceInfo from 'commands/getDeviceInfo' +import firmwareCheckId from 'commands/firmwareCheckId' import { getCurrentDevice } from 'reducers/devices' -import { createCancelablePolling, delay } from 'helpers/promise' - import TrackPage from 'analytics/TrackPage' import Box from 'components/base/Box' import Text from 'components/base/Text' import DeviceConfirm from 'components/DeviceConfirm' - import type { Device } from 'types/common' import type { StepProps } from '../' -import Installing from '../Installing' - const Container = styled(Box).attrs({ alignItems: 'center', fontSize: 4, @@ -55,79 +47,37 @@ type Props = StepProps & { device: Device, } -type State = { - installing: boolean, -} - -class StepFullFirmwareInstall extends PureComponent { - state = { - installing: false, - } - +class StepFullFirmwareInstall extends PureComponent { componentDidMount() { - this.install() - } - - componentWillUnmount() { - if (this._unsubConnect) this._unsubConnect() - } + const { osu, device, transitionTo, setError } = this.props - ensureDevice = () => { - const { unsubscribe, promise } = createCancelablePolling(async () => { - const { device } = this.props - if (!device) { - throw new Error('No device') - } - - const deviceInfo = await getDeviceInfo - .send({ devicePath: device.path }) - .pipe(timeout(DEVICE_INFOS_TIMEOUT)) - .toPromise() - return { device, deviceInfo } - }) - this._unsubConnect = unsubscribe - return promise - } - - install = async () => { - const { - installOsuFirmware, - installFinalFirmware, - firmware, - shouldFlashMcu, - transitionTo, - setError, - } = this.props - const { device, deviceInfo } = await this.ensureDevice() - - if (deviceInfo.isBootloader) { - transitionTo('updateMCU') + if (!osu) { + transitionTo('finish') + return } - try { - if (deviceInfo.isOSU) { - this.setState({ installing: true }) - await installFinalFirmware(device) - transitionTo('finish') - } else { - await installOsuFirmware(device) - this.setState({ installing: true }) - if (this._unsubConnect) this._unsubConnect() - if ((firmware && firmware.shouldFlashMcu) || shouldFlashMcu) { - delay(1000) + this.sub = firmwareCheckId + .send({ + devicePath: device.path, + osuFirmware: osu, + }) + .subscribe({ + complete: () => { transitionTo('updateMCU') - } else { - const { device: freshDevice } = await this.ensureDevice() - await installFinalFirmware(freshDevice) + }, + error: error => { + setError(error) transitionTo('finish') - } - } - } catch (error) { - setError(error) - transitionTo('finish') - } + }, + }) } + componentWillUnmount() { + if (this.sub) this.sub.unsubscribe() + } + + sub: * + formatHashName = (hash: string): string => { if (!hash) { return '' @@ -138,11 +88,8 @@ class StepFullFirmwareInstall extends PureComponent { } renderBody = () => { - const { installing } = this.state - const { t, firmware } = this.props - return installing ? ( - - ) : ( + const { t, osu } = this.props + return ( {t('manager.modal.confirmIdentifierText')} @@ -151,7 +98,7 @@ class StepFullFirmwareInstall extends PureComponent { {t('manager.modal.identifier')} -
{firmware && this.formatHashName(firmware.hash)}
+
{osu && this.formatHashName(osu.hash)}
@@ -160,14 +107,11 @@ class StepFullFirmwareInstall extends PureComponent { ) } - _unsubConnect: * - render() { - const { installing } = this.state const { t } = this.props return ( - {installing ? '' : t('manager.modal.confirmIdentifier')} + {t('manager.modal.confirmIdentifier')} {this.renderBody()} diff --git a/src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js b/src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js index 2ee8f1a9..308a58b8 100644 --- a/src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js +++ b/src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js @@ -2,21 +2,15 @@ import React, { PureComponent, Fragment } from 'react' import styled from 'styled-components' -import { connect } from 'react-redux' -import { timeout } from 'rxjs/operators/timeout' +import { filter, tap } from 'rxjs/operators' -import { DEVICE_INFOS_TIMEOUT } from 'config/constants' import { i } from 'helpers/staticPath' -import { getCurrentDevice } from 'reducers/devices' -import { createCancelablePolling } from 'helpers/promise' -import getDeviceInfo from 'commands/getDeviceInfo' +import firmwareMain from 'commands/firmwareMain' import TrackPage from 'analytics/TrackPage' import Box from 'components/base/Box' import Text from 'components/base/Text' -import type { Device } from 'types/common' - import type { StepProps } from '../' import Installing from '../Installing' @@ -46,107 +40,59 @@ const Separator = styled(Box).attrs({ background-color: currentColor; ` -const mapStateToProps = state => ({ - device: getCurrentDevice(state), -}) - -type Props = StepProps & { device?: Device } +type Props = StepProps type State = { installing: boolean, + progress: number, } class StepFlashMcu extends PureComponent { state = { installing: false, + progress: 0, } componentDidMount() { - this.install() + const { final: finalFirmware, transitionTo, setError } = this.props + + this.sub = firmwareMain + .send({ finalFirmware }) + .pipe( + tap(e => console.log(e)), // eslint-disable-line no-console + // ^ TODO remove at the end + filter(e => e.type === 'bulk-progress' || e.type === 'install'), + ) + .subscribe({ + next: e => { + if (e.type === 'install') { + this.setState({ installing: e.step, progress: 0 }) + } else { + this.setState({ progress: e.progress }) + } + }, + complete: () => { + transitionTo('finish') + }, + error: error => { + setError(error) + transitionTo('finish') + }, + }) } componentWillUnmount() { - if (this._unsubConnect) this._unsubConnect() - if (this._unsubDeviceInfo) this._unsubDeviceInfo() - } - - getDeviceInfo = () => { - const { unsubscribe, promise } = createCancelablePolling(async () => { - const { device } = this.props - if (!device) { - throw new Error('No device') - } - const deviceInfo = await getDeviceInfo - .send({ devicePath: device.path }) - .pipe(timeout(DEVICE_INFOS_TIMEOUT)) - .toPromise() - - return { device, deviceInfo } - }) - this._unsubDeviceInfo = unsubscribe - return promise + if (this.sub) this.sub.unsubscribe() } - waitForDeviceInBootloader = () => { - const { unsubscribe, promise } = createCancelablePolling(async () => { - const { device } = this.props - if (!device) { - throw new Error('No device') - } - const deviceInfo = await getDeviceInfo - .send({ devicePath: device.path }) - .pipe(timeout(DEVICE_INFOS_TIMEOUT)) - .toPromise() - - if (!deviceInfo.isBootloader) { - throw new Error('Device is not in bootloader') - } - return { device, deviceInfo } - }) - this._unsubConnect = unsubscribe - return promise - } - - flash = async () => { - await this.waitForDeviceInBootloader() - const { flashMCU, device } = this.props - if (device) { - this.setState({ installing: true }) - await flashMCU(device) - } - } - - install = async () => { - const { transitionTo, installFinalFirmware, setError } = this.props - const { deviceInfo, device } = await this.getDeviceInfo() - - try { - if (deviceInfo.isBootloader) { - await this.flash() - this.install() - } else if (deviceInfo.isOSU) { - await installFinalFirmware(device) - transitionTo('finish') - } else { - transitionTo('finish') - } - } catch (error) { - setError(error) - transitionTo('finish') - } - } - - firstFlash = async () => { - await this.flash() - this.install() - } + sub: * renderBody = () => { - const { installing } = this.state + const { installing, progress } = this.state const { t } = this.props return installing ? ( - + ) : ( @@ -176,9 +122,6 @@ class StepFlashMcu extends PureComponent { ) } - _unsubConnect: * - _unsubDeviceInfo: * - render() { const { t } = this.props const { installing } = this.state @@ -192,4 +135,4 @@ class StepFlashMcu extends PureComponent { } } -export default connect(mapStateToProps)(StepFlashMcu) +export default StepFlashMcu diff --git a/src/helpers/devices/getDeviceInfo.js b/src/helpers/devices/getDeviceInfo.js index 24b6d7d1..1bfef909 100644 --- a/src/helpers/devices/getDeviceInfo.js +++ b/src/helpers/devices/getDeviceInfo.js @@ -1,42 +1,5 @@ // @flow -import type Transport from '@ledgerhq/hw-transport' +import getDeviceInfo from '@ledgerhq/live-common/lib/hw/getDeviceInfo' -import getFirmwareInfo from 'helpers/firmware/getFirmwareInfo' -import { FORCE_PROVIDER } from 'config/constants' - -import type { DeviceInfo } from 'helpers/types' - -const PROVIDERS = { - '': 1, - das: 2, - club: 3, - shitcoins: 4, - ee: 5, -} - -export default async (transport: Transport<*>): Promise => { - const res = await getFirmwareInfo(transport) - const { seVersion } = res - const { targetId, mcuVersion, flags } = res - const parsedVersion = - seVersion.match(/([0-9]+.[0-9])+(.[0-9]+)?((?!-osu)-([a-z]+))?(-osu)?/) || [] - const isOSU = typeof parsedVersion[5] !== 'undefined' - const providerName = parsedVersion[4] || '' - const providerId = FORCE_PROVIDER || PROVIDERS[providerName] - const isBootloader = targetId === 0x01000001 - const majMin = parsedVersion[1] - const patch = parsedVersion[2] || '.0' - const fullVersion = `${majMin}${patch}${providerName ? `-${providerName}` : ''}` - return { - targetId, - seVersion: majMin + patch, - isOSU, - mcuVersion, - isBootloader, - providerName, - providerId, - flags, - fullVersion, - } -} +export default getDeviceInfo diff --git a/src/helpers/devices/getLatestFirmwareForDevice.js b/src/helpers/devices/getLatestFirmwareForDevice.js deleted file mode 100644 index 80e14af8..00000000 --- a/src/helpers/devices/getLatestFirmwareForDevice.js +++ /dev/null @@ -1,76 +0,0 @@ -// @flow -import network from 'api/network' -import { GET_LATEST_FIRMWARE } from 'helpers/urls' -import type { - DeviceInfo, - DeviceVersion, - FinalFirmware, - OsuFirmware, - McuVersion, -} from 'helpers/types' - -import getFinalFirmwareById from 'helpers/firmware/getFinalFirmwareById' -import getMcus from 'helpers/firmware/getMcus' - -import getCurrentFirmware from './getCurrentFirmware' -import getDeviceVersion from './getDeviceVersion' - -type NetworkResponse = { - data: { - result: string, - se_firmware_osu_version: OsuFirmware, - }, -} - -type Result = ?(OsuFirmware & { shouldFlashMcu: boolean }) - -export default async (deviceInfo: DeviceInfo): Promise => { - // Get device infos from targetId - const deviceVersion: DeviceVersion = await getDeviceVersion( - deviceInfo.targetId, - deviceInfo.providerId, - ) - - // Get firmware infos with firmware name and device version - const seFirmwareVersion: FinalFirmware = await getCurrentFirmware({ - fullVersion: deviceInfo.fullVersion, - deviceId: deviceVersion.id, - provider: deviceInfo.providerId, - }) - - // Fetch next possible firmware - const { data }: NetworkResponse = await network({ - method: 'POST', - url: GET_LATEST_FIRMWARE, - data: { - current_se_firmware_final_version: seFirmwareVersion.id, - device_version: deviceVersion.id, - provider: deviceInfo.providerId, - }, - }) - - if (data.result === 'null') { - return null - } - - const { se_firmware_osu_version } = data - const { next_se_firmware_final_version } = se_firmware_osu_version - const seFirmwareFinalVersion: FinalFirmware = await getFinalFirmwareById( - next_se_firmware_final_version, - ) - - const mcus: Array = await getMcus() - - const currentMcuVersionId: Array = mcus - .filter(mcu => mcu.name === deviceInfo.mcuVersion) - .map(mcu => mcu.id) - - if (!seFirmwareFinalVersion.mcu_versions.includes(...currentMcuVersionId)) { - return { - ...se_firmware_osu_version, - shouldFlashMcu: true, - } - } - - return { ...se_firmware_osu_version, shouldFlashMcu: false } -} diff --git a/src/helpers/devices/shouldFlashMcu.js b/src/helpers/devices/shouldFlashMcu.js deleted file mode 100644 index 1ed0a768..00000000 --- a/src/helpers/devices/shouldFlashMcu.js +++ /dev/null @@ -1,49 +0,0 @@ -// @flow -import network from 'api/network' -import { GET_LATEST_FIRMWARE } from 'helpers/urls' -import type { DeviceInfo } from 'helpers/types' - -import getFinalFirmwareById from 'helpers/firmware/getFinalFirmwareById' -import getMcus from 'helpers/firmware/getMcus' - -import getOsuFirmware from './getOsuFirmware' -import getDeviceVersion from './getDeviceVersion' - -export default async (deviceInfo: DeviceInfo): Promise => { - // Get device infos from targetId - const deviceVersion = await getDeviceVersion(deviceInfo.targetId, deviceInfo.providerId) - - // Get firmware infos with firmware name and device version - const seFirmwareVersion = await getOsuFirmware({ - version: deviceInfo.fullVersion, - deviceId: deviceVersion.id, - provider: deviceInfo.providerId, - }) - - // Fetch next possible firmware - const { data } = await network({ - method: 'POST', - url: GET_LATEST_FIRMWARE, - data: { - current_se_firmware_final_version: seFirmwareVersion.id, - device_version: deviceVersion.id, - provider: deviceInfo.providerId, - }, - }) - - if (data.result === 'null') { - return false - } - - const { se_firmware_osu_version } = data - const { next_se_firmware_final_version } = se_firmware_osu_version - const seFirmwareFinalVersion = await getFinalFirmwareById(next_se_firmware_final_version) - - const mcus = await getMcus() - - const currentMcuVersionId = mcus - .filter(mcu => mcu.name === deviceInfo.mcuVersion) - .map(mcu => mcu.id) - - return !seFirmwareFinalVersion.mcu_versions.includes(...currentMcuVersionId) -} diff --git a/src/helpers/firmware/installFinalFirmware.js b/src/helpers/firmware/installFinalFirmware.js deleted file mode 100644 index 8d643e31..00000000 --- a/src/helpers/firmware/installFinalFirmware.js +++ /dev/null @@ -1,51 +0,0 @@ -// @flow -import type Transport from '@ledgerhq/hw-transport' -import type { DeviceInfo, DeviceVersion, OsuFirmware, FinalFirmware } from 'helpers/types' - -import { WS_INSTALL } from 'helpers/urls' -import { createDeviceSocket } from 'helpers/socket' -import getDeviceVersion from 'helpers/devices/getDeviceVersion' -import getOsuFirmware from 'helpers/devices/getOsuFirmware' -import getDeviceInfo from 'helpers/devices/getDeviceInfo' -import { ManagerDeviceLockedError } from '@ledgerhq/live-common/lib/errors' - -import getFinalFirmwareById from './getFinalFirmwareById' - -function remapSocketError(promise) { - return promise.catch((e: Error) => { - switch (true) { - case e.message.endsWith('6982'): - throw new ManagerDeviceLockedError() - default: - throw e - } - }) -} - -type Result = Promise<{ success: boolean }> - -export default async (transport: Transport<*>): Result => { - try { - const deviceInfo: DeviceInfo = await getDeviceInfo(transport) - const device: DeviceVersion = await getDeviceVersion(deviceInfo.targetId, deviceInfo.providerId) - const firmware: OsuFirmware = await getOsuFirmware({ - deviceId: device.id, - version: deviceInfo.fullVersion, - provider: deviceInfo.providerId, - }) - const { next_se_firmware_final_version } = firmware - const nextFirmware: FinalFirmware = await getFinalFirmwareById(next_se_firmware_final_version) - - const params = { - targetId: deviceInfo.targetId, - ...nextFirmware, - firmwareKey: nextFirmware.firmware_key, - } - - const url = WS_INSTALL(params) - await remapSocketError(createDeviceSocket(transport, url).toPromise()) - return { success: true } - } catch (error) { - throw error - } -} diff --git a/src/helpers/firmware/installMcu.js b/src/helpers/firmware/installMcu.js deleted file mode 100644 index b8ece4a4..00000000 --- a/src/helpers/firmware/installMcu.js +++ /dev/null @@ -1,34 +0,0 @@ -// @flow -import type Transport from '@ledgerhq/hw-transport' - -import { WS_MCU } from 'helpers/urls' -import { createDeviceSocket } from 'helpers/socket' -import getNextMCU from 'helpers/firmware/getNextMCU' -import getDeviceInfo from 'helpers/devices/getDeviceInfo' -import { ManagerDeviceLockedError } from '@ledgerhq/live-common/lib/errors' - -import type { DeviceInfo } from 'helpers/types' - -function remapSocketError(promise) { - return promise.catch((e: Error) => { - switch (true) { - case e.message.endsWith('6982'): - throw new ManagerDeviceLockedError() - default: - throw e - } - }) -} - -type Result = Promise - -export default async (transport: Transport<*>): Result => { - const { seVersion: version, targetId }: DeviceInfo = await getDeviceInfo(transport) - const nextVersion = await getNextMCU(version) - const params = { - targetId, - version: nextVersion.name, - } - const url = WS_MCU(params) - await remapSocketError(createDeviceSocket(transport, url).toPromise()) -} diff --git a/src/helpers/firmware/installOsuFirmware.js b/src/helpers/firmware/installOsuFirmware.js deleted file mode 100644 index a1194d3c..00000000 --- a/src/helpers/firmware/installOsuFirmware.js +++ /dev/null @@ -1,50 +0,0 @@ -// @flow -import type Transport from '@ledgerhq/hw-transport' - -import { WS_INSTALL } from 'helpers/urls' -import { createDeviceSocket } from 'helpers/socket' - -import type { Firmware } from 'components/modals/UpdateFirmware' - -import { - ManagerNotEnoughSpaceError, - ManagerDeviceLockedError, - UserRefusedFirmwareUpdate, -} from '@ledgerhq/live-common/lib/errors' - -function remapError(promise) { - return promise.catch((e: Error) => { - switch (true) { - case e.message.endsWith('6985'): - throw new UserRefusedFirmwareUpdate() - case e.message.endsWith('6982'): - throw new ManagerDeviceLockedError() - case e.message.endsWith('6a84') || e.message.endsWith('6a85'): - throw new ManagerNotEnoughSpaceError() - default: - throw e - } - }) -} - -type Result = Promise<{ success: boolean }> - -export default async ( - transport: Transport<*>, - targetId: string | number, - firmware: Firmware, -): Result => { - try { - const params = { - targetId, - ...firmware, - firmwareKey: firmware.firmware_key, - } - delete params.shouldFlashMcu - const url = WS_INSTALL(params) - await remapError(createDeviceSocket(transport, url).toPromise()) - return { success: true } - } catch (error) { - throw error - } -} diff --git a/src/helpers/live-common-setup-internal-hw.js b/src/helpers/live-common-setup-internal-hw.js index 02250401..e4dc602d 100644 --- a/src/helpers/live-common-setup-internal-hw.js +++ b/src/helpers/live-common-setup-internal-hw.js @@ -40,7 +40,6 @@ setErrorRemapping(e => { registerTransportModule({ id: 'hid', open: async devicePath => { - // $FlowFixMe const t = await retry(() => TransportNodeHid.open(devicePath), { maxRetry: 2 }) t.setDebugMode(logger.apdu) return t diff --git a/src/helpers/live-common-setup.js b/src/helpers/live-common-setup.js index b740c0a0..458cdf39 100644 --- a/src/helpers/live-common-setup.js +++ b/src/helpers/live-common-setup.js @@ -1,8 +1,10 @@ // @flow -import { setNetwork } from '@ledgerhq/live-common/lib/network' +import WebSocket from 'ws' +import { setNetwork, setWebSocketImplementation } from '@ledgerhq/live-common/lib/network' import { setEnv } from '@ledgerhq/live-common/lib/env' import network from 'api/network' import * as constants from 'config/constants' +setWebSocketImplementation(WebSocket) setNetwork(network) setEnv('FORCE_PROVIDER', constants.FORCE_PROVIDER) diff --git a/static/i18n/en/app.json b/static/i18n/en/app.json index dc2bc93c..9a5868d8 100644 --- a/static/i18n/en/app.json +++ b/static/i18n/en/app.json @@ -445,6 +445,11 @@ "desc": "View the user data that is stored on your computer, including your accounts, caches and settings.", "btn": "View" }, + "repairDevice": { + "title": "Repair your Ledger device", + "desc": "If you encountered some issue while updating your device and cannot resume the update process, you can try this option to repair your device.", + "button": "Repair" + }, "exportLogs": { "title": "Export logs", "desc": "Exporting Ledger Live logs may be necessary for troubleshooting purposes.", @@ -841,6 +846,10 @@ "title": "Something went wrong, please reconnect your device", "description": "{{message}}" }, + "UnexpectedBootloader": { + "title": "Opps, your device should not be in Bootloader mode", + "description": "Please restart your device or contact us" + }, "UserRefusedFirmwareUpdate": { "title": "Firmware update refused on device", "description": "Please retry or contact Ledger Support" diff --git a/yarn.lock b/yarn.lock index 5af319d7..399f121c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1701,9 +1701,9 @@ bip32-path "0.4.2" "@ledgerhq/hw-transport-node-hid@^4.32.0": - version "4.32.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-4.32.0.tgz#75fec81c44e9f8fbe0f918080e2b70e99de2a346" - integrity sha512-uZO+52TBxaYVhGIULHbhvyZWx+uLjvflDwfLicQR1eYxbYACB6xLXwq4sz9gL5He966t637Zx9iPsLi87rtqvQ== + version "4.33.3" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-4.33.3.tgz#5e96dca2be0a23d80814303f262398087b208a6a" + integrity sha512-hmNAm7k385RJXY38hVUpzYgGgyk9QjScD3erNlFCTO8FnnxmEJCFUmVhWkv4sTwufuUJSpXL3ZXXNZ44qLMJpg== dependencies: "@ledgerhq/hw-transport" "^4.32.0" lodash "^4.17.11" @@ -1725,10 +1725,10 @@ bindings "^1.3.0" nan "^2.6.2" -"@ledgerhq/live-common@4.8.0-beta.4": - version "4.8.0-beta.4" - resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-4.8.0-beta.4.tgz#291641f42a5cac8c26cf3baf0c303542509df86c" - integrity sha512-xmNLrljtCPSDJDiJndIlSX+wsgVQBNEZH25c+Dz3/uaZVtOVldE4iav7r7qKkGVNoUwvEhoqSAcjSuqKEFiBhg== +"@ledgerhq/live-common@4.8.0-beta.12": + version "4.8.0-beta.12" + resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-4.8.0-beta.12.tgz#4319aa397896f242d753ea63ff7ac4223788eb88" + integrity sha512-J2gaXqQkDuqZl2SgjNE7ZOSX0nMl9xqHu5jwHqiyBSlXvykdXWMmaPLcBcP8F+xszpKCIB0N6XaJFUAHHbD0Nw== dependencies: "@aeternity/ledger-app-api" "0.0.4" "@ledgerhq/hw-app-btc" "^4.32.0" @@ -4119,11 +4119,16 @@ binaryextensions@2: resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-2.1.1.tgz#3209a51ca4a4ad541a3b8d3d6a6d5b83a2485935" integrity sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA== -bindings@^1.2.1, bindings@^1.3.0: +bindings@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.0.tgz#b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7" integrity sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw== +bindings@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.1.tgz#21fc7c6d67c18516ec5aaa2815b145ff77b26ea5" + integrity sha512-i47mqjF9UbjxJhxGf+pZ6kSxrnI3wBLlnGI2ArWJ4r0VrvDS7ZYXkprq/pLaBWYq4GM0r4zdHY+NNRqEMU7uew== + bip32-path@0.4.2: version "0.4.2" resolved "https://registry.yarnpkg.com/bip32-path/-/bip32-path-0.4.2.tgz#5db0416ad6822712f077836e2557b8697c0c7c99" @@ -4440,7 +4445,7 @@ buffer-alloc-unsafe@^1.1.0: resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== -buffer-alloc@^1.1.0: +buffer-alloc@^1.1.0, buffer-alloc@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== @@ -4867,10 +4872,10 @@ chokidar@^2.0.0, chokidar@^2.0.2: optionalDependencies: fsevents "^1.2.2" -chownr@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" - integrity sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE= +chownr@^1.0.1, chownr@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" + integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== chrome-trace-event@^1.0.0: version "1.0.0" @@ -7488,6 +7493,11 @@ expand-template@^1.0.2: resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-1.1.1.tgz#981f188c0c3a87d2e28f559bc541426ff94f21dd" integrity sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg== +expand-template@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" + integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== + expand-tilde@^2.0.0, expand-tilde@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" @@ -8282,7 +8292,7 @@ glob-to-regexp@^0.3.0: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1: +glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== @@ -8294,6 +8304,18 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.0.5: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + global-dirs@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" @@ -8997,7 +9019,7 @@ i18next@^11.2.2: resolved "https://registry.yarnpkg.com/i18next/-/i18next-11.3.3.tgz#a6ca3c2a93237c94e242bda7df3411588ac37ea1" integrity sha512-YR1p0IJCKbUxi9DKKb7SK5kQMVcUIUA1xxPlxr7mn3pvkFdEE1eZi/TiYC5eyOE6wvWYOb5xZc+1HVSD5dJXMg== -iconv-lite@0.4, iconv-lite@^0.4.17, iconv-lite@^0.4.22, iconv-lite@^0.4.23, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@0.4, iconv-lite@^0.4.17, iconv-lite@^0.4.22, iconv-lite@^0.4.23, iconv-lite@~0.4.13: version "0.4.23" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA== @@ -9009,6 +9031,13 @@ iconv-lite@0.4.19: resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" integrity sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ== +iconv-lite@^0.4.4: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + icss-replace-symbols@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" @@ -11114,18 +11143,18 @@ minimist@~0.0.1: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= -minipass@^2.2.1, minipass@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.3.tgz#a7dcc8b7b833f5d368759cce544dccb55f50f233" - integrity sha512-/jAn9/tEX4gnpyRATxgHEOV6xbcyxgT7iUnxo9Y3+OB0zX00TgKIv/2FZCf5brBbICcwbLqVv2ImjvWWrQMSYw== +minipass@^2.2.1, minipass@^2.3.4: + version "2.3.5" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" + integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== dependencies: safe-buffer "^5.1.2" yallist "^3.0.0" -minizlib@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb" - integrity sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA== +minizlib@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" + integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== dependencies: minipass "^2.2.1" @@ -11220,7 +11249,12 @@ mute-stream@0.0.7: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= -nan@^2.10.0, nan@^2.2.1, nan@^2.6.2, nan@^2.8.0, nan@^2.9.2: +nan@^2.10.0, nan@^2.8.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.0.tgz#9d443fdb5e13a20770cc5e602eee59760a685885" + integrity sha512-zT5nC0JhbljmyEf+Z456nvm7iO7XgRV2hYxoBtPpnyp+0Q4aCoP6uWNn76v/I6k2kCYNLWqWbwBWQcjsNI/bjw== + +nan@^2.2.1, nan@^2.6.2, nan@^2.9.2: version "2.10.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA== @@ -11242,15 +11276,20 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" +napi-build-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.1.tgz#1381a0f92c39d66bf19852e7873432fc2123e508" + integrity sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -needle@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.1.tgz#b5e325bd3aae8c2678902fa296f729455d1d3a7d" - integrity sha512-t/ZswCM9JTWjAdXS9VpvqhI2Ct2sL2MdY4fUXqGJaGBk13ge99ObqRksRTbBE56K+wxUXwwfZYOuZHifFW9q+Q== +needle@^2.2.1: + version "2.2.4" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" + integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA== dependencies: debug "^2.1.2" iconv-lite "^0.4.4" @@ -11283,13 +11322,20 @@ no-case@^2.2.0: dependencies: lower-case "^1.1.1" -node-abi@^2.0.0, node-abi@^2.2.0: +node-abi@^2.0.0: version "2.4.3" resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.4.3.tgz#43666b7b17e57863e572409edbb82115ac7af28b" integrity sha512-b656V5C0628gOOA2kwcpNA/bxdlqYF9FvxJ+qqVX0ctdXNVZpS8J6xEUYir3WAKc7U0BH/NRlSpNbGsy+azjeg== dependencies: semver "^5.4.1" +node-abi@^2.2.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.5.0.tgz#942e1a78bce764bc0c1672d5821e492b9d032052" + integrity sha512-9g2twBGSP6wIR5PW7tXvAWnEWKJDH/VskdXp168xsw9VVxpEGov8K4jsP4/VeoC7b2ZAyzckvMCuQuQlw44lXg== + dependencies: + semver "^5.4.1" + node-dir@0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.8.tgz#55fb8deb699070707fb67f91a460f0448294c77d" @@ -11339,13 +11385,13 @@ node-gyp@^3.6.0: which "1" node-hid@^0.7.2: - version "0.7.3" - resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-0.7.3.tgz#736e9a4dee5eec96c20fbe301e0311bb185cb2f4" - integrity sha512-LOCqWqcOlng+Kn1Qj/54zrPVfCagg1O7RlSgMmugykBcoYvUud6BswTrJM2aXuBac+bCCm3lA2srRG8YfmyXZQ== + version "0.7.4" + resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-0.7.4.tgz#2db109acee654b56bf518ffb3fd92cf9cd0647c1" + integrity sha512-gvgNDPoszObn7avIDYMUvVv1T0xQB4/CZFJWckra/LXAc0qHYho4M1LCnCKlLIocL2R5/3qGv0J4AjRMdwgjxg== dependencies: bindings "^1.3.0" nan "^2.10.0" - prebuild-install "^4.0.0" + prebuild-install "^5.2.1" node-int64@^0.4.0: version "0.4.0" @@ -11407,13 +11453,29 @@ node-object-hash@^1.2.0: integrity sha512-JQVqSM5/mOaUoUhCYR0t1vgm8RFo7qpJtPvnoFCLeqQh1xrfmr3BCD3nGBnACzpIEF7F7EVgqGD3O4lao/BY/A== node-pre-gyp@^0.10.0: - version "0.10.2" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.2.tgz#e8945c20ef6795a20aac2b44f036eb13cf5146e3" - integrity sha512-16lql9QTqs6KsB9fl3neWyZm02KxIKdI9FlJjrB0y7eMTP5Nyz+xalwPbOlw3iw7EejllJPmlJSnY711PLD1ug== + version "0.10.3" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" + integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + +node-pre-gyp@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz#db1f33215272f692cd38f03238e3e9b47c5dd054" + integrity sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q== dependencies: detect-libc "^1.0.2" mkdirp "^0.5.1" - needle "^2.2.0" + needle "^2.2.1" nopt "^4.0.1" npm-packlist "^1.1.6" npmlog "^4.0.2" @@ -11516,9 +11578,9 @@ normalize-url@^1.4.0, normalize-url@^1.9.1: sort-keys "^1.0.0" npm-bundled@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.3.tgz#7e71703d973af3370a9591bafe3a63aca0be2308" - integrity sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow== + version "1.0.5" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" + integrity sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g== npm-install-package@~2.1.0: version "2.1.0" @@ -11526,9 +11588,9 @@ npm-install-package@~2.1.0: integrity sha1-1+/jz816sAYUuJbqUxGdyaslkSU= npm-packlist@^1.1.6: - version "1.1.10" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.10.tgz#1039db9e985727e464df066f4cf0ab6ef85c398a" - integrity sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA== + version "1.1.12" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.12.tgz#22bde2ebc12e72ca482abd67afc51eb49377243a" + integrity sha512-WJKFOVMeAlsU/pjXuqVdzU0WfgtIBCupkEVwn+1Y0ERAbUfWw8R4GjgVbaKnUjRoD2FoQbHOCbOyT5Mbs9Lw4g== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" @@ -12600,22 +12662,23 @@ prebuild-install@^2.0.0: tunnel-agent "^0.6.0" which-pm-runs "^1.0.0" -prebuild-install@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-4.0.0.tgz#206ce8106ce5efa4b6cf062fc8a0a7d93c17f3a8" - integrity sha512-7tayxeYboJX0RbVzdnKyGl2vhQRWr6qfClEXDhOkXjuaOKCw2q8aiuFhONRYVsG/czia7KhpykIlI2S2VaPunA== +prebuild-install@^5.2.1: + version "5.2.2" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.2.2.tgz#237888f21bfda441d0ee5f5612484390bccd4046" + integrity sha512-4e8VJnP3zJdZv/uP0eNWmr2r9urp4NECw7Mt1OSAi3rcLrbBRxGiAkfUFtre2MhQ5wfREAjRV+K1gubvs/GPsA== dependencies: detect-libc "^1.0.3" - expand-template "^1.0.2" + expand-template "^2.0.3" github-from-package "0.0.0" minimist "^1.2.0" mkdirp "^0.5.1" + napi-build-utils "^1.0.1" node-abi "^2.2.0" noop-logger "^0.1.1" npmlog "^4.0.1" os-homedir "^1.0.1" pump "^2.0.1" - rc "^1.1.6" + rc "^1.2.7" simple-get "^2.7.0" tar-fs "^1.13.0" tunnel-agent "^0.6.0" @@ -14325,7 +14388,7 @@ semver-diff@^2.0.0: dependencies: semver "^5.0.3" -"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0: +"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== @@ -14335,6 +14398,11 @@ semver@^5.0.1: resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" integrity sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw== +semver@^5.3.0, semver@^5.4.1: + version "5.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" + integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== + semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" @@ -15287,7 +15355,20 @@ tar-fs@^1.13.0: pump "^1.0.0" tar-stream "^1.1.2" -tar-stream@^1.1.2, tar-stream@^1.5.0: +tar-stream@^1.1.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" + integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== + dependencies: + bl "^1.0.0" + buffer-alloc "^1.2.0" + end-of-stream "^1.0.0" + fs-constants "^1.0.0" + readable-stream "^2.3.0" + to-buffer "^1.1.1" + xtend "^4.0.0" + +tar-stream@^1.5.0: version "1.6.1" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.1.tgz#f84ef1696269d6223ca48f6e1eeede3f7e81f395" integrity sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA== @@ -15310,14 +15391,14 @@ tar@^2.0.0: inherits "2" tar@^4: - version "4.4.4" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.4.tgz#ec8409fae9f665a4355cc3b4087d0820232bb8cd" - integrity sha512-mq9ixIYfNF9SK0IS/h2HKMu8Q2iaCuhDDsZhdEag/FHv8fOaYld4vN7ouMgcSSt5WKZzPs8atclTcJm36OTh4w== + version "4.4.8" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d" + integrity sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ== dependencies: - chownr "^1.0.1" + chownr "^1.1.1" fs-minipass "^1.2.5" - minipass "^2.3.3" - minizlib "^1.1.0" + minipass "^2.3.4" + minizlib "^1.1.1" mkdirp "^0.5.0" safe-buffer "^5.1.2" yallist "^3.0.2" @@ -15455,7 +15536,7 @@ to-arraybuffer@^1.0.0: resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= -to-buffer@^1.1.0: +to-buffer@^1.1.0, to-buffer@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== @@ -15977,12 +16058,12 @@ url@^0.11.0, url@~0.11.0: querystring "0.2.0" usb@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/usb/-/usb-1.3.3.tgz#4e8a4b44ab8833fa1c4fb99778ebae1d2d626970" - integrity sha512-WRBxI54yEs2QPj28G6kITI3Wu7VxrtHbqiDvDRUDKdg97lcK1pTP8y9LoDWF22OiCCrEvrdeq0lNcr84QOzjXQ== + version "1.5.0" + resolved "https://registry.yarnpkg.com/usb/-/usb-1.5.0.tgz#3e07b23c6dacf06a7c8801ae913926702a818218" + integrity sha512-/0stiQEmweuO2BKv2avzQQ8ypDUjo4Osz5sSEi+d0F4Rc+ddX1xED3uf4Tkelc1eADlfn0JQZYHP0bI7CNDA0Q== dependencies: nan "^2.8.0" - node-pre-gyp "^0.10.0" + node-pre-gyp "^0.11.0" use@^3.1.0: version "3.1.0" @@ -16791,9 +16872,9 @@ yallist@^2.1.2: integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= yallist@^3.0.0, yallist@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" - integrity sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k= + version "3.0.3" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" + integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== yaml-loader@^0.5.0: version "0.5.0" From 4a2366a13cae3516039fa10aea841cb6800964d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Mon, 17 Dec 2018 19:48:37 +0100 Subject: [PATCH 04/26] Use wording perf update type --- src/components/SettingsPage/sections/Help.js | 5 +---- src/components/modals/UpdateFirmware/Installing.js | 5 +++-- .../modals/UpdateFirmware/steps/02-step-flash-mcu.js | 6 +++--- static/i18n/en/app.json | 7 +++++-- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/components/SettingsPage/sections/Help.js b/src/components/SettingsPage/sections/Help.js index 15eba3c4..10949ceb 100644 --- a/src/components/SettingsPage/sections/Help.js +++ b/src/components/SettingsPage/sections/Help.js @@ -73,10 +73,7 @@ class SectionHelp extends PureComponent { > - + diff --git a/src/components/modals/UpdateFirmware/Installing.js b/src/components/modals/UpdateFirmware/Installing.js index 5a06c152..e3fff13d 100644 --- a/src/components/modals/UpdateFirmware/Installing.js +++ b/src/components/modals/UpdateFirmware/Installing.js @@ -11,9 +11,10 @@ import type { T } from 'types/common' type Props = { t: T, progress: number, + installing: string, } -function Installing({ t, progress }: Props) { +function Installing({ t, progress, installing }: Props) { return ( @@ -21,7 +22,7 @@ function Installing({ t, progress }: Props) { - {t('manager.modal.installing')} + {t(`manager.modal.steps.${installing}`)} diff --git a/src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js b/src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js index 308a58b8..500a022a 100644 --- a/src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js +++ b/src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js @@ -43,13 +43,13 @@ const Separator = styled(Box).attrs({ type Props = StepProps type State = { - installing: boolean, + installing: ?string, progress: number, } class StepFlashMcu extends PureComponent { state = { - installing: false, + installing: null, progress: 0, } @@ -92,7 +92,7 @@ class StepFlashMcu extends PureComponent { const { t } = this.props return installing ? ( - + ) : ( diff --git a/static/i18n/en/app.json b/static/i18n/en/app.json index 9a5868d8..633e2eba 100644 --- a/static/i18n/en/app.json +++ b/static/i18n/en/app.json @@ -258,9 +258,12 @@ }, "modal": { "steps": { - "updateMCU": "MCU update" + "updateMCU": "MCU update", + "osu": "Installing OSU...", + "flash-mcu": "MCU updating...", + "flash-bootloader": "Bootloader updating...", + "firmware": "Firmware updating..." }, - "installing": "Firmware updating...", "confirmIdentifier": "Verify the identifier", "confirmIdentifierText": "Verify that the identifier on your device is the same as the identifier below. Press the right button and enter your PIN code to confirm", "identifier": "Identifier", From e2579ac6e70633bffca580ee4dd1cb446a57f169 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Mon, 17 Dec 2018 20:59:01 +0100 Subject: [PATCH 05/26] Re-use all remaining hw / manager code out of live-common --- src/commands/debugAppInfosForCurrency.js | 2 +- src/commands/getCurrentFirmware.js | 21 --- src/commands/getDeviceInfo.js | 5 +- src/commands/getIsGenuine.js | 14 +- src/commands/getMemInfo.js | 19 --- src/commands/index.js | 12 -- src/commands/isDashboardOpen.js | 19 --- src/commands/listAppVersions.js | 15 -- src/commands/listApps.js | 15 -- src/commands/listCategories.js | 17 --- src/commands/uninstallApp.js | 2 +- src/components/GenuineCheck.js | 13 +- src/components/ManagerPage/AppSearchBar.js | 2 +- src/components/ManagerPage/AppsList.js | 29 ++-- src/components/ManagerPage/Dashboard.js | 2 +- src/components/ManagerPage/index.js | 2 +- src/config/constants.js | 6 - src/helpers/apps/installApp.js | 52 ------- src/helpers/apps/listAppVersions.js | 30 ---- src/helpers/apps/listApps.js | 10 -- src/helpers/apps/listCategories.js | 10 -- src/helpers/apps/uninstallApp.js | 41 ------ src/helpers/debugAppInfosForCurrency/btc.js | 9 -- .../debugAppInfosForCurrency/ethereum.js | 10 -- src/helpers/debugAppInfosForCurrency/index.js | 29 ---- .../debugAppInfosForCurrency/ripple.js | 10 -- src/helpers/devices/getBitcoinLikeInfo.js | 21 --- src/helpers/devices/getCurrentFirmware.js | 24 ---- src/helpers/devices/getDeviceInfo.js | 5 - src/helpers/devices/getDeviceVersion.js | 17 --- src/helpers/devices/getIsGenuine.js | 32 ----- src/helpers/devices/getMemInfo.js | 10 -- src/helpers/devices/getOsuFirmware.js | 23 --- src/helpers/devices/isDashboardOpen.js | 16 --- src/helpers/firmware/getFinalFirmwareById.js | 8 -- src/helpers/firmware/getFirmwareInfo.js | 51 ------- src/helpers/firmware/getMcus.js | 13 -- src/helpers/firmware/getNextMCU.js | 25 ---- src/helpers/socket.js | 132 ------------------ src/helpers/urls.js | 37 ----- src/logger/logger.js | 8 +- 41 files changed, 38 insertions(+), 780 deletions(-) delete mode 100644 src/commands/getCurrentFirmware.js delete mode 100644 src/commands/getMemInfo.js delete mode 100644 src/commands/isDashboardOpen.js delete mode 100644 src/commands/listAppVersions.js delete mode 100644 src/commands/listApps.js delete mode 100644 src/commands/listCategories.js delete mode 100644 src/helpers/apps/installApp.js delete mode 100644 src/helpers/apps/listAppVersions.js delete mode 100644 src/helpers/apps/listApps.js delete mode 100644 src/helpers/apps/listCategories.js delete mode 100644 src/helpers/apps/uninstallApp.js delete mode 100644 src/helpers/debugAppInfosForCurrency/btc.js delete mode 100644 src/helpers/debugAppInfosForCurrency/ethereum.js delete mode 100644 src/helpers/debugAppInfosForCurrency/index.js delete mode 100644 src/helpers/debugAppInfosForCurrency/ripple.js delete mode 100644 src/helpers/devices/getBitcoinLikeInfo.js delete mode 100644 src/helpers/devices/getCurrentFirmware.js delete mode 100644 src/helpers/devices/getDeviceInfo.js delete mode 100644 src/helpers/devices/getDeviceVersion.js delete mode 100644 src/helpers/devices/getIsGenuine.js delete mode 100644 src/helpers/devices/getMemInfo.js delete mode 100644 src/helpers/devices/getOsuFirmware.js delete mode 100644 src/helpers/devices/isDashboardOpen.js delete mode 100644 src/helpers/firmware/getFinalFirmwareById.js delete mode 100644 src/helpers/firmware/getFirmwareInfo.js delete mode 100644 src/helpers/firmware/getMcus.js delete mode 100644 src/helpers/firmware/getNextMCU.js delete mode 100644 src/helpers/socket.js delete mode 100644 src/helpers/urls.js diff --git a/src/commands/debugAppInfosForCurrency.js b/src/commands/debugAppInfosForCurrency.js index 8ba70516..dd576dda 100644 --- a/src/commands/debugAppInfosForCurrency.js +++ b/src/commands/debugAppInfosForCurrency.js @@ -1,10 +1,10 @@ // @flow import { getCryptoCurrencyById } from '@ledgerhq/live-common/lib/currencies' +import debugAppInfosForCurrency from '@ledgerhq/live-common/lib/hw/debugAppInfosForCurrency' import { createCommand, Command } from 'helpers/ipc' import { from } from 'rxjs' import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' -import debugAppInfosForCurrency from 'helpers/debugAppInfosForCurrency' type Input = { currencyId: string, diff --git a/src/commands/getCurrentFirmware.js b/src/commands/getCurrentFirmware.js deleted file mode 100644 index d4ae0c86..00000000 --- a/src/commands/getCurrentFirmware.js +++ /dev/null @@ -1,21 +0,0 @@ -// @flow - -import { createCommand, Command } from 'helpers/ipc' -import { fromPromise } from 'rxjs/observable/fromPromise' - -import getCurrentFirmware from 'helpers/devices/getCurrentFirmware' -import type { FinalFirmware } from 'helpers/types' - -type Input = { - deviceId: string | number, - fullVersion: string, - provider: number, -} - -type Result = FinalFirmware - -const cmd: Command = createCommand('getCurrentFirmware', data => - fromPromise(getCurrentFirmware(data)), -) - -export default cmd diff --git a/src/commands/getDeviceInfo.js b/src/commands/getDeviceInfo.js index 22135389..a0529571 100644 --- a/src/commands/getDeviceInfo.js +++ b/src/commands/getDeviceInfo.js @@ -3,9 +3,8 @@ import { createCommand, Command } from 'helpers/ipc' import { from } from 'rxjs' import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' - -import getDeviceInfo from 'helpers/devices/getDeviceInfo' -import type { DeviceInfo } from 'helpers/types' +import getDeviceInfo from '@ledgerhq/live-common/lib/hw/getDeviceInfo' +import type { DeviceInfo } from '@ledgerhq/live-common/lib/types/manager' type Input = { devicePath: string, diff --git a/src/commands/getIsGenuine.js b/src/commands/getIsGenuine.js index 406d7cac..edc357e1 100644 --- a/src/commands/getIsGenuine.js +++ b/src/commands/getIsGenuine.js @@ -1,11 +1,12 @@ // @flow import { createCommand, Command } from 'helpers/ipc' -import { from } from 'rxjs' -import type { DeviceInfo } from 'helpers/types' - -import getIsGenuine from 'helpers/devices/getIsGenuine' +import { of } from 'rxjs' +import { delay } from 'rxjs/operators' +import genuineCheck from '@ledgerhq/live-common/lib/hw/genuineCheck' import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' +import type { DeviceInfo } from '@ledgerhq/live-common/lib/types/manager' +import { SKIP_GENUINE } from 'config/constants' type Input = { devicePath: string, @@ -14,7 +15,10 @@ type Input = { type Result = string const cmd: Command = createCommand('getIsGenuine', ({ devicePath, deviceInfo }) => - withDevice(devicePath)(transport => from(getIsGenuine(transport, deviceInfo))), + withDevice(devicePath)( + transport => + SKIP_GENUINE ? of('0000').pipe(delay(1000)) : genuineCheck(transport, deviceInfo), + ), ) export default cmd diff --git a/src/commands/getMemInfo.js b/src/commands/getMemInfo.js deleted file mode 100644 index acaf532f..00000000 --- a/src/commands/getMemInfo.js +++ /dev/null @@ -1,19 +0,0 @@ -// @flow - -import { createCommand, Command } from 'helpers/ipc' -import { from } from 'rxjs' - -import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' -import getMemInfo from 'helpers/devices/getMemInfo' - -type Input = { - devicePath: string, -} - -type Result = * - -const cmd: Command = createCommand('getMemInfo', ({ devicePath }) => - withDevice(devicePath)(transport => from(getMemInfo(transport))), -) - -export default cmd diff --git a/src/commands/index.js b/src/commands/index.js index a55d2bb4..ac155d41 100644 --- a/src/commands/index.js +++ b/src/commands/index.js @@ -9,12 +9,9 @@ import firmwareMain from 'commands/firmwareMain' import firmwareRepair from 'commands/firmwareRepair' import getAddress from 'commands/getAddress' import getDeviceInfo from 'commands/getDeviceInfo' -import getCurrentFirmware from 'commands/getCurrentFirmware' import getIsGenuine from 'commands/getIsGenuine' import getLatestFirmwareForDevice from 'commands/getLatestFirmwareForDevice' -import getMemInfo from 'commands/getMemInfo' import installApp from 'commands/installApp' -import isDashboardOpen from 'commands/isDashboardOpen' import killInternalProcess from 'commands/killInternalProcess' import libcoreGetFees from 'commands/libcoreGetFees' import libcoreGetVersion from 'commands/libcoreGetVersion' @@ -23,9 +20,6 @@ import libcoreScanFromXPUB from 'commands/libcoreScanFromXPUB' import libcoreSignAndBroadcast from 'commands/libcoreSignAndBroadcast' import libcoreSyncAccount from 'commands/libcoreSyncAccount' import libcoreValidAddress from 'commands/libcoreValidAddress' -import listApps from 'commands/listApps' -import listAppVersions from 'commands/listAppVersions' -import listCategories from 'commands/listCategories' import listenDevices from 'commands/listenDevices' import ping from 'commands/ping' import signTransaction from 'commands/signTransaction' @@ -41,12 +35,9 @@ const all: Array> = [ firmwareRepair, getAddress, getDeviceInfo, - getCurrentFirmware, getIsGenuine, getLatestFirmwareForDevice, - getMemInfo, installApp, - isDashboardOpen, killInternalProcess, libcoreGetFees, libcoreGetVersion, @@ -55,9 +46,6 @@ const all: Array> = [ libcoreSignAndBroadcast, libcoreSyncAccount, libcoreValidAddress, - listApps, - listAppVersions, - listCategories, listenDevices, ping, signTransaction, diff --git a/src/commands/isDashboardOpen.js b/src/commands/isDashboardOpen.js deleted file mode 100644 index ce9c48db..00000000 --- a/src/commands/isDashboardOpen.js +++ /dev/null @@ -1,19 +0,0 @@ -// @flow - -import { createCommand, Command } from 'helpers/ipc' -import { from } from 'rxjs' -import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' - -import isDashboardOpen from '../helpers/devices/isDashboardOpen' - -type Input = { - devicePath: string, -} - -type Result = boolean - -const cmd: Command = createCommand('isDashboardOpen', ({ devicePath }) => - withDevice(devicePath)(transport => from(isDashboardOpen(transport))), -) - -export default cmd diff --git a/src/commands/listAppVersions.js b/src/commands/listAppVersions.js deleted file mode 100644 index a802b2c6..00000000 --- a/src/commands/listAppVersions.js +++ /dev/null @@ -1,15 +0,0 @@ -// @flow - -import { createCommand, Command } from 'helpers/ipc' -import { fromPromise } from 'rxjs/observable/fromPromise' -import type { DeviceInfo, ApplicationVersion } from 'helpers/types' - -import listAppVersions from 'helpers/apps/listAppVersions' - -type Result = Array - -const cmd: Command = createCommand('listAppVersions', deviceInfo => - fromPromise(listAppVersions(deviceInfo)), -) - -export default cmd diff --git a/src/commands/listApps.js b/src/commands/listApps.js deleted file mode 100644 index 13f78609..00000000 --- a/src/commands/listApps.js +++ /dev/null @@ -1,15 +0,0 @@ -// @flow - -import { createCommand, Command } from 'helpers/ipc' -import { fromPromise } from 'rxjs/observable/fromPromise' - -import listApps from 'helpers/apps/listApps' -import type { Application } from 'helpers/types' - -type Input = void - -type Result = Array - -const cmd: Command = createCommand('listApps', () => fromPromise(listApps())) - -export default cmd diff --git a/src/commands/listCategories.js b/src/commands/listCategories.js deleted file mode 100644 index 641b4ad8..00000000 --- a/src/commands/listCategories.js +++ /dev/null @@ -1,17 +0,0 @@ -// @flow - -import { createCommand, Command } from 'helpers/ipc' -import { fromPromise } from 'rxjs/observable/fromPromise' - -import listCategories from 'helpers/apps/listCategories' -import type { Category } from 'helpers/types' - -type Input = void - -type Result = Array - -const cmd: Command = createCommand('listCategories', () => - fromPromise(listCategories()), -) - -export default cmd diff --git a/src/commands/uninstallApp.js b/src/commands/uninstallApp.js index 684712c3..6d713a4c 100644 --- a/src/commands/uninstallApp.js +++ b/src/commands/uninstallApp.js @@ -4,7 +4,7 @@ import { createCommand, Command } from 'helpers/ipc' import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' import uninstallApp from '@ledgerhq/live-common/lib/hw/uninstallApp' -import type { ApplicationVersion } from 'helpers/types' +import type { ApplicationVersion } from '@ledgerhq/live-common/lib/types/manager' type Input = { app: ApplicationVersion, diff --git a/src/components/GenuineCheck.js b/src/components/GenuineCheck.js index 76a53ba7..09107831 100644 --- a/src/components/GenuineCheck.js +++ b/src/components/GenuineCheck.js @@ -9,7 +9,8 @@ import { delay, createCancelablePolling } from 'helpers/promise' import logger from 'logger' import type { T, Device } from 'types/common' -import type { DeviceInfo } from 'helpers/types' +import manager from '@ledgerhq/live-common/lib/manager' +import type { DeviceInfo } from '@ledgerhq/live-common/lib/types/manager' import { GENUINE_TIMEOUT, DEVICE_INFOS_TIMEOUT, GENUINE_CACHE_DELAY } from 'config/constants' @@ -92,6 +93,16 @@ class GenuineCheck extends PureComponent { return true } + // Preload things in parallel + Promise.all([ + // Step dashboard, we preload the applist before entering manager while we're still doing the genuine check + manager.getAppsList(deviceInfo), + // we also preload as much info as possible in case of a MCU + manager.getLatestFirmwareForDevice(deviceInfo), + ]).catch(e => { + logger.warn(e) + }) + if (genuineDevices.has(device)) { logger.log("genuine was already checked. don't check again") await delay(GENUINE_CACHE_DELAY) diff --git a/src/components/ManagerPage/AppSearchBar.js b/src/components/ManagerPage/AppSearchBar.js index 7e055e08..378bc423 100644 --- a/src/components/ManagerPage/AppSearchBar.js +++ b/src/components/ManagerPage/AppSearchBar.js @@ -3,7 +3,7 @@ import React, { PureComponent, Fragment } from 'react' import styled from 'styled-components' -import type { ApplicationVersion } from 'helpers/types' +import type { ApplicationVersion } from '@ledgerhq/live-common/lib/types/manager' import Box from 'components/base/Box' import Space from 'components/base/Space' diff --git a/src/components/ManagerPage/AppsList.js b/src/components/ManagerPage/AppsList.js index a155af7c..97f9cea2 100644 --- a/src/components/ManagerPage/AppsList.js +++ b/src/components/ManagerPage/AppsList.js @@ -9,11 +9,10 @@ import { compose } from 'redux' import { throttleTime, filter, map } from 'rxjs/operators' import type { Device, T } from 'types/common' -import type { ApplicationVersion, DeviceInfo } from 'helpers/types' +import type { ApplicationVersion, DeviceInfo } from '@ledgerhq/live-common/lib/types/manager' +import manager from '@ledgerhq/live-common/lib/manager' import { getFullListSortedCryptoCurrencies } from 'helpers/countervalues' import { developerModeSelector } from 'reducers/settings' -import listApps from 'commands/listApps' -import listAppVersions from 'commands/listAppVersions' import installApp from 'commands/installApp' import uninstallApp from 'commands/uninstallApp' import Box from 'components/base/Box' @@ -131,24 +130,14 @@ class AppsList extends PureComponent { } async fetchAppList() { - try { - const { deviceInfo } = this.props - - const [ - applicationsList, - compatibleAppVersionsList, - sortedCryptoCurrencies, - ] = await Promise.all([ - listApps.send().toPromise(), - listAppVersions.send(deviceInfo).toPromise(), - getFullListSortedCryptoCurrencies(), - ]) + const { deviceInfo, isDevMode } = this.props - const filteredAppVersionsList = this.prepareAppList({ - applicationsList, - compatibleAppVersionsList, - sortedCryptoCurrencies, - }) + try { + const filteredAppVersionsList = await manager.getAppsList( + deviceInfo, + isDevMode, + getFullListSortedCryptoCurrencies, + ) if (!this._unmounted) { this.setState({ diff --git a/src/components/ManagerPage/Dashboard.js b/src/components/ManagerPage/Dashboard.js index 3e6d3687..b26e3b09 100644 --- a/src/components/ManagerPage/Dashboard.js +++ b/src/components/ManagerPage/Dashboard.js @@ -4,7 +4,7 @@ import { translate } from 'react-i18next' import styled from 'styled-components' import type { T, Device } from 'types/common' -import type { DeviceInfo } from 'helpers/types' +import type { DeviceInfo } from '@ledgerhq/live-common/lib/types/manager' import Box from 'components/base/Box' import Text from 'components/base/Text' diff --git a/src/components/ManagerPage/index.js b/src/components/ManagerPage/index.js index 24ee0407..59fb7c65 100644 --- a/src/components/ManagerPage/index.js +++ b/src/components/ManagerPage/index.js @@ -5,7 +5,7 @@ import invariant from 'invariant' import { openURL } from 'helpers/linking' import { urls } from 'config/urls' import type { Device } from 'types/common' -import type { DeviceInfo } from 'helpers/types' +import type { DeviceInfo } from '@ledgerhq/live-common/lib/types/manager' import { getFullListSortedCryptoCurrencies } from 'helpers/countervalues' import Dashboard from './Dashboard' diff --git a/src/config/constants.js b/src/config/constants.js index ac43b517..76f8af9c 100644 --- a/src/config/constants.js +++ b/src/config/constants.js @@ -58,12 +58,6 @@ export const LEDGER_REST_API_BASE = stringFromEnv( 'LEDGER_REST_API_BASE', 'https://explorers.api.live.ledger.com', ) -export const MANAGER_API_BASE = stringFromEnv( - 'MANAGER_API_BASE', - 'https://manager.api.live.ledger.com/api', -) - -export const BASE_SOCKET_URL = stringFromEnv('BASE_SOCKET_URL', 'wss://api.ledgerwallet.com/update') // Provider export const FORCE_PROVIDER = intFromEnv('FORCE_PROVIDER', 0) diff --git a/src/helpers/apps/installApp.js b/src/helpers/apps/installApp.js deleted file mode 100644 index 1c854062..00000000 --- a/src/helpers/apps/installApp.js +++ /dev/null @@ -1,52 +0,0 @@ -// @flow -import type Transport from '@ledgerhq/hw-transport' - -import { createDeviceSocket } from 'helpers/socket' - -import type { ApplicationVersion } from 'helpers/types' -import { WS_INSTALL } from 'helpers/urls' - -import { - ManagerNotEnoughSpaceError, - ManagerDeviceLockedError, - ManagerAppAlreadyInstalledError, - ManagerAppRelyOnBTCError, -} from '@ledgerhq/live-common/lib/errors' - -function remapError(promise) { - return promise.catch((e: Error) => { - switch (true) { - case e.message.endsWith('6982'): - throw new ManagerDeviceLockedError() - case e.message.endsWith('6a84') || e.message.endsWith('6a85'): - throw new ManagerNotEnoughSpaceError() - case e.message.endsWith('6a80') || e.message.endsWith('6a81'): - throw new ManagerAppAlreadyInstalledError() - case e.message.endsWith('6a83'): - throw new ManagerAppRelyOnBTCError() - default: - throw e - } - }) -} - -/** - * Install an app on the device - */ -export default async function installApp( - transport: Transport<*>, - targetId: string | number, - { app }: { app: ApplicationVersion }, -): Promise { - const params = { - targetId, - perso: app.perso, - deleteKey: app.delete_key, - firmware: app.firmware, - firmwareKey: app.firmware_key, - hash: app.hash, - } - - const url = WS_INSTALL(params) - await remapError(createDeviceSocket(transport, url).toPromise()) -} diff --git a/src/helpers/apps/listAppVersions.js b/src/helpers/apps/listAppVersions.js deleted file mode 100644 index bc48fc6a..00000000 --- a/src/helpers/apps/listAppVersions.js +++ /dev/null @@ -1,30 +0,0 @@ -// @flow -import network from 'api/network' -import type { DeviceInfo, DeviceVersion, FinalFirmware, ApplicationVersion } from 'helpers/types' - -import { APPLICATIONS_BY_DEVICE } from 'helpers/urls' -import getDeviceVersion from 'helpers/devices/getDeviceVersion' -import getCurrentFirmware from 'helpers/devices/getCurrentFirmware' - -type NetworkResponse = { data: { application_versions: Array } } - -export default async (deviceInfo: DeviceInfo): Promise> => { - const deviceData: DeviceVersion = await getDeviceVersion( - deviceInfo.targetId, - deviceInfo.providerId, - ) - const firmwareData: FinalFirmware = await getCurrentFirmware({ - deviceId: deviceData.id, - fullVersion: deviceInfo.fullVersion, - provider: deviceInfo.providerId, - }) - const params = { - provider: deviceInfo.providerId, - current_se_firmware_final_version: firmwareData.id, - device_version: deviceData.id, - } - const { - data: { application_versions }, - }: NetworkResponse = await network({ method: 'POST', url: APPLICATIONS_BY_DEVICE, data: params }) - return application_versions.length > 0 ? application_versions : [] -} diff --git a/src/helpers/apps/listApps.js b/src/helpers/apps/listApps.js deleted file mode 100644 index 14fed369..00000000 --- a/src/helpers/apps/listApps.js +++ /dev/null @@ -1,10 +0,0 @@ -// @flow -import network from 'api/network' - -import { GET_APPLICATIONS } from 'helpers/urls' -import type { Application } from 'helpers/types' - -export default async (): Promise> => { - const { data } = await network({ method: 'GET', url: GET_APPLICATIONS }) - return data.length > 0 ? data : [] -} diff --git a/src/helpers/apps/listCategories.js b/src/helpers/apps/listCategories.js deleted file mode 100644 index 1c903b0a..00000000 --- a/src/helpers/apps/listCategories.js +++ /dev/null @@ -1,10 +0,0 @@ -// @flow -import network from 'api/network' - -import { GET_CATEGORIES } from 'helpers/urls' -import type { Category } from 'helpers/types' - -export default async (): Promise> => { - const { data }: { data: Array } = await network({ method: 'GET', url: GET_CATEGORIES }) - return data.length > 0 ? data : [] -} diff --git a/src/helpers/apps/uninstallApp.js b/src/helpers/apps/uninstallApp.js deleted file mode 100644 index 161c0ae8..00000000 --- a/src/helpers/apps/uninstallApp.js +++ /dev/null @@ -1,41 +0,0 @@ -// @flow -import type Transport from '@ledgerhq/hw-transport' - -import { createDeviceSocket } from 'helpers/socket' - -import type { ApplicationVersion } from 'helpers/types' -import { ManagerDeviceLockedError, ManagerUninstallBTCDep } from '@ledgerhq/live-common/lib/errors' -import { WS_INSTALL } from 'helpers/urls' - -function remapError(promise) { - return promise.catch((e: Error) => { - switch (true) { - case e.message.endsWith('6982'): - throw new ManagerDeviceLockedError() - case e.message.endsWith('6a83'): - throw new ManagerUninstallBTCDep() - default: - throw e - } - }) -} - -/** - * Install an app on the device - */ -export default async function uninstallApp( - transport: Transport<*>, - targetId: string | number, - { app }: { app: ApplicationVersion }, -): Promise { - const params = { - targetId, - perso: app.perso, - deleteKey: app.delete_key, - firmware: app.delete, - firmwareKey: app.delete_key, - hash: app.hash, - } - const url = WS_INSTALL(params) - await remapError(createDeviceSocket(transport, url).toPromise()) -} diff --git a/src/helpers/debugAppInfosForCurrency/btc.js b/src/helpers/debugAppInfosForCurrency/btc.js deleted file mode 100644 index 74e7460a..00000000 --- a/src/helpers/debugAppInfosForCurrency/btc.js +++ /dev/null @@ -1,9 +0,0 @@ -// @flow - -import type Transport from '@ledgerhq/hw-transport' - -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 deleted file mode 100644 index ce090c76..00000000 --- a/src/helpers/debugAppInfosForCurrency/ethereum.js +++ /dev/null @@ -1,10 +0,0 @@ -// @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 deleted file mode 100644 index 95aeead3..00000000 --- a/src/helpers/debugAppInfosForCurrency/index.js +++ /dev/null @@ -1,29 +0,0 @@ -// @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 deleted file mode 100644 index dcabc884..00000000 --- a/src/helpers/debugAppInfosForCurrency/ripple.js +++ /dev/null @@ -1,10 +0,0 @@ -// @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 } -} diff --git a/src/helpers/devices/getBitcoinLikeInfo.js b/src/helpers/devices/getBitcoinLikeInfo.js deleted file mode 100644 index 82e8ed75..00000000 --- a/src/helpers/devices/getBitcoinLikeInfo.js +++ /dev/null @@ -1,21 +0,0 @@ -// @flow - -import type Transport from '@ledgerhq/hw-transport' - -const getBitcoinLikeInfo = ( - transport: Transport, -): Promise<{ - P2PKH: number, - P2SH: number, - message: Buffer, - short: Buffer, -}> => - transport.send(0xe0, 0x16, 0x00, 0x00).then(res => { - const P2PKH = res.readUInt16BE(0) - const P2SH = res.readUInt16BE(2) - const message = res.slice(5, res.readUInt8(4)) - const short = res.slice(5 + message.length + 1, res.readUInt8(5 + message.length)) - return { P2PKH, P2SH, message, short } - }) - -export default getBitcoinLikeInfo diff --git a/src/helpers/devices/getCurrentFirmware.js b/src/helpers/devices/getCurrentFirmware.js deleted file mode 100644 index c4ef5979..00000000 --- a/src/helpers/devices/getCurrentFirmware.js +++ /dev/null @@ -1,24 +0,0 @@ -// @flow -import network from 'api/network' - -import { GET_CURRENT_FIRMWARE } from 'helpers/urls' -import type { FinalFirmware } from 'helpers/types' - -type Input = { - fullVersion: string, - deviceId: string | number, - provider: number, -} - -export default async (input: Input): Promise => { - const { data }: { data: FinalFirmware } = await network({ - method: 'POST', - url: GET_CURRENT_FIRMWARE, - data: { - device_version: input.deviceId, - version_name: input.fullVersion, - provider: input.provider, - }, - }) - return data -} diff --git a/src/helpers/devices/getDeviceInfo.js b/src/helpers/devices/getDeviceInfo.js deleted file mode 100644 index 1bfef909..00000000 --- a/src/helpers/devices/getDeviceInfo.js +++ /dev/null @@ -1,5 +0,0 @@ -// @flow - -import getDeviceInfo from '@ledgerhq/live-common/lib/hw/getDeviceInfo' - -export default getDeviceInfo diff --git a/src/helpers/devices/getDeviceVersion.js b/src/helpers/devices/getDeviceVersion.js deleted file mode 100644 index c681cfa9..00000000 --- a/src/helpers/devices/getDeviceVersion.js +++ /dev/null @@ -1,17 +0,0 @@ -// @flow -import { GET_DEVICE_VERSION } from 'helpers/urls' -import network from 'api/network' - -import type { DeviceVersion } from 'helpers/types' - -export default async (targetId: string | number, provider: number): Promise => { - const { data }: { data: DeviceVersion } = await network({ - method: 'POST', - url: GET_DEVICE_VERSION, - data: { - provider, - target_id: targetId, - }, - }) - return data -} diff --git a/src/helpers/devices/getIsGenuine.js b/src/helpers/devices/getIsGenuine.js deleted file mode 100644 index 3357042b..00000000 --- a/src/helpers/devices/getIsGenuine.js +++ /dev/null @@ -1,32 +0,0 @@ -// @flow -import type Transport from '@ledgerhq/hw-transport' -import { SKIP_GENUINE } from 'config/constants' -import { WS_GENUINE } from 'helpers/urls' -import type { DeviceInfo, FinalFirmware, DeviceVersion } from 'helpers/types' - -import { createDeviceSocket } from 'helpers/socket' -import getCurrentFirmware from './getCurrentFirmware' -import getDeviceVersion from './getDeviceVersion' - -export default async (transport: Transport<*>, deviceInfo: DeviceInfo): Promise => { - const deviceVersion: DeviceVersion = await getDeviceVersion( - deviceInfo.targetId, - deviceInfo.providerId, - ) - - const firmware: FinalFirmware = await getCurrentFirmware({ - deviceId: deviceVersion.id, - fullVersion: deviceInfo.fullVersion, - provider: deviceInfo.providerId, - }) - - const params = { - targetId: deviceInfo.targetId, - perso: firmware.perso, - } - - const url = WS_GENUINE(params) - return SKIP_GENUINE - ? new Promise(resolve => setTimeout(() => resolve('0000'), 1000)) - : createDeviceSocket(transport, url).toPromise() -} diff --git a/src/helpers/devices/getMemInfo.js b/src/helpers/devices/getMemInfo.js deleted file mode 100644 index 04c5a833..00000000 --- a/src/helpers/devices/getMemInfo.js +++ /dev/null @@ -1,10 +0,0 @@ -// @flow - -import type Transport from '@ledgerhq/hw-transport' - -import getFirmwareInfo from 'helpers/firmware/getFirmwareInfo' - -export default async function getMemInfos(transport: Transport<*>): Promise { - const { targetId } = await getFirmwareInfo(transport) // eslint-disable-line - return new Promise(resolve => setTimeout(() => resolve({}), 1000)) -} diff --git a/src/helpers/devices/getOsuFirmware.js b/src/helpers/devices/getOsuFirmware.js deleted file mode 100644 index 07b7dae9..00000000 --- a/src/helpers/devices/getOsuFirmware.js +++ /dev/null @@ -1,23 +0,0 @@ -// @flow -import network from 'api/network' - -import { GET_CURRENT_OSU } from 'helpers/urls' - -type Input = { - version: string, - deviceId: string | number, - provider: number, -} - -export default async (input: Input): Promise<*> => { - const { data } = await network({ - method: 'POST', - url: GET_CURRENT_OSU, - data: { - device_version: input.deviceId, - version_name: `${input.version}-osu`, - provider: input.provider, - }, - }) - return data -} diff --git a/src/helpers/devices/isDashboardOpen.js b/src/helpers/devices/isDashboardOpen.js deleted file mode 100644 index e49d64d1..00000000 --- a/src/helpers/devices/isDashboardOpen.js +++ /dev/null @@ -1,16 +0,0 @@ -// @flow - -import type Transport from '@ledgerhq/hw-transport' - -import getFirmwareInfo from 'helpers/firmware/getFirmwareInfo' - -type Result = boolean - -export default async (transport: Transport<*>): Promise => { - const { targetId, seVersion } = await getFirmwareInfo(transport) - if (targetId && seVersion) { - return true - } - - return false -} diff --git a/src/helpers/firmware/getFinalFirmwareById.js b/src/helpers/firmware/getFinalFirmwareById.js deleted file mode 100644 index d3296a9c..00000000 --- a/src/helpers/firmware/getFinalFirmwareById.js +++ /dev/null @@ -1,8 +0,0 @@ -// @flow -import network from 'api/network' -import { GET_FINAL_FIRMWARE } from 'helpers/urls' - -export default async (id: number) => { - const { data } = await network({ method: 'GET', url: `${GET_FINAL_FIRMWARE}/${id}` }) - return data -} diff --git a/src/helpers/firmware/getFirmwareInfo.js b/src/helpers/firmware/getFirmwareInfo.js deleted file mode 100644 index b3c4a81c..00000000 --- a/src/helpers/firmware/getFirmwareInfo.js +++ /dev/null @@ -1,51 +0,0 @@ -// @flow - -import type Transport from '@ledgerhq/hw-transport' -import type { FirmwareInfo } from 'helpers/types' - -const APDUS = { - GET_FIRMWARE: [0xe0, 0x01, 0x00, 0x00], - // we dont have common call that works inside app & dashboard - // TODO: this should disappear. - GET_FIRMWARE_FALLBACK: [0xe0, 0xc4, 0x00, 0x00], -} - -/** - * Retrieve targetId and firmware version from device - */ -export default async function getFirmwareInfo(transport: Transport<*>): Promise { - const res = await transport.send(...APDUS.GET_FIRMWARE) - const byteArray = [...res] - const data = byteArray.slice(0, byteArray.length - 2) - const targetIdStr = Buffer.from(data.slice(0, 4)) - const targetId = targetIdStr.readUIntBE(0, 4) - const seVersionLength = data[4] - const seVersion = Buffer.from(data.slice(5, 5 + seVersionLength)).toString() - const flagsLength = data[5 + seVersionLength] - const flags = Buffer.from( - data.slice(5 + seVersionLength + 1, 5 + seVersionLength + 1 + flagsLength), - ).toString() - - const mcuVersionLength = data[5 + seVersionLength + 1 + flagsLength] - let mcuVersion = Buffer.from( - data.slice( - 7 + seVersionLength + flagsLength, - 7 + seVersionLength + flagsLength + mcuVersionLength, - ), - ) - if (mcuVersion[mcuVersion.length - 1] === 0) { - mcuVersion = mcuVersion.slice(0, mcuVersion.length - 1) - } - mcuVersion = mcuVersion.toString() - - if (!seVersionLength) { - return { - targetId, - seVersion: '0.0.0', - flags: '', - mcuVersion: '', - } - } - - return { targetId, seVersion, flags, mcuVersion } -} diff --git a/src/helpers/firmware/getMcus.js b/src/helpers/firmware/getMcus.js deleted file mode 100644 index 9f0057f4..00000000 --- a/src/helpers/firmware/getMcus.js +++ /dev/null @@ -1,13 +0,0 @@ -// @flow -import network from 'api/network' - -import { GET_MCUS } from 'helpers/urls' - -export default async (): Promise<*> => { - const { data } = await network({ - method: 'GET', - url: GET_MCUS, - }) - - return data -} diff --git a/src/helpers/firmware/getNextMCU.js b/src/helpers/firmware/getNextMCU.js deleted file mode 100644 index 92f877a3..00000000 --- a/src/helpers/firmware/getNextMCU.js +++ /dev/null @@ -1,25 +0,0 @@ -// @flow -import network from 'api/network' - -import { GET_NEXT_MCU } from 'helpers/urls' -import type { OsuFirmware } from 'helpers/types' -import { LatestMCUInstalledError } from '@ledgerhq/live-common/lib/errors' - -type NetworkResponse = { data: OsuFirmware | 'default' } - -export default async (bootloaderVersion: string): Promise<*> => { - const { data }: NetworkResponse = await network({ - method: 'POST', - url: GET_NEXT_MCU, - data: { - bootloader_version: bootloaderVersion, - }, - }) - - // FIXME: nextVersion will not be able to "default" when - // Error handling is standardize on the API side - if (data === 'default' || !data.name) { - throw new LatestMCUInstalledError('there is no next mcu version to install') - } - return data -} diff --git a/src/helpers/socket.js b/src/helpers/socket.js deleted file mode 100644 index 452df930..00000000 --- a/src/helpers/socket.js +++ /dev/null @@ -1,132 +0,0 @@ -// @flow - -import invariant from 'invariant' -import logger from 'logger' -import Websocket from 'ws' -import type Transport from '@ledgerhq/hw-transport' -import { Observable } from 'rxjs' -import { - WebsocketConnectionError, - WebsocketConnectionFailed, - DeviceSocketFail, - DeviceSocketNoBulkStatus, - DeviceSocketNoHandler, -} from '@ledgerhq/live-common/lib/errors' - -/** - * use Ledger WebSocket API to exchange data with the device - * Returns an Observable of the final result - */ -export const createDeviceSocket = (transport: Transport<*>, url: string) => - Observable.create(o => { - let ws - let lastMessage: ?string - - try { - ws = new Websocket(url) - } catch (err) { - o.error(new WebsocketConnectionFailed(err.message, { url })) - return () => {} - } - invariant(ws, 'websocket is available') - - ws.on('open', () => { - logger.websocket('OPENED', { url }) - }) - - ws.on('error', e => { - logger.websocket('ERROR', { message: e.message, stack: e.stack }) - o.error(new WebsocketConnectionError(e.message, { url })) - }) - - ws.on('close', () => { - logger.websocket('CLOSE') - o.next(lastMessage || '') - o.complete() - }) - - const send = (nonce, response, data) => { - const msg = { - nonce, - response, - data, - } - logger.websocket('SEND', msg) - const strMsg = JSON.stringify(msg) - ws.send(strMsg) - } - - const handlers = { - exchange: async input => { - const { data, nonce } = input - const r: Buffer = await transport.exchange(Buffer.from(data, 'hex')) - const status = r.slice(r.length - 2) - const buffer = r.slice(0, r.length - 2) - const strStatus = status.toString('hex') - send(nonce, strStatus === '9000' ? 'success' : 'error', buffer.toString('hex')) - }, - - bulk: async input => { - const { data, nonce } = input - - // Execute all apdus and collect last status - let lastStatus = null - for (const apdu of data) { - const r: Buffer = await transport.exchange(Buffer.from(apdu, 'hex')) - lastStatus = r.slice(r.length - 2) - - if (lastStatus.toString('hex') !== '9000') break - } - - if (!lastStatus) { - throw new DeviceSocketNoBulkStatus() - } - - const strStatus = lastStatus.toString('hex') - - send( - nonce, - strStatus === '9000' ? 'success' : 'error', - strStatus === '9000' ? '' : strStatus, - ) - }, - - success: msg => { - lastMessage = msg.data || msg.result - ws.close() - }, - - error: msg => { - logger.websocket('ERROR', { data: msg.data }) - throw new DeviceSocketFail(msg.data, { url }) - }, - } - - const stackMessage = async rawMsg => { - try { - const msg = JSON.parse(rawMsg) - if (!(msg.query in handlers)) { - throw new DeviceSocketNoHandler(`Cannot handle msg of type ${msg.query}`, { - query: msg.query, - url, - }) - } - logger.websocket('RECEIVE', msg) - await handlers[msg.query](msg) - } catch (err) { - logger.websocket('ERROR', { message: err.message, stack: err.stack }) - o.error(err) - } - } - - ws.on('message', async rawMsg => { - stackMessage(rawMsg) - }) - - return () => { - if (ws.readyState === 1) { - lastMessage = null - ws.close() - } - } - }) diff --git a/src/helpers/urls.js b/src/helpers/urls.js deleted file mode 100644 index 8d953b53..00000000 --- a/src/helpers/urls.js +++ /dev/null @@ -1,37 +0,0 @@ -// @flow -import qs from 'qs' - -import { MANAGER_API_BASE, BASE_SOCKET_URL } from 'config/constants' -import type { LedgerScriptParams } from 'helpers/types' - -const urlBuilder = (base: string) => (endpoint: string): string => `${base}/${endpoint}` - -const managerUrlbuilder = urlBuilder(MANAGER_API_BASE) - -const wsURLBuilder = (endpoint: string) => (params?: Object) => - `${BASE_SOCKET_URL}/${endpoint}${params ? `?${qs.stringify(params)}` : ''}` - -// const wsURLBuilderProxy = (endpoint: string) => (params?: Object) => -// `ws://manager.ledger.fr:3501/${endpoint}${params ? `?${qs.stringify(params)}` : ''}` - -// FIXME we shouldn't do this here. we should just collocate these where it's used. - -export const GET_FINAL_FIRMWARE: string = managerUrlbuilder('firmware_final_versions') -export const GET_DEVICE_VERSION: string = managerUrlbuilder('get_device_version') -export const APPLICATIONS_BY_DEVICE: string = managerUrlbuilder('get_apps') -export const GET_CURRENT_FIRMWARE: string = managerUrlbuilder('get_firmware_version') -export const GET_CURRENT_OSU: string = managerUrlbuilder('get_osu_version') -export const GET_LATEST_FIRMWARE: string = managerUrlbuilder('get_latest_firmware') -export const GET_NEXT_MCU: string = managerUrlbuilder('mcu_versions_bootloader') -export const GET_MCUS: string = managerUrlbuilder('mcu_versions') -export const GET_CATEGORIES: string = managerUrlbuilder('categories') -export const GET_APPLICATIONS: string = managerUrlbuilder('applications') - -export const WS_INSTALL: (arg: LedgerScriptParams) => string = wsURLBuilder('install') -export const WS_GENUINE: (arg: { - targetId: string | number, - perso: string, -}) => string = wsURLBuilder('genuine') -export const WS_MCU: (arg: { targetId: string | number, version: string }) => string = wsURLBuilder( - 'mcu', -) diff --git a/src/logger/logger.js b/src/logger/logger.js index 04e161cb..63161dec 100644 --- a/src/logger/logger.js +++ b/src/logger/logger.js @@ -109,13 +109,7 @@ const logAnalytics = !__DEV__ || DEBUG_ANALYTICS const logApdu = !__DEV__ || DEBUG_DEVICE const blacklistTooVerboseCommandInput = [] -const blacklistTooVerboseCommandResponse = [ - 'libcoreSyncAccount', - 'libcoreScanAccounts', - 'listApps', - 'listAppVersions', - 'listCategories', -] +const blacklistTooVerboseCommandResponse = ['libcoreSyncAccount', 'libcoreScanAccounts'] export default { onCmd: (type: string, id: string, spentTime: number, data?: any) => { From a9115825fb7a2e3fa5ef6b6a9ca8bdde12ce88b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Tue, 18 Dec 2018 07:28:16 +0100 Subject: [PATCH 06/26] Refine the FU calls --- package.json | 2 +- src/commands/firmwareMain.js | 2 +- ...{firmwareCheckId.js => firmwarePrepare.js} | 8 ++-- src/commands/firmwareRepair.js | 2 +- src/commands/index.js | 4 +- .../SettingsPage/RepairDeviceButton.js | 39 ++++++++----------- .../steps/01-step-install-full-firmware.js | 4 +- .../UpdateFirmware/steps/02-step-flash-mcu.js | 35 ++++++----------- yarn.lock | 8 ++-- 9 files changed, 44 insertions(+), 60 deletions(-) rename src/commands/{firmwareCheckId.js => firmwarePrepare.js} (59%) diff --git a/package.json b/package.json index 9c98dca4..fc10cc89 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "@ledgerhq/hw-transport": "^4.32.0", "@ledgerhq/hw-transport-node-hid": "^4.32.0", "@ledgerhq/ledger-core": "2.0.0-rc.14", - "@ledgerhq/live-common": "4.8.0-beta.12", + "@ledgerhq/live-common": "4.8.0-beta.13", "animated": "^0.2.2", "async": "^2.6.1", "axios": "^0.18.0", diff --git a/src/commands/firmwareMain.js b/src/commands/firmwareMain.js index 4397a590..aa5d3b6c 100644 --- a/src/commands/firmwareMain.js +++ b/src/commands/firmwareMain.js @@ -8,7 +8,7 @@ type Input = { finalFirmware: FinalFirmware, } -type Result = * +type Result = { progress: number, installing: ?string } const cmd: Command = createCommand( 'firmwareMain', diff --git a/src/commands/firmwareCheckId.js b/src/commands/firmwarePrepare.js similarity index 59% rename from src/commands/firmwareCheckId.js rename to src/commands/firmwarePrepare.js index 17025469..ebab01d3 100644 --- a/src/commands/firmwareCheckId.js +++ b/src/commands/firmwarePrepare.js @@ -1,6 +1,6 @@ // @flow -import checkId from '@ledgerhq/live-common/lib/hw/firmwareUpdate-checkId' +import prepare from '@ledgerhq/live-common/lib/hw/firmwareUpdate-prepare' import type { OsuFirmware } from '@ledgerhq/live-common/lib/types/manager' import { createCommand, Command } from 'helpers/ipc' @@ -9,11 +9,11 @@ type Input = { osuFirmware: OsuFirmware, } -type Result = * +type Result = { progress: number } const cmd: Command = createCommand( - 'firmwareCheckId', - ({ devicePath, osuFirmware }) => checkId(devicePath, osuFirmware), + 'firmwarePrepare', + ({ devicePath, osuFirmware }) => prepare(devicePath, osuFirmware), ) export default cmd diff --git a/src/commands/firmwareRepair.js b/src/commands/firmwareRepair.js index 41e34401..64009722 100644 --- a/src/commands/firmwareRepair.js +++ b/src/commands/firmwareRepair.js @@ -4,7 +4,7 @@ import repair from '@ledgerhq/live-common/lib/hw/firmwareUpdate-repair' import { createCommand, Command } from 'helpers/ipc' type Input = void -type Result = * +type Result = { progress: number } const cmd: Command = createCommand( 'firmwareRepair', diff --git a/src/commands/index.js b/src/commands/index.js index ac155d41..c9f32998 100644 --- a/src/commands/index.js +++ b/src/commands/index.js @@ -4,7 +4,7 @@ import invariant from 'invariant' import type { Command } from 'helpers/ipc' import debugAppInfosForCurrency from 'commands/debugAppInfosForCurrency' -import firmwareCheckId from 'commands/firmwareCheckId' +import firmwarePrepare from 'commands/firmwarePrepare' import firmwareMain from 'commands/firmwareMain' import firmwareRepair from 'commands/firmwareRepair' import getAddress from 'commands/getAddress' @@ -30,7 +30,7 @@ import uninstallApp from 'commands/uninstallApp' const all: Array> = [ debugAppInfosForCurrency, - firmwareCheckId, + firmwarePrepare, firmwareMain, firmwareRepair, getAddress, diff --git a/src/components/SettingsPage/RepairDeviceButton.js b/src/components/SettingsPage/RepairDeviceButton.js index c7f7db54..e68f2fa1 100644 --- a/src/components/SettingsPage/RepairDeviceButton.js +++ b/src/components/SettingsPage/RepairDeviceButton.js @@ -16,13 +16,15 @@ type State = { opened: boolean, isLoading: boolean, error: ?Error, + progress: number, } -class CleanButton extends PureComponent { +class RepairDeviceButton extends PureComponent { state = { opened: false, isLoading: false, error: null, + progress: 0, } open = () => this.setState({ opened: true }) @@ -37,32 +39,25 @@ class CleanButton extends PureComponent { action = () => { if (this.state.isLoading) return this.setState({ isLoading: true }) - this.sub = firmwareRepair - .send() - .pipe( - tap(e => console.log(e)), // eslint-disable-line no-console - // ^ TODO remove at the end - filter(e => e.type === 'bulk-progress'), - ) - .subscribe({ - next: () => { - // TODO cc @val - }, - error: error => { - this.setState({ error, opened: false, isLoading: false }) - }, - complete: () => { - this.setState({ opened: false, isLoading: false }) - }, - }) + this.sub = firmwareRepair.send().subscribe({ + next: patch => { + this.setState(patch) + }, + error: error => { + this.setState({ error, opened: false, isLoading: false }) + }, + complete: () => { + this.setState({ opened: false, isLoading: false }) + }, + }) } render() { const { t } = this.props - const { opened, isLoading, error } = this.state + const { opened, isLoading, error, progress } = this.state // @val basically I think we want to diverge from the traditional ConfirmModal to make our own version // with the progress and the error cases handled. - console.log({ error }) // eslint-disable-line no-console + console.log({ error, progress }) // eslint-disable-line no-console // ^ TODO use error to pass in that custom thing return ( @@ -87,4 +82,4 @@ class CleanButton extends PureComponent { } } -export default translate()(CleanButton) +export default translate()(RepairDeviceButton) diff --git a/src/components/modals/UpdateFirmware/steps/01-step-install-full-firmware.js b/src/components/modals/UpdateFirmware/steps/01-step-install-full-firmware.js index 4121ff06..8e50bf5c 100644 --- a/src/components/modals/UpdateFirmware/steps/01-step-install-full-firmware.js +++ b/src/components/modals/UpdateFirmware/steps/01-step-install-full-firmware.js @@ -4,7 +4,7 @@ import React, { PureComponent, Fragment } from 'react' import styled from 'styled-components' import { connect } from 'react-redux' -import firmwareCheckId from 'commands/firmwareCheckId' +import firmwarePrepare from 'commands/firmwarePrepare' import { getCurrentDevice } from 'reducers/devices' import TrackPage from 'analytics/TrackPage' import Box from 'components/base/Box' @@ -56,7 +56,7 @@ class StepFullFirmwareInstall extends PureComponent { return } - this.sub = firmwareCheckId + this.sub = firmwarePrepare .send({ devicePath: device.path, osuFirmware: osu, diff --git a/src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js b/src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js index 500a022a..e484f520 100644 --- a/src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js +++ b/src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js @@ -56,29 +56,18 @@ class StepFlashMcu extends PureComponent { componentDidMount() { const { final: finalFirmware, transitionTo, setError } = this.props - this.sub = firmwareMain - .send({ finalFirmware }) - .pipe( - tap(e => console.log(e)), // eslint-disable-line no-console - // ^ TODO remove at the end - filter(e => e.type === 'bulk-progress' || e.type === 'install'), - ) - .subscribe({ - next: e => { - if (e.type === 'install') { - this.setState({ installing: e.step, progress: 0 }) - } else { - this.setState({ progress: e.progress }) - } - }, - complete: () => { - transitionTo('finish') - }, - error: error => { - setError(error) - transitionTo('finish') - }, - }) + this.sub = firmwareMain.send({ finalFirmware }).subscribe({ + next: patch => { + this.setState(patch) + }, + complete: () => { + transitionTo('finish') + }, + error: error => { + setError(error) + transitionTo('finish') + }, + }) } componentWillUnmount() { diff --git a/yarn.lock b/yarn.lock index 399f121c..eadd7f00 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1725,10 +1725,10 @@ bindings "^1.3.0" nan "^2.6.2" -"@ledgerhq/live-common@4.8.0-beta.12": - version "4.8.0-beta.12" - resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-4.8.0-beta.12.tgz#4319aa397896f242d753ea63ff7ac4223788eb88" - integrity sha512-J2gaXqQkDuqZl2SgjNE7ZOSX0nMl9xqHu5jwHqiyBSlXvykdXWMmaPLcBcP8F+xszpKCIB0N6XaJFUAHHbD0Nw== +"@ledgerhq/live-common@4.8.0-beta.13": + version "4.8.0-beta.13" + resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-4.8.0-beta.13.tgz#64ecb2a8a8845f92519dfb9552623a42a9e3824e" + integrity sha512-Y66m+3q/6L8CAFUPXjlpS8jPE2168Y/X8JMC05voFKTC2U3Y1RGaRd/nEBA53Z2BFrbwZ2yIViylew4nFvH2Sg== dependencies: "@aeternity/ledger-app-api" "0.0.4" "@ledgerhq/hw-app-btc" "^4.32.0" From cbef835c05acf12a3279419c6e98908457295993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Tue, 18 Dec 2018 07:29:13 +0100 Subject: [PATCH 07/26] lint --- src/components/SettingsPage/RepairDeviceButton.js | 1 - src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js | 1 - 2 files changed, 2 deletions(-) diff --git a/src/components/SettingsPage/RepairDeviceButton.js b/src/components/SettingsPage/RepairDeviceButton.js index e68f2fa1..9e83f35e 100644 --- a/src/components/SettingsPage/RepairDeviceButton.js +++ b/src/components/SettingsPage/RepairDeviceButton.js @@ -1,7 +1,6 @@ // @flow import React, { Fragment, PureComponent } from 'react' -import { filter, tap } from 'rxjs/operators' import { translate } from 'react-i18next' import type { T } from 'types/common' import firmwareRepair from 'commands/firmwareRepair' diff --git a/src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js b/src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js index e484f520..8ddf57c3 100644 --- a/src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js +++ b/src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js @@ -2,7 +2,6 @@ import React, { PureComponent, Fragment } from 'react' import styled from 'styled-components' -import { filter, tap } from 'rxjs/operators' import { i } from 'helpers/staticPath' import firmwareMain from 'commands/firmwareMain' From c950d68ea69a31c72a81807c37501a8432e75f77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Tue, 18 Dec 2018 07:43:31 +0100 Subject: [PATCH 08/26] install/uninstall is throttle/filtered/mapped on live-common side --- package.json | 2 +- src/commands/installApp.js | 4 +--- src/commands/uninstallApp.js | 2 -- src/components/ManagerPage/AppsList.js | 30 ++++++++++---------------- yarn.lock | 8 +++---- 5 files changed, 17 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index fc10cc89..c5a0ffe4 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "@ledgerhq/hw-transport": "^4.32.0", "@ledgerhq/hw-transport-node-hid": "^4.32.0", "@ledgerhq/ledger-core": "2.0.0-rc.14", - "@ledgerhq/live-common": "4.8.0-beta.13", + "@ledgerhq/live-common": "4.8.0-beta.14", "animated": "^0.2.2", "async": "^2.6.1", "axios": "^0.18.0", diff --git a/src/commands/installApp.js b/src/commands/installApp.js index 71e04ecb..3842ea21 100644 --- a/src/commands/installApp.js +++ b/src/commands/installApp.js @@ -1,7 +1,5 @@ // @flow - import { createCommand, Command } from 'helpers/ipc' - import installApp from '@ledgerhq/live-common/lib/hw/installApp' import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' import type { ApplicationVersion } from '@ledgerhq/live-common/lib/types/manager' @@ -12,7 +10,7 @@ type Input = { app: ApplicationVersion, } -type Result = * +type Result = { progress: number } const cmd: Command = createCommand('installApp', ({ devicePath, targetId, app }) => withDevice(devicePath)(transport => installApp(transport, targetId, app)), diff --git a/src/commands/uninstallApp.js b/src/commands/uninstallApp.js index 6d713a4c..056ba069 100644 --- a/src/commands/uninstallApp.js +++ b/src/commands/uninstallApp.js @@ -1,9 +1,7 @@ // @flow - import { createCommand, Command } from 'helpers/ipc' import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' import uninstallApp from '@ledgerhq/live-common/lib/hw/uninstallApp' - import type { ApplicationVersion } from '@ledgerhq/live-common/lib/types/manager' type Input = { diff --git a/src/components/ManagerPage/AppsList.js b/src/components/ManagerPage/AppsList.js index 97f9cea2..1aef7d88 100644 --- a/src/components/ManagerPage/AppsList.js +++ b/src/components/ManagerPage/AppsList.js @@ -6,7 +6,6 @@ import styled from 'styled-components' import { translate } from 'react-i18next' import { connect } from 'react-redux' import { compose } from 'redux' -import { throttleTime, filter, map } from 'rxjs/operators' import type { Device, T } from 'types/common' import type { ApplicationVersion, DeviceInfo } from '@ledgerhq/live-common/lib/types/manager' @@ -158,24 +157,17 @@ class AppsList extends PureComponent { device: { path: devicePath }, deviceInfo: { targetId }, } = this.props - this.sub = cmd - .send({ app, devicePath, targetId }) - .pipe( - filter(e => e.type === 'bulk-progress'), // only bulk progress interests the UI - throttleTime(100), // throttle to only emit 10 event/s max, to not spam the UI - map(e => e.progress), // extract a stream of progress percentage - ) - .subscribe({ - next: progress => { - this.setState({ progress }) - }, - complete: () => { - this.setState({ status: 'success' }) - }, - error: error => { - this.setState({ status: 'error', error, app: '', mode: 'home' }) - }, - }) + this.sub = cmd.send({ app, devicePath, targetId }).subscribe({ + next: patch => { + this.setState(patch) + }, + complete: () => { + this.setState({ status: 'success' }) + }, + error: error => { + this.setState({ status: 'error', error, app: '', mode: 'home' }) + }, + }) } handleInstallApp = (app: ApplicationVersion) => () => diff --git a/yarn.lock b/yarn.lock index eadd7f00..b3578bfa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1725,10 +1725,10 @@ bindings "^1.3.0" nan "^2.6.2" -"@ledgerhq/live-common@4.8.0-beta.13": - version "4.8.0-beta.13" - resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-4.8.0-beta.13.tgz#64ecb2a8a8845f92519dfb9552623a42a9e3824e" - integrity sha512-Y66m+3q/6L8CAFUPXjlpS8jPE2168Y/X8JMC05voFKTC2U3Y1RGaRd/nEBA53Z2BFrbwZ2yIViylew4nFvH2Sg== +"@ledgerhq/live-common@4.8.0-beta.14": + version "4.8.0-beta.14" + resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-4.8.0-beta.14.tgz#958bf811b2e1846fd3c218c863b1cfc729c2df19" + integrity sha512-gA2fvLbEfbXJ8IFm73Z236J3MrH7XQdFE3m12y3qWNYk4Bd1M1DWpIg4kFNPfxYTVaQ/Os0vJ08BOv9tj5lW9A== dependencies: "@aeternity/ledger-app-api" "0.0.4" "@ledgerhq/hw-app-btc" "^4.32.0" From 1e76487b84449ddad88dd7b74ad68ecdf32636d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Tue, 18 Dec 2018 09:46:49 +0100 Subject: [PATCH 09/26] Display a progress under the step 01 because can be long --- .../steps/01-step-install-full-firmware.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/components/modals/UpdateFirmware/steps/01-step-install-full-firmware.js b/src/components/modals/UpdateFirmware/steps/01-step-install-full-firmware.js index 8e50bf5c..2ef804ff 100644 --- a/src/components/modals/UpdateFirmware/steps/01-step-install-full-firmware.js +++ b/src/components/modals/UpdateFirmware/steps/01-step-install-full-firmware.js @@ -9,6 +9,7 @@ import { getCurrentDevice } from 'reducers/devices' import TrackPage from 'analytics/TrackPage' import Box from 'components/base/Box' import Text from 'components/base/Text' +import ProgressBar from 'components/ProgressBar' import DeviceConfirm from 'components/DeviceConfirm' import type { Device } from 'types/common' import type { StepProps } from '../' @@ -47,7 +48,11 @@ type Props = StepProps & { device: Device, } -class StepFullFirmwareInstall extends PureComponent { +class StepFullFirmwareInstall extends PureComponent { + state = { + progress: 0, + } + componentDidMount() { const { osu, device, transitionTo, setError } = this.props @@ -62,6 +67,9 @@ class StepFullFirmwareInstall extends PureComponent { osuFirmware: osu, }) .subscribe({ + next: patch => { + this.setState(patch) + }, complete: () => { transitionTo('updateMCU') }, @@ -94,12 +102,13 @@ class StepFullFirmwareInstall extends PureComponent { {t('manager.modal.confirmIdentifierText')} - + {t('manager.modal.identifier')}
{osu && this.formatHashName(osu.hash)}
+ From 734f9362d529fb438e2cf465ec4d236a0f451928 Mon Sep 17 00:00:00 2001 From: "Valentin D. Pinkman" Date: Tue, 18 Dec 2018 16:23:13 +0100 Subject: [PATCH 10/26] repair modal UI + error case --- .../SettingsPage/RepairDeviceButton.js | 17 +- src/components/base/Modal/RepairModal.js | 169 ++++++++++++++++++ src/components/base/Modal/index.js | 1 + static/i18n/en/app.json | 14 +- 4 files changed, 185 insertions(+), 16 deletions(-) create mode 100644 src/components/base/Modal/RepairModal.js diff --git a/src/components/SettingsPage/RepairDeviceButton.js b/src/components/SettingsPage/RepairDeviceButton.js index 9e83f35e..6a913b79 100644 --- a/src/components/SettingsPage/RepairDeviceButton.js +++ b/src/components/SettingsPage/RepairDeviceButton.js @@ -5,7 +5,7 @@ import { translate } from 'react-i18next' import type { T } from 'types/common' import firmwareRepair from 'commands/firmwareRepair' import Button from 'components/base/Button' -import { ConfirmModal } from 'components/base/Modal' +import { RepairModal } from 'components/base/Modal' type Props = { t: T, @@ -32,7 +32,7 @@ class RepairDeviceButton extends PureComponent { close = () => { if (this.sub) this.sub.unsubscribe() - this.setState({ opened: false }) + this.setState({ opened: false, isLoading: false }) } action = () => { @@ -43,7 +43,7 @@ class RepairDeviceButton extends PureComponent { this.setState(patch) }, error: error => { - this.setState({ error, opened: false, isLoading: false }) + this.setState({ error, isLoading: false }) }, complete: () => { this.setState({ opened: false, isLoading: false }) @@ -54,17 +54,14 @@ class RepairDeviceButton extends PureComponent { render() { const { t } = this.props const { opened, isLoading, error, progress } = this.state - // @val basically I think we want to diverge from the traditional ConfirmModal to make our own version - // with the progress and the error cases handled. - console.log({ error, progress }) // eslint-disable-line no-console - // ^ TODO use error to pass in that custom thing + return ( - { onConfirm={this.action} isLoading={isLoading} title={t('settings.repairDevice.title')} - subTitle={t('common.areYouSure')} desc={t('settings.repairDevice.desc')} + confirmText={t('settings.repairDevice.button')} + progress={progress} + error={error} /> ) diff --git a/src/components/base/Modal/RepairModal.js b/src/components/base/Modal/RepairModal.js new file mode 100644 index 00000000..7f59dbb1 --- /dev/null +++ b/src/components/base/Modal/RepairModal.js @@ -0,0 +1,169 @@ +// @flow + +import React, { PureComponent } from 'react' +import { translate } from 'react-i18next' +import styled from 'styled-components' + +import type { T } from 'types/common' + +import { i } from 'helpers/staticPath' +import TrackPage from 'analytics/TrackPage' +import Button from 'components/base/Button' +import Box from 'components/base/Box' +import Text from 'components/base/Text' +import ProgressCircle from 'components/ProgressCircle' +import TranslatedError from 'components/TranslatedError' + +import { Modal, ModalContent, ModalBody, ModalTitle, ModalFooter } from './index' + +const Bullet = styled.span` + font-weight: 600; + color: #142533; +` + +const Separator = styled(Box).attrs({ + color: 'fog', +})` + height: 1px; + width: 100%; + background-color: currentColor; +` + +const ConnectStep = ({ t, desc }: { t: *, desc?: string }) => ( + + {desc ? ( + + {desc} + + ) : null} + + + {'1.'} + {t('manager.modal.mcuFirst')} + + {t('manager.modal.mcuFirst')} + + + + + {'2.'} + {t('manager.modal.mcuSecond')} + + {t('manager.modal.mcuFirst')} + + +) + +const FlashStep = ({ progress, t }: { progress: number, t: * }) => ( + <> + + + + + + {t(`manager.modal.steps.flash`)} + + + + + {t('manager.modal.mcuPin')} + + + +) + +const ErrorStep = ({ error }: { error: Error }) => ( + + + +) + +type Props = { + isOpened: boolean, + isDanger: boolean, + title: string, + subTitle?: string, + desc: string, + renderIcon?: Function, + confirmText?: string, + cancelText?: string, + onReject: Function, + onConfirm: Function, + t: T, + isLoading?: boolean, + analyticsName: string, + cancellable?: boolean, + progress: number, + error?: Error, +} + +class RepairModal extends PureComponent { + render() { + const { + cancellable, + isOpened, + title, + desc, + confirmText, + isDanger, + onReject, + onConfirm, + isLoading, + renderIcon, + t, + analyticsName, + progress, + error, + ...props + } = this.props + + const realConfirmText = confirmText || t('common.confirm') + + return ( + ( + + + {title} + {isLoading && progress > 0 ? ( + + ) : error ? ( + + ) : ( + + )} + + {!isLoading && ( + + )} + {error ? null : ( + + )} + + + )} + /> + ) + } +} + +export default translate()(RepairModal) diff --git a/src/components/base/Modal/index.js b/src/components/base/Modal/index.js index ca84f4fb..cad43fda 100644 --- a/src/components/base/Modal/index.js +++ b/src/components/base/Modal/index.js @@ -22,6 +22,7 @@ import GrowScroll from 'components/base/GrowScroll' export { default as ModalBody } from './ModalBody' export { default as ConfirmModal } from './ConfirmModal' +export { default as RepairModal } from './RepairModal' export { default as ModalTitle } from './ModalTitle' const springConfig = { diff --git a/static/i18n/en/app.json b/static/i18n/en/app.json index 633e2eba..3eb80cc6 100644 --- a/static/i18n/en/app.json +++ b/static/i18n/en/app.json @@ -262,7 +262,8 @@ "osu": "Installing OSU...", "flash-mcu": "MCU updating...", "flash-bootloader": "Bootloader updating...", - "firmware": "Firmware updating..." + "firmware": "Firmware updating...", + "flash": "Flashing your device..." }, "confirmIdentifier": "Verify the identifier", "confirmIdentifierText": "Verify that the identifier on your device is the same as the identifier below. Press the right button and enter your PIN code to confirm", @@ -296,8 +297,7 @@ "confirmAddress": { "title": "Verification", "action": "Verify address on device", - "text": "Please verify that the {{currencyName}} address shown on your device matches the one on your computer" - , + "text": "Please verify that the {{currencyName}} address shown on your device matches the one on your computer", "support": "Contact us" }, "receiveFunds": { @@ -359,7 +359,7 @@ "export": { "desc": "Import accounts on your Ledger Live Mobile app", "button": "Export", - "modal":{ + "modal": { "button": "Done", "title": "Scan to export to mobile", "listTitle": "To import accounts on your Ledger Live Mobile app:", @@ -643,7 +643,7 @@ "step2": { "title": "Did you save your recovery phrase by yourself?" }, - "step3":{ + "step3": { "title": "Is your Ledger device genuine?" }, "isGenuinePassed": "Your device is genuine", @@ -666,7 +666,7 @@ }, "setPassword": { "title": "Password lock (optional)", - "desc": "Set a password to prevent unauthorized access to Ledger Live data on your computer, including account names, transactions and public addresses", + "desc": "Set a password to prevent unauthorized access to Ledger Live data on your computer, including account names, transactions and public addresses", "disclaimer": { "note1": "Make sure to remember your password. Do not share it.", "note2": "Losing your password requires resetting Ledger Live and re-adding accounts.", @@ -903,4 +903,4 @@ "title": "Couldn’t load fee rates, please set manual fees" } } -} +} \ No newline at end of file From 228d2dfeed7ec21a8b238de422832695f6184264 Mon Sep 17 00:00:00 2001 From: "Valentin D. Pinkman" Date: Tue, 18 Dec 2018 17:14:50 +0100 Subject: [PATCH 11/26] fixes on modal ui and navigate to manager when repair is finished --- .../SettingsPage/RepairDeviceButton.js | 24 +++++++++++++++++-- src/components/base/Modal/RepairModal.js | 14 ++++++----- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/components/SettingsPage/RepairDeviceButton.js b/src/components/SettingsPage/RepairDeviceButton.js index 6a913b79..056d1f30 100644 --- a/src/components/SettingsPage/RepairDeviceButton.js +++ b/src/components/SettingsPage/RepairDeviceButton.js @@ -1,7 +1,12 @@ // @flow import React, { Fragment, PureComponent } from 'react' +import { compose } from 'redux' +import { connect } from 'react-redux' +import { withRouter } from 'react-router' import { translate } from 'react-i18next' +import { push } from 'react-router-redux' + import type { T } from 'types/common' import firmwareRepair from 'commands/firmwareRepair' import Button from 'components/base/Button' @@ -9,6 +14,7 @@ import { RepairModal } from 'components/base/Modal' type Props = { t: T, + push: Function, } type State = { @@ -37,6 +43,7 @@ class RepairDeviceButton extends PureComponent { action = () => { if (this.state.isLoading) return + const { push } = this.props this.setState({ isLoading: true }) this.sub = firmwareRepair.send().subscribe({ next: patch => { @@ -46,7 +53,9 @@ class RepairDeviceButton extends PureComponent { this.setState({ error, isLoading: false }) }, complete: () => { - this.setState({ opened: false, isLoading: false }) + this.setState({ opened: false, isLoading: false }, () => { + push('/manager') + }) }, }) } @@ -80,4 +89,15 @@ class RepairDeviceButton extends PureComponent { } } -export default translate()(RepairDeviceButton) +const mapDispatchToProps = { + push, +} + +export default compose( + translate(), + withRouter, + connect( + null, + mapDispatchToProps, + ), +)(RepairDeviceButton) diff --git a/src/components/base/Modal/RepairModal.js b/src/components/base/Modal/RepairModal.js index 7f59dbb1..a93e5f5c 100644 --- a/src/components/base/Modal/RepairModal.js +++ b/src/components/base/Modal/RepairModal.js @@ -63,7 +63,7 @@ const ConnectStep = ({ t, desc }: { t: *, desc?: string }) => ( ) const FlashStep = ({ progress, t }: { progress: number, t: * }) => ( - <> + @@ -77,13 +77,15 @@ const FlashStep = ({ progress, t }: { progress: number, t: * }) => ( {t('manager.modal.mcuPin')}
- + ) const ErrorStep = ({ error }: { error: Error }) => ( - - - + + + + + ) type Props = { @@ -136,7 +138,7 @@ class RepairModal extends PureComponent { {title} - {isLoading && progress > 0 ? ( + {isLoading ? ( ) : error ? ( From 746d7425b4814485e554714ebf17f448bcd46e9f Mon Sep 17 00:00:00 2001 From: "Valentin D. Pinkman" Date: Tue, 18 Dec 2018 18:30:24 +0100 Subject: [PATCH 12/26] update live-common and add screen for repair modal --- package.json | 2 +- .../SettingsPage/RepairDeviceButton.js | 16 ++-- src/components/base/Modal/RepairModal.js | 77 +++++++++++++++---- yarn.lock | 8 +- 4 files changed, 76 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index c5a0ffe4..96699b66 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "@ledgerhq/hw-transport": "^4.32.0", "@ledgerhq/hw-transport-node-hid": "^4.32.0", "@ledgerhq/ledger-core": "2.0.0-rc.14", - "@ledgerhq/live-common": "4.8.0-beta.14", + "@ledgerhq/live-common": "4.8.0-beta.16", "animated": "^0.2.2", "async": "^2.6.1", "axios": "^0.18.0", diff --git a/src/components/SettingsPage/RepairDeviceButton.js b/src/components/SettingsPage/RepairDeviceButton.js index 056d1f30..e876a789 100644 --- a/src/components/SettingsPage/RepairDeviceButton.js +++ b/src/components/SettingsPage/RepairDeviceButton.js @@ -22,6 +22,7 @@ type State = { isLoading: boolean, error: ?Error, progress: number, + confirmed: boolean, } class RepairDeviceButton extends PureComponent { @@ -30,15 +31,18 @@ class RepairDeviceButton extends PureComponent { isLoading: false, error: null, progress: 0, + confirmed: false, } - open = () => this.setState({ opened: true }) + open = () => this.setState({ opened: true, error: null }) + + setConfirm = () => this.setState({ confirmed: true }) sub: * close = () => { if (this.sub) this.sub.unsubscribe() - this.setState({ opened: false, isLoading: false }) + this.setState({ opened: false, isLoading: false, error: null, confirmed: false }) } action = () => { @@ -50,10 +54,10 @@ class RepairDeviceButton extends PureComponent { this.setState(patch) }, error: error => { - this.setState({ error, isLoading: false }) + this.setState({ error, isLoading: false, confirmed: false }) }, complete: () => { - this.setState({ opened: false, isLoading: false }, () => { + this.setState({ opened: false, isLoading: false, confirmed: false }, () => { push('/manager') }) }, @@ -62,7 +66,7 @@ class RepairDeviceButton extends PureComponent { render() { const { t } = this.props - const { opened, isLoading, error, progress } = this.state + const { opened, isLoading, error, progress, confirmed } = this.state return ( @@ -83,6 +87,8 @@ class RepairDeviceButton extends PureComponent { confirmText={t('settings.repairDevice.button')} progress={progress} error={error} + setConfirm={this.setConfirm} + confirmed={confirmed} /> ) diff --git a/src/components/base/Modal/RepairModal.js b/src/components/base/Modal/RepairModal.js index a93e5f5c..5d8f7ee8 100644 --- a/src/components/base/Modal/RepairModal.js +++ b/src/components/base/Modal/RepairModal.js @@ -13,9 +13,16 @@ import Box from 'components/base/Box' import Text from 'components/base/Text' import ProgressCircle from 'components/ProgressCircle' import TranslatedError from 'components/TranslatedError' +import ExclamationCircleThin from 'icons/ExclamationCircleThin' import { Modal, ModalContent, ModalBody, ModalTitle, ModalFooter } from './index' +const Container = styled(Box).attrs({ + alignItems: 'center', + fontSize: 4, + color: 'dark', +})`` + const Bullet = styled.span` font-weight: 600; color: #142533; @@ -29,13 +36,18 @@ const Separator = styled(Box).attrs({ background-color: currentColor; ` -const ConnectStep = ({ t, desc }: { t: *, desc?: string }) => ( +const DisclaimerStep = ({ desc }: { desc?: string }) => ( {desc ? ( - + {desc} ) : null} + +) + +const ConnectStep = ({ t }: { t: * }) => ( + {'1.'} @@ -67,12 +79,10 @@ const FlashStep = ({ progress, t }: { progress: number, t: * }) => ( - - - {t(`manager.modal.steps.flash`)} - + + {t(`manager.modal.steps.flash`)} - + {t('manager.modal.mcuPin')} @@ -82,9 +92,31 @@ const FlashStep = ({ progress, t }: { progress: number, t: * }) => ( const ErrorStep = ({ error }: { error: Error }) => ( - - - + + + + + + + + + + + ) @@ -105,9 +137,15 @@ type Props = { cancellable?: boolean, progress: number, error?: Error, + confirmed: boolean, + setConfirm: Function, +} + +type State = { + confirmed: boolean, } -class RepairModal extends PureComponent { +class RepairModal extends PureComponent { render() { const { cancellable, @@ -124,6 +162,8 @@ class RepairModal extends PureComponent { analyticsName, progress, error, + confirmed, + setConfirm, ...props } = this.props @@ -138,26 +178,29 @@ class RepairModal extends PureComponent { {title} - {isLoading ? ( - - ) : error ? ( + {error ? ( - ) : ( + ) : isLoading ? ( + + ) : confirmed ? ( + ) : ( + )} + {!isLoading && ( )} {error ? null : ( )} diff --git a/yarn.lock b/yarn.lock index b3578bfa..006df270 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1725,10 +1725,10 @@ bindings "^1.3.0" nan "^2.6.2" -"@ledgerhq/live-common@4.8.0-beta.14": - version "4.8.0-beta.14" - resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-4.8.0-beta.14.tgz#958bf811b2e1846fd3c218c863b1cfc729c2df19" - integrity sha512-gA2fvLbEfbXJ8IFm73Z236J3MrH7XQdFE3m12y3qWNYk4Bd1M1DWpIg4kFNPfxYTVaQ/Os0vJ08BOv9tj5lW9A== +"@ledgerhq/live-common@4.8.0-beta.16": + version "4.8.0-beta.16" + resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-4.8.0-beta.16.tgz#cd9939be8b1cf446d71a990ad92e2de208683778" + integrity sha512-BS+M/qRB6cwSPhAQAuHg83TGv0nkp3UDoF7OF3r3GONHQvDqVVxQ44T03YuGMdFkZpk51u8t3DKHuDZe9klP5g== dependencies: "@aeternity/ledger-app-api" "0.0.4" "@ledgerhq/hw-app-btc" "^4.32.0" From 81e916060dfd22d2c40c357d0e74d8c583c97ee1 Mon Sep 17 00:00:00 2001 From: "Valentin D. Pinkman" Date: Tue, 18 Dec 2018 18:46:25 +0100 Subject: [PATCH 13/26] fix connecting step and flash step --- .../SettingsPage/RepairDeviceButton.js | 14 +- src/components/base/Modal/RepairModal.js | 127 ++++++++---------- 2 files changed, 62 insertions(+), 79 deletions(-) diff --git a/src/components/SettingsPage/RepairDeviceButton.js b/src/components/SettingsPage/RepairDeviceButton.js index e876a789..d627cad0 100644 --- a/src/components/SettingsPage/RepairDeviceButton.js +++ b/src/components/SettingsPage/RepairDeviceButton.js @@ -22,7 +22,6 @@ type State = { isLoading: boolean, error: ?Error, progress: number, - confirmed: boolean, } class RepairDeviceButton extends PureComponent { @@ -31,18 +30,15 @@ class RepairDeviceButton extends PureComponent { isLoading: false, error: null, progress: 0, - confirmed: false, } open = () => this.setState({ opened: true, error: null }) - setConfirm = () => this.setState({ confirmed: true }) - sub: * close = () => { if (this.sub) this.sub.unsubscribe() - this.setState({ opened: false, isLoading: false, error: null, confirmed: false }) + this.setState({ opened: false, isLoading: false, error: null, progress: 0 }) } action = () => { @@ -54,10 +50,10 @@ class RepairDeviceButton extends PureComponent { this.setState(patch) }, error: error => { - this.setState({ error, isLoading: false, confirmed: false }) + this.setState({ error, isLoading: false, progress: 0 }) }, complete: () => { - this.setState({ opened: false, isLoading: false, confirmed: false }, () => { + this.setState({ opened: false, isLoading: false, progress: 0 }, () => { push('/manager') }) }, @@ -66,7 +62,7 @@ class RepairDeviceButton extends PureComponent { render() { const { t } = this.props - const { opened, isLoading, error, progress, confirmed } = this.state + const { opened, isLoading, error, progress } = this.state return ( @@ -87,8 +83,6 @@ class RepairDeviceButton extends PureComponent { confirmText={t('settings.repairDevice.button')} progress={progress} error={error} - setConfirm={this.setConfirm} - confirmed={confirmed} /> ) diff --git a/src/components/base/Modal/RepairModal.js b/src/components/base/Modal/RepairModal.js index 5d8f7ee8..37d00df9 100644 --- a/src/components/base/Modal/RepairModal.js +++ b/src/components/base/Modal/RepairModal.js @@ -46,49 +46,48 @@ const DisclaimerStep = ({ desc }: { desc?: string }) => ( ) -const ConnectStep = ({ t }: { t: * }) => ( - - - - {'1.'} - {t('manager.modal.mcuFirst')} - - {t('manager.modal.mcuFirst')} - - - - - {'2.'} - {t('manager.modal.mcuSecond')} - - {t('manager.modal.mcuFirst')} - - -) - -const FlashStep = ({ progress, t }: { progress: number, t: * }) => ( - - - - - - {t(`manager.modal.steps.flash`)} - - - - {t('manager.modal.mcuPin')} - - - -) +const FlashStep = ({ progress, t }: { progress: number, t: * }) => + progress === 0 ? ( + + + + {'1.'} + {t('manager.modal.mcuFirst')} + + {t('manager.modal.mcuFirst')} + + + + + {'2.'} + {t('manager.modal.mcuSecond')} + + {t('manager.modal.mcuFirst')} + + + ) : ( + + + + + + {t(`manager.modal.steps.flash`)} + + + + {t('manager.modal.mcuPin')} + + + + ) const ErrorStep = ({ error }: { error: Error }) => ( @@ -137,15 +136,9 @@ type Props = { cancellable?: boolean, progress: number, error?: Error, - confirmed: boolean, - setConfirm: Function, -} - -type State = { - confirmed: boolean, } -class RepairModal extends PureComponent { +class RepairModal extends PureComponent { render() { const { cancellable, @@ -162,8 +155,6 @@ class RepairModal extends PureComponent { analyticsName, progress, error, - confirmed, - setConfirm, ...props } = this.props @@ -182,28 +173,26 @@ class RepairModal extends PureComponent { ) : isLoading ? ( - ) : confirmed ? ( - ) : ( )} - - {!isLoading && ( + {!isLoading ? ( + - )} - {error ? null : ( - - )} - + {error ? null : ( + + )} + + ) : null} )} /> From 981aa09f2424ca5a9173ba488c9e23fabee35e0e Mon Sep 17 00:00:00 2001 From: "Valentin D. Pinkman" Date: Wed, 19 Dec 2018 11:38:37 +0100 Subject: [PATCH 14/26] small fixes on types --- .../SettingsPage/RepairDeviceButton.js | 2 +- .../modals/UpdateFirmware/Disclaimer.js | 26 +++++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/components/SettingsPage/RepairDeviceButton.js b/src/components/SettingsPage/RepairDeviceButton.js index d627cad0..1332bf3e 100644 --- a/src/components/SettingsPage/RepairDeviceButton.js +++ b/src/components/SettingsPage/RepairDeviceButton.js @@ -14,7 +14,7 @@ import { RepairModal } from 'components/base/Modal' type Props = { t: T, - push: Function, + push: string => void, } type State = { diff --git a/src/components/modals/UpdateFirmware/Disclaimer.js b/src/components/modals/UpdateFirmware/Disclaimer.js index bdc9d22f..76d16fae 100644 --- a/src/components/modals/UpdateFirmware/Disclaimer.js +++ b/src/components/modals/UpdateFirmware/Disclaimer.js @@ -22,8 +22,8 @@ type Props = { t: T, status: ModalStatus, firmware: { - osu: OsuFirmware, - final: FinalFirmware, + osu: ?OsuFirmware, + final: ?FinalFirmware, }, goToNextStep: () => void, onClose: () => void, @@ -48,7 +48,9 @@ class DisclaimerModal extends PureComponent { You are about to install - {`firmware version ${firmware ? getCleanVersion(firmware.osu.name) : ''}`} + {`firmware version ${ + firmware && firmware.osu ? getCleanVersion(firmware.osu.name) : '' + }`} @@ -57,14 +59,16 @@ class DisclaimerModal extends PureComponent { {t('manager.firmware.disclaimerAppReinstall')} - - - - {firmware.osu.notes} - - - - + {firmware && firmware.osu ? ( + + + + {firmware.osu.notes} + + + + + ) : null}