diff --git a/src/commands/installFinalFirmware.js b/src/commands/installFinalFirmware.js index 54fda5c5..42671301 100644 --- a/src/commands/installFinalFirmware.js +++ b/src/commands/installFinalFirmware.js @@ -3,23 +3,19 @@ import { createCommand, Command } from 'helpers/ipc' import { fromPromise } from 'rxjs/observable/fromPromise' import { withDevice } from 'helpers/deviceAccess' -import type { DeviceInfo } from 'helpers/devices/getDeviceInfo' import installFinalFirmware from 'helpers/firmware/installFinalFirmware' type Input = { devicePath: string, - deviceInfo: DeviceInfo, } type Result = { success: boolean, } -const cmd: Command = createCommand( - 'installFinalFirmware', - ({ devicePath, deviceInfo }) => - fromPromise(withDevice(devicePath)(transport => installFinalFirmware(transport, deviceInfo))), +const cmd: Command = createCommand('installFinalFirmware', ({ devicePath }) => + fromPromise(withDevice(devicePath)(transport => installFinalFirmware(transport))), ) export default cmd diff --git a/src/commands/installMcu.js b/src/commands/installMcu.js index 7e49ea16..7d85e40b 100644 --- a/src/commands/installMcu.js +++ b/src/commands/installMcu.js @@ -8,16 +8,12 @@ import installMcu from 'helpers/firmware/installMcu' type Input = { devicePath: string, - targetId: string | number, - version: string, } type Result = * -const cmd: Command = createCommand( - 'installMcu', - ({ devicePath, targetId, version }) => - fromPromise(withDevice(devicePath)(transport => installMcu(transport, { targetId, version }))), +const cmd: Command = createCommand('installMcu', ({ devicePath }) => + fromPromise(withDevice(devicePath)(transport => installMcu(transport))), ) export default cmd diff --git a/src/commands/installOsuFirmware.js b/src/commands/installOsuFirmware.js index 02767210..fd990d54 100644 --- a/src/commands/installOsuFirmware.js +++ b/src/commands/installOsuFirmware.js @@ -11,7 +11,7 @@ import type { LedgerScriptParams } from 'helpers/common' type Input = { devicePath: string, targetId: string | number, - firmware: LedgerScriptParams, + firmware: LedgerScriptParams & { shouldUpdateMcu: boolean }, } type Result = * diff --git a/src/components/ManagerPage/FirmwareFinalUpdate.js b/src/components/ManagerPage/FirmwareFinalUpdate.js deleted file mode 100644 index 19e9b76f..00000000 --- a/src/components/ManagerPage/FirmwareFinalUpdate.js +++ /dev/null @@ -1,67 +0,0 @@ -// @flow - -import React, { PureComponent } from 'react' -import { translate } from 'react-i18next' -import logger from 'logger' -import type { DeviceInfo } from 'helpers/devices/getDeviceInfo' - -import type { Device, T } from 'types/common' - -import installFinalFirmware from 'commands/installFinalFirmware' - -import Box, { Card } from 'components/base/Box' -import Button from 'components/base/Button' - -type Props = { - t: T, - device: Device, - deviceInfo: DeviceInfo, -} - -type State = {} - -class FirmwareFinalUpdate extends PureComponent { - componentDidMount() {} - - componentWillUnmount() { - this._unmounting = true - } - - _unmounting = false - - installFinalFirmware = async () => { - try { - const { device, deviceInfo } = this.props - const { success } = await installFinalFirmware - .send({ - devicePath: device.path, - deviceInfo, - }) - .toPromise() - if (success) { - this.setState() - } - } catch (err) { - logger.log(err) - } - } - - render() { - const { t, ...props } = this.props - - return ( - - - {t('app:manager.firmware.update')} - - - - - - - - ) - } -} - -export default translate()(FirmwareFinalUpdate) diff --git a/src/components/ManagerPage/FirmwareUpdate.js b/src/components/ManagerPage/FirmwareUpdate.js index 60afcc15..103e1c89 100644 --- a/src/components/ManagerPage/FirmwareUpdate.js +++ b/src/components/ManagerPage/FirmwareUpdate.js @@ -1,7 +1,7 @@ // @flow /* eslint-disable react/jsx-no-literals */ // FIXME -import React, { PureComponent } from 'react' +import React, { PureComponent, Fragment } from 'react' import { translate } from 'react-i18next' import isEqual from 'lodash/isEqual' import isEmpty from 'lodash/isEmpty' @@ -14,6 +14,8 @@ import type { LedgerScriptParams } from 'helpers/common' import getLatestFirmwareForDevice from 'commands/getLatestFirmwareForDevice' 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' import type { DeviceInfo } from 'helpers/devices/getDeviceInfo' @@ -40,7 +42,7 @@ type Props = { } type State = { - latestFirmware: ?LedgerScriptParams, + latestFirmware: ?LedgerScriptParams & ?{ shouldUpdateMcu: boolean }, modal: ModalStatus, } @@ -78,26 +80,42 @@ class FirmwareUpdate extends PureComponent { } } - installFirmware = async () => { + installOsuFirmware = async () => { try { const { latestFirmware } = this.state - const { deviceInfo } = this.props - invariant(latestFirmware, 'did not find a new firmware or firmware is not set') const { + deviceInfo, device: { path: devicePath }, } = this.props + invariant(latestFirmware, 'did not find a new firmware or firmware is not set') + this.setState({ modal: 'install' }) const { success } = await installOsuFirmware .send({ devicePath, firmware: latestFirmware, targetId: deviceInfo.targetId }) .toPromise() - if (success) { - this.fetchLatestFirmware() - } + return success } catch (err) { logger.log(err) + throw err } } + installFinalFirmware = async () => { + try { + const { device } = this.props + const { success } = await installFinalFirmware.send({ devicePath: device.path }).toPromise() + return success + } catch (err) { + logger.log(err) + throw err + } + } + + flashMCU = async () => { + const { device } = this.props + await installMcu.send({ devicePath: device.path }).toPromise() + } + handleCloseModal = () => this.setState({ modal: 'closed' }) handleDisclaimerModal = () => this.setState({ modal: 'disclaimer' }) @@ -130,19 +148,27 @@ class FirmwareUpdate extends PureComponent { })} - + {modal !== 'closed' ? : null} - - + {latestFirmware && ( + + + + + )} ) } diff --git a/src/components/ManagerPage/FlashMcu.js b/src/components/ManagerPage/FlashMcu.js deleted file mode 100644 index 76a9b77d..00000000 --- a/src/components/ManagerPage/FlashMcu.js +++ /dev/null @@ -1,50 +0,0 @@ -// @flow -import React, { PureComponent } from 'react' - -import type { Device } from 'types/common' -import installMcu from 'commands/installMcu' - -import type { DeviceInfo } from 'helpers/devices/getDeviceInfo' - -type Props = { - device: Device, - deviceInfo: DeviceInfo, -} - -type State = { - flashing: boolean, -} - -class FlashMcu extends PureComponent { - state = { - flashing: false, - } - - flashMCU = async () => { - const { device, deviceInfo } = this.props - const { flashing } = this.state - - if (!flashing) { - this.setState({ flashing: true }) - await installMcu - .send({ - devicePath: device.path, - targetId: deviceInfo.targetId, - version: deviceInfo.seVersion, - }) - .toPromise() - this.setState({ flashing: false }) - } - } - - render() { - return ( -
-

{'Flashing MCU'}

- -
- ) - } -} - -export default FlashMcu diff --git a/src/components/ManagerPage/UpdateFirmwareButton.js b/src/components/ManagerPage/UpdateFirmwareButton.js index cdfead05..e3a58aac 100644 --- a/src/components/ManagerPage/UpdateFirmwareButton.js +++ b/src/components/ManagerPage/UpdateFirmwareButton.js @@ -18,16 +18,16 @@ type FirmwareInfos = { type Props = { t: T, firmware: ?FirmwareInfos, - installFirmware: () => void, + onClick: () => void, } -const UpdateFirmwareButton = ({ t, firmware, installFirmware }: Props) => +const UpdateFirmwareButton = ({ t, firmware, onClick }: Props) => firmware ? ( {t('app:manager.firmware.latest', { version: getCleanVersion(firmware.name) })} - diff --git a/src/components/ManagerPage/index.js b/src/components/ManagerPage/index.js index e0b3f76e..9eba78a4 100644 --- a/src/components/ManagerPage/index.js +++ b/src/components/ManagerPage/index.js @@ -40,10 +40,6 @@ class ManagerPage extends PureComponent { invariant(device, 'Inexistant device considered genuine') invariant(deviceInfo, 'Inexistant device infos for genuine device') - // TODO - // renderFinalUpdate - // renderMcuUpdate - return } } diff --git a/src/components/modals/ReleaseNotes.js b/src/components/modals/ReleaseNotes.js index 2d4950e3..d80999d8 100644 --- a/src/components/modals/ReleaseNotes.js +++ b/src/components/modals/ReleaseNotes.js @@ -25,7 +25,7 @@ type State = { markdown: ?string, } -const Notes = styled(Box).attrs({ +export const Notes = styled(Box).attrs({ ff: 'Open Sans', fontSize: 4, color: 'smoke', diff --git a/src/components/modals/UpdateFirmware/Disclaimer.js b/src/components/modals/UpdateFirmware/Disclaimer.js index 379c8928..bb462158 100644 --- a/src/components/modals/UpdateFirmware/Disclaimer.js +++ b/src/components/modals/UpdateFirmware/Disclaimer.js @@ -3,6 +3,7 @@ import React, { PureComponent, Fragment } from 'react' import { translate, Trans } from 'react-i18next' +import ReactMarkdown from 'react-markdown' import type { T } from 'types/common' @@ -11,11 +12,12 @@ import Text from 'components/base/Text' import Button from 'components/base/Button' import GrowScroll from 'components/base/GrowScroll' import GradientBox from 'components/GradientBox' - -import { getCleanVersion } from 'components/ManagerPage/FirmwareUpdate' +import { Notes } from 'components/modals/ReleaseNotes' import type { ModalStatus } from 'components/ManagerPage/FirmwareUpdate' +import { getCleanVersion } from 'components/ManagerPage/FirmwareUpdate' + type FirmwareInfos = { name: string, notes: string, @@ -58,9 +60,9 @@ class DisclaimerModal extends PureComponent { - - {firmware.notes} - + + {firmware.notes} + diff --git a/src/components/modals/UpdateFirmware/index.js b/src/components/modals/UpdateFirmware/index.js index abb71c8b..a86b8bef 100644 --- a/src/components/modals/UpdateFirmware/index.js +++ b/src/components/modals/UpdateFirmware/index.js @@ -14,18 +14,20 @@ import type { ModalStatus } from 'components/ManagerPage/FirmwareUpdate' import type { LedgerScriptParams } from 'helpers/common' import StepOSUInstaller from './steps/01-step-osu-installer' +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' export type StepProps = DefaultStepProps & { firmware: ?LedgerScriptParams, onCloseModal: () => void, + installOsuFirmware: () => void, + installFinalFirmware: () => void, + flashMcu: () => void, } type StepId = 'idCheck' | 'updateMCU' | 'finish' -// FIXME: Debugging for now to move between steps -// Remove when plugged to firmware update function DebugFooter({ transitionTo, where, @@ -36,45 +38,74 @@ function DebugFooter({ return } -const createSteps = ({ t }: { t: T }) => [ - { - id: 'idCheck', - label: t('app:manager.modal.steps.idCheck'), - component: StepOSUInstaller, - footer: ({ firmware, ...props }: StepProps) => ( - - ), - onBack: null, - hideFooter: false, - }, - { - id: 'updateMCU', - label: t('app:manager.modal.steps.updateMCU'), - component: StepFlashMcu, - footer: ({ firmware, ...props }: StepProps) => ( - - - - - ), - onBack: null, - hideFooter: false, - }, - { +const createSteps = ({ + t, + firmware, +}: { + t: T, + firmware: LedgerScriptParams & { shouldUpdateMcu: boolean }, +}): Array<*> => { + const finalStep = { id: 'finish', label: t('app:addAccounts.breadcrumb.finish'), component: StepConfirmation, footer: StepConfirmFooter, onBack: null, hideFooter: false, - }, -] + } + + if (firmware.shouldUpdateMcu) { + return [ + { + id: 'idCheck', + label: t('app:manager.modal.steps.idCheck'), + component: StepOSUInstaller, + footer: ({ firmware, ...props }: StepProps) => ( + + ), + onBack: null, + hideFooter: false, + }, + { + id: 'updateMCU', + label: t('app:manager.modal.steps.updateMCU'), + component: StepFlashMcu, + footer: ({ firmware, ...props }: StepProps) => ( + + + + + ), + onBack: null, + hideFooter: false, + }, + finalStep, + ] + } + + return [ + { + id: 'idCheck', + label: t('app:manager.modal.steps.idCheck'), + component: StepFullFirmwareInstall, + footer: ({ firmware, ...props }: StepProps) => ( + + ), + onBack: null, + hideFooter: false, + }, + finalStep, + ] +} type Props = { t: T, status: ModalStatus, onClose: () => void, - firmware: ?LedgerScriptParams, + firmware: LedgerScriptParams & { shouldUpdateMcu: boolean }, + installOsuFirmware: () => void, + installFinalFirmware: () => void, + flashMcu: () => void, } type State = { @@ -86,17 +117,18 @@ class UpdateModal extends PureComponent { stepId: 'idCheck', } - STEPS = createSteps({ t: this.props.t }) + STEPS = createSteps({ t: this.props.t, firmware: this.props.firmware }) handleStepChange = (step: Step) => this.setState({ stepId: step.id }) render(): React$Node { - const { status, t, firmware, onClose } = this.props + const { status, t, firmware, onClose, ...props } = this.props const { stepId } = this.state const additionalProps = { firmware, onCloseModal: onClose, + ...props, } return ( @@ -104,6 +136,7 @@ class UpdateModal extends PureComponent { onClose={onClose} isOpened={status === 'install'} refocusWhenChange={stepId} + preventBackdropClick={false} render={() => ( - {t('app:manager.modal.confirmIdentifier')} - - {t('app:manager.modal.confirmIdentifierText')} - - - - {t('app:manager.modal.identifier')} +class StepFullFirmwareInstall extends PureComponent { + componentDidMount() { + this.install() + } + + install = async () => { + const { installOsuFirmware, installFinalFirmware, transitionTo } = this.props + const success = await installOsuFirmware() + if (success) { + const finalSuccess = await installFinalFirmware() + if (finalSuccess) { + transitionTo('finish') + } + } + } + + renderBody = () => { + const { installing } = this.state + const { firmware, t } = this.props + + if (installing) { + return ( + + + + ) + } + + return ( + + + + {t('app:manager.modal.identifier')} + +
+ {firmware && firmware.hash} +
+
+ + + +
+ ) + } + + render() { + const { t } = this.props + return ( + + {t('app:manager.modal.confirmIdentifier')} + + {t('app:manager.modal.confirmIdentifierText')} -
- {firmware && firmware.hash} -
-
- - - - - ) + {this.renderBody()} + + ) + } } export default StepFullFirmwareInstall diff --git a/src/components/modals/UpdateFirmware/steps/01-step-osu-installer.js b/src/components/modals/UpdateFirmware/steps/01-step-osu-installer.js index 5aa12aa2..e42cb954 100644 --- a/src/components/modals/UpdateFirmware/steps/01-step-osu-installer.js +++ b/src/components/modals/UpdateFirmware/steps/01-step-osu-installer.js @@ -1,11 +1,10 @@ // @flow -import React from 'react' +import React, { PureComponent } from 'react' import styled from 'styled-components' import Box from 'components/base/Box' import Text from 'components/base/Text' -import Button from 'components/base/Button' import DeviceConfirm from 'components/DeviceConfirm' import type { StepProps } from '../' @@ -46,27 +45,41 @@ const Ellipsis = styled.span` width: 100%; ` -// TODO: Change to class component and add osu firmware install -function StepOSUInstaller({ t, firmware }: StepProps) { - return ( - - {t('app:manager.modal.confirmIdentifier')} - - {t('app:manager.modal.confirmIdentifierText')} - - - - {t('app:manager.modal.identifier')} +class StepOSUInstaller extends PureComponent { + componentDidMount() { + this.install() + } + + install = async () => { + const { installOsuFirmware, transitionTo } = this.props + const success = await installOsuFirmware() + if (success) { + transitionTo('updateMCU') + } + } + + render() { + const { t, firmware } = this.props + return ( + + {t('app:manager.modal.confirmIdentifier')} + + {t('app:manager.modal.confirmIdentifierText')} -
- {firmware && firmware.hash} -
-
- - - -
- ) + + + {t('app:manager.modal.identifier')} + +
+ {firmware && firmware.hash} +
+
+ + + + + ) + } } export default StepOSUInstaller 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 3991634c..b4781936 100644 --- a/src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js +++ b/src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js @@ -1,12 +1,21 @@ // @flow -import React from 'react' +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 { i } from 'helpers/staticPath' +import { getCurrentDevice } from 'reducers/devices' +import { createCancelablePolling } from 'helpers/promise' +import getDeviceInfo from 'commands/getDeviceInfo' import Box from 'components/base/Box' import Text from 'components/base/Text' +import Progress from 'components/base/Progress' + +import type { Device } from 'types/common' import type { StepProps } from '../' @@ -35,36 +44,112 @@ const Separator = styled(Box).attrs({ background-color: currentColor; ` -// TODO: Change to class component and add flash mcu and final -function StepFlashMcu({ t }: StepProps) { - return ( - - {t('app:manager.modal.mcuTitle')} - - - {'1.'} - {t('app:manager.modal.mcuFirst')} - - {t('app:manager.modal.mcuFirst')} - - - - - {'2.'} - {t('app:manager.modal.mcuSecond')} - - {t('app:manager.modal.mcuFirst')} - - - ) +const mapStateToProps = state => ({ + device: getCurrentDevice(state), +}) + +type Props = StepProps & { device?: Device } + +type State = { + installing: boolean, +} + +class StepFlashMcu extends PureComponent { + state = { + installing: false, + } + + componentDidMount() { + this.install() + } + + componentWillUnmount() { + this._unsubConnect() + } + + 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 + } + + install = async () => { + await this.waitForDeviceInBootloader() + const { flashMcu, installFinalFirmware, transitionTo } = this.props + this.setState({ installing: true }) + await flashMcu() + const finalSuccess = await installFinalFirmware() + + if (finalSuccess) { + transitionTo('finish') + } + } + + renderBody = () => { + const { installing } = this.state + const { t } = this.props + + if (installing) { + return ( + + + + ) + } + + return ( + + + + {'1.'} + {t('app:manager.modal.mcuFirst')} + + {t('app:manager.modal.mcuFirst')} + + + + + {'2.'} + {t('app:manager.modal.mcuSecond')} + + {t('app:manager.modal.mcuFirst')} + + + ) + } + + _unsubConnect: * + + render() { + const { t } = this.props + return ( + + {t('app:manager.modal.mcuTitle')} + {this.renderBody()} + + ) + } } -export default StepFlashMcu +export default connect(mapStateToProps)(StepFlashMcu) diff --git a/src/helpers/devices/getLatestFirmwareForDevice.js b/src/helpers/devices/getLatestFirmwareForDevice.js index 6a0a2624..3406b8af 100644 --- a/src/helpers/devices/getLatestFirmwareForDevice.js +++ b/src/helpers/devices/getLatestFirmwareForDevice.js @@ -3,6 +3,9 @@ import network from 'api/network' import { GET_LATEST_FIRMWARE } from 'helpers/urls' import type { DeviceInfo } from 'helpers/devices/getDeviceInfo' +import getFinalFirmwareById from 'helpers/firmware/getFinalFirmwareById' +import getMcus from 'helpers/firmware/getMcus' + import getCurrentFirmware from './getCurrentFirmware' import getDeviceVersion from './getDeviceVersion' @@ -34,7 +37,23 @@ export default async (deviceInfo: DeviceInfo) => { } const { se_firmware_osu_version } = data - return se_firmware_osu_version + 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) + + if (!seFirmwareFinalVersion.mcu_versions.includes(...currentMcuVersionId)) { + return { + ...se_firmware_osu_version, + shouldUpdateMcu: true, + } + } + + return { ...se_firmware_osu_version, shouldUpdateMcu: false } } catch (err) { const error = Error(err.message) error.stack = err.stack diff --git a/src/helpers/firmware/getMcus.js b/src/helpers/firmware/getMcus.js new file mode 100644 index 00000000..3f0b0399 --- /dev/null +++ b/src/helpers/firmware/getMcus.js @@ -0,0 +1,19 @@ +// @flow +import network from 'api/network' + +import { GET_MCUS } from 'helpers/urls' + +export default async (): Promise<*> => { + try { + const { data } = await network({ + method: 'GET', + url: GET_MCUS, + }) + + return data + } catch (err) { + const error = Error(err.message) + error.stack = err.stack + throw err + } +} diff --git a/src/helpers/devices/getNextMCU.js b/src/helpers/firmware/getNextMCU.js similarity index 100% rename from src/helpers/devices/getNextMCU.js rename to src/helpers/firmware/getNextMCU.js diff --git a/src/helpers/firmware/installFinalFirmware.js b/src/helpers/firmware/installFinalFirmware.js index e4d5269b..6e47a9fc 100644 --- a/src/helpers/firmware/installFinalFirmware.js +++ b/src/helpers/firmware/installFinalFirmware.js @@ -6,12 +6,14 @@ 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 getFinalFirmwareById from './getFinalFirmwareById' -type Result = * +type Result = Promise<{ success: boolean, error?: string }> -export default async (transport: Transport<*>, deviceInfo: DeviceInfo): Result => { +export default async (transport: Transport<*>): Result => { try { + const deviceInfo: DeviceInfo = await getDeviceInfo(transport) const device = await getDeviceVersion(deviceInfo.targetId, deviceInfo.providerId) const firmware = await getOsuFirmware({ deviceId: device.id, version: deviceInfo.fullVersion }) const { next_se_firmware_final_version } = firmware diff --git a/src/helpers/firmware/installMcu.js b/src/helpers/firmware/installMcu.js index 44ae9c37..b07faea3 100644 --- a/src/helpers/firmware/installMcu.js +++ b/src/helpers/firmware/installMcu.js @@ -3,18 +3,16 @@ import type Transport from '@ledgerhq/hw-transport' import { WS_MCU } from 'helpers/urls' import { createDeviceSocket } from 'helpers/socket' -import getNextMCU from 'helpers/devices/getNextMCU' +import getNextMCU from 'helpers/firmware/getNextMCU' +import getDeviceInfo from 'helpers/devices/getDeviceInfo' type Result = Promise<*> -export default async ( - transport: Transport<*>, - args: { targetId: string | number, version: string }, -): Result => { - const { version } = args +export default async (transport: Transport<*>): Result => { + const { seVersion: version, targetId } = await getDeviceInfo(transport) const nextVersion = await getNextMCU(version) const params = { - targetId: args.targetId, + targetId, version: nextVersion.name, } const url = WS_MCU(params) diff --git a/src/helpers/firmware/installOsuFirmware.js b/src/helpers/firmware/installOsuFirmware.js index 5995b7ae..2795f951 100644 --- a/src/helpers/firmware/installOsuFirmware.js +++ b/src/helpers/firmware/installOsuFirmware.js @@ -6,12 +6,31 @@ import { createDeviceSocket } from 'helpers/socket' import type { LedgerScriptParams } from 'helpers/common' +import { createCustomErrorClass } from '../errors' + +const ManagerUnexpectedError = createCustomErrorClass('ManagerUnexpected') +const ManagerNotEnoughSpaceError = createCustomErrorClass('ManagerNotEnoughSpace') +const ManagerDeviceLockedError = createCustomErrorClass('ManagerDeviceLocked') + +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() + default: + throw new ManagerUnexpectedError(e.message, { msg: e.message }) + } + }) +} + type Result = Promise<{ success: boolean, error?: any }> export default async ( transport: Transport<*>, targetId: string | number, - firmware: LedgerScriptParams, + firmware: LedgerScriptParams & { shouldUpdateMcu: boolean }, ): Result => { try { const params = { @@ -19,8 +38,9 @@ export default async ( ...firmware, firmwareKey: firmware.firmware_key, } + delete params.shouldUpdateMcu const url = WS_INSTALL(params) - await createDeviceSocket(transport, url).toPromise() + await remapError(createDeviceSocket(transport, url).toPromise()) return { success: true } } catch (error) { const result = { success: false, error } diff --git a/src/helpers/urls.js b/src/helpers/urls.js index 6ff24a70..11bed849 100644 --- a/src/helpers/urls.js +++ b/src/helpers/urls.js @@ -21,6 +21,7 @@ export const GET_CURRENT_FIRMWARE: string = managerUrlbuilder('get_firmware_vers 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') diff --git a/static/images/logos/bootloaderMode.png b/static/images/logos/bootloaderMode.png new file mode 100755 index 00000000..b6983a79 Binary files /dev/null and b/static/images/logos/bootloaderMode.png differ diff --git a/static/images/logos/unplugDevice.png b/static/images/logos/unplugDevice.png index 41aac779..38158a4a 100755 Binary files a/static/images/logos/unplugDevice.png and b/static/images/logos/unplugDevice.png differ