Browse Source

Re-use all remaining hw / manager code out of live-common

gre-patch-1
Gaëtan Renaudeau 6 years ago
parent
commit
e2579ac6e7
No known key found for this signature in database GPG Key ID: 7B66B85F042E5451
  1. 2
      src/commands/debugAppInfosForCurrency.js
  2. 21
      src/commands/getCurrentFirmware.js
  3. 5
      src/commands/getDeviceInfo.js
  4. 14
      src/commands/getIsGenuine.js
  5. 19
      src/commands/getMemInfo.js
  6. 12
      src/commands/index.js
  7. 19
      src/commands/isDashboardOpen.js
  8. 15
      src/commands/listAppVersions.js
  9. 15
      src/commands/listApps.js
  10. 17
      src/commands/listCategories.js
  11. 2
      src/commands/uninstallApp.js
  12. 13
      src/components/GenuineCheck.js
  13. 2
      src/components/ManagerPage/AppSearchBar.js
  14. 29
      src/components/ManagerPage/AppsList.js
  15. 2
      src/components/ManagerPage/Dashboard.js
  16. 2
      src/components/ManagerPage/index.js
  17. 6
      src/config/constants.js
  18. 52
      src/helpers/apps/installApp.js
  19. 30
      src/helpers/apps/listAppVersions.js
  20. 10
      src/helpers/apps/listApps.js
  21. 10
      src/helpers/apps/listCategories.js
  22. 41
      src/helpers/apps/uninstallApp.js
  23. 9
      src/helpers/debugAppInfosForCurrency/btc.js
  24. 10
      src/helpers/debugAppInfosForCurrency/ethereum.js
  25. 29
      src/helpers/debugAppInfosForCurrency/index.js
  26. 10
      src/helpers/debugAppInfosForCurrency/ripple.js
  27. 21
      src/helpers/devices/getBitcoinLikeInfo.js
  28. 24
      src/helpers/devices/getCurrentFirmware.js
  29. 5
      src/helpers/devices/getDeviceInfo.js
  30. 17
      src/helpers/devices/getDeviceVersion.js
  31. 32
      src/helpers/devices/getIsGenuine.js
  32. 10
      src/helpers/devices/getMemInfo.js
  33. 23
      src/helpers/devices/getOsuFirmware.js
  34. 16
      src/helpers/devices/isDashboardOpen.js
  35. 8
      src/helpers/firmware/getFinalFirmwareById.js
  36. 51
      src/helpers/firmware/getFirmwareInfo.js
  37. 13
      src/helpers/firmware/getMcus.js
  38. 25
      src/helpers/firmware/getNextMCU.js
  39. 132
      src/helpers/socket.js
  40. 37
      src/helpers/urls.js
  41. 8
      src/logger/logger.js

2
src/commands/debugAppInfosForCurrency.js

@ -1,10 +1,10 @@
// @flow // @flow
import { getCryptoCurrencyById } from '@ledgerhq/live-common/lib/currencies' import { getCryptoCurrencyById } from '@ledgerhq/live-common/lib/currencies'
import debugAppInfosForCurrency from '@ledgerhq/live-common/lib/hw/debugAppInfosForCurrency'
import { createCommand, Command } from 'helpers/ipc' import { createCommand, Command } from 'helpers/ipc'
import { from } from 'rxjs' import { from } from 'rxjs'
import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess'
import debugAppInfosForCurrency from 'helpers/debugAppInfosForCurrency'
type Input = { type Input = {
currencyId: string, currencyId: string,

21
src/commands/getCurrentFirmware.js

@ -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<Input, Result> = createCommand('getCurrentFirmware', data =>
fromPromise(getCurrentFirmware(data)),
)
export default cmd

5
src/commands/getDeviceInfo.js

@ -3,9 +3,8 @@
import { createCommand, Command } from 'helpers/ipc' import { createCommand, Command } from 'helpers/ipc'
import { from } from 'rxjs' import { from } from 'rxjs'
import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess'
import getDeviceInfo from '@ledgerhq/live-common/lib/hw/getDeviceInfo'
import getDeviceInfo from 'helpers/devices/getDeviceInfo' import type { DeviceInfo } from '@ledgerhq/live-common/lib/types/manager'
import type { DeviceInfo } from 'helpers/types'
type Input = { type Input = {
devicePath: string, devicePath: string,

14
src/commands/getIsGenuine.js

@ -1,11 +1,12 @@
// @flow // @flow
import { createCommand, Command } from 'helpers/ipc' import { createCommand, Command } from 'helpers/ipc'
import { from } from 'rxjs' import { of } from 'rxjs'
import type { DeviceInfo } from 'helpers/types' import { delay } from 'rxjs/operators'
import genuineCheck from '@ledgerhq/live-common/lib/hw/genuineCheck'
import getIsGenuine from 'helpers/devices/getIsGenuine'
import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' 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 = { type Input = {
devicePath: string, devicePath: string,
@ -14,7 +15,10 @@ type Input = {
type Result = string type Result = string
const cmd: Command<Input, Result> = createCommand('getIsGenuine', ({ devicePath, deviceInfo }) => const cmd: Command<Input, Result> = 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 export default cmd

19
src/commands/getMemInfo.js

@ -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<Input, Result> = createCommand('getMemInfo', ({ devicePath }) =>
withDevice(devicePath)(transport => from(getMemInfo(transport))),
)
export default cmd

12
src/commands/index.js

@ -9,12 +9,9 @@ import firmwareMain from 'commands/firmwareMain'
import firmwareRepair from 'commands/firmwareRepair' import firmwareRepair from 'commands/firmwareRepair'
import getAddress from 'commands/getAddress' import getAddress from 'commands/getAddress'
import getDeviceInfo from 'commands/getDeviceInfo' import getDeviceInfo from 'commands/getDeviceInfo'
import getCurrentFirmware from 'commands/getCurrentFirmware'
import getIsGenuine from 'commands/getIsGenuine' import getIsGenuine from 'commands/getIsGenuine'
import getLatestFirmwareForDevice from 'commands/getLatestFirmwareForDevice' import getLatestFirmwareForDevice from 'commands/getLatestFirmwareForDevice'
import getMemInfo from 'commands/getMemInfo'
import installApp from 'commands/installApp' import installApp from 'commands/installApp'
import isDashboardOpen from 'commands/isDashboardOpen'
import killInternalProcess from 'commands/killInternalProcess' import killInternalProcess from 'commands/killInternalProcess'
import libcoreGetFees from 'commands/libcoreGetFees' import libcoreGetFees from 'commands/libcoreGetFees'
import libcoreGetVersion from 'commands/libcoreGetVersion' import libcoreGetVersion from 'commands/libcoreGetVersion'
@ -23,9 +20,6 @@ import libcoreScanFromXPUB from 'commands/libcoreScanFromXPUB'
import libcoreSignAndBroadcast from 'commands/libcoreSignAndBroadcast' import libcoreSignAndBroadcast from 'commands/libcoreSignAndBroadcast'
import libcoreSyncAccount from 'commands/libcoreSyncAccount' import libcoreSyncAccount from 'commands/libcoreSyncAccount'
import libcoreValidAddress from 'commands/libcoreValidAddress' 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 listenDevices from 'commands/listenDevices'
import ping from 'commands/ping' import ping from 'commands/ping'
import signTransaction from 'commands/signTransaction' import signTransaction from 'commands/signTransaction'
@ -41,12 +35,9 @@ const all: Array<Command<any, any>> = [
firmwareRepair, firmwareRepair,
getAddress, getAddress,
getDeviceInfo, getDeviceInfo,
getCurrentFirmware,
getIsGenuine, getIsGenuine,
getLatestFirmwareForDevice, getLatestFirmwareForDevice,
getMemInfo,
installApp, installApp,
isDashboardOpen,
killInternalProcess, killInternalProcess,
libcoreGetFees, libcoreGetFees,
libcoreGetVersion, libcoreGetVersion,
@ -55,9 +46,6 @@ const all: Array<Command<any, any>> = [
libcoreSignAndBroadcast, libcoreSignAndBroadcast,
libcoreSyncAccount, libcoreSyncAccount,
libcoreValidAddress, libcoreValidAddress,
listApps,
listAppVersions,
listCategories,
listenDevices, listenDevices,
ping, ping,
signTransaction, signTransaction,

19
src/commands/isDashboardOpen.js

@ -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<Input, Result> = createCommand('isDashboardOpen', ({ devicePath }) =>
withDevice(devicePath)(transport => from(isDashboardOpen(transport))),
)
export default cmd

15
src/commands/listAppVersions.js

@ -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<ApplicationVersion>
const cmd: Command<DeviceInfo, Result> = createCommand('listAppVersions', deviceInfo =>
fromPromise(listAppVersions(deviceInfo)),
)
export default cmd

15
src/commands/listApps.js

@ -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<Application>
const cmd: Command<Input, Result> = createCommand('listApps', () => fromPromise(listApps()))
export default cmd

17
src/commands/listCategories.js

@ -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<Category>
const cmd: Command<Input, Result> = createCommand('listCategories', () =>
fromPromise(listCategories()),
)
export default cmd

2
src/commands/uninstallApp.js

@ -4,7 +4,7 @@ import { createCommand, Command } from 'helpers/ipc'
import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess' import { withDevice } from '@ledgerhq/live-common/lib/hw/deviceAccess'
import uninstallApp from '@ledgerhq/live-common/lib/hw/uninstallApp' 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 = { type Input = {
app: ApplicationVersion, app: ApplicationVersion,

13
src/components/GenuineCheck.js

@ -9,7 +9,8 @@ import { delay, createCancelablePolling } from 'helpers/promise'
import logger from 'logger' import logger from 'logger'
import type { T, Device } from 'types/common' 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' import { GENUINE_TIMEOUT, DEVICE_INFOS_TIMEOUT, GENUINE_CACHE_DELAY } from 'config/constants'
@ -92,6 +93,16 @@ class GenuineCheck extends PureComponent<Props> {
return true 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)) { if (genuineDevices.has(device)) {
logger.log("genuine was already checked. don't check again") logger.log("genuine was already checked. don't check again")
await delay(GENUINE_CACHE_DELAY) await delay(GENUINE_CACHE_DELAY)

2
src/components/ManagerPage/AppSearchBar.js

@ -3,7 +3,7 @@
import React, { PureComponent, Fragment } from 'react' import React, { PureComponent, Fragment } from 'react'
import styled from 'styled-components' 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 Box from 'components/base/Box'
import Space from 'components/base/Space' import Space from 'components/base/Space'

29
src/components/ManagerPage/AppsList.js

@ -9,11 +9,10 @@ import { compose } from 'redux'
import { throttleTime, filter, map } from 'rxjs/operators' import { throttleTime, filter, map } from 'rxjs/operators'
import type { Device, T } from 'types/common' 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 { getFullListSortedCryptoCurrencies } from 'helpers/countervalues'
import { developerModeSelector } from 'reducers/settings' import { developerModeSelector } from 'reducers/settings'
import listApps from 'commands/listApps'
import listAppVersions from 'commands/listAppVersions'
import installApp from 'commands/installApp' import installApp from 'commands/installApp'
import uninstallApp from 'commands/uninstallApp' import uninstallApp from 'commands/uninstallApp'
import Box from 'components/base/Box' import Box from 'components/base/Box'
@ -131,24 +130,14 @@ class AppsList extends PureComponent<Props, State> {
} }
async fetchAppList() { async fetchAppList() {
try { const { deviceInfo, isDevMode } = this.props
const { deviceInfo } = this.props
const [
applicationsList,
compatibleAppVersionsList,
sortedCryptoCurrencies,
] = await Promise.all([
listApps.send().toPromise(),
listAppVersions.send(deviceInfo).toPromise(),
getFullListSortedCryptoCurrencies(),
])
const filteredAppVersionsList = this.prepareAppList({ try {
applicationsList, const filteredAppVersionsList = await manager.getAppsList(
compatibleAppVersionsList, deviceInfo,
sortedCryptoCurrencies, isDevMode,
}) getFullListSortedCryptoCurrencies,
)
if (!this._unmounted) { if (!this._unmounted) {
this.setState({ this.setState({

2
src/components/ManagerPage/Dashboard.js

@ -4,7 +4,7 @@ import { translate } from 'react-i18next'
import styled from 'styled-components' import styled from 'styled-components'
import type { T, Device } from 'types/common' 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 Box from 'components/base/Box'
import Text from 'components/base/Text' import Text from 'components/base/Text'

2
src/components/ManagerPage/index.js

@ -5,7 +5,7 @@ import invariant from 'invariant'
import { openURL } from 'helpers/linking' import { openURL } from 'helpers/linking'
import { urls } from 'config/urls' import { urls } from 'config/urls'
import type { Device } from 'types/common' 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 { getFullListSortedCryptoCurrencies } from 'helpers/countervalues'
import Dashboard from './Dashboard' import Dashboard from './Dashboard'

6
src/config/constants.js

@ -58,12 +58,6 @@ export const LEDGER_REST_API_BASE = stringFromEnv(
'LEDGER_REST_API_BASE', 'LEDGER_REST_API_BASE',
'https://explorers.api.live.ledger.com', '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 // Provider
export const FORCE_PROVIDER = intFromEnv('FORCE_PROVIDER', 0) export const FORCE_PROVIDER = intFromEnv('FORCE_PROVIDER', 0)

52
src/helpers/apps/installApp.js

@ -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<void> {
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())
}

30
src/helpers/apps/listAppVersions.js

@ -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<ApplicationVersion> } }
export default async (deviceInfo: DeviceInfo): Promise<Array<ApplicationVersion>> => {
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 : []
}

10
src/helpers/apps/listApps.js

@ -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<Array<Application>> => {
const { data } = await network({ method: 'GET', url: GET_APPLICATIONS })
return data.length > 0 ? data : []
}

10
src/helpers/apps/listCategories.js

@ -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<Array<Category>> => {
const { data }: { data: Array<Category> } = await network({ method: 'GET', url: GET_CATEGORIES })
return data.length > 0 ? data : []
}

41
src/helpers/apps/uninstallApp.js

@ -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<void> {
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())
}

9
src/helpers/debugAppInfosForCurrency/btc.js

@ -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 }
}

10
src/helpers/debugAppInfosForCurrency/ethereum.js

@ -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 }
}

29
src/helpers/debugAppInfosForCurrency/index.js

@ -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

10
src/helpers/debugAppInfosForCurrency/ripple.js

@ -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 }
}

21
src/helpers/devices/getBitcoinLikeInfo.js

@ -1,21 +0,0 @@
// @flow
import type Transport from '@ledgerhq/hw-transport'
const getBitcoinLikeInfo = (
transport: Transport<any>,
): 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

24
src/helpers/devices/getCurrentFirmware.js

@ -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<FinalFirmware> => {
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
}

5
src/helpers/devices/getDeviceInfo.js

@ -1,5 +0,0 @@
// @flow
import getDeviceInfo from '@ledgerhq/live-common/lib/hw/getDeviceInfo'
export default getDeviceInfo

17
src/helpers/devices/getDeviceVersion.js

@ -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<DeviceVersion> => {
const { data }: { data: DeviceVersion } = await network({
method: 'POST',
url: GET_DEVICE_VERSION,
data: {
provider,
target_id: targetId,
},
})
return data
}

32
src/helpers/devices/getIsGenuine.js

@ -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<string> => {
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()
}

10
src/helpers/devices/getMemInfo.js

@ -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<Object> {
const { targetId } = await getFirmwareInfo(transport) // eslint-disable-line
return new Promise(resolve => setTimeout(() => resolve({}), 1000))
}

23
src/helpers/devices/getOsuFirmware.js

@ -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
}

16
src/helpers/devices/isDashboardOpen.js

@ -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<Result> => {
const { targetId, seVersion } = await getFirmwareInfo(transport)
if (targetId && seVersion) {
return true
}
return false
}

8
src/helpers/firmware/getFinalFirmwareById.js

@ -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
}

51
src/helpers/firmware/getFirmwareInfo.js

@ -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<FirmwareInfo> {
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 }
}

13
src/helpers/firmware/getMcus.js

@ -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
}

25
src/helpers/firmware/getNextMCU.js

@ -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
}

132
src/helpers/socket.js

@ -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()
}
}
})

37
src/helpers/urls.js

@ -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',
)

8
src/logger/logger.js

@ -109,13 +109,7 @@ const logAnalytics = !__DEV__ || DEBUG_ANALYTICS
const logApdu = !__DEV__ || DEBUG_DEVICE const logApdu = !__DEV__ || DEBUG_DEVICE
const blacklistTooVerboseCommandInput = [] const blacklistTooVerboseCommandInput = []
const blacklistTooVerboseCommandResponse = [ const blacklistTooVerboseCommandResponse = ['libcoreSyncAccount', 'libcoreScanAccounts']
'libcoreSyncAccount',
'libcoreScanAccounts',
'listApps',
'listAppVersions',
'listCategories',
]
export default { export default {
onCmd: (type: string, id: string, spentTime: number, data?: any) => { onCmd: (type: string, id: string, spentTime: number, data?: any) => {

Loading…
Cancel
Save