Browse Source

Merge pull request #628 from valpinkman/feature/new-api-server

[STAND-BY] Feature/new api server
master
Valentin D. Pinkman 7 years ago
committed by GitHub
parent
commit
1031366614
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 19
      src/commands/getCurrentFirmware.js
  2. 19
      src/commands/getFirmwareInfo.js
  3. 14
      src/commands/getIsGenuine.js
  4. 4
      src/commands/index.js
  5. 9
      src/commands/installApp.js
  6. 25
      src/commands/installMcu.js
  7. 11
      src/commands/installOsuFirmware.js
  8. 5
      src/commands/listApps.js
  9. 9
      src/commands/uninstallApp.js
  10. 17
      src/components/ManagerPage/AppSearchBar.js
  11. 41
      src/components/ManagerPage/AppsList.js
  12. 2
      src/components/ManagerPage/Dashboard.js
  13. 16
      src/components/ManagerPage/FirmwareUpdate.js
  14. 55
      src/components/ManagerPage/FlashMcu.js
  15. 5
      src/components/ManagerPage/UpdateFirmwareButton.js
  16. 7
      src/components/ManagerPage/index.js
  17. 15
      src/components/TriggerOnMount/index.js
  18. 2
      src/components/Workflow/EnsureGenuine.js
  19. 64
      src/components/Workflow/index.js
  20. 17
      src/helpers/apps/installApp.js
  21. 26
      src/helpers/apps/listApps.js
  22. 19
      src/helpers/apps/uninstallApp.js
  23. 49
      src/helpers/common.js
  24. 26
      src/helpers/devices/getCurrentFirmware.js
  25. 19
      src/helpers/devices/getDeviceVersion.js
  26. 34
      src/helpers/devices/getFirmwareInfo.js
  27. 24
      src/helpers/devices/getIsGenuine.js
  28. 37
      src/helpers/devices/getLatestFirmwareForDevice.js
  29. 7
      src/helpers/devices/getMemInfo.js
  30. 26
      src/helpers/devices/getNextMCU.js
  31. 10
      src/helpers/firmware/installFinalFirmware.js
  32. 25
      src/helpers/firmware/installMcu.js
  33. 23
      src/helpers/firmware/installOsuFirmware.js
  34. 27
      src/helpers/urls.js
  35. 1
      static/i18n/en/errors.yml

19
src/commands/getCurrentFirmware.js

@ -0,0 +1,19 @@
// @flow
import { createCommand, Command } from 'helpers/ipc'
import { fromPromise } from 'rxjs/observable/fromPromise'
import getCurrentFirmware from 'helpers/devices/getCurrentFirmware'
type Input = {
deviceId: string | number,
version: string,
}
type Result = *
const cmd: Command<Input, Result> = createCommand('getCurrentFirmware', data =>
fromPromise(getCurrentFirmware(data)),
)
export default cmd

19
src/commands/getFirmwareInfo.js

@ -1,19 +0,0 @@
// @flow
import { createCommand, Command } from 'helpers/ipc'
import { fromPromise } from 'rxjs/observable/fromPromise'
import getFirmwareInfo from 'helpers/devices/getFirmwareInfo'
type Input = {
targetId: string | number,
version: string,
}
type Result = *
const cmd: Command<Input, Result> = createCommand('getFirmwareInfo', data =>
fromPromise(getFirmwareInfo(data)),
)
export default cmd

14
src/commands/getIsGenuine.js

@ -6,11 +6,19 @@ import { fromPromise } from 'rxjs/observable/fromPromise'
import getIsGenuine from 'helpers/devices/getIsGenuine'
import { withDevice } from 'helpers/deviceAccess'
type Input = * // FIXME !
type Input = {
devicePath: string,
targetId: string | number,
version: string,
}
type Result = string
const cmd: Command<Input, Result> = createCommand('getIsGenuine', ({ devicePath, targetId }) =>
fromPromise(withDevice(devicePath)(transport => getIsGenuine(transport, { targetId }))),
const cmd: Command<Input, Result> = createCommand(
'getIsGenuine',
({ devicePath, targetId, version }) =>
fromPromise(
withDevice(devicePath)(transport => getIsGenuine(transport, { targetId, version })),
),
)
export default cmd

4
src/commands/index.js

@ -5,7 +5,7 @@ import type { Command } from 'helpers/ipc'
import getAddress from 'commands/getAddress'
import getDeviceInfo from 'commands/getDeviceInfo'
import getFirmwareInfo from 'commands/getFirmwareInfo'
import getCurrentFirmware from 'commands/getCurrentFirmware'
import getIsGenuine from 'commands/getIsGenuine'
import getLatestFirmwareForDevice from 'commands/getLatestFirmwareForDevice'
import getMemInfo from 'commands/getMemInfo'
@ -32,7 +32,7 @@ import uninstallApp from 'commands/uninstallApp'
const all: Array<Command<any, any>> = [
getAddress,
getDeviceInfo,
getFirmwareInfo,
getCurrentFirmware,
getIsGenuine,
getLatestFirmwareForDevice,
getMemInfo,

9
src/commands/installApp.js

@ -9,14 +9,17 @@ import installApp from 'helpers/apps/installApp'
import type { LedgerScriptParams } from 'helpers/common'
type Input = {
appParams: LedgerScriptParams,
app: LedgerScriptParams,
devicePath: string,
targetId: string | number,
}
type Result = *
const cmd: Command<Input, Result> = createCommand('installApp', ({ devicePath, ...rest }) =>
fromPromise(withDevice(devicePath)(transport => installApp(transport, rest))),
const cmd: Command<Input, Result> = createCommand(
'installApp',
({ devicePath, targetId, ...app }) =>
fromPromise(withDevice(devicePath)(transport => installApp(transport, targetId, app))),
)
export default cmd

25
src/commands/installMcu.js

@ -3,24 +3,21 @@
import { createCommand, Command } from 'helpers/ipc'
import { fromPromise } from 'rxjs/observable/fromPromise'
// import { withDevice } from 'helpers/deviceAccess'
import { withDevice } from 'helpers/deviceAccess'
import installMcu from 'helpers/firmware/installMcu'
// type Input = {
// devicePath: string,
// firmware: Object,
// }
type Input = {
devicePath: string,
targetId: string | number,
version: string,
}
// type Result = {
// targetId: number | string,
// version: string,
// final: boolean,
// mcu: boolean,
// }
type Input = *
type Result = *
const cmd: Command<Input, Result> = createCommand('installMcu', () => fromPromise(installMcu()))
const cmd: Command<Input, Result> = createCommand(
'installMcu',
({ devicePath, targetId, version }) =>
fromPromise(withDevice(devicePath)(transport => installMcu(transport, { targetId, version }))),
)
export default cmd

11
src/commands/installOsuFirmware.js

@ -6,17 +6,22 @@ import { fromPromise } from 'rxjs/observable/fromPromise'
import { withDevice } from 'helpers/deviceAccess'
import installOsuFirmware from 'helpers/firmware/installOsuFirmware'
import type { LedgerScriptParams } from 'helpers/common'
type Input = {
devicePath: string,
firmware: Object,
targetId: string | number,
firmware: LedgerScriptParams,
}
type Result = *
const cmd: Command<Input, Result> = createCommand(
'installOsuFirmware',
({ devicePath, firmware }) =>
fromPromise(withDevice(devicePath)(transport => installOsuFirmware(transport, firmware))),
({ devicePath, firmware, targetId }) =>
fromPromise(
withDevice(devicePath)(transport => installOsuFirmware(transport, targetId, firmware)),
),
)
export default cmd

5
src/commands/listApps.js

@ -7,12 +7,13 @@ import listApps from 'helpers/apps/listApps'
type Input = {
targetId: string | number,
version: string,
}
type Result = *
const cmd: Command<Input, Result> = createCommand('listApps', ({ targetId }) =>
fromPromise(listApps(targetId)),
const cmd: Command<Input, Result> = createCommand('listApps', ({ targetId, version }) =>
fromPromise(listApps(targetId, version)),
)
export default cmd

9
src/commands/uninstallApp.js

@ -9,14 +9,17 @@ import uninstallApp from 'helpers/apps/uninstallApp'
import type { LedgerScriptParams } from 'helpers/common'
type Input = {
appParams: LedgerScriptParams,
app: LedgerScriptParams,
devicePath: string,
targetId: string | number,
}
type Result = *
const cmd: Command<Input, Result> = createCommand('uninstallApp', ({ devicePath, ...rest }) =>
fromPromise(withDevice(devicePath)(transport => uninstallApp(transport, rest))),
const cmd: Command<Input, Result> = createCommand(
'uninstallApp',
({ devicePath, targetId, ...rest }) =>
fromPromise(withDevice(devicePath)(transport => uninstallApp(transport, targetId, rest))),
)
export default cmd

17
src/components/ManagerPage/AppSearchBar.js

@ -4,6 +4,8 @@ import styled from 'styled-components'
import { color, fontSize, space } from 'styled-system'
import fontFamily from 'styles/styled/fontFamily'
import type { LedgerScriptParams } from 'helpers/common'
import { ff } from 'styles/helpers'
import Box from 'components/base/Box'
@ -12,20 +14,9 @@ import Search from 'components/base/Search'
import SearchIcon from 'icons/Search'
import CrossIcon from 'icons/Cross'
type LedgerApp = {
name: string,
version: string,
icon: string,
app: Object,
bolos_version: {
min: number,
max: number,
},
}
type Props = {
list: Array<LedgerApp>,
children: (list: Array<LedgerApp>) => React$Node,
list: Array<LedgerScriptParams>,
children: (list: Array<LedgerScriptParams>) => React$Node,
}
type State = {

41
src/components/ManagerPage/AppsList.js

@ -6,6 +6,7 @@ import styled from 'styled-components'
import { translate } from 'react-i18next'
import type { Device, T } from 'types/common'
import type { LedgerScriptParams } from 'helpers/common'
import listApps from 'commands/listApps'
import installApp from 'commands/installApp'
@ -43,27 +44,17 @@ const ICONS_FALLBACK = {
type Status = 'loading' | 'idle' | 'busy' | 'success' | 'error'
type Mode = 'home' | 'installing' | 'uninstalling'
type LedgerApp = {
name: string,
version: string,
icon: string,
app: Object,
bolos_version: {
min: number,
max: number,
},
}
type Props = {
device: Device,
targetId: string | number,
t: T,
version: string,
}
type State = {
status: Status,
error: string | null,
appsList: LedgerApp[],
appsList: LedgerScriptParams[] | Array<*>,
app: string,
mode: Mode,
}
@ -89,8 +80,8 @@ class AppsList extends PureComponent<Props, State> {
async fetchAppList() {
try {
const { targetId } = this.props
const appsList = CACHED_APPS || (await listApps.send({ targetId }).toPromise())
const { targetId, version } = this.props
const appsList = CACHED_APPS || (await listApps.send({ targetId, version }).toPromise())
CACHED_APPS = appsList
if (!this._unmounted) {
this.setState({ appsList, status: 'idle' })
@ -100,14 +91,14 @@ class AppsList extends PureComponent<Props, State> {
}
}
handleInstallApp = (args: { app: any, name: string }) => async () => {
const { app: appParams, name } = args
this.setState({ status: 'busy', app: name, mode: 'installing' })
handleInstallApp = (app: LedgerScriptParams) => async () => {
this.setState({ status: 'busy', app: app.name, mode: 'installing' })
try {
const {
device: { path: devicePath },
targetId,
} = this.props
const data = { appParams, devicePath }
const data = { app, devicePath, targetId }
await installApp.send(data).toPromise()
this.setState({ status: 'success', app: '' })
} catch (err) {
@ -115,14 +106,14 @@ class AppsList extends PureComponent<Props, State> {
}
}
handleUninstallApp = (args: { app: any, name: string }) => async () => {
const { app: appParams, name } = args
this.setState({ status: 'busy', app: name, mode: 'uninstalling' })
handleUninstallApp = (app: LedgerScriptParams) => async () => {
this.setState({ status: 'busy', app: app.name, mode: 'uninstalling' })
try {
const {
device: { path: devicePath },
targetId,
} = this.props
const data = { appParams, devicePath }
const data = { app, devicePath, targetId }
await uninstallApp.send(data).toPromise()
this.setState({ status: 'success', app: '' })
} catch (err) {
@ -184,15 +175,15 @@ class AppsList extends PureComponent<Props, State> {
}
renderList() {
const { appsList } = this.state
return appsList.length > 0 ? (
const { appsList, status } = this.state
return status === 'idle' ? (
<Box>
<AppSearchBar list={appsList}>
{items => (
<List>
{items.map(c => (
<ManagerApp
key={`${c.name}_${c.version}_${c.bolos_version.min}`}
key={`${c.name}_${c.version}`}
name={c.name}
version={`Version ${c.version}`}
icon={ICONS_FALLBACK[c.icon] || c.icon}

2
src/components/ManagerPage/Dashboard.js

@ -43,7 +43,7 @@ const Dashboard = ({ device, deviceInfo, t }: Props) => (
/>
</Box>
<Box mt={5}>
<AppsList device={device} targetId={deviceInfo.targetId} />
<AppsList device={device} targetId={deviceInfo.targetId} version={deviceInfo.version} />
</Box>
</Box>
)

16
src/components/ManagerPage/FirmwareUpdate.js

@ -10,6 +10,8 @@ import logger from 'logger'
import type { Device, T } from 'types/common'
import type { LedgerScriptParams } from 'helpers/common'
import getLatestFirmwareForDevice from 'commands/getLatestFirmwareForDevice'
import installOsuFirmware from 'commands/installOsuFirmware'
@ -23,11 +25,6 @@ import UpdateFirmwareButton from './UpdateFirmwareButton'
let CACHED_LATEST_FIRMWARE = null
type FirmwareInfos = {
name: string,
notes: string,
}
type DeviceInfos = {
targetId: number | string,
version: string,
@ -40,7 +37,7 @@ type Props = {
}
type State = {
latestFirmware: ?FirmwareInfos,
latestFirmware: ?LedgerScriptParams,
}
class FirmwareUpdate extends PureComponent<Props, State> {
@ -84,12 +81,13 @@ class FirmwareUpdate extends PureComponent<Props, State> {
installFirmware = async () => {
try {
const { latestFirmware } = this.state
const { infos } = this.props
invariant(latestFirmware, 'did not find a new firmware or firmware is not set')
const {
device: { path: devicePath },
} = this.props
const { success } = await installOsuFirmware
.send({ devicePath, firmware: latestFirmware })
.send({ devicePath, firmware: latestFirmware, targetId: infos.targetId })
.toPromise()
if (success) {
this.fetchLatestFirmware()
@ -119,7 +117,9 @@ class FirmwareUpdate extends PureComponent<Props, State> {
</Box>
</Box>
<Text ff="Open Sans|SemiBold" fontSize={2}>
{t('app:manager.firmware.installed', { version: infos.version })}
{t('app:manager.firmware.installed', {
version: infos.version,
})}
</Text>
</Box>
<UpdateFirmwareButton firmware={latestFirmware} installFirmware={this.installFirmware} />

55
src/components/ManagerPage/FlashMcu.js

@ -0,0 +1,55 @@
// @flow
import React, { PureComponent } from 'react'
import type { Device } from 'types/common'
import installMcu from 'commands/installMcu'
type DeviceInfo = {
targetId: number | string,
version: string,
final: boolean,
mcu: boolean,
}
type Props = {
device: Device,
deviceInfo: DeviceInfo,
}
type State = {
flashing: boolean,
}
class FlashMcu extends PureComponent<Props, State> {
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.version,
})
.toPromise()
this.setState({ flashing: false })
}
}
render() {
return (
<div>
<h1>Flashing MCU</h1>
<button onClick={this.flashMCU}>flash</button>
</div>
)
}
}
export default FlashMcu

5
src/components/ManagerPage/UpdateFirmwareButton.js

@ -18,11 +18,14 @@ type Props = {
installFirmware: () => void,
}
const getCleanVersion = (input: string): string =>
input.endsWith('-osu') ? input.replace('-osu', '') : input
const UpdateFirmwareButton = ({ t, firmware, installFirmware }: Props) =>
firmware ? (
<Fragment>
<Text ff="Open Sans|Regular" fontSize={4} style={{ marginLeft: 'auto', marginRight: 15 }}>
{t('app:manager.firmware.latest', { version: firmware.name })}
{t('app:manager.firmware.latest', { version: getCleanVersion(firmware.name) })}
</Text>
<Button primary onClick={installFirmware}>
{t('app:manager.firmware.update')}

7
src/components/ManagerPage/index.js

@ -9,6 +9,7 @@ import type { Device } from 'types/common'
import Workflow from 'components/Workflow'
import WorkflowWithIcon from 'components/Workflow/WorkflowWithIcon'
import Dashboard from './Dashboard'
import FlashMcu from './FlashMcu'
type DeviceInfo = {
targetId: number | string,
@ -25,11 +26,11 @@ type Error = {
function ManagerPage(): Node {
return (
<Workflow
renderFinalUpdate={(deviceInfo: DeviceInfo) => (
renderFinalUpdate={(device: Device, deviceInfo: DeviceInfo) => (
<p>UPDATE FINAL FIRMARE (TEMPLATE + ACTION WIP) {deviceInfo.final}</p>
)}
renderMcuUpdate={(deviceInfo: DeviceInfo) => (
<p>FLASH MCU (TEMPLATE + ACTION WIP) {deviceInfo.mcu}</p>
renderMcuUpdate={(device: Device, deviceInfo: DeviceInfo) => (
<FlashMcu device={device} deviceInfo={deviceInfo} />
)}
renderDashboard={(device: Device, deviceInfo: DeviceInfo) => (
<Dashboard device={device} deviceInfo={deviceInfo} />

15
src/components/TriggerOnMount/index.js

@ -1,15 +0,0 @@
// @flow
import { PureComponent } from 'react'
type Props = {
callback: () => void,
}
class TriggerOnMount extends PureComponent<Props> {
componentDidMount() {
const { callback } = this.props
callback()
}
}
export default TriggerOnMount

2
src/components/Workflow/EnsureGenuine.js

@ -61,7 +61,7 @@ class EnsureGenuine extends PureComponent<Props, State> {
this._checking = true
try {
const res = await getIsGenuine
.send({ devicePath: device.path, targetId: infos.targetId })
.send({ devicePath: device.path, targetId: infos.targetId, version: infos.version })
.pipe(timeout(GENUINE_TIMEOUT))
.toPromise()
if (this._unmounting) return

64
src/components/Workflow/index.js

@ -31,9 +31,10 @@ type Props = {
genuineError: ?Error,
},
) => Node,
renderMcuUpdate?: (deviceInfo: DeviceInfo) => Node,
renderFinalUpdate?: (deviceInfo: DeviceInfo) => Node,
renderMcuUpdate?: (device: Device, deviceInfo: DeviceInfo) => Node,
renderFinalUpdate?: (device: Device, deviceInfo: DeviceInfo) => Node,
renderDashboard?: (device: Device, deviceInfo: DeviceInfo, isGenuine: boolean) => Node,
onGenuineCheck?: (isGenuine: boolean) => void,
renderError?: (dashboardError: ?Error, genuineError: ?Error) => Node,
}
type State = {}
@ -47,42 +48,47 @@ class Workflow extends PureComponent<Props, State> {
renderMcuUpdate,
renderError,
renderDefault,
onGenuineCheck,
} = this.props
return (
<EnsureDevice>
{(device: Device) => (
<EnsureDashboard device={device}>
{(deviceInfo: ?DeviceInfo, dashboardError: ?Error) => (
<EnsureGenuine device={device} infos={deviceInfo}>
{(isGenuine: ?boolean, genuineError: ?Error) => {
if (dashboardError || genuineError) {
return renderError
? renderError(dashboardError, genuineError)
: renderDefault(device, deviceInfo, isGenuine, {
genuineError,
dashboardError,
})
}
{(deviceInfo: ?DeviceInfo, dashboardError: ?Error) => {
if (deviceInfo && deviceInfo.mcu && renderMcuUpdate) {
return renderMcuUpdate(device, deviceInfo)
}
if (deviceInfo && deviceInfo.mcu && renderMcuUpdate) {
return renderMcuUpdate(deviceInfo)
}
if (deviceInfo && deviceInfo.final && renderFinalUpdate) {
return renderFinalUpdate(device, deviceInfo)
}
if (deviceInfo && deviceInfo.final && renderFinalUpdate) {
return renderFinalUpdate(deviceInfo)
}
return (
<EnsureGenuine device={device} infos={deviceInfo}>
{(isGenuine: ?boolean, genuineError: ?Error) => {
if (dashboardError || genuineError) {
return renderError
? renderError(dashboardError, genuineError)
: renderDefault(device, deviceInfo, isGenuine, {
genuineError,
dashboardError,
})
}
if (isGenuine && deviceInfo && device && !dashboardError && !genuineError) {
if (renderDashboard) return renderDashboard(device, deviceInfo, isGenuine)
}
if (isGenuine && deviceInfo && device && !dashboardError && !genuineError) {
if (onGenuineCheck) onGenuineCheck(isGenuine)
return renderDefault(device, deviceInfo, isGenuine, {
genuineError,
dashboardError,
})
}}
</EnsureGenuine>
)}
if (renderDashboard) return renderDashboard(device, deviceInfo, isGenuine)
}
return renderDefault(device, deviceInfo, isGenuine, {
genuineError,
dashboardError,
})
}}
</EnsureGenuine>
)
}}
</EnsureDashboard>
)}
</EnsureDevice>

17
src/helpers/apps/installApp.js

@ -1,8 +1,10 @@
// @flow
import qs from 'qs'
import type Transport from '@ledgerhq/hw-transport'
import { createSocketDialog } from 'helpers/common'
import { BASE_SOCKET_URL_SECURE } from 'config/constants'
import { createDeviceSocket } from 'helpers/socket'
import type { LedgerScriptParams } from 'helpers/common'
/**
@ -10,7 +12,14 @@ import type { LedgerScriptParams } from 'helpers/common'
*/
export default async function installApp(
transport: Transport<*>,
{ appParams }: { appParams: LedgerScriptParams },
targetId: string | number,
{ app }: { app: LedgerScriptParams },
): Promise<*> {
return createSocketDialog(transport, '/install', appParams)
const params = {
targetId,
...app,
firmwareKey: app.firmware_key,
}
const url = `${BASE_SOCKET_URL_SECURE}/install?${qs.stringify(params)}`
return createDeviceSocket(transport, url).toPromise()
}

26
src/helpers/apps/listApps.js

@ -1,20 +1,24 @@
// @flow
import axios from 'axios'
import { MANAGER_API_BASE } from 'config/constants'
import { APPLICATIONS_BY_DEVICE } from 'helpers/urls'
import getDeviceVersion from 'helpers/devices/getDeviceVersion'
import getCurrentFirmware from 'helpers/devices/getCurrentFirmware'
export default async (targetId: string | number) => {
export default async (targetId: string | number, version: string) => {
try {
const { data: deviceData } = await axios.get(
`${MANAGER_API_BASE}/device_versions_target_id/${targetId}`,
)
const { data } = await axios.get('https://api.ledgerwallet.com/update/applications')
if (deviceData.name in data) {
return data[deviceData.name]
const provider = 1
const deviceData = await getDeviceVersion(targetId)
const firmwareData = await getCurrentFirmware({ deviceId: deviceData.id, version })
const params = {
provider,
current_se_firmware_final_version: firmwareData.id,
device_version: deviceData.id,
}
return data['nanos-1.4']
const {
data: { application_versions },
} = await axios.post(APPLICATIONS_BY_DEVICE, params)
return application_versions.length > 0 ? application_versions : []
} catch (err) {
const error = Error(err.message)
error.stack = err.stack

19
src/helpers/apps/uninstallApp.js

@ -1,8 +1,10 @@
// @flow
import qs from 'qs'
import type Transport from '@ledgerhq/hw-transport'
import { createSocketDialog } from 'helpers/common'
import { BASE_SOCKET_URL_SECURE } from 'config/constants'
import { createDeviceSocket } from 'helpers/socket'
import type { LedgerScriptParams } from 'helpers/common'
/**
@ -10,12 +12,15 @@ import type { LedgerScriptParams } from 'helpers/common'
*/
export default async function uninstallApp(
transport: Transport<*>,
{ appParams }: { appParams: LedgerScriptParams },
targetId: string | number,
{ app }: { app: LedgerScriptParams },
): Promise<*> {
const params = {
...appParams,
firmware: appParams.delete,
firmwareKey: appParams.deleteKey,
targetId,
...app,
firmware: app.delete,
firmwareKey: app.delete_key,
}
return createSocketDialog(transport, '/install', params)
const url = `${BASE_SOCKET_URL_SECURE}/install?${qs.stringify(params)}`
return createDeviceSocket(transport, url).toPromise()
}

49
src/helpers/common.js

@ -1,11 +1,7 @@
// @flow
// FIXME remove this file! 'helpers/common.js' RLY? :P
import qs from 'qs'
import type Transport from '@ledgerhq/hw-transport'
import { BASE_SOCKET_URL, BASE_SOCKET_URL_SECURE } from 'config/constants'
import { createDeviceSocket } from './socket'
const APDUS = {
GET_FIRMWARE: [0xe0, 0x01, 0x00, 0x00],
@ -16,35 +12,14 @@ const APDUS = {
export type LedgerScriptParams = {
firmware?: string,
firmwareKey?: string,
firmware_key?: string,
delete?: string,
deleteKey?: string,
delete_key?: string,
targetId?: string | number,
}
type FirmwareUpdateType = 'osu' | 'final'
export async function getMemInfos(transport: Transport<*>): Promise<Object> {
const { targetId } = await getFirmwareInfo(transport)
// Dont ask me about this `perso_11`: I don't know. But we need it.
return createSocketDialog(transport, '/get-mem-infos', { targetId, perso: 'perso_11' })
}
/**
* Open socket connection with firmware api, and init a dialog
* with the device
*/
export async function createSocketDialog(
transport: Transport<*>,
endpoint: string,
params: LedgerScriptParams,
managerUrl: boolean = false,
): Promise<string> {
console.warn('DEPRECATED createSocketDialog: use createDeviceSocket') // eslint-disable-line
const url = `${managerUrl ? BASE_SOCKET_URL_SECURE : BASE_SOCKET_URL}${endpoint}?${qs.stringify(
params,
)}`
return createDeviceSocket(transport, url).toPromise()
name: string,
version: string,
icon: string,
app?: number,
}
/**
@ -66,15 +41,3 @@ export async function getFirmwareInfo(transport: Transport<*>) {
throw error
}
}
/**
* Helpers to build OSU and Final firmware params
*/
export const buildParamsFromFirmware = (type: FirmwareUpdateType): Function => (
data: any,
): LedgerScriptParams => ({
firmware: data[`${type}_firmware`],
firmwareKey: data[`${type}_firmware_key`],
perso: data[`${type}_perso`],
targetId: data[`${type}_target_id`],
})

26
src/helpers/devices/getCurrentFirmware.js

@ -0,0 +1,26 @@
// @flow
import axios from 'axios'
import { GET_CURRENT_FIRMWARE } from 'helpers/urls'
type Input = {
version: string,
deviceId: string | number,
}
let error
export default async (input: Input): Promise<*> => {
try {
const provider = 1
const { data } = await axios.post(GET_CURRENT_FIRMWARE, {
device_version: input.deviceId,
version_name: input.version,
provider,
})
return data
} catch (err) {
error = Error(err.message)
error.stack = err.stack
throw error
}
}

19
src/helpers/devices/getDeviceVersion.js

@ -0,0 +1,19 @@
// @flow
import axios from 'axios'
import { GET_DEVICE_VERSION } from 'helpers/urls'
export default async (targetId: string | number): Promise<*> => {
try {
const provider = 1
const { data } = await axios.post(GET_DEVICE_VERSION, {
provider,
target_id: targetId,
})
return data
} catch (err) {
const error = Error(err.message)
error.stack = err.stack
throw err
}
}

34
src/helpers/devices/getFirmwareInfo.js

@ -1,34 +0,0 @@
// @flow
import axios from 'axios'
import isEmpty from 'lodash/isEmpty'
import { MANAGER_API_BASE } from 'config/constants'
type Input = {
version: string,
targetId: string | number,
}
let error
export default async (data: Input) => {
try {
const { data: seFirmwareVersion } = await axios.post(
`${MANAGER_API_BASE}/firmware_versions_name`,
{
se_firmware_name: data.version,
target_id: data.targetId,
},
)
if (!isEmpty(seFirmwareVersion)) {
return seFirmwareVersion
}
error = Error('could not retrieve firmware informations, try again later')
throw error
} catch (err) {
error = Error(err.message)
error.stack = err.stack
throw error
}
}

24
src/helpers/devices/getIsGenuine.js

@ -1,12 +1,26 @@
// @flow
import type Transport from '@ledgerhq/hw-transport'
import { createSocketDialog } from 'helpers/common'
import { SKIP_GENUINE } from 'config/constants'
import { WS_GENUINE } from 'helpers/urls'
import { createDeviceSocket } from 'helpers/socket'
import getCurrentFirmware from './getCurrentFirmware'
import getDeviceVersion from './getDeviceVersion'
export default async (
transport: Transport<*>,
{ targetId }: { targetId: string | number },
): Promise<string> =>
SKIP_GENUINE
app: { targetId: string | number, version: string },
): Promise<string> => {
const { targetId, version } = app
const device = await getDeviceVersion(app.targetId)
const firmware = await getCurrentFirmware({ deviceId: device.id, version })
const params = {
targetId,
version,
perso: firmware.perso,
}
const url = WS_GENUINE(params)
return SKIP_GENUINE
? new Promise(resolve => setTimeout(() => resolve('0000'), 1000))
: createSocketDialog(transport, '/genuine', { targetId }, true)
: createDeviceSocket(transport, url).toPromise()
}

37
src/helpers/devices/getLatestFirmwareForDevice.js

@ -1,39 +1,38 @@
// @flow
import axios from 'axios'
import isEmpty from 'lodash/isEmpty'
import { MANAGER_API_BASE } from 'config/constants'
import { GET_LATEST_FIRMWARE } from 'helpers/urls'
import getFirmwareInfo from './getFirmwareInfo'
import getCurrentFirmware from './getCurrentFirmware'
import getDeviceVersion from './getDeviceVersion'
type Input = {
targetId: string | number,
version: string,
targetId: string | number,
}
export default async (data: Input) => {
export default async (input: Input) => {
try {
// Get firmware infos with firmware name and device version
const seFirmwareVersion = await getFirmwareInfo(data)
const provider = 1
const { targetId, version } = input
// Get device infos from targetId
const { data: deviceVersion } = await axios.get(
`${MANAGER_API_BASE}/device_versions_target_id/${data.targetId}`,
)
const deviceVersion = await getDeviceVersion(targetId)
// Get firmware infos with firmware name and device version
const seFirmwareVersion = await getCurrentFirmware({ version, deviceId: deviceVersion.id })
// Fetch next possible firmware
const { data: serverData } = await axios.post(`${MANAGER_API_BASE}/get_latest_firmware`, {
current_se_firmware_version: seFirmwareVersion.id,
const { data } = await axios.post(GET_LATEST_FIRMWARE, {
current_se_firmware_final_version: seFirmwareVersion.id,
device_version: deviceVersion.id,
providers: [1],
provider,
})
const { se_firmware_version } = serverData
if (!isEmpty(se_firmware_version)) {
return se_firmware_version
if (data.result === 'null') {
return null
}
return null
const { se_firmware_osu_version } = data
return se_firmware_osu_version
} catch (err) {
const error = Error(err.message)
error.stack = err.stack

7
src/helpers/devices/getMemInfo.js

@ -2,10 +2,9 @@
import type Transport from '@ledgerhq/hw-transport'
import { getFirmwareInfo, createSocketDialog } from 'helpers/common'
import { getFirmwareInfo } from 'helpers/common'
export default async function getMemInfos(transport: Transport<*>): Promise<Object> {
const { targetId } = await getFirmwareInfo(transport)
// Dont ask me about this `perso_11`: I don't know. But we need it.
return createSocketDialog(transport, '/get-mem-infos', { targetId, perso: 'perso_11' })
const { targetId } = await getFirmwareInfo(transport) // eslint-disable-line
return new Promise(resolve => setTimeout(() => resolve({}), 1000))
}

26
src/helpers/devices/getNextMCU.js

@ -0,0 +1,26 @@
// @flow
import axios from 'axios'
import { GET_NEXT_MCU } from 'helpers/urls'
import createCustomErrorClass from 'helpers/createCustomErrorClass'
const LatestMCUInstalledError = createCustomErrorClass('LatestMCUInstalledError')
export default async (bootloaderVersion: string): Promise<*> => {
try {
const { data } = await axios.post(GET_NEXT_MCU, {
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
} catch (err) {
const error = Error(err.message)
error.stack = err.stack
throw err
}
}

10
src/helpers/firmware/installFinalFirmware.js

@ -1,18 +1,16 @@
// @flow
import type Transport from '@ledgerhq/hw-transport'
import { createSocketDialog, buildParamsFromFirmware } from 'helpers/common'
import { WS_INSTALL } from 'helpers/urls'
import { createDeviceSocket } from 'helpers/socket'
type Input = Object
type Result = *
const buildOsuParams = buildParamsFromFirmware('final')
export default async (transport: Transport<*>, firmware: Input): Result => {
try {
const osuData = buildOsuParams(firmware)
await createSocketDialog(transport, '/install', osuData)
const url = WS_INSTALL(firmware)
await createDeviceSocket(transport, url).toPromise()
return { success: true }
} catch (err) {
const error = Error(err.message)

25
src/helpers/firmware/installMcu.js

@ -1,8 +1,23 @@
// @flow
import type Transport from '@ledgerhq/hw-transport'
type Result = Promise<boolean>
import { WS_MCU } from 'helpers/urls'
import { createDeviceSocket } from 'helpers/socket'
import getNextMCU from 'helpers/devices/getNextMCU'
// TODO: IMPLEMENTATION FOR FLASHING FIRMWARE
// GETTING APDUS FROM SERVER
// SEND THE APDUS TO DEVICE
export default async (): Result => new Promise(resolve => resolve(true))
type Result = Promise<*>
export default async (
transport: Transport<*>,
args: { targetId: string | number, version: string },
): Result => {
const { version } = args
const nextVersion = await getNextMCU(version)
const params = {
targetId: args.targetId,
version: nextVersion.name,
}
const url = WS_MCU(params)
return createDeviceSocket(transport, url).toPromise()
}

23
src/helpers/firmware/installOsuFirmware.js

@ -1,19 +1,26 @@
// @flow
import type Transport from '@ledgerhq/hw-transport'
import { createSocketDialog, buildParamsFromFirmware } from 'helpers/common'
import { WS_INSTALL } from 'helpers/urls'
import { createDeviceSocket } from 'helpers/socket'
type Input = Object
import type { LedgerScriptParams } from 'helpers/common'
type Result = Promise<{ success: boolean, error?: any }>
const buildOsuParams = buildParamsFromFirmware('osu')
export default async (transport: Transport<*>, firmware: Input): Result => {
export default async (
transport: Transport<*>,
targetId: string | number,
firmware: LedgerScriptParams,
): Result => {
try {
const osuData = buildOsuParams(firmware)
await createSocketDialog(transport, '/install', osuData)
const params = {
targetId,
...firmware,
firmwareKey: firmware.firmware_key,
}
const url = WS_INSTALL(params)
await createDeviceSocket(transport, url).toPromise()
return { success: true }
} catch (err) {
const error = Error(err.message)

27
src/helpers/urls.js

@ -0,0 +1,27 @@
// @flow
import qs from 'qs'
import { MANAGER_API_BASE, BASE_SOCKET_URL_SECURE } from 'config/constants'
import type { LedgerScriptParams } from 'helpers/common'
const urlBuilder = (base: string) => (endpoint: string): string => `${base}/${endpoint}`
const managerUrlbuilder = urlBuilder(MANAGER_API_BASE)
const wsURLBuilder = (endpoint: string) => (params?: Object) =>
`${BASE_SOCKET_URL_SECURE}/${endpoint}${params ? `?${qs.stringify(params)}` : ''}`
// const wsURLBuilderProxy = (endpoint: string) => (params?: Object) =>
// `ws://manager.ledger.fr:3501/${endpoint}${params ? `?${qs.stringify(params)}` : ''}`
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_LATEST_FIRMWARE: string = managerUrlbuilder('get_latest_firmware')
export const GET_NEXT_MCU: string = managerUrlbuilder('mcu_versions_bootloader')
export const WS_INSTALL: (arg: LedgerScriptParams) => string = wsURLBuilder('install')
export const WS_GENUINE: (arg: { targetId: string | number }) => string = wsURLBuilder('genuine')
export const WS_MCU: (arg: { targetId: string | number, version: string }) => string = wsURLBuilder(
'mcu',
)

1
static/i18n/en/errors.yml

@ -19,3 +19,4 @@ WebsocketConnectionFailed: Failed to establish a socket connection
DeviceSocketFail: Device socket failure
DeviceSocketNoBulkStatus: Device socket failure (bulk)
DeviceSocketNoHandler: Device socket failure (handler {{query}})
LatestMCUInstalledError: The latest MCU is already installed on the Device

Loading…
Cancel
Save